Skills DirectorySkills Directory
SkillsLearnSecurityCategoriesDocsCommunityBlog
Sign InSubmit Skill
Skills Directory

Security-tested agent skills for Claude, coding agents, and AI workflows.

Directory

  • Browse Skills
  • All Skills A–Z
  • Claude Skills
  • Claude Code Skills
  • Agent Skills
  • Categories
  • Submit a Skill

Learn

  • Learn Hub
  • Install Claude Skills
  • Write SKILL.md
  • Skills vs MCP
  • Directories Compared

Security

  • Security
  • Methodology
  • Secure Claude Skills
  • Security Badges

Company

  • About
  • Community
  • Blog
  • API Docs
  • Advertise

2026 Skills Directory. All rights reserved.

Back to skills

Fix Ci Failures

ASecurity

Diagnose and fix CI failures on main or release branches. Checks GitHub Actions run status, reads failure logs, applies fixes, and verifies a re-run passes. Use when CI is red on main, a release is broken, or you want to confirm all checks are green before shipping.

8 stars
0 votes
0 copies
0 views
Added 9/20/2026
developmentpythongobashreactnodedebugginggitapidatabase

Works with

api

Security Analysis

A100/100

Scanned 9/20/2026

Install to Claude Code

$npx -y skills add tstapler/dotfiles --skill fix-ci-failures --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Fix Ci Failures?

Add the live security badge to your README — it updates automatically with every re-scan.

Security grade badge for Fix Ci Failures
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/tstapler-fix-ci-failures/badge)](https://www.skillsdirectory.com/skills/tstapler-fix-ci-failures)

More formats (shields.io, HTML) on the badges page.

Download Zip
Files
SKILL.md
---
name: fix-ci-failures
description: Diagnose and fix CI failures on main or release branches. Checks GitHub Actions run status, reads failure logs, applies fixes, and verifies a re-run passes. Use when CI is red on main, a release is broken, or you want to confirm all checks are green before shipping.
---

# fix-ci-failures

Systematically diagnose, fix, and verify all CI failures on a branch.

## Workflow

### Step 1 — Assess current state

```bash
gh run list --branch main --limit 5 --json status,conclusion,name,headSha \
  | python3 -c "
import json,sys
runs = json.load(sys.stdin)
sha = runs[0]['headSha'][:8]
print('HEAD:', sha)
for r in runs:
    if r['headSha'][:8] == sha:
        icon = '✅' if r['conclusion'] == 'success' else ('❌' if r['conclusion'] == 'failure' else '⏳')
        print(f'{icon} {r[\"conclusion\"] or r[\"status\"]:12} {r[\"name\"]}')"
```

If any jobs are still `in_progress`, wait before diagnosing. Get the run IDs of failures:

```bash
gh run list --branch main --limit 5 --json databaseId,name,conclusion,headSha \
  | python3 -c "
import json,sys
runs = json.load(sys.stdin)
sha = runs[0]['headSha'][:8]
for r in runs:
    if r['headSha'][:8] == sha and r['conclusion'] == 'failure':
        print(r['databaseId'], r['name'])"
```

### Step 2 — Read failure logs for each failed job

```bash
gh run view --log-failed <RUN_ID> 2>&1 | grep -E "Error:|error:|FAIL|fatal|##\[error\]" \
  | grep -v "Warning\|warning\|boundaries" | head -30
```

**Critical**: always read logs to the end — the REAL failure is usually the last `##[error]` line, not the first warning in the log. Debug messages that look like errors (e.g. `❯ error message:` in release-please logs) are often not the actual failure.

```bash
gh run view --log-failed <RUN_ID> 2>&1 | tail -40
```

### Step 3 — Classify each failure

| Symptom | Category | Fix |
|---|---|---|
| `GitHub Actions is not permitted to create or approve pull requests` | Repo settings | Enable in Settings → Actions → General, or add RELEASE_TOKEN PAT |
| `Permission to *.git denied to github-actions[bot]` | Workflow permissions | Add `permissions: contents: write` to the job |
| `git push` rejected (fetch first) | Race condition | Add retry loop: `for i in 1 2 3; do git pull --rebase --autostash && git push && break \|\| sleep 5; done` |
| `ESLint: Error:` in specific file | Code lint | Fix the violation in the flagged file |
| `gofmt` unformatted files | Go formatting | `gofmt -w <files>` |
| `go vet` / `lint-custom` compile error | Working tree contamination from other sessions | `git checkout -- <file>` to restore, then re-run |
| `useMemo/useState called conditionally` | React hooks rule | Move hook call above the early return |
| `Component definition is missing display name` | React displayName | Add `.displayName = "Name"` or use `Object.assign(component, { displayName: "Name" })` |
| `unexpected token` in commit body | Commit parser quirk | Usually a debug message, not the real failure — read to end of log |
| Benchmark baseline push rejected | Same race condition | Retry loop (see above) |
| `node_modules` / dependency install fails | Infrastructure | Check for lockfile conflicts; re-run often fixes it |

### Step 4 — Apply fixes

Fix each failure using the appropriate pattern. Follow these rules:

1. **Check if the failure pre-existed our commits** before fixing:
   ```bash
   git log --oneline <baseline-sha>..HEAD -- <file>
   ```
   If the file isn't in our commit range, the failure is from another session's work — still fix it.

2. **Never restore working-tree contamination as a fix** — always identify root cause.

3. **For gofmt**: run on the exact files listed, not `gofmt -w .` (avoid touching unrelated files).

4. **For React hooks**: move the hook call above ALL early returns. Hooks on empty arrays/maps are cheap no-ops.

5. **For missing displayName inside useMemo object literals**: use `// eslint-disable-next-line react/display-name` — the lint rule cannot see displayName assignments at object-literal depth, and this is the correct suppression.

6. **For permissions**: `permissions: contents: write` goes on the **job** level, not workflow level, unless all jobs need it.

### Step 5 — Commit, push, and watch

```bash
git add <changed files>
git commit -m "fix(ci): <description of what was broken and how fixed>"
git fetch origin main && git rebase origin/main && git push origin main
```

**Primary: use `gh run watch` (GitHub's native blocking wait)**

Get the new run ID immediately after push, then watch it with `run_in_background: true`
so Claude is notified when it completes — no polling required:

```bash
# Wait ~5s for the run to register, then grab the latest run ID
sleep 5
RUN_ID=$(gh run list --branch main --limit 1 --json databaseId --jq '.[0].databaseId')
echo "Watching run $RUN_ID"
gh run watch "$RUN_ID" --exit-status
```

Run this with `run_in_background: true`. Claude will be notified when it finishes.
Exit code 0 = all green; non-zero = something failed.

> **Note**: `gh run watch` requires `checks:read` permission. If you authenticated
> with a fine-grained PAT that lacks this scope, it will fail — fall back to the
> polling loop below.

**Fallback: polling loop (use only if `gh run watch` is unavailable)**

```bash
until gh run list --branch main --limit 3 --json status,conclusion,name,headSha \
  | python3 -c "
import json,sys
runs = json.load(sys.stdin)
sha = runs[0]['headSha'][:8]
mine = [r for r in runs if r['headSha'][:8] == sha]
done = [r for r in mine if r['status'] == 'completed']
print(f'{len(done)}/{len(mine)} on {sha}')
for r in done:
    icon = '✅' if r['conclusion'] == 'success' else '❌'
    print(f'  {icon} {r[\"conclusion\"]} {r[\"name\"]}')
if len(done) == len(mine): sys.exit(0)
sys.exit(1)"; do sleep 30; done
```

### Step 6 — Verify all checks pass

After the run completes, confirm every job is green:

```bash
gh run list --branch main --limit 3 --json status,conclusion,name,headSha \
  | python3 -c "
import json,sys
runs = json.load(sys.stdin)
sha = runs[0]['headSha'][:8]
failures = [r for r in runs if r['headSha'][:8] == sha and r['conclusion'] == 'failure']
if failures:
    print('STILL FAILING:')
    for r in failures: print(' ❌', r['name'])
    sys.exit(1)
else:
    print('✅ All checks green on', sha)"
```

If still failing, return to Step 2.

## Known permanent failures (acceptable on this repo)

These are infra races that self-resolve — do NOT spend time fixing them if they're the only remaining failures:

- **Benchmarks "Update baseline" push rejected** — race when multiple commits land rapidly. The retry loop fixes most cases; occasional failures are acceptable and self-resolve on the next push.
- **Release Please creating a release PR** — requires `RELEASE_TOKEN` PAT or "Allow GitHub Actions to create PRs" repo setting. Fix once per repo, not per run.
- **Publish Demo GIFs 403** — requires `permissions: contents: write` on the job. Fix the workflow file once.

## Escaping working-tree contamination

Other sessions may leave modified files in the working tree that break compilation when CI's linter runs. Before diagnosing:

```bash
git status --short | grep -v "^??"  # look for unexpected modified files
```

If you see files you didn't touch that are broken, restore them:
```bash
git checkout -- <file>
```

Then re-run CI locally (`make lint-custom`, `make lint-css-tokens`) to confirm your commits are clean before pushing.

---

## Related Skills

| Skill | When to apply |
|-------|--------------|
| `github-actions-debugging` | Diagnose failures inside specific workflow steps or composite actions |
| `lean-agent-loop` | Parallelize multiple failing job categories and iterate fix cycles until all checks pass |

Attribution

tstaplertstapler
View sourceMore from tstapler →
SSkills DirectorySkills Directory

Your tool, in front of Claude Code builders.

3 founder slots · $299/mo · GSC-verified traffic · sponsors can never buy grades.

See placements

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments (0)

No comments yet. Be the first to comment!

SSkills DirectorySkills Directory

Your tool, in front of Claude Code builders.

3 founder slots · $299/mo · GSC-verified traffic · sponsors can never buy grades.

See placements

Related Skills

Browser Extension Developer

Use this skill when developing or maintaining browser extension code in the `browser/` directory, including Chrome/Firefox/Edge compatibility, content scripts, background scripts, or i18n updates.

281612 votes

Seo Optimizer

SEO optimization with keyword analysis, readability assessment, technical validation, content quality. Use for search rankings, blog posts, content audits, or encountering keyword density, readability scores, meta tags, schema markup errors.

2132 votes

Google Official Seo Guide

Official Google SEO guide covering search optimization, best practices, Search Console, crawling, indexing, and improving website search visibility based on official Google documentation

1862 votes

Tanstack Start

Build a full-stack TanStack Start app on Cloudflare Workers from scratch — SSR, file-based routing, server functions, D1+Drizzle, better-auth, Tailwind v4+shadcn/ui. Use whenever the user mentions TanStack Start, asks to scaffold a full-stack Cloudflare app with SSR, wants an SSR dashboard, or asks for a React 19 + Cloudflare Workers app with file-based routing and server functions — even if they don't name TanStack Start specifically. No template repo — Claude generates every file fresh per ...

9881 votes

Pentest

PTES-aligned adversarial security audit for backend, frontend, and mobile applications. Produces a CVSS-scored Hacker Report with verified PoCs and phased remediation.

5491 votes
View all in development →