Build an AI Pipeline Failure Analyzer with GitHub Actions and Claude API
Build an AI tool that automatically analyzes GitHub Actions failures, fetches logs, identifies root causes with Claude API, and posts a fix directly as a PR comment โ cutting MTTR for CI failures by 70%.
When a CI pipeline fails, developers spend 10-20 minutes reading logs and diagnosing the cause. This tool automates that: Claude reads the failure, identifies the root cause, and posts the fix as a comment on the PR โ all within 60 seconds of the failure.
Architecture
GitHub Actions failure
โ
Failure Analyzer workflow triggers
โ
Fetch failed job logs via GitHub API
โ
Send logs to Claude API with context
โ
Claude identifies root cause + fix
โ
Post analysis as PR comment
Step 1: The Analyzer Workflow
Create .github/workflows/analyze-failure.yml:
name: Analyze CI Failure
on:
workflow_run:
workflows: ["CI", "Build and Deploy"] # Trigger when these fail
types: [completed]
jobs:
analyze:
if: ${{ github.event.workflow_run.conclusion == 'failure' }}
runs-on: ubuntu-latest
permissions:
actions: read
pull-requests: write
steps:
- name: Analyze failure with Claude
uses: actions/github-script@v7
env:
ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
script: |
const { analyzeFailure } = require('./scripts/analyze-failure.js');
await analyzeFailure({ github, context });Step 2: The Analyzer Script
Create scripts/analyze-failure.js:
const https = require('https');
async function callClaude(prompt) {
return new Promise((resolve, reject) => {
const body = JSON.stringify({
model: 'claude-sonnet-5',
max_tokens: 2000,
messages: [{ role: 'user', content: prompt }]
});
const options = {
hostname: 'api.anthropic.com',
path: '/v1/messages',
method: 'POST',
headers: {
'Content-Type': 'application/json',
'x-api-key': process.env.ANTHROPIC_API_KEY,
'anthropic-version': '2023-06-01',
'Content-Length': Buffer.byteLength(body)
}
};
const req = https.request(options, (res) => {
let data = '';
res.on('data', chunk => data += chunk);
res.on('end', () => {
const parsed = JSON.parse(data);
resolve(parsed.content[0].text);
});
});
req.on('error', reject);
req.write(body);
req.end();
});
}
async function getFailedJobLogs(github, owner, repo, runId) {
// Get list of jobs
const jobs = await github.rest.actions.listJobsForWorkflowRun({
owner, repo, run_id: runId
});
const failedJobs = jobs.data.jobs.filter(job => job.conclusion === 'failure');
const logsPerJob = [];
for (const job of failedJobs.slice(0, 3)) { // Max 3 jobs
try {
const logs = await github.rest.actions.downloadJobLogsForWorkflowRun({
owner, repo, job_id: job.id
});
// Extract last 200 lines โ where errors usually are
const logText = typeof logs.data === 'string'
? logs.data.split('\n').slice(-200).join('\n')
: String(logs.data).slice(-8000);
logsPerJob.push({
jobName: job.name,
conclusion: job.conclusion,
logs: logText
});
} catch (e) {
logsPerJob.push({ jobName: job.name, logs: `Could not fetch logs: ${e.message}` });
}
}
return logsPerJob;
}
async function analyzeFailure({ github, context }) {
const run = context.payload.workflow_run;
const owner = context.repo.owner;
const repo = context.repo.repo;
console.log(`Analyzing failure for run ${run.id}: ${run.name}`);
// Get failed job logs
const failedJobLogs = await getFailedJobLogs(github, owner, repo, run.id);
if (failedJobLogs.length === 0) {
console.log('No failed jobs found');
return;
}
// Build prompt for Claude
const logsFormatted = failedJobLogs.map(job =>
`## Job: ${job.jobName}\n\`\`\`\n${job.logs}\n\`\`\``
).join('\n\n');
const prompt = `You are a CI/CD expert analyzing a GitHub Actions pipeline failure.
## Workflow Information
- Workflow: ${run.name}
- Branch: ${run.head_branch}
- Commit: ${run.head_sha.slice(0, 8)}
- Trigger: ${run.event}
## Failed Job Logs
${logsFormatted}
Analyze this failure and provide:
1. **Root Cause** (1-2 sentences): What exactly caused the failure
2. **Category**: test-failure | build-error | dependency-issue | config-error | flaky-test | infra-issue | permission-error
3. **Fix** (specific steps or code to resolve it)
4. **Confidence**: high | medium | low
5. **Estimated Fix Time**: e.g. "5 minutes", "30 minutes", "1-2 hours"
Format your response as a GitHub PR comment using markdown. Start with an emoji that reflects severity (๐ด critical, ๐ก flaky/infra, ๐ข easy fix).`;
const analysis = await callClaude(prompt);
// Find the PR associated with this workflow run
const prs = await github.rest.pulls.list({
owner, repo,
head: `${owner}:${run.head_branch}`,
state: 'open'
});
const comment = `## ๐ค AI Failure Analysis
**Workflow:** ${run.name} | **Job(s):** ${failedJobLogs.map(j => j.jobName).join(', ')}
${analysis}
---
*Analyzed by Claude AI ยท [View failed run](${run.html_url})*`;
if (prs.data.length > 0) {
// Post to the PR
const prNumber = prs.data[0].number;
await github.rest.issues.createComment({
owner, repo,
issue_number: prNumber,
body: comment
});
console.log(`Posted analysis to PR #${prNumber}`);
} else {
// Post to commit if no PR
await github.rest.repos.createCommitComment({
owner, repo,
commit_sha: run.head_sha,
body: comment
});
console.log(`Posted analysis to commit ${run.head_sha.slice(0, 8)}`);
}
}
module.exports = { analyzeFailure };What Claude Analyzes
Claude sees the raw log output and categorizes failures accurately:
Test failures:
๐ด Root Cause: Unit test `TestUserAuth` failed because the mock Redis client
was not returning expected data for expired sessions. Line 47 of auth_test.go
asserts `result.Valid == false` but mock returns `Valid == true`.
Fix: Update mock in `auth_test.go` line 23:
mockRedis.On("Get", expiredKey).Return("", redis.Nil)
Dependency issues:
๐ก Root Cause: npm install failed with ECONNRESET โ likely a transient
registry connectivity issue. This is probably a flaky infra failure.
Fix: Re-run the workflow. If it keeps failing, add `--legacy-peer-deps`
flag or pin npm registry to a mirror.
Config errors:
๐ด Root Cause: AWS credentials not found. The `AWS_ROLE_ARN` secret is
missing from this repository's Actions secrets.
Fix: Go to Settings โ Secrets โ Actions โ New secret:
Name: AWS_ROLE_ARN
Value: arn:aws:iam::123456789:role/github-actions
Example PR Comment Output
## ๐ค AI Failure Analysis
**Workflow:** CI | **Job(s):** test, build
๐ด **Root Cause**: The Docker build failed because the base image
`python:3.11-slim` changed and the new version removed `libpq-dev`.
Your requirements.txt includes `psycopg2==2.9.9` which requires PostgreSQL
client libraries at build time.
**Category**: dependency-issue | **Confidence**: high | **Estimated Fix Time**: 15 minutes
**Fix**:
Option 1 โ Install build dependency explicitly:
```dockerfile
RUN apt-get update && apt-get install -y libpq-dev gcc && rm -rf /var/lib/apt/lists/*Option 2 โ Use psycopg2-binary instead (no build deps required):
psycopg2-binary==2.9.9
Option 2 is recommended for containers.
## Extend It
Add Slack notification when Claude detects a critical failure:
```javascript
// In analyze-failure.js, after posting the PR comment:
if (analysis.includes('CRITICAL') || analysis.includes('๐ด')) {
await fetch(process.env.SLACK_WEBHOOK_URL, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
text: `CI failure detected on ${run.head_branch}: ${run.html_url}\n${analysis.slice(0, 300)}...`
})
});
}
Teams using this report cutting MTTR from 15-20 minutes to under 5 minutes for common failure categories.
More AI + CI/CD tools? Read our Build AI PR description generator and AI-powered GitHub Actions reviewer.
Today I Fixed
Short real fixes from production โ posted daily
Stay ahead of the curve
Get the latest DevOps, Kubernetes, AWS, and AI/ML guides delivered straight to your inbox. No spam โ just practical engineering content.
Related Articles
Build an AI Code Review Bot with GitHub Actions and Claude API (2026)
Automate code reviews on every PR using Claude AI via GitHub Actions. The bot reviews Dockerfile security, Terraform changes, and general code quality โ and posts inline comments.
Build an AI GitHub Actions Failure Analyzer with Claude API
Step-by-step tutorial to build a bot that automatically analyzes failed GitHub Actions workflows using Claude API, posts the diagnosis as a PR comment, and suggests specific fixes โ saving your team hours of debugging CI failures.
Build an AI Secret Scanner with Claude API for Git Repos
Build a Git pre-commit and CI hook using Claude API that detects hardcoded secrets, API keys, passwords, and credentials in code โ with context-aware analysis that reduces false positives from regex-only scanners.