feat(lisp): surface catalog_ops on Step (#920) #986
Workflow file for this run
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Claude Batch Fix | |
| on: | |
| # Manual trigger | |
| workflow_dispatch: | |
| # Auto-trigger when quick-fix label is added (checks if threshold reached) | |
| issues: | |
| types: [labeled] | |
| # Clean up batch-pending labels when batch PR is closed without merge | |
| pull_request: | |
| types: [closed] | |
| jobs: | |
| # Clean up batch-pending labels if PR closed without merge | |
| cleanup-on-pr-close: | |
| if: | | |
| github.event_name == 'pull_request' && | |
| github.event.pull_request.merged == false && | |
| startsWith(github.event.pull_request.head.ref, 'batch-fix/') | |
| runs-on: ubuntu-latest | |
| permissions: | |
| issues: write | |
| steps: | |
| - name: Remove batch-pending labels | |
| env: | |
| GH_TOKEN: ${{ github.token }} | |
| run: | | |
| echo "Batch PR closed without merge - removing batch-pending labels" | |
| # Find all issues with batch-pending and remove the label | |
| ISSUES=$(gh issue list \ | |
| --repo "${{ github.repository }}" \ | |
| --label "batch-pending" \ | |
| --state open \ | |
| --json number \ | |
| --jq '.[].number') | |
| for issue in $ISSUES; do | |
| echo "Removing batch-pending from issue #$issue" | |
| gh issue edit "$issue" \ | |
| --repo "${{ github.repository }}" \ | |
| --remove-label "batch-pending" || true | |
| done | |
| echo "Cleanup complete - issues are available for next batch" | |
| check-threshold: | |
| # Only run on label event if it's the quick-fix label | |
| if: | | |
| github.event_name == 'workflow_dispatch' || | |
| (github.event_name == 'issues' && github.event.label.name == 'quick-fix') | |
| runs-on: ubuntu-latest | |
| outputs: | |
| should_run: ${{ steps.check.outputs.should_run }} | |
| issue_count: ${{ steps.check.outputs.issue_count }} | |
| steps: | |
| - name: Check quick-fix issue count | |
| id: check | |
| env: | |
| GH_TOKEN: ${{ github.token }} | |
| run: | | |
| # Get open quick-fix issues that are NOT already in a batch | |
| # Exclude issues with batch-pending label | |
| ISSUES=$(gh issue list \ | |
| --repo "${{ github.repository }}" \ | |
| --label "quick-fix" \ | |
| --state open \ | |
| --json number,title,labels \ | |
| --limit 20 \ | |
| | jq '[.[] | select(.labels | map(.name) | index("batch-pending") | not)]') | |
| COUNT=$(echo "$ISSUES" | jq length) | |
| echo "issue_count=$COUNT" >> $GITHUB_OUTPUT | |
| echo "Found $COUNT available quick-fix issues (excluding batch-pending)" | |
| # Threshold: 5 issues for auto-trigger, always run for manual if any exist | |
| if [ "${{ github.event_name }}" == "workflow_dispatch" ] && [ "$COUNT" -gt 0 ]; then | |
| echo "Manual trigger with $COUNT issues - proceeding" | |
| echo "should_run=true" >> $GITHUB_OUTPUT | |
| elif [ "$COUNT" -ge 5 ]; then | |
| echo "Threshold reached ($COUNT >= 5) - proceeding" | |
| echo "should_run=true" >> $GITHUB_OUTPUT | |
| else | |
| echo "Below threshold ($COUNT < 5) - skipping" | |
| echo "should_run=false" >> $GITHUB_OUTPUT | |
| fi | |
| batch-fix: | |
| needs: check-threshold | |
| if: needs.check-threshold.outputs.should_run == 'true' | |
| runs-on: ubuntu-latest | |
| concurrency: | |
| group: claude-automation | |
| cancel-in-progress: false | |
| permissions: | |
| contents: write | |
| pull-requests: write | |
| issues: write | |
| id-token: write | |
| env: | |
| MIX_ENV: test | |
| steps: | |
| - name: Checkout repository | |
| uses: actions/checkout@v4 | |
| with: | |
| fetch-depth: 0 | |
| token: ${{ secrets.PAT_WORKFLOW_TRIGGER || github.token }} | |
| - name: Setup Elixir environment | |
| uses: ./.github/actions/setup-elixir | |
| - name: Setup Claude Code | |
| id: setup-claude | |
| uses: ./.github/actions/setup-claude-code | |
| - name: Prepare issue list and mark as pending | |
| id: issues | |
| env: | |
| GH_TOKEN: ${{ github.token }} | |
| run: | | |
| # Get quick-fix issues NOT already in a batch | |
| gh issue list \ | |
| --repo "${{ github.repository }}" \ | |
| --label "quick-fix" \ | |
| --state open \ | |
| --json number,title,body,labels \ | |
| --limit 20 \ | |
| | jq '[.[] | select(.labels | map(.name) | index("batch-pending") | not)]' \ | |
| > /tmp/quick-fix-issues.json | |
| COUNT=$(jq length /tmp/quick-fix-issues.json) | |
| if [ "$COUNT" -eq 0 ]; then | |
| echo "No issues to fix (all may have batch-pending)" | |
| echo "has_issues=false" >> $GITHUB_OUTPUT | |
| exit 0 | |
| fi | |
| echo "has_issues=true" >> $GITHUB_OUTPUT | |
| # Create summary for prompt | |
| jq -r '.[] | "- #\(.number): \(.title)"' /tmp/quick-fix-issues.json > /tmp/issue-summary.txt | |
| echo "Issues to fix:" | |
| cat /tmp/issue-summary.txt | |
| # Get issue numbers | |
| ISSUE_NUMBERS=$(jq -r '.[].number' /tmp/quick-fix-issues.json | tr '\n' ' ') | |
| echo "issue_numbers=$ISSUE_NUMBERS" >> $GITHUB_OUTPUT | |
| # Mark issues as batch-pending to prevent duplicate processing | |
| echo "Marking issues as batch-pending..." | |
| for issue in $ISSUE_NUMBERS; do | |
| echo "Adding batch-pending to issue #$issue" | |
| gh issue edit "$issue" \ | |
| --repo "${{ github.repository }}" \ | |
| --add-label "batch-pending" || true | |
| done | |
| - name: Run Claude Batch Fix | |
| if: steps.issues.outputs.has_issues == 'true' | |
| id: claude-fix | |
| uses: anthropics/claude-code-action@v1 | |
| env: | |
| GH_TOKEN: ${{ secrets.PAT_WORKFLOW_TRIGGER || github.token }} | |
| with: | |
| allowed_bots: "claude" | |
| claude_code_oauth_token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }} | |
| # Use PAT for git operations to avoid GitHub App workflow permission issues | |
| github_token: ${{ secrets.PAT_WORKFLOW_TRIGGER || github.token }} | |
| path_to_claude_code_executable: ${{ steps.setup-claude.outputs.executable-path }} | |
| prompt: | | |
| # Batch Fix: Quick-Fix Issues | |
| Fix all the following quick-fix issues in a SINGLE PR. | |
| ## Issues to Fix | |
| Read issue summary: `cat /tmp/issue-summary.txt` | |
| ## Detailed Issue Information | |
| Read detailed info: `cat /tmp/quick-fix-issues.json` | |
| ## Instructions | |
| 1. **Read each issue** to understand what needs to be fixed | |
| 2. **Check for duplicates**: If two issues describe the same fix, only fix it once | |
| and note in the PR which issues were duplicates | |
| 3. **Create a single branch** named `batch-fix/quick-fixes-$(date +%Y%m%d)-$(date +%H%M)` | |
| 4. **Fix ALL issues** with minimal, focused changes | |
| 5. **Run tests**: `mix test` to verify nothing is broken | |
| 6. **Create ONE PR** that: | |
| - Has title: "fix: batch quick-fixes (N issues)" | |
| - Lists all issues being fixed in the body | |
| - Uses "Closes #N" for each issue so they auto-close on merge | |
| - Notes any issues skipped (duplicates, unclear, too complex) | |
| ## PR Body Template | |
| ```markdown | |
| ## Summary | |
| Batch fix for quick-fix issues. | |
| ## Issues Fixed | |
| - Closes #X: [title] | |
| - Closes #Y: [title] | |
| ... | |
| ## Issues Skipped (if any) | |
| - #Z: [reason - duplicate of #X / unclear / too complex] | |
| ## Changes | |
| - [Brief description of each change] | |
| --- | |
| 🤖 Generated with [Claude Code](https://claude.com/claude-code) | |
| ``` | |
| ## Rules | |
| - Make minimal changes - only fix what each issue describes | |
| - Don't refactor unrelated code | |
| - Don't add new features | |
| - If an issue is unclear or too complex, skip it and note why in the PR | |
| - If issues are duplicates, close all of them but only fix once | |
| - Run `mix format` before committing | |
| Begin fixing the issues now. | |
| claude_args: '--model claude-sonnet-4-6 --allowed-tools "Read,Write,Edit,MultiEdit,Glob,Grep,LS,Bash,Task,TodoWrite,TodoRead"' | |
| show_full_output: true | |
| # If Claude fails, remove batch-pending so issues can be retried | |
| - name: Cleanup on failure | |
| if: failure() && steps.issues.outputs.has_issues == 'true' | |
| env: | |
| GH_TOKEN: ${{ github.token }} | |
| ISSUE_NUMBERS: ${{ steps.issues.outputs.issue_numbers }} | |
| run: | | |
| echo "Batch fix failed - removing batch-pending labels" | |
| for issue in $ISSUE_NUMBERS; do | |
| echo "Removing batch-pending from issue #$issue" | |
| gh issue edit "$issue" \ | |
| --repo "${{ github.repository }}" \ | |
| --remove-label "batch-pending" || true | |
| done |