1+ name : Auto Fix CI Failures
2+
3+ on :
4+ workflow_run :
5+ workflows : ["CI"]
6+ types :
7+ - completed
8+
9+ permissions :
10+ contents : write
11+ pull-requests : write
12+ actions : read
13+ issues : write
14+ id-token : write # Required for OIDC token exchange
15+
16+ jobs :
17+ auto-fix :
18+ if : |
19+ github.event.workflow_run.conclusion == 'failure' &&
20+ github.event.workflow_run.pull_requests[0] &&
21+ !startsWith(github.event.workflow_run.head_branch, 'claude-auto-fix-ci-')
22+ runs-on : ubuntu-latest
23+ steps :
24+ - name : Checkout code
25+ uses : actions/checkout@v5
26+ with :
27+ ref : ${{ github.event.workflow_run.head_branch }}
28+ fetch-depth : 0
29+ token : ${{ secrets.GITHUB_TOKEN }}
30+
31+ - name : Setup git identity
32+ run : |
33+ git config --global user.email "claude[bot]@users.noreply.github.com"
34+ git config --global user.name "claude[bot]"
35+
36+ - name : Create fix branch
37+ id : branch
38+ run : |
39+ BRANCH_NAME="claude-auto-fix-ci-${{ github.event.workflow_run.head_branch }}-${{ github.run_id }}"
40+ git checkout -b "$BRANCH_NAME"
41+ echo "branch_name=$BRANCH_NAME" >> $GITHUB_OUTPUT
42+
43+ - name : Get CI failure details
44+ id : failure_details
45+ uses : actions/github-script@v7
46+ with :
47+ script : |
48+ const run = await github.rest.actions.getWorkflowRun({
49+ owner: context.repo.owner,
50+ repo: context.repo.repo,
51+ run_id: ${{ github.event.workflow_run.id }}
52+ });
53+
54+ const jobs = await github.rest.actions.listJobsForWorkflowRun({
55+ owner: context.repo.owner,
56+ repo: context.repo.repo,
57+ run_id: ${{ github.event.workflow_run.id }}
58+ });
59+
60+ const failedJobs = jobs.data.jobs.filter(job => job.conclusion === 'failure');
61+
62+ let errorLogs = [];
63+ for (const job of failedJobs) {
64+ const logs = await github.rest.actions.downloadJobLogsForWorkflowRun({
65+ owner: context.repo.owner,
66+ repo: context.repo.repo,
67+ job_id: job.id
68+ });
69+ errorLogs.push({
70+ jobName: job.name,
71+ logs: logs.data
72+ });
73+ }
74+
75+ return {
76+ runUrl: run.data.html_url,
77+ failedJobs: failedJobs.map(j => j.name),
78+ errorLogs: errorLogs
79+ };
80+
81+ - name : Fix CI failures with Claude
82+ id : claude
83+ uses : anthropics/claude-code-action@v1
84+ with :
85+ prompt : |
86+ /fix-ci
87+ Failed CI Run: ${{ fromJSON(steps.failure_details.outputs.result).runUrl }}
88+ Failed Jobs: ${{ join(fromJSON(steps.failure_details.outputs.result).failedJobs, ', ') }}
89+ PR Number: ${{ github.event.workflow_run.pull_requests[0].number }}
90+ Branch Name: ${{ steps.branch.outputs.branch_name }}
91+ Base Branch: ${{ github.event.workflow_run.head_branch }}
92+ Repository: ${{ github.repository }}
93+
94+ Error logs:
95+ ${{ toJSON(fromJSON(steps.failure_details.outputs.result).errorLogs) }}
96+ anthropic_api_key : ${{ secrets.ANTHROPIC_API_KEY }}
97+ claude_args : " --allowedTools 'Edit,MultiEdit,Write,Read,Glob,Grep,LS,Bash(git:*),Bash(bun:*),Bash(npm:*),Bash(npx:*),Bash(gh:*)'"
0 commit comments