Skip to content

Commit 4ec65ed

Browse files
committed
Add auto-fix CI workflows with slash command and inline approaches
- Add /fix-ci slash command for programmatic CI failure fixing - Create auto-fix-ci.yml workflow using slash command approach - Create auto-fix-ci-inline.yml workflow with full inline prompt - Both workflows automatically analyze CI failures and create fix branches
1 parent 9613b21 commit 4ec65ed

4 files changed

Lines changed: 426 additions & 0 deletions

File tree

.claude/commands/fix-ci.md

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
---
2+
description: Analyze and fix CI failures by examining logs and making targeted fixes
3+
allowed_tools: "Read, Write, Edit, MultiEdit, Bash, Grep, Glob, TodoWrite"
4+
---
5+
6+
# Fix CI Failures
7+
8+
You are tasked with analyzing CI failure logs and fixing the issues. Follow these steps:
9+
10+
## Context Provided
11+
12+
$ARGUMENTS
13+
14+
## Step 1: Analyze the Failure
15+
16+
Parse the provided CI failure information to understand:
17+
- Which jobs failed and why
18+
- The specific error messages and stack traces
19+
- Whether failures are test-related, build-related, or linting issues
20+
21+
## Step 2: Search and Understand the Codebase
22+
23+
Use search tools to locate the failing code:
24+
- Search for the failing test names or functions
25+
- Find the source files mentioned in error messages
26+
- Review related configuration files (package.json, tsconfig.json, etc.)
27+
28+
## Step 3: Apply Targeted Fixes
29+
30+
Make minimal, focused changes:
31+
- **For test failures**: Determine if the test or implementation needs fixing
32+
- **For type errors**: Fix type definitions or correct the code logic
33+
- **For linting issues**: Apply formatting using the project's tools
34+
- **For build errors**: Resolve dependency or configuration issues
35+
- **For missing imports**: Add the necessary imports or install packages
36+
37+
Requirements:
38+
- Only fix the actual CI failures, avoid unrelated changes
39+
- Follow existing code patterns and conventions
40+
- Ensure changes are production-ready, not temporary hacks
41+
- Preserve existing functionality while fixing issues
42+
43+
## Step 4: Create Branch and Commit Changes
44+
45+
After applying fixes:
46+
1. Create a branch named `claude-fix-ci-${timestamp}`
47+
2. Stage all modified files with `git add`
48+
3. Commit with a descriptive message explaining what was fixed
49+
4. Document which CI jobs/tests were addressed
50+
51+
## Step 5: Verify Fixes Locally
52+
53+
Run available verification commands:
54+
- Execute the failing tests locally to confirm they pass
55+
- Run the project's lint command (check package.json for scripts)
56+
- Run type checking if available
57+
- Execute any build commands to ensure compilation succeeds
58+
59+
## Important Guidelines
60+
61+
- Focus exclusively on fixing the reported CI failures
62+
- Maintain code quality and follow the project's established patterns
63+
- If a fix requires significant refactoring, document why it's necessary
64+
- When multiple solutions exist, choose the simplest one that maintains code quality
65+
- Add clear comments only if the fix is non-obvious
66+
67+
Begin by analyzing the failure details provided above.
Lines changed: 175 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,175 @@
1+
name: Auto Fix CI Failures (Inline)
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+
15+
jobs:
16+
auto-fix:
17+
if: |
18+
github.event.workflow_run.conclusion == 'failure' &&
19+
github.event.workflow_run.name != 'Auto Fix CI Failures' &&
20+
github.event.workflow_run.name != 'Auto Fix CI Failures (Inline)'
21+
runs-on: ubuntu-latest
22+
steps:
23+
- name: Checkout code
24+
uses: actions/checkout@v4
25+
with:
26+
ref: ${{ github.event.workflow_run.head_branch }}
27+
fetch-depth: 0
28+
token: ${{ secrets.GITHUB_TOKEN }}
29+
30+
- name: Setup git
31+
run: |
32+
git config --global user.name "claude[bot]"
33+
git config --global user.email "198276+claude[bot]@users.noreply.github.com"
34+
35+
- name: Create fix branch
36+
id: branch
37+
run: |
38+
BRANCH_NAME="claude-auto-fix-ci-${{ github.event.workflow_run.head_branch }}-${{ github.run_id }}"
39+
git checkout -b "$BRANCH_NAME"
40+
echo "branch_name=$BRANCH_NAME" >> $GITHUB_OUTPUT
41+
42+
- name: Get CI failure details
43+
id: failure_details
44+
uses: actions/github-script@v7
45+
with:
46+
script: |
47+
const run = await github.rest.actions.getWorkflowRun({
48+
owner: context.repo.owner,
49+
repo: context.repo.repo,
50+
run_id: ${{ github.event.workflow_run.id }}
51+
});
52+
53+
const jobs = await github.rest.actions.listJobsForWorkflowRun({
54+
owner: context.repo.owner,
55+
repo: context.repo.repo,
56+
run_id: ${{ github.event.workflow_run.id }}
57+
});
58+
59+
const failedJobs = jobs.data.jobs.filter(job => job.conclusion === 'failure');
60+
61+
let errorLogs = [];
62+
for (const job of failedJobs) {
63+
const logs = await github.rest.actions.downloadJobLogsForWorkflowRun({
64+
owner: context.repo.owner,
65+
repo: context.repo.repo,
66+
job_id: job.id
67+
});
68+
errorLogs.push({
69+
jobName: job.name,
70+
logs: logs.data
71+
});
72+
}
73+
74+
return {
75+
runUrl: run.data.html_url,
76+
failedJobs: failedJobs.map(j => j.name),
77+
errorLogs: errorLogs
78+
};
79+
80+
- name: Fix CI failures with Claude
81+
uses: km-anthropic/claude-code-action@v1-dev
82+
with:
83+
prompt: |
84+
You are tasked with analyzing CI failure logs and fixing the issues. Follow these steps:
85+
86+
## Context Provided
87+
88+
Failed CI Run: ${{ fromJSON(steps.failure_details.outputs.result).runUrl }}
89+
Failed Jobs: ${{ join(fromJSON(steps.failure_details.outputs.result).failedJobs, ', ') }}
90+
91+
Error logs:
92+
${{ toJSON(fromJSON(steps.failure_details.outputs.result).errorLogs) }}
93+
94+
## Step 1: Analyze the Failure
95+
96+
Parse the provided CI failure information to understand:
97+
- Which jobs failed and why
98+
- The specific error messages and stack traces
99+
- Whether failures are test-related, build-related, or linting issues
100+
101+
## Step 2: Search and Understand the Codebase
102+
103+
Use search tools to locate the failing code:
104+
- Search for the failing test names or functions
105+
- Find the source files mentioned in error messages
106+
- Review related configuration files (package.json, tsconfig.json, etc.)
107+
108+
## Step 3: Apply Targeted Fixes
109+
110+
Make minimal, focused changes:
111+
- **For test failures**: Determine if the test or implementation needs fixing
112+
- **For type errors**: Fix type definitions or correct the code logic
113+
- **For linting issues**: Apply formatting using the project's tools
114+
- **For build errors**: Resolve dependency or configuration issues
115+
- **For missing imports**: Add the necessary imports or install packages
116+
117+
Requirements:
118+
- Only fix the actual CI failures, avoid unrelated changes
119+
- Follow existing code patterns and conventions
120+
- Ensure changes are production-ready, not temporary hacks
121+
- Preserve existing functionality while fixing issues
122+
123+
## Step 4: Create Branch and Commit Changes
124+
125+
After applying fixes:
126+
1. Stage all modified files with `git add`
127+
2. Commit with a descriptive message explaining what was fixed
128+
3. Document which CI jobs/tests were addressed
129+
130+
## Step 5: Verify Fixes Locally
131+
132+
Run available verification commands:
133+
- Execute the failing tests locally to confirm they pass
134+
- Run the project's lint command (check package.json for scripts)
135+
- Run type checking if available
136+
- Execute any build commands to ensure compilation succeeds
137+
138+
## Important Guidelines
139+
140+
- Focus exclusively on fixing the reported CI failures
141+
- Maintain code quality and follow the project's established patterns
142+
- If a fix requires significant refactoring, document why it's necessary
143+
- When multiple solutions exist, choose the simplest one that maintains code quality
144+
145+
Begin by analyzing the failure details provided above.
146+
anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }}
147+
github_token: ${{ secrets.GITHUB_TOKEN }}
148+
timeout_minutes: "30"
149+
use_sticky_comment: "true"
150+
claude_args: "--max-turns 15"
151+
152+
- name: Push fix branch
153+
if: success()
154+
run: |
155+
git push origin ${{ steps.branch.outputs.branch_name }}
156+
157+
- name: Create pull request comment
158+
if: success()
159+
uses: actions/github-script@v7
160+
with:
161+
script: |
162+
const branchName = '${{ steps.branch.outputs.branch_name }}';
163+
const baseBranch = '${{ github.event.workflow_run.head_branch }}';
164+
const prUrl = `https://github.com/${context.repo.owner}/${context.repo.repo}/compare/${baseBranch}...${branchName}?quick_pull=1`;
165+
166+
const issueNumber = ${{ github.event.workflow_run.pull_requests[0]?.number || 'null' }};
167+
168+
if (issueNumber) {
169+
await github.rest.issues.createComment({
170+
owner: context.repo.owner,
171+
repo: context.repo.repo,
172+
issue_number: issueNumber,
173+
body: `## 🤖 CI Auto-Fix Available\n\nClaude has analyzed the CI failures and prepared fixes.\n\n[**→ Create pull request to fix CI**](${prUrl})\n\n_This fix was generated automatically based on the [failed CI run](${{ fromJSON(steps.failure_details.outputs.result).runUrl }})._`
174+
});
175+
}

.github/workflows/auto-fix-ci.yml

Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
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+
15+
jobs:
16+
auto-fix:
17+
if: |
18+
github.event.workflow_run.conclusion == 'failure' &&
19+
github.event.workflow_run.name != 'Auto Fix CI Failures'
20+
runs-on: ubuntu-latest
21+
steps:
22+
- name: Checkout code
23+
uses: actions/checkout@v4
24+
with:
25+
ref: ${{ github.event.workflow_run.head_branch }}
26+
fetch-depth: 0
27+
token: ${{ secrets.GITHUB_TOKEN }}
28+
29+
- name: Setup git
30+
run: |
31+
git config --global user.name "claude[bot]"
32+
git config --global user.email "198276+claude[bot]@users.noreply.github.com"
33+
34+
- name: Create fix branch
35+
id: branch
36+
run: |
37+
BRANCH_NAME="claude-auto-fix-ci-${{ github.event.workflow_run.head_branch }}-${{ github.run_id }}"
38+
git checkout -b "$BRANCH_NAME"
39+
echo "branch_name=$BRANCH_NAME" >> $GITHUB_OUTPUT
40+
41+
- name: Get CI failure details
42+
id: failure_details
43+
uses: actions/github-script@v7
44+
with:
45+
script: |
46+
const run = await github.rest.actions.getWorkflowRun({
47+
owner: context.repo.owner,
48+
repo: context.repo.repo,
49+
run_id: ${{ github.event.workflow_run.id }}
50+
});
51+
52+
const jobs = await github.rest.actions.listJobsForWorkflowRun({
53+
owner: context.repo.owner,
54+
repo: context.repo.repo,
55+
run_id: ${{ github.event.workflow_run.id }}
56+
});
57+
58+
const failedJobs = jobs.data.jobs.filter(job => job.conclusion === 'failure');
59+
60+
let errorLogs = [];
61+
for (const job of failedJobs) {
62+
const logs = await github.rest.actions.downloadJobLogsForWorkflowRun({
63+
owner: context.repo.owner,
64+
repo: context.repo.repo,
65+
job_id: job.id
66+
});
67+
errorLogs.push({
68+
jobName: job.name,
69+
logs: logs.data
70+
});
71+
}
72+
73+
return {
74+
runUrl: run.data.html_url,
75+
failedJobs: failedJobs.map(j => j.name),
76+
errorLogs: errorLogs
77+
};
78+
79+
- name: Fix CI failures with Claude
80+
uses: km-anthropic/claude-code-action@v1-dev
81+
with:
82+
prompt: |
83+
/fix-ci Failed CI Run: ${{ fromJSON(steps.failure_details.outputs.result).runUrl }}
84+
Failed Jobs: ${{ join(fromJSON(steps.failure_details.outputs.result).failedJobs, ', ') }}
85+
86+
Error logs:
87+
${{ toJSON(fromJSON(steps.failure_details.outputs.result).errorLogs) }}
88+
anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }}
89+
github_token: ${{ secrets.GITHUB_TOKEN }}
90+
timeout_minutes: "30"
91+
use_sticky_comment: "true"
92+
claude_args: "--max-turns 15"
93+
94+
- name: Push fix branch
95+
if: success()
96+
run: |
97+
git push origin ${{ steps.branch.outputs.branch_name }}
98+
99+
- name: Create pull request comment
100+
if: success()
101+
uses: actions/github-script@v7
102+
with:
103+
script: |
104+
const branchName = '${{ steps.branch.outputs.branch_name }}';
105+
const baseBranch = '${{ github.event.workflow_run.head_branch }}';
106+
const prUrl = `https://github.com/${context.repo.owner}/${context.repo.repo}/compare/${baseBranch}...${branchName}?quick_pull=1`;
107+
108+
const issueNumber = ${{ github.event.workflow_run.pull_requests[0]?.number || 'null' }};
109+
110+
if (issueNumber) {
111+
await github.rest.issues.createComment({
112+
owner: context.repo.owner,
113+
repo: context.repo.repo,
114+
issue_number: issueNumber,
115+
body: `## 🤖 CI Auto-Fix Available\n\nClaude has analyzed the CI failures and prepared fixes.\n\n[**→ Create pull request to fix CI**](${prUrl})\n\n_This fix was generated automatically based on the [failed CI run](${{ fromJSON(steps.failure_details.outputs.result).runUrl }})._`
116+
});
117+
}

0 commit comments

Comments
 (0)