Skip to content

Auto-Cleanup Fixup #151

Auto-Cleanup Fixup

Auto-Cleanup Fixup #151

# Reacts to CI failures on the auto-cleanup PR and attempts a minimal fix.
# Companion to auto-cleanup.yml, so it uses the same dedicated Anthropic key to
# keep auto-cleanup spend isolated from terminal-bench.
# Prompt lives in: .github/prompts/auto-cleanup-fixup.md
name: Auto-Cleanup Fixup
on:
workflow_run:
workflows: ["PR"]
types: [completed]
branches: [auto-cleanup]
permissions:
contents: write
pull-requests: write
actions: read
jobs:
fixup:
# Only run for failed PR workflow runs from this repository's own
# auto-cleanup branch. This blocks untrusted fork-origin runs from
# reaching token creation and mux execution.
if: ${{ github.event.workflow_run.conclusion == 'failure' && github.event.workflow_run.head_repository.full_name == github.repository && github.event.workflow_run.head_branch == 'auto-cleanup' }}
runs-on: ubuntu-latest
steps:
- name: Check required secrets
id: precheck
env:
# Keep the runtime env name stable while routing spend to a dedicated key.
ANTHROPIC_API_KEY: ${{ secrets.AUTO_CLEANUP_ANTHROPIC_API_KEY }}
MUX_APP_ID: ${{ secrets.MUX_APP_ID }}
MUX_APP_PRIVATE_KEY: ${{ secrets.MUX_APP_PRIVATE_KEY }}
run: |
missing=0
[ -z "$ANTHROPIC_API_KEY" ] && echo "Skipping (missing AUTO_CLEANUP_ANTHROPIC_API_KEY)." && missing=1
[ -z "$MUX_APP_ID" ] && echo "Skipping (missing MUX_APP_ID)." && missing=1
[ -z "$MUX_APP_PRIVATE_KEY" ] && echo "Skipping (missing MUX_APP_PRIVATE_KEY)." && missing=1
if [ "$missing" -eq 1 ]; then
echo "enabled=false" >> "$GITHUB_OUTPUT"
else
echo "enabled=true" >> "$GITHUB_OUTPUT"
fi
- uses: actions/create-github-app-token@d72941d797fd3113feb6b93fd0dec494b13a2547 # v1.12.0
id: app-token
if: ${{ steps.precheck.outputs.enabled == 'true' }}
with:
app-id: ${{ secrets.MUX_APP_ID }}
private-key: ${{ secrets.MUX_APP_PRIVATE_KEY }}
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1
if: ${{ steps.precheck.outputs.enabled == 'true' }}
with:
# Diagnose/fix the exact failed run revision, not a moving branch tip.
ref: ${{ github.event.workflow_run.head_sha }}
fetch-depth: 0
token: ${{ steps.app-token.outputs.token }}
- name: Attach auto-cleanup branch to failed revision
if: ${{ steps.precheck.outputs.enabled == 'true' }}
env:
FAILED_HEAD_SHA: ${{ github.event.workflow_run.head_sha }}
run: |
git checkout -B auto-cleanup "$FAILED_HEAD_SHA"
actual_sha=$(git rev-parse HEAD)
if [ "$actual_sha" != "$FAILED_HEAD_SHA" ]; then
echo "❌ Expected HEAD to match failed run SHA"
echo "expected=$FAILED_HEAD_SHA actual=$actual_sha"
exit 1
fi
- uses: oven-sh/setup-bun@b7a1c7ccf290d58743029c4f6903da283811b979 # v2.1.0
if: ${{ steps.precheck.outputs.enabled == 'true' }}
with:
bun-version: 1.3.5
# Pin the git identity so the AI agent doesn't invent its own.
- name: Configure git identity
if: ${{ steps.precheck.outputs.enabled == 'true' }}
run: |
git config user.name "mux-bot[bot]"
git config user.email "264182336+mux-bot[bot]@users.noreply.github.com"
# Circuit breaker: if the last commit is already a fixup, we already
# retried once and should stop to prevent an infinite failure loop.
- name: Circuit breaker - skip if already retried
id: circuit
if: ${{ steps.precheck.outputs.enabled == 'true' }}
run: |
last_msg=$(git log -1 --format='%s')
if [[ "$last_msg" == fix:* ]] || [[ "$last_msg" == "fix(ci):"* ]]; then
echo "⚠️ Last commit is already a fixup ('$last_msg'). Skipping to prevent loop."
echo "should_run=false" >> "$GITHUB_OUTPUT"
else
echo "should_run=true" >> "$GITHUB_OUTPUT"
fi
- name: Comment on PR when circuit breaker triggers
if: ${{ steps.precheck.outputs.enabled == 'true' && steps.circuit.outputs.should_run == 'false' }}
env:
GH_TOKEN: ${{ steps.app-token.outputs.token }}
run: |
pr_number=$(gh pr list --state open --head auto-cleanup --json number -q '.[0].number')
if [ -n "$pr_number" ] && [ "$pr_number" != "null" ]; then
gh pr comment "$pr_number" --body \
"⚠️ Auto-fixup circuit breaker triggered: the previous fixup commit also failed CI. Manual intervention needed."
else
echo "No open auto-cleanup PR found; skipping circuit-breaker comment."
fi
- name: Fix CI failure with mux
if: ${{ steps.precheck.outputs.enabled == 'true' && steps.circuit.outputs.should_run == 'true' }}
env:
ANTHROPIC_API_KEY: ${{ secrets.AUTO_CLEANUP_ANTHROPIC_API_KEY }}
GH_TOKEN: ${{ steps.app-token.outputs.token }}
FAILED_RUN_ID: ${{ github.event.workflow_run.id }}
run: |
bunx mux@next run \
--model anthropic:claude-opus-4-7 \
--thinking xhigh \
< .github/prompts/auto-cleanup-fixup.md