Skip to content

feat(lisp): surface catalog_ops on Step (#920) #986

feat(lisp): surface catalog_ops on Step (#920)

feat(lisp): surface catalog_ops on Step (#920) #986

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