GitHub CI Fix Analyzer
Diagnose failing GitHub PR checks by inspecting Actions runs, extracting log snippets, and recommending targeted fixes.
Overview
This skill analyzes failing CI checks on GitHub pull requests to identify root causes and guide fixes. It uses the gh CLI to inspect check statuses, fetch workflow run logs, and extract actionable failure snippets. The pipeline handles gh field drift across CLI versions, falls back to job-level log fetching when run logs are unavailable, and scopes external CI providers out of the analysis.
What it analyzes:
- PR check statuses (pass, fail, pending, cancelled, timed out)
- GitHub Actions workflow run logs and job-level logs
- Failure markers (error, traceback, assertion, panic, timeout, segfault)
- Run metadata (workflow name, conclusion, branch, SHA, event trigger)
What it reports:
- Failing check names with run URLs and log snippets
- Root cause classification (build, test, lint, timeout, infrastructure, permission)
- Fix recommendations prioritized by severity
- External check URLs (Buildkite, CircleCI) without deep inspection
Analysis Checklist
Prerequisites
Check Inspection
Log Retrieval
Diagnosis
Metrics
Failure Classification
| Category |
Log Markers |
Common Causes |
| Build error |
error, fatal, cannot find module |
Missing dependency, syntax error, type error |
| Test failure |
FAIL, AssertionError, expected ... got |
Regression, flaky test, missing fixture |
| Lint violation |
warning, rule codes (E501, W503) |
Style drift, new linter rule |
| Timeout |
timeout, timed_out, cancelled |
Slow test, infinite loop, resource starvation |
| Infrastructure |
rate limit, connection refused, 503 |
Runner capacity, network issue, outage |
| Permission |
403, permission denied, EACCES |
Missing secret, token scope, file perms |
Severity Levels
| Level |
Criteria |
Action |
| Critical |
All checks failing, merge blocked |
Fix immediately |
| High |
Required check failing |
Fix before merge |
| Medium |
Optional check failing |
Fix if straightforward |
| Low |
Warning-only, non-blocking |
Address in follow-up |
Workflow
Step 1: Verify gh Authentication
gh auth status
# If unauthenticated: gh auth login (ensure repo + workflow scopes)
Step 2: Resolve the Pull Request
# Current branch PR
gh pr view --json number,url
# Explicit PR
gh pr view 123 --json number,url
Step 3: Run the Inspection Script
python3 "<skill-directory>/scripts/inspect_pr_checks.py" \
--repo "." --pr "<number-or-url>"
Flags: --json (machine output), --max-lines 200 (snippet window, default 160), --context 40 (context lines, default 30).
Manual fallback if the script is unavailable:
gh pr checks <pr> --json name,state,conclusion,detailsUrl,startedAt,completedAt
gh run view <run_id> --json conclusion,status,workflowName,name,event,headBranch,headSha,url
gh run view <run_id> --log
Step 4: Scope External Checks
If detailsUrl lacks /actions/runs/, classify the check as external. Report name and URL only. Do not fetch logs from Buildkite, CircleCI, or other providers.
Step 5: Summarize Failures
For each failing check report: check name, workflow, run URL, failure category, log snippet, and missing-log note if applicable.
Step 6: Draft Fix Plan
- Identify root cause file and line from log
- Cross-reference with PR diff to confirm if newly introduced
- Draft concrete fix steps per failing check
- Wait for explicit user approval before implementing
Step 7: Implement After Approval
- Apply the fix (edit files, update config, add dependencies)
- Summarize changes made
- Suggest running relevant local tests before pushing
- Offer to open or update the PR
Step 8: Recheck Status
python3 "<skill-directory>/scripts/inspect_pr_checks.py" --repo "." --pr "<number>"
# Or: gh pr checks <pr>
Report Format
GitHub CI Analysis Report
=========================
PR: #123 (feature/add-auth)
Repository: org/repo
Checks: 8 total, 2 failing, 6 passing
Failing:
1. [CRITICAL] test-suite (failure)
Workflow: CI / test-suite
Run: https://github.com/org/repo/actions/runs/12345
Category: Test failure
Snippet: AssertionError: expected 200 got 401 at test_auth.py:45
2. [MEDIUM] lint (failure)
Workflow: CI / lint
Run: https://github.com/org/repo/actions/runs/12346
Category: Lint violation
Snippet: E501 line too long (120 > 88) at src/auth/handler.py:23
External (not analyzed):
- Buildkite / deploy-preview: https://buildkite.com/org/pipeline/build/456
Examples
Example 1: Failing test suite
User: CI is red on my PR, can you investigate?
Assistant: I will check your PR checks now.
Assistant: I will check your PR checks now.
1. Running gh auth status... authenticated
2. Running inspect_pr_checks.py --repo . --pr 789
3. Found 1 failing check:
[HIGH] test-suite (failure)
Workflow: CI / test-suite
Run: https://github.com/org/repo/actions/runs/99001
Category: Test failure
Snippet:
tests/test_login.py:32
AssertionError: expected status 200 but got 403
Fixture missing read:user OAuth scope
Root cause: The PR adds a new OAuth scope requirement but the test
fixture in tests/conftest.py still uses the old scope set.
Fix plan:
1. Update tests/conftest.py mock_oauth_scopes to include read:user
2. Re-run pytest tests/test_login.py locally to confirm
Shall I apply this fix?
Example 2: External CI provider
User: Why is the Buildkite check failing on PR #456?
Assistant: Checking PR #456 checks...
The Buildkite check is an external provider (not GitHub Actions).
I can only report its details URL:
- deploy-preview: https://buildkite.com/org/pipeline/build/789
Open the Buildkite link directly to inspect the build logs.
GitHub Actions checks on this PR are all passing.
Interpretation Guide
gh CLI Field Drift
The gh CLI may change available --json fields between versions. The bundled script handles this automatically by parsing the "Available fields:" error message and retrying with a compatible field set. The fallback fields are: name, state, bucket, link, startedAt, completedAt, workflow.
Log Retrieval Hierarchy
gh run view <id> --log -- preferred, returns the full run log
gh api /repos/{owner}/{repo}/actions/jobs/{id}/logs -- fallback for in-progress or partial runs
- Run metadata only -- when both log sources fail, report metadata without snippet
Failure Marker Scanning
The script scans log lines in reverse order for these markers: error, fail, failed, traceback, exception, assert, panic, fatal, timeout, segmentation fault. It returns a context window (default 30 lines) around the last match, capped at --max-lines (default 160).
Notes
- Always wait for user approval before implementing fixes.
- Do not attempt to parse logs from external CI providers.
- If
gh auth fails, guide the user through gh auth login with correct scopes.
- The bundled script exits non-zero when failures remain (usable in automation).
- Merge commits and bot-triggered checks may produce different failure patterns.
- For very large logs, increase
--max-lines and --context to capture more context.
1---2name: gh-fix-ci3description: Analyze failing GitHub PR checks by inspecting GitHub Actions runs via the gh CLI, fetching workflow logs, extracting failure snippets, and producing a structured diagnosis with fix recommendations. Trigger when the user asks to debug CI failures, inspect red checks on a pull request, or troubleshoot GitHub Actions errors. Treats external CI providers (Buildkite, CircleCI) as out of scope and reports only their details URL.4---5
6# GitHub CI Fix Analyzer
7
8Diagnose failing GitHub PR checks by inspecting Actions runs, extracting log snippets, and recommending targeted fixes.
9
10## Overview
11
12This skill analyzes failing CI checks on GitHub pull requests to identify root causes and guide fixes. It uses the `gh` CLI to inspect check statuses, fetch workflow run logs, and extract actionable failure snippets. The pipeline handles `gh` field drift across CLI versions, falls back to job-level log fetching when run logs are unavailable, and scopes external CI providers out of the analysis.
13
14**What it analyzes:**
15- PR check statuses (pass, fail, pending, cancelled, timed out)
16- GitHub Actions workflow run logs and job-level logs
17- Failure markers (error, traceback, assertion, panic, timeout, segfault)
18- Run metadata (workflow name, conclusion, branch, SHA, event trigger)
19
20**What it reports:**
21- Failing check names with run URLs and log snippets
22- Root cause classification (build, test, lint, timeout, infrastructure, permission)
23- Fix recommendations prioritized by severity
24- External check URLs (Buildkite, CircleCI) without deep inspection
25
26## Analysis Checklist
27
28### Prerequisites
29
30- [ ] `gh` CLI is installed and on PATH
31- [ ] `gh auth status` succeeds with `repo` and `workflow` scopes
32- [ ] Working directory is inside a git repository
33- [ ] PR exists (explicit number/URL or current branch has an open PR)
34
35### Check Inspection
36
37- [ ] Fetch all PR checks via `gh pr checks <pr> --json`
38- [ ] Handle field drift: retry with available fields if primary set is rejected
39- [ ] Filter to failure/error/cancelled/timed_out conclusions
40- [ ] Classify each check as GitHub Actions or external provider
41- [ ] For external checks, record details URL only
42
43### Log Retrieval
44
45- [ ] Fetch run metadata via `gh run view <run_id> --json`
46- [ ] Fetch run logs via `gh run view <run_id> --log`
47- [ ] Fall back to job log via `gh api /repos/{owner}/{repo}/actions/jobs/{job_id}/logs`
48- [ ] Handle zip payloads from job log API (report as unavailable)
49- [ ] Extract failure snippet: scan for last failure marker, take context window
50
51### Diagnosis
52
53- [ ] Summarize each failing check with name, URL, and log snippet
54- [ ] Classify failure type (build, test, lint, timeout, infrastructure, permission)
55- [ ] Identify the specific file and line when available
56- [ ] Cross-reference failure with recent PR diff
57- [ ] Present fix plan and wait for explicit user approval
58
59## Metrics
60
61### Failure Classification
62
63| Category | Log Markers | Common Causes |
64|----------|-------------|---------------|
65| Build error | `error`, `fatal`, `cannot find module` | Missing dependency, syntax error, type error |
66| Test failure | `FAIL`, `AssertionError`, `expected ... got` | Regression, flaky test, missing fixture |
67| Lint violation | `warning`, rule codes (E501, W503) | Style drift, new linter rule |
68| Timeout | `timeout`, `timed_out`, `cancelled` | Slow test, infinite loop, resource starvation |
69| Infrastructure | `rate limit`, `connection refused`, `503` | Runner capacity, network issue, outage |
70| Permission | `403`, `permission denied`, `EACCES` | Missing secret, token scope, file perms |
71
72### Severity Levels
73
74| Level | Criteria | Action |
75|-------|----------|--------|
76| Critical | All checks failing, merge blocked | Fix immediately |
77| High | Required check failing | Fix before merge |
78| Medium | Optional check failing | Fix if straightforward |
79| Low | Warning-only, non-blocking | Address in follow-up |
80
81## Workflow
82
83### Step 1: Verify gh Authentication
84
85```bash
86gh auth status
87# If unauthenticated: gh auth login (ensure repo + workflow scopes)
88```
89
90### Step 2: Resolve the Pull Request
91
92```bash
93# Current branch PR
94gh pr view --json number,url
95# Explicit PR
96gh pr view 123 --json number,url
97```
98
99### Step 3: Run the Inspection Script
100
101```bash
102python3 "<skill-directory>/scripts/inspect_pr_checks.py" \
103 --repo "." --pr "<number-or-url>"
104```
105
106Flags: `--json` (machine output), `--max-lines 200` (snippet window, default 160), `--context 40` (context lines, default 30).
107
108Manual fallback if the script is unavailable:
109
110```bash
111gh pr checks <pr> --json name,state,conclusion,detailsUrl,startedAt,completedAt
112gh run view <run_id> --json conclusion,status,workflowName,name,event,headBranch,headSha,url
113gh run view <run_id> --log
114```
115
116### Step 4: Scope External Checks
117
118If `detailsUrl` lacks `/actions/runs/`, classify the check as external. Report name and URL only. Do not fetch logs from Buildkite, CircleCI, or other providers.
119
120### Step 5: Summarize Failures
121
122For each failing check report: check name, workflow, run URL, failure category, log snippet, and missing-log note if applicable.
123
124### Step 6: Draft Fix Plan
125
126- Identify root cause file and line from log
127- Cross-reference with PR diff to confirm if newly introduced
128- Draft concrete fix steps per failing check
129- Wait for explicit user approval before implementing
130
131### Step 7: Implement After Approval
132
1331. Apply the fix (edit files, update config, add dependencies)
1342. Summarize changes made
1353. Suggest running relevant local tests before pushing
1364. Offer to open or update the PR
137
138### Step 8: Recheck Status
139
140```bash
141python3 "<skill-directory>/scripts/inspect_pr_checks.py" --repo "." --pr "<number>"
142# Or: gh pr checks <pr>
143```
144
145## Report Format
146
147```
148GitHub CI Analysis Report
149=========================
150PR: #123 (feature/add-auth)
151Repository: org/repo
152
153Checks: 8 total, 2 failing, 6 passing
154
155Failing:
1561. [CRITICAL] test-suite (failure)
157 Workflow: CI / test-suite
158 Run: https://github.com/org/repo/actions/runs/12345
159 Category: Test failure
160 Snippet: AssertionError: expected 200 got 401 at test_auth.py:45
161
1622. [MEDIUM] lint (failure)
163 Workflow: CI / lint
164 Run: https://github.com/org/repo/actions/runs/12346
165 Category: Lint violation
166 Snippet: E501 line too long (120 > 88) at src/auth/handler.py:23
167
168External (not analyzed):
169- Buildkite / deploy-preview: https://buildkite.com/org/pipeline/build/456
170```
171
172## Examples
173
174### Example 1: Failing test suite
175
176```
177User: CI is red on my PR, can you investigate?
178
179Assistant: I will check your PR checks now.
180
181Assistant: I will check your PR checks now.
182
1831. Running gh auth status... authenticated
1842. Running inspect_pr_checks.py --repo . --pr 789
1853. Found 1 failing check:
186
187 [HIGH] test-suite (failure)
188 Workflow: CI / test-suite
189 Run: https://github.com/org/repo/actions/runs/99001
190 Category: Test failure
191 Snippet:
192 tests/test_login.py:32
193 AssertionError: expected status 200 but got 403
194 Fixture missing read:user OAuth scope
195
196Root cause: The PR adds a new OAuth scope requirement but the test
197fixture in tests/conftest.py still uses the old scope set.
198
199Fix plan:
2001. Update tests/conftest.py mock_oauth_scopes to include read:user
2012. Re-run pytest tests/test_login.py locally to confirm
202
203Shall I apply this fix?
204```
205
206### Example 2: External CI provider
207
208```
209User: Why is the Buildkite check failing on PR #456?
210Assistant: Checking PR #456 checks...
211
212The Buildkite check is an external provider (not GitHub Actions).
213I can only report its details URL:
214- deploy-preview: https://buildkite.com/org/pipeline/build/789
215
216Open the Buildkite link directly to inspect the build logs.
217GitHub Actions checks on this PR are all passing.
218```
219
220## Interpretation Guide
221
222### gh CLI Field Drift
223
224The `gh` CLI may change available `--json` fields between versions. The bundled script handles this automatically by parsing the "Available fields:" error message and retrying with a compatible field set. The fallback fields are: `name`, `state`, `bucket`, `link`, `startedAt`, `completedAt`, `workflow`.
225
226### Log Retrieval Hierarchy
227
2281. `gh run view <id> --log` -- preferred, returns the full run log
2292. `gh api /repos/{owner}/{repo}/actions/jobs/{id}/logs` -- fallback for in-progress or partial runs
2303. Run metadata only -- when both log sources fail, report metadata without snippet
231
232### Failure Marker Scanning
233
234The script scans log lines in reverse order for these markers: `error`, `fail`, `failed`, `traceback`, `exception`, `assert`, `panic`, `fatal`, `timeout`, `segmentation fault`. It returns a context window (default 30 lines) around the last match, capped at `--max-lines` (default 160).
235
236## Notes
237
238- Always wait for user approval before implementing fixes.
239- Do not attempt to parse logs from external CI providers.
240- If `gh auth` fails, guide the user through `gh auth login` with correct scopes.
241- The bundled script exits non-zero when failures remain (usable in automation).
242- Merge commits and bot-triggered checks may produce different failure patterns.
243- For very large logs, increase `--max-lines` and `--context` to capture more context.