Skip to content

Commit 77076e1

Browse files
committed
chore: ci-failure-auto-fix workflow
1 parent c0ab3f9 commit 77076e1

1 file changed

Lines changed: 97 additions & 0 deletions

File tree

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
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

Comments
 (0)