diff --git a/.github/workflows/buddy-bot.yml b/.github/workflows/buddy-bot.yml new file mode 100644 index 0000000..a2264e7 --- /dev/null +++ b/.github/workflows/buddy-bot.yml @@ -0,0 +1,512 @@ +name: Buddy Bot + +on: + schedule: + # Check for rebase requests every minute + - cron: '*/1 * * * *' + # Update dependencies every 2 hours + - cron: '0 */2 * * *' + # Update dashboard 15 minutes after dependency updates (ensures updates are reflected) + - cron: '15 */2 * * *' + + workflow_dispatch: # Manual trigger + inputs: + job: + description: Which job to run + required: false + default: all + type: choice + options: + - all + - check + - update + - dashboard + # Update job inputs + strategy: + description: Update strategy + required: false + default: patch + type: choice + options: + - all + - major + - minor + - patch + packages: + description: Specific packages (comma-separated) + required: false + type: string + # Dashboard job inputs + title: + description: Custom dashboard title + required: false + type: string + issue_number: + description: Specific issue number to update + required: false + type: string + # Common inputs + dry_run: + description: Dry run (preview only) + required: false + default: false + type: boolean + verbose: + description: Enable verbose logging + required: false + default: true + type: boolean + +env: + # For workflow file updates, you need a Personal Access Token with 'repo' and 'workflow' scopes + # Create a PAT at: https://github.com/settings/tokens + # Add it as a repository secret named 'BUDDY_BOT_TOKEN' + # If BUDDY_BOT_TOKEN is not available, falls back to GITHUB_TOKEN (limited permissions) + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + BUDDY_BOT_TOKEN: ${{ secrets.BUDDY_BOT_TOKEN }} + +permissions: + contents: write + pull-requests: write + issues: write + actions: write + checks: read + statuses: read + +jobs: + # Job to determine which jobs should run based on trigger + determine-jobs: + runs-on: ubuntu-latest + outputs: + run_check: ${{ steps.determine.outputs.run_check }} + run_update: ${{ steps.determine.outputs.run_update }} + run_dashboard: ${{ steps.determine.outputs.run_dashboard }} + steps: + - name: Determine which jobs to run + id: determine + run: | + # Default to not running any jobs + echo "run_check=false" >> $GITHUB_OUTPUT + echo "run_update=false" >> $GITHUB_OUTPUT + echo "run_dashboard=false" >> $GITHUB_OUTPUT + + if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then + JOB="${{ github.event.inputs.job || 'all' }}" + if [ "$JOB" = "all" ] || [ "$JOB" = "check" ]; then + echo "run_check=true" >> $GITHUB_OUTPUT + fi + if [ "$JOB" = "all" ] || [ "$JOB" = "update" ]; then + echo "run_update=true" >> $GITHUB_OUTPUT + fi + if [ "$JOB" = "all" ] || [ "$JOB" = "dashboard" ]; then + echo "run_dashboard=true" >> $GITHUB_OUTPUT + fi + elif [ "${{ github.event_name }}" = "schedule" ]; then + # Determine based on cron schedule + if [ "${{ github.event.schedule }}" = "*/1 * * * *" ]; then + echo "run_check=true" >> $GITHUB_OUTPUT + elif [ "${{ github.event.schedule }}" = "0 */2 * * *" ]; then + echo "run_update=true" >> $GITHUB_OUTPUT + elif [ "${{ github.event.schedule }}" = "15 */2 * * *" ]; then + echo "run_dashboard=true" >> $GITHUB_OUTPUT + fi + fi + + # Shared setup job for common dependencies + setup: + runs-on: ubuntu-latest + needs: determine-jobs + if: ${{ needs.determine-jobs.outputs.run_check == 'true' || needs.determine-jobs.outputs.run_update == 'true' || needs.determine-jobs.outputs.run_dashboard == 'true' }} + steps: + - name: Checkout repository + uses: actions/checkout@v4 + with: + token: ${{ secrets.GITHUB_TOKEN }} + fetch-depth: 0 # Fetch full history for rebasing + persist-credentials: true + + - name: Setup Bun + uses: oven-sh/setup-bun@v2.0.2 + + - name: Setup PHP and Composer (if needed) + if: ${{ hashFiles('composer.json') != '' }} + uses: shivammathur/setup-php@2.35.4 + with: + php-version: '8.4' + tools: composer + coverage: none + + - name: Install Composer dependencies (if needed) + if: ${{ hashFiles('composer.json') != '' }} + run: composer install --prefer-dist --optimize-autoloader + + - name: Install dependencies + run: bun install + + - name: Configure Git + run: | + git config --global user.name "github-actions[bot]" + git config --global user.email "github-actions[bot]@users.noreply.github.com" + + # Check job (handles both rebase requests and auto-closing PRs) + check: + runs-on: ubuntu-latest + needs: [determine-jobs, setup] + if: ${{ needs.determine-jobs.outputs.run_check == 'true' }} + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + with: + token: ${{ secrets.GITHUB_TOKEN }} + fetch-depth: 0 + persist-credentials: true + + - name: Setup Bun + uses: oven-sh/setup-bun@v2.0.2 + + - name: Install dependencies + run: bun install + + - name: Configure Git + run: | + git config --global user.name "github-actions[bot]" + git config --global user.email "github-actions[bot]@users.noreply.github.com" + + - name: Check token permissions + run: | + if [ -z "${{ secrets.BUDDY_BOT_TOKEN }}" ]; then + echo "โš ๏ธ Using GITHUB_TOKEN (limited permissions)" + echo "๐Ÿ’ก For full workflow file update support:" + echo " 1. Create a Personal Access Token with 'repo' and 'workflow' scopes" + echo " 2. Add it as repository secret 'BUDDY_BOT_TOKEN'" + echo " 3. Re-run this workflow" + else + echo "โœ… Using BUDDY_BOT_TOKEN (full permissions)" + fi + + - name: Check for PRs that need attention + run: | + echo "๐Ÿ” Checking for PRs that need attention (rebase requests or auto-closing)..." + echo "๐Ÿ”ง Environment info:" + echo "Current directory: $(pwd)" + echo "GITHUB_TOKEN set: $([[ -n "$GITHUB_TOKEN" ]] && echo "Yes" || echo "No")" + echo "Repository: ${{ github.repository }}" + echo "Event: ${{ github.event_name }}" + echo "" + + echo "๐Ÿš€ Running update-check command..." + set -e # Exit on any error + + if [ "${{ github.event.inputs.dry_run }}" = "true" ]; then + echo "๐Ÿ“‹ Running in DRY RUN mode..." + bunx buddy-bot update-check --dry-run --verbose + else + echo "๐Ÿ”„ Running in LIVE mode..." + bunx buddy-bot update-check --verbose + fi + + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + BUDDY_BOT_TOKEN: ${{ secrets.BUDDY_BOT_TOKEN }} + + - name: Create check summary + if: always() + run: | + echo "## ๐Ÿ” Check Summary" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + echo "- **Triggered by**: ${{ github.event_name }}" >> $GITHUB_STEP_SUMMARY + echo "- **Dry run**: ${{ github.event.inputs.dry_run || 'false' }}" >> $GITHUB_STEP_SUMMARY + echo "- **Time**: $(date)" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + + if [ "${{ github.event_name }}" = "schedule" ]; then + echo "โฐ **Scheduled Check**: Automatically checks every minute" >> $GITHUB_STEP_SUMMARY + else + echo "๐Ÿ–ฑ๏ธ **Manual Check**: Manually triggered from Actions tab" >> $GITHUB_STEP_SUMMARY + fi + + echo "" >> $GITHUB_STEP_SUMMARY + echo "๐Ÿ“‹ View detailed logs above for check results (rebase requests, auto-closing, and branch cleanup)." >> $GITHUB_STEP_SUMMARY + + # Dependency update job + dependency-update: + runs-on: ubuntu-latest + needs: [determine-jobs, setup] + if: ${{ needs.determine-jobs.outputs.run_update == 'true' }} + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + with: + token: ${{ secrets.GITHUB_TOKEN }} + fetch-depth: 0 + persist-credentials: true + + - name: Setup Bun + uses: oven-sh/setup-bun@v2.0.2 + + - name: Setup PHP and Composer (if needed) + if: ${{ hashFiles('composer.json') != '' }} + uses: shivammathur/setup-php@2.35.4 + with: + php-version: '8.4' + tools: composer + coverage: none + + - name: Install Composer dependencies (if needed) + if: ${{ hashFiles('composer.json') != '' }} + run: composer install --prefer-dist --optimize-autoloader + + - name: Install dependencies + run: bun install + + - name: Configure Git + run: | + git config --global user.name "github-actions[bot]" + git config --global user.email "github-actions[bot]@users.noreply.github.com" + + - name: Display update configuration + run: | + echo "๐Ÿงช **Buddy Bot Update Mode**" + echo "Strategy: ${{ github.event.inputs.strategy || 'patch' }}" + echo "Dry Run: ${{ github.event.inputs.dry_run || 'false' }}" + echo "Packages: ${{ github.event.inputs.packages || 'all' }}" + echo "Verbose: ${{ github.event.inputs.verbose || 'true' }}" + echo "Triggered by: ${{ github.event_name }}" + echo "Repository: ${{ github.repository }}" + echo "Branch: ${{ github.ref_name }}" + + - name: Run Buddy dependency updates + if: ${{ github.event.inputs.dry_run != 'true' }} + run: | + STRATEGY="${{ github.event.inputs.strategy || 'patch' }}" + PACKAGES="${{ github.event.inputs.packages }}" + VERBOSE="${{ github.event.inputs.verbose || 'true' }}" + + echo "๐Ÿš€ Running dependency updates..." + echo "This will create/update PRs if outdated dependencies are found" + echo "" + + set -e # Exit on any error + + if [ "$PACKAGES" != "" ]; then + if [ "$VERBOSE" = "true" ]; then + bunx buddy-bot update --packages "$PACKAGES" --verbose + else + bunx buddy-bot update --packages "$PACKAGES" + fi + else + if [ "$VERBOSE" = "true" ]; then + bunx buddy-bot update --strategy "$STRATEGY" --verbose + else + bunx buddy-bot update --strategy "$STRATEGY" + fi + fi + + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + BUDDY_BOT_TOKEN: ${{ secrets.BUDDY_BOT_TOKEN }} + + - name: Dry run notification + if: ${{ github.event.inputs.dry_run == 'true' }} + run: | + echo "โ„น๏ธ **Dry Run Mode** - No changes were made" + echo "To apply updates, run this workflow again with 'Dry run' set to false" + + - name: Create update summary + if: always() + run: | + echo "## ๐Ÿš€ Dependency Update Summary" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + echo "- **Strategy**: ${{ github.event.inputs.strategy || 'patch' }}" >> $GITHUB_STEP_SUMMARY + echo "- **Triggered by**: ${{ github.event_name }}" >> $GITHUB_STEP_SUMMARY + echo "- **Dry run**: ${{ github.event.inputs.dry_run || 'false' }}" >> $GITHUB_STEP_SUMMARY + echo "- **Packages**: ${{ github.event.inputs.packages || 'all' }}" >> $GITHUB_STEP_SUMMARY + echo "- **Verbose**: ${{ github.event.inputs.verbose || 'true' }}" >> $GITHUB_STEP_SUMMARY + echo "- **Time**: $(date)" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + + if [ "${{ github.event_name }}" = "schedule" ]; then + echo "โฐ **Scheduled Run**: This was triggered automatically every 2 hours" >> $GITHUB_STEP_SUMMARY + echo "๐Ÿ’ก **Tip**: Use 'Actions' tab to manually trigger with custom settings" >> $GITHUB_STEP_SUMMARY + else + echo "๐Ÿ–ฑ๏ธ **Manual Trigger**: This was triggered manually from the Actions tab" >> $GITHUB_STEP_SUMMARY + echo "โฐ **Auto-Schedule**: This workflow also runs every 2 hours" >> $GITHUB_STEP_SUMMARY + fi + + echo "" >> $GITHUB_STEP_SUMMARY + echo "๐Ÿ“Š View detailed logs above for scan and update results." >> $GITHUB_STEP_SUMMARY + + # Dashboard update job + dashboard-update: + runs-on: ubuntu-latest + needs: [determine-jobs, setup, dependency-update] + if: ${{ needs.determine-jobs.outputs.run_dashboard == 'true' && always() }} + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + with: + token: ${{ secrets.GITHUB_TOKEN }} + + - name: Setup Bun + uses: oven-sh/setup-bun@v2.0.2 + + - name: Install dependencies + run: bun install + + - name: Display dashboard configuration + run: | + echo "๐Ÿ“Š **Buddy Bot Dashboard Management**" + echo "Pin Dashboard: ${{ github.event.inputs.pin || 'true' }}" + echo "Custom Title: ${{ github.event.inputs.title || 'default' }}" + echo "Issue Number: ${{ github.event.inputs.issue_number || 'auto-detect' }}" + echo "Verbose: ${{ github.event.inputs.verbose || 'true' }}" + echo "Dry Run: ${{ github.event.inputs.dry_run || 'false' }}" + echo "Triggered by: ${{ github.event_name }}" + echo "Repository: ${{ github.repository }}" + echo "Branch: ${{ github.ref_name }}" + + - name: Pre-flight dashboard check + if: ${{ github.event.inputs.dry_run != 'true' }} + run: | + echo "๐Ÿ” Pre-flight check: Looking for existing dashboard issues..." + + # Check for existing dashboard issues to prevent duplicates + if command -v gh &> /dev/null; then + EXISTING_DASHBOARDS=$(gh issue list --label "dashboard,dependencies" --state open --json number,title,url --jq length 2>/dev/null || echo "0") + echo "Found $EXISTING_DASHBOARDS existing dashboard issue(s)" + + if [ "$EXISTING_DASHBOARDS" -gt 1 ]; then + echo "โš ๏ธ WARNING: Multiple dashboard issues detected!" + gh issue list --label "dashboard,dependencies" --state open --json number,title,url --jq '.[] | " - #\(.number): \(.title) - \(.url)"' 2>/dev/null || true + echo "" + echo "๐Ÿ”ง Buddy Bot will attempt to update the most recent one and may close duplicates" + elif [ "$EXISTING_DASHBOARDS" -eq 1 ]; then + DASHBOARD_INFO=$(gh issue list --label "dashboard,dependencies" --state open --json number,title,url --jq '.[0] | "#\(.number): \(.title) - \(.url)"' 2>/dev/null || echo "Found 1 dashboard") + echo "โœ… Found existing dashboard: $DASHBOARD_INFO" + else + echo "โ„น๏ธ No existing dashboard found - a new one will be created" + fi + else + echo "โš ๏ธ GitHub CLI not available - cannot perform pre-flight check" + fi + + - name: Update Dependency Dashboard + run: | + PIN="${{ github.event.inputs.pin || 'true' }}" + TITLE="${{ github.event.inputs.title }}" + ISSUE_NUMBER="${{ github.event.inputs.issue_number }}" + VERBOSE="${{ github.event.inputs.verbose || 'true' }}" + DRY_RUN="${{ github.event.inputs.dry_run || 'false' }}" + + echo "๐Ÿ“Š Updating dependency dashboard..." + echo "Pin: $PIN" + echo "Title: ${TITLE:-default}" + echo "Issue Number: ${ISSUE_NUMBER:-auto-detect}" + echo "Verbose: $VERBOSE" + echo "Dry Run: $DRY_RUN" + echo "" + + set -e # Exit on any error + + # Build the command + COMMAND="bunx buddy-bot dashboard" + + if [ "$TITLE" != "" ]; then + COMMAND="$COMMAND --title \"$TITLE\"" + fi + + if [ "$ISSUE_NUMBER" != "" ]; then + COMMAND="$COMMAND --issue-number \"$ISSUE_NUMBER\"" + fi + + if [ "$VERBOSE" = "true" ]; then + COMMAND="$COMMAND --verbose" + fi + + if [ "$DRY_RUN" = "true" ]; then + echo "๐Ÿ“‹ DRY RUN MODE - Command that would be executed:" + echo "$COMMAND" + echo "" + echo "โ„น๏ธ In dry run mode, dashboard content would be generated but no issue would be created/updated" + + # Run scan to show what would be included + echo "๐Ÿ” Scanning for dependencies that would be included:" + if [ "$VERBOSE" = "true" ]; then + bunx buddy-bot scan --verbose + else + bunx buddy-bot scan + fi + else + echo "๐Ÿš€ Executing dashboard update:" + echo "$COMMAND" + echo "" + eval "$COMMAND" + fi + + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + BUDDY_BOT_TOKEN: ${{ secrets.BUDDY_BOT_TOKEN }} + + - name: Dry run notification + if: ${{ github.event.inputs.dry_run == 'true' }} + run: | + echo "โ„น๏ธ **Dry Run Mode** - Dashboard preview completed" + echo "To actually update the dashboard, run this workflow again with 'Dry run' set to false" + + - name: Check dashboard status + if: ${{ github.event.inputs.dry_run != 'true' }} + run: | + echo "โœ… Dashboard update completed" + echo "๐Ÿ”— Check your repository issues for the updated dependency dashboard" + + # Try to find and link to the dashboard issue + echo "๐Ÿ“Š Looking for dependency dashboard issue..." + + # Use GitHub CLI to find the dashboard issue + if command -v gh &> /dev/null; then + DASHBOARD_URL=$(gh issue list --label "dashboard,dependencies" --state open --limit 1 --json url --jq '.[0].url' 2>/dev/null || echo "") + if [ "$DASHBOARD_URL" != "null" ] && [ "$DASHBOARD_URL" != "" ]; then + echo "๐ŸŽฏ Dashboard found: $DASHBOARD_URL" + else + echo "๐Ÿ” Dashboard issue not found via CLI, check issues manually" + fi + else + echo "๐Ÿ’ก Check your issues tab for the dependency dashboard" + fi + + - name: Create dashboard summary + if: always() + run: | + echo "## ๐Ÿ“Š Dependency Dashboard Summary" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + echo "- **Pin Dashboard**: ${{ github.event.inputs.pin || 'true' }}" >> $GITHUB_STEP_SUMMARY + echo "- **Custom Title**: ${{ github.event.inputs.title || 'default' }}" >> $GITHUB_STEP_SUMMARY + echo "- **Issue Number**: ${{ github.event.inputs.issue_number || 'auto-detect' }}" >> $GITHUB_STEP_SUMMARY + echo "- **Triggered by**: ${{ github.event_name }}" >> $GITHUB_STEP_SUMMARY + echo "- **Dry run**: ${{ github.event.inputs.dry_run || 'false' }}" >> $GITHUB_STEP_SUMMARY + echo "- **Verbose**: ${{ github.event.inputs.verbose || 'true' }}" >> $GITHUB_STEP_SUMMARY + echo "- **Time**: $(date)" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + + if [ "${{ github.event_name }}" = "schedule" ]; then + echo "โฐ **Scheduled Update**: This was triggered automatically" >> $GITHUB_STEP_SUMMARY + echo "๐Ÿ”„ **Schedule**: Every 2 hours, 15 minutes after dependency updates" >> $GITHUB_STEP_SUMMARY + echo "๐Ÿ’ก **Tip**: Use 'Actions' tab to manually trigger with custom settings" >> $GITHUB_STEP_SUMMARY + else + echo "๐Ÿ–ฑ๏ธ **Manual Trigger**: This was triggered manually from the Actions tab" >> $GITHUB_STEP_SUMMARY + echo "โฐ **Auto-Schedule**: This workflow also runs automatically on schedule" >> $GITHUB_STEP_SUMMARY + fi + + echo "" >> $GITHUB_STEP_SUMMARY + + if [ "${{ github.event.inputs.dry_run }}" = "true" ]; then + echo "๐Ÿ“‹ **Dry Run**: No changes were made. Dashboard content was previewed only." >> $GITHUB_STEP_SUMMARY + else + echo "โœ… **Dashboard Updated**: Check your repository issues for the updated dependency dashboard." >> $GITHUB_STEP_SUMMARY + fi + + echo "" >> $GITHUB_STEP_SUMMARY + echo "๐Ÿ“Š View detailed logs above for dashboard update results." >> $GITHUB_STEP_SUMMARY diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 3e3540b..a89c5d0 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -23,7 +23,7 @@ jobs: bun-version: 1.2.18 - name: Use cached node_modules - uses: actions/cache@v4 + uses: actions/cache@v4.2.4 with: path: node_modules key: node-modules-${{ hashFiles('**/bun.lock') }} diff --git a/deps.yaml b/deps.yaml index f21568f..4655bab 100644 --- a/deps.yaml +++ b/deps.yaml @@ -1,2 +1,2 @@ dependencies: - bun.sh: ^1.2.16 + bun.sh: ^1.2.20 diff --git a/package.json b/package.json index 83704a2..42bae72 100644 --- a/package.json +++ b/package.json @@ -26,11 +26,13 @@ }, "scripts": { "build": "for dir in packages/*; do if [ -f \"$dir/package.json\" ]; then echo \"Building $dir\" && bun run --cwd $dir build; fi; done", + "fresh": "bunx rimraf node_modules/ bun.lock && bun i", "lint": "bunx --bun eslint .", "lint:fix": "bunx --bun eslint . --fix", - "fresh": "bunx rimraf node_modules/ bun.lock && bun i", - "changelog": "bunx changelogen --output CHANGELOG.md", - "release": "bun run changelog && bunx bumpp -r --all", + "changelog": "bunx logsmith --verbose", + "changelog:generate": "bunx logsmith --output CHANGELOG.md", + "release": "bun run changelog:generate && bunx bumpx prompt --recursive", + "postinstall": "bunx git-hooks", "test": "bun test", "dev:docs": "bun --bun vitepress dev docs", "build:docs": "bun --bun vitepress build docs", @@ -38,25 +40,28 @@ "typecheck": "bun --bun tsc --noEmit" }, "devDependencies": { + "@stacksjs/bumpx": "workspace:*", "@stacksjs/docs": "^0.70.23", "@stacksjs/eslint-config": "^4.14.0-beta.3", "@stacksjs/gitlint": "^0.1.5", - "@stacksjs/logsmith": "^0.1.2", - "@types/bun": "^1.2.15", - "bumpp": "^10.1.1", + "@stacksjs/logsmith": "^0.1.8", + "@types/bun": "^1.2.20", + "buddy-bot": "^0.8.8", "bun-git-hooks": "^0.2.19", "bun-plugin-dtsx": "^0.9.5", "bunfig": "^0.10.1", - "changelogen": "^0.6.1", - "lint-staged": "^15.5.2", - "simple-git-hooks": "^2.13.0", "typescript": "^5.8.3" }, "overrides": { "unconfig": "0.3.10" }, - "lint-staged": { - "*.{js,ts}": "bunx --bun eslint . --fix" + "git-hooks": { + "pre-commit": { + "staged-lint": { + "*.{js,ts,json,yaml,yml,md}": "bun lint:fix" + } + }, + "commit-msg": "bunx gitlint --edit $1" }, "workspaces": [ "packages/*" diff --git a/packages/action/package.json b/packages/action/package.json index a555ae4..29c05be 100644 --- a/packages/action/package.json +++ b/packages/action/package.json @@ -38,6 +38,6 @@ }, "devDependencies": { "bun-plugin-dtsx": "^0.21.12", - "typescript": "^5.8.3" + "typescript": "^5.9.2" } }