From e9dc3050fb1fc00e6531050e36dfcc5c21187ff4 Mon Sep 17 00:00:00 2001 From: km-anthropic Date: Tue, 19 Aug 2025 13:44:34 -0700 Subject: [PATCH] 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 --- .claude/commands/fix-ci.md | 67 +++++++++ .github/workflows/auto-fix-ci-inline.yml | 175 +++++++++++++++++++++++ .github/workflows/auto-fix-ci.yml | 117 +++++++++++++++ slash-commands/fix-ci.md | 67 +++++++++ 4 files changed, 426 insertions(+) create mode 100644 .claude/commands/fix-ci.md create mode 100644 .github/workflows/auto-fix-ci-inline.yml create mode 100644 .github/workflows/auto-fix-ci.yml create mode 100644 slash-commands/fix-ci.md diff --git a/.claude/commands/fix-ci.md b/.claude/commands/fix-ci.md new file mode 100644 index 0000000..33efbde --- /dev/null +++ b/.claude/commands/fix-ci.md @@ -0,0 +1,67 @@ +--- +description: Analyze and fix CI failures by examining logs and making targeted fixes +allowed_tools: "Read, Write, Edit, MultiEdit, Bash, Grep, Glob, TodoWrite" +--- + +# Fix CI Failures + +You are tasked with analyzing CI failure logs and fixing the issues. Follow these steps: + +## Context Provided + +$ARGUMENTS + +## Step 1: Analyze the Failure + +Parse the provided CI failure information to understand: +- Which jobs failed and why +- The specific error messages and stack traces +- Whether failures are test-related, build-related, or linting issues + +## Step 2: Search and Understand the Codebase + +Use search tools to locate the failing code: +- Search for the failing test names or functions +- Find the source files mentioned in error messages +- Review related configuration files (package.json, tsconfig.json, etc.) + +## Step 3: Apply Targeted Fixes + +Make minimal, focused changes: +- **For test failures**: Determine if the test or implementation needs fixing +- **For type errors**: Fix type definitions or correct the code logic +- **For linting issues**: Apply formatting using the project's tools +- **For build errors**: Resolve dependency or configuration issues +- **For missing imports**: Add the necessary imports or install packages + +Requirements: +- Only fix the actual CI failures, avoid unrelated changes +- Follow existing code patterns and conventions +- Ensure changes are production-ready, not temporary hacks +- Preserve existing functionality while fixing issues + +## Step 4: Create Branch and Commit Changes + +After applying fixes: +1. Create a branch named `claude-fix-ci-${timestamp}` +2. Stage all modified files with `git add` +3. Commit with a descriptive message explaining what was fixed +4. Document which CI jobs/tests were addressed + +## Step 5: Verify Fixes Locally + +Run available verification commands: +- Execute the failing tests locally to confirm they pass +- Run the project's lint command (check package.json for scripts) +- Run type checking if available +- Execute any build commands to ensure compilation succeeds + +## Important Guidelines + +- Focus exclusively on fixing the reported CI failures +- Maintain code quality and follow the project's established patterns +- If a fix requires significant refactoring, document why it's necessary +- When multiple solutions exist, choose the simplest one that maintains code quality +- Add clear comments only if the fix is non-obvious + +Begin by analyzing the failure details provided above. \ No newline at end of file diff --git a/.github/workflows/auto-fix-ci-inline.yml b/.github/workflows/auto-fix-ci-inline.yml new file mode 100644 index 0000000..6334849 --- /dev/null +++ b/.github/workflows/auto-fix-ci-inline.yml @@ -0,0 +1,175 @@ +name: Auto Fix CI Failures (Inline) + +on: + workflow_run: + workflows: ["CI"] + types: + - completed + +permissions: + contents: write + pull-requests: write + actions: read + issues: write + +jobs: + auto-fix: + if: | + github.event.workflow_run.conclusion == 'failure' && + github.event.workflow_run.name != 'Auto Fix CI Failures' && + github.event.workflow_run.name != 'Auto Fix CI Failures (Inline)' + runs-on: ubuntu-latest + steps: + - name: Checkout code + uses: actions/checkout@v4 + with: + ref: ${{ github.event.workflow_run.head_branch }} + fetch-depth: 0 + token: ${{ secrets.GITHUB_TOKEN }} + + - name: Setup git + run: | + git config --global user.name "claude[bot]" + git config --global user.email "198276+claude[bot]@users.noreply.github.com" + + - name: Create fix branch + id: branch + run: | + BRANCH_NAME="claude-auto-fix-ci-${{ github.event.workflow_run.head_branch }}-${{ github.run_id }}" + git checkout -b "$BRANCH_NAME" + echo "branch_name=$BRANCH_NAME" >> $GITHUB_OUTPUT + + - name: Get CI failure details + id: failure_details + uses: actions/github-script@v7 + with: + script: | + const run = await github.rest.actions.getWorkflowRun({ + owner: context.repo.owner, + repo: context.repo.repo, + run_id: ${{ github.event.workflow_run.id }} + }); + + const jobs = await github.rest.actions.listJobsForWorkflowRun({ + owner: context.repo.owner, + repo: context.repo.repo, + run_id: ${{ github.event.workflow_run.id }} + }); + + const failedJobs = jobs.data.jobs.filter(job => job.conclusion === 'failure'); + + let errorLogs = []; + for (const job of failedJobs) { + const logs = await github.rest.actions.downloadJobLogsForWorkflowRun({ + owner: context.repo.owner, + repo: context.repo.repo, + job_id: job.id + }); + errorLogs.push({ + jobName: job.name, + logs: logs.data + }); + } + + return { + runUrl: run.data.html_url, + failedJobs: failedJobs.map(j => j.name), + errorLogs: errorLogs + }; + + - name: Fix CI failures with Claude + uses: km-anthropic/claude-code-action@v1-dev + with: + prompt: | + You are tasked with analyzing CI failure logs and fixing the issues. Follow these steps: + + ## Context Provided + + Failed CI Run: ${{ fromJSON(steps.failure_details.outputs.result).runUrl }} + Failed Jobs: ${{ join(fromJSON(steps.failure_details.outputs.result).failedJobs, ', ') }} + + Error logs: + ${{ toJSON(fromJSON(steps.failure_details.outputs.result).errorLogs) }} + + ## Step 1: Analyze the Failure + + Parse the provided CI failure information to understand: + - Which jobs failed and why + - The specific error messages and stack traces + - Whether failures are test-related, build-related, or linting issues + + ## Step 2: Search and Understand the Codebase + + Use search tools to locate the failing code: + - Search for the failing test names or functions + - Find the source files mentioned in error messages + - Review related configuration files (package.json, tsconfig.json, etc.) + + ## Step 3: Apply Targeted Fixes + + Make minimal, focused changes: + - **For test failures**: Determine if the test or implementation needs fixing + - **For type errors**: Fix type definitions or correct the code logic + - **For linting issues**: Apply formatting using the project's tools + - **For build errors**: Resolve dependency or configuration issues + - **For missing imports**: Add the necessary imports or install packages + + Requirements: + - Only fix the actual CI failures, avoid unrelated changes + - Follow existing code patterns and conventions + - Ensure changes are production-ready, not temporary hacks + - Preserve existing functionality while fixing issues + + ## Step 4: Create Branch and Commit Changes + + After applying fixes: + 1. Stage all modified files with `git add` + 2. Commit with a descriptive message explaining what was fixed + 3. Document which CI jobs/tests were addressed + + ## Step 5: Verify Fixes Locally + + Run available verification commands: + - Execute the failing tests locally to confirm they pass + - Run the project's lint command (check package.json for scripts) + - Run type checking if available + - Execute any build commands to ensure compilation succeeds + + ## Important Guidelines + + - Focus exclusively on fixing the reported CI failures + - Maintain code quality and follow the project's established patterns + - If a fix requires significant refactoring, document why it's necessary + - When multiple solutions exist, choose the simplest one that maintains code quality + + Begin by analyzing the failure details provided above. + anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }} + github_token: ${{ secrets.GITHUB_TOKEN }} + timeout_minutes: "30" + use_sticky_comment: "true" + claude_args: "--max-turns 15" + + - name: Push fix branch + if: success() + run: | + git push origin ${{ steps.branch.outputs.branch_name }} + + - name: Create pull request comment + if: success() + uses: actions/github-script@v7 + with: + script: | + const branchName = '${{ steps.branch.outputs.branch_name }}'; + const baseBranch = '${{ github.event.workflow_run.head_branch }}'; + const prUrl = `https://github.com/${context.repo.owner}/${context.repo.repo}/compare/${baseBranch}...${branchName}?quick_pull=1`; + + const issueNumber = ${{ github.event.workflow_run.pull_requests[0]?.number || 'null' }}; + + if (issueNumber) { + await github.rest.issues.createComment({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: issueNumber, + 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 }})._` + }); + } \ No newline at end of file diff --git a/.github/workflows/auto-fix-ci.yml b/.github/workflows/auto-fix-ci.yml new file mode 100644 index 0000000..9f5df9c --- /dev/null +++ b/.github/workflows/auto-fix-ci.yml @@ -0,0 +1,117 @@ +name: Auto Fix CI Failures + +on: + workflow_run: + workflows: ["CI"] + types: + - completed + +permissions: + contents: write + pull-requests: write + actions: read + issues: write + +jobs: + auto-fix: + if: | + github.event.workflow_run.conclusion == 'failure' && + github.event.workflow_run.name != 'Auto Fix CI Failures' + runs-on: ubuntu-latest + steps: + - name: Checkout code + uses: actions/checkout@v4 + with: + ref: ${{ github.event.workflow_run.head_branch }} + fetch-depth: 0 + token: ${{ secrets.GITHUB_TOKEN }} + + - name: Setup git + run: | + git config --global user.name "claude[bot]" + git config --global user.email "198276+claude[bot]@users.noreply.github.com" + + - name: Create fix branch + id: branch + run: | + BRANCH_NAME="claude-auto-fix-ci-${{ github.event.workflow_run.head_branch }}-${{ github.run_id }}" + git checkout -b "$BRANCH_NAME" + echo "branch_name=$BRANCH_NAME" >> $GITHUB_OUTPUT + + - name: Get CI failure details + id: failure_details + uses: actions/github-script@v7 + with: + script: | + const run = await github.rest.actions.getWorkflowRun({ + owner: context.repo.owner, + repo: context.repo.repo, + run_id: ${{ github.event.workflow_run.id }} + }); + + const jobs = await github.rest.actions.listJobsForWorkflowRun({ + owner: context.repo.owner, + repo: context.repo.repo, + run_id: ${{ github.event.workflow_run.id }} + }); + + const failedJobs = jobs.data.jobs.filter(job => job.conclusion === 'failure'); + + let errorLogs = []; + for (const job of failedJobs) { + const logs = await github.rest.actions.downloadJobLogsForWorkflowRun({ + owner: context.repo.owner, + repo: context.repo.repo, + job_id: job.id + }); + errorLogs.push({ + jobName: job.name, + logs: logs.data + }); + } + + return { + runUrl: run.data.html_url, + failedJobs: failedJobs.map(j => j.name), + errorLogs: errorLogs + }; + + - name: Fix CI failures with Claude + uses: km-anthropic/claude-code-action@v1-dev + with: + prompt: | + /fix-ci Failed CI Run: ${{ fromJSON(steps.failure_details.outputs.result).runUrl }} + Failed Jobs: ${{ join(fromJSON(steps.failure_details.outputs.result).failedJobs, ', ') }} + + Error logs: + ${{ toJSON(fromJSON(steps.failure_details.outputs.result).errorLogs) }} + anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }} + github_token: ${{ secrets.GITHUB_TOKEN }} + timeout_minutes: "30" + use_sticky_comment: "true" + claude_args: "--max-turns 15" + + - name: Push fix branch + if: success() + run: | + git push origin ${{ steps.branch.outputs.branch_name }} + + - name: Create pull request comment + if: success() + uses: actions/github-script@v7 + with: + script: | + const branchName = '${{ steps.branch.outputs.branch_name }}'; + const baseBranch = '${{ github.event.workflow_run.head_branch }}'; + const prUrl = `https://github.com/${context.repo.owner}/${context.repo.repo}/compare/${baseBranch}...${branchName}?quick_pull=1`; + + const issueNumber = ${{ github.event.workflow_run.pull_requests[0]?.number || 'null' }}; + + if (issueNumber) { + await github.rest.issues.createComment({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: issueNumber, + 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 }})._` + }); + } \ No newline at end of file diff --git a/slash-commands/fix-ci.md b/slash-commands/fix-ci.md new file mode 100644 index 0000000..33efbde --- /dev/null +++ b/slash-commands/fix-ci.md @@ -0,0 +1,67 @@ +--- +description: Analyze and fix CI failures by examining logs and making targeted fixes +allowed_tools: "Read, Write, Edit, MultiEdit, Bash, Grep, Glob, TodoWrite" +--- + +# Fix CI Failures + +You are tasked with analyzing CI failure logs and fixing the issues. Follow these steps: + +## Context Provided + +$ARGUMENTS + +## Step 1: Analyze the Failure + +Parse the provided CI failure information to understand: +- Which jobs failed and why +- The specific error messages and stack traces +- Whether failures are test-related, build-related, or linting issues + +## Step 2: Search and Understand the Codebase + +Use search tools to locate the failing code: +- Search for the failing test names or functions +- Find the source files mentioned in error messages +- Review related configuration files (package.json, tsconfig.json, etc.) + +## Step 3: Apply Targeted Fixes + +Make minimal, focused changes: +- **For test failures**: Determine if the test or implementation needs fixing +- **For type errors**: Fix type definitions or correct the code logic +- **For linting issues**: Apply formatting using the project's tools +- **For build errors**: Resolve dependency or configuration issues +- **For missing imports**: Add the necessary imports or install packages + +Requirements: +- Only fix the actual CI failures, avoid unrelated changes +- Follow existing code patterns and conventions +- Ensure changes are production-ready, not temporary hacks +- Preserve existing functionality while fixing issues + +## Step 4: Create Branch and Commit Changes + +After applying fixes: +1. Create a branch named `claude-fix-ci-${timestamp}` +2. Stage all modified files with `git add` +3. Commit with a descriptive message explaining what was fixed +4. Document which CI jobs/tests were addressed + +## Step 5: Verify Fixes Locally + +Run available verification commands: +- Execute the failing tests locally to confirm they pass +- Run the project's lint command (check package.json for scripts) +- Run type checking if available +- Execute any build commands to ensure compilation succeeds + +## Important Guidelines + +- Focus exclusively on fixing the reported CI failures +- Maintain code quality and follow the project's established patterns +- If a fix requires significant refactoring, document why it's necessary +- When multiple solutions exist, choose the simplest one that maintains code quality +- Add clear comments only if the fix is non-obvious + +Begin by analyzing the failure details provided above. \ No newline at end of file