Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions docs/README.skills.md
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,7 @@ See [CONTRIBUTING.md](../CONTRIBUTING.md#adding-skills) for guidelines on how to
| [desk-open](../skills/desk-open/SKILL.md)<br />`gh skills install github/awesome-copilot desk-open` | Create and open a new desk in the workshop. Sets up the folder structure, initial journal, and desk identity so the next session that sits down finds the trail. | None |
| [devops-rollout-plan](../skills/devops-rollout-plan/SKILL.md)<br />`gh skills install github/awesome-copilot devops-rollout-plan` | Generate comprehensive rollout plans with preflight checks, step-by-step deployment, verification signals, rollback procedures, and communication plans for infrastructure and application changes | None |
| [diagnose](../skills/diagnose/SKILL.md)<br />`gh skills install github/awesome-copilot diagnose` | Perform a systematic diagnostic scan of an AI workflow across 5 quality dimensions — prompt quality, context efficiency, tool health, architecture fitness, and safety — producing a scored report with prioritized remediation actions. | None |
| [diagnose-ci-gate](../skills/diagnose-ci-gate/SKILL.md)<br />`gh skills install github/awesome-copilot diagnose-ci-gate` | Determine whether a failing CI check was caused by the current change, then recommend exactly one action. Use when a required check fails on a pull request, when asked "is this failure mine?", when a job passes locally but fails in CI, or before retrying a red build. Covers fetching the real log, reading the first error instead of the tail, classifying bug / flaky / environment / pipeline, comparing against the base branch and recent runs, reproducing with CI versions, and fixing a flaky test rather than re-running it forever. | `references/validation.md` |
| [doc-and-modernize](../skills/doc-and-modernize/SKILL.md)<br />`gh skills install github/awesome-copilot doc-and-modernize` | Two related workflows for a locally-cloned codebase, in one skill. Documentation mode produces a single, comprehensive, verifiable architecture document primarily by reading files on disk (local-first) — use it whenever the user wants to understand, map, document, research, or onboard onto a codebase ("research this repo", "write up the architecture", "do an architecture deep dive", "document how this codebase works", "map the system design", "create an onboarding doc"). Modernization mode generates a phased plan to modernize, migrate, upgrade, or rewrite a legacy system ("modernize this", "plan the migration", "how would we rewrite this", "how do we get off this legacy stack"); if no architecture document exists yet it first runs Documentation mode, then continues straight through to the plan. It assumes the legacy stack may be dead, runs a time-boxed feasibility spike, and picks the highest achievable rung on a safety ladder instead of demanding a fully-green legacy CI gate up front. | `references/copilot-instructions.template.md`<br />`references/migration-hazards.md` |
| [docs-sync-audit](../skills/docs-sync-audit/SKILL.md)<br />`gh skills install github/awesome-copilot docs-sync-audit` | Run a read-only documentation drift audit for a feature, PR, branch, release, API, configuration change, workflow, CLI, package, or repository area. Use when the user asks whether docs are stale, missing, inconsistent with code, or need updates after code changes. Checks README files, setup guides, API docs, env docs, changelogs, examples, comments, generated docs, and user-facing instructions. This is not a general code review; it compares what the docs claim against what the code does. | `scripts/docs_drift.py` |
| [documentation-writer](../skills/documentation-writer/SKILL.md)<br />`gh skills install github/awesome-copilot documentation-writer` | Diátaxis Documentation Expert. An expert technical writer specializing in creating high-quality software documentation, guided by the principles and structure of the Diátaxis technical documentation authoring framework. | None |
Expand Down
196 changes: 196 additions & 0 deletions skills/diagnose-ci-gate/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,196 @@
---
name: 'diagnose-ci-gate'
description: 'Determine whether a failing CI check was caused by the current change, then recommend exactly one action. Use when a required check fails on a pull request, when asked "is this failure mine?", when a job passes locally but fails in CI, or before retrying a red build. Covers fetching the real log, reading the first error instead of the tail, classifying bug / flaky / environment / pipeline, comparing against the base branch and recent runs, reproducing with CI versions, and fixing a flaky test rather than re-running it forever.'
---

# Diagnose CI Gate

A red check is a claim, not a diagnosis. Before you change code or press
re-run, establish three things from evidence: what actually failed, which class
of failure it is, and whether this change caused it.

This skill is for a failing required check on a pull request or a branch. For
cutting CI cost in general, use the `github-actions-efficiency` skill. For a
domain-specific flaky suite, use the skill for that tool (for example
`cypress-flake-fixer`) after this triage.

## When to Use This Skill

- A required check fails on a pull request and you need to know if it is yours
- A job passes locally but fails in CI, or fails on only some runs
- Someone says "that failure is unrelated, just re-run it"
- A build has been retried several times and keeps failing
- You are about to edit a workflow file to make a check pass

## Prerequisites

- `gh` CLI authenticated, or the raw logs pasted by the user
- Read access to the base branch and its recent runs
- The commands in the failing step, so they can be reproduced

If logs are truncated, partial, or only a summary, stop and ask for the full
log. Do not diagnose from the last few lines of a summarized check.

## Workflow

### 1. Get the failing job, not the check summary

```bash
gh pr checks <pr-number> # which check, which state
gh run list --branch <branch> --limit 10 # current and recent runs
gh run view <run-id> --log-failed # only the failing steps
gh run view <run-id> --job <job-id> --log # one job, full log
```

Record the commit SHA under test, the runner image, and the time. A failure on
an older SHA is a different problem from a failure on the current head.

### 2. Read from the first error

Read the top of the failing step, not the bottom. The first error is usually
the cause; everything after it is fallout from that cause or from the runner
giving up.

Quote the exact lines, and name the command that produced them. If the log
shows only a summary line (`Process completed with exit code 1`), find the step
that emitted it and read that step's output.

### 3. Classify the failure

| Class | Signal | Confirm by |
| --- | --- | --- |
| **Bug** | Same failure every run, deterministic input | Re-running fails identically at the same assertion |
| **Flaky** | Passes sometimes, timing/ordering/network/shared state | At least one green run of the same job on the same SHA, or a local loop that fails intermittently |
| **Environment** | Tool version, missing secret, runner image, cache, disk or memory | Version in CI differs from local, or the step fails before any project code runs |
| **Pipeline** | The workflow itself is wrong: bad path filter, wrong working directory, missing dependency install, YAML error, or a check that asserts a target the pull request cannot produce (such as a production URL for a page that is not merged yet) | The command succeeds against the pull request's own build, and the workflow line or its target is demonstrably wrong |

Write the class and the evidence for it in one sentence each. A failure that
cannot be classified is not ready for a fix.

### 4. Decide whether this change caused it

Compare with the base branch before claiming anything about ownership:

```bash
gh run list --branch main --limit 10
git merge-base HEAD origin/main
```

If the same job fails on the base branch, or on recent runs of the base branch,
it is pre-existing. Say so and link the run.

Some jobs only run on pull requests, so no base-branch run exists. In that case,
say that instead of implying you compared, and use the diff to establish what
the change added.

To test the base directly without disturbing the worktree, create a unique
throwaway worktree and remove it when done:

```bash
base_dir="$(mktemp -d)"
git worktree add "$base_dir" "$(git merge-base HEAD origin/main)"
( cd "$base_dir" && <failing command> )
git worktree remove --force "$base_dir"
```

`mktemp -d` returns a fresh path, so concurrent runs cannot collide. `--force` is
safe here because the directory was created for this check and the failing
command may have written build output into it. Never point this at a path that
holds work, and remove the worktree with `git worktree remove` instead of
deleting the directory by hand. If a directory was deleted by hand, run
`git worktree prune`.

This example is POSIX shell. On Windows, run it from Git Bash, or use
PowerShell:

```powershell
$baseDir = Join-Path $env:TEMP ("ci-base-" + [guid]::NewGuid())
git worktree add $baseDir (git merge-base HEAD origin/main)
Push-Location $baseDir; <failing command>; Pop-Location
git worktree remove --force $baseDir
```

If it passes on the base and fails on the head, name the commit and the file and
line that introduced it. If the change is a dependency bump, check the lockfile
diff and the tool version, not only the source diff.

### 5. Reproduce with CI's versions

Run the failing command with the versions CI used, from the same working
directory, with the same environment variables and the same install step. Read
the versions from the log, not from your local machine.

If you cannot reproduce it, say so and name every difference you found: OS,
runtime version, dependency resolution, environment variable, timezone,
parallelism, cached state. "Cannot reproduce" is a finding, not a failure.

### 6. Choose exactly one action

- **Retry** - only when you already have evidence the failure is flaky. Name
the green run of the same job on the same SHA.
- **Fix the code** - name the file, line, and change. This is the default for a
deterministic bug.
- **Fix the pipeline** - name the workflow file and line. This is for pipeline
faults, not for hiding a real failure.

For a flaky test, do the follow-up work instead of re-running forever:

1. Run it repeatedly and record the failure rate: `for i in $(seq 1 20); do <command>; done`
2. Find the shared state, timing assumption, or ordering dependency behind it
3. Fix or quarantine it with an owner and a removal date, and say which

### 7. Verify and report

Re-run the check after the fix and show the result. For a flaky test, show the
repeated runs.

Report in this shape:

```text
Check: <name> on <SHA>
First error: <quoted line> (<step>, <command>)
Class: bug | flaky | environment | pipeline
Ownership: introduced by <commit/file:line> | pre-existing (<run link>)
Reproduced: yes (<command>) | no (<differences>)
Action: retry | fix code | fix pipeline
Result: <run link, or the repeated-run tally>
```

## Verification Checklist

- [ ] The quoted error comes from the real log, with the step and command named
- [ ] The failure is classified, with the evidence for that class
- [ ] The base branch and recent runs were checked before claiming ownership
- [ ] The failure was reproduced with CI versions, or the differences are listed
- [ ] The recommended action is one of retry, fix code, or fix pipeline, with a reason
- [ ] The check was re-run after the fix, and the result is shown

## Rules

- Never recommend re-running without evidence that the failure is flaky
- Never call a failure unrelated without comparing against the base branch
- Never skip, delete, or weaken a failing test to make a check pass
- Never add `continue-on-error`, `if: always()`, or a path filter to hide a real failure
- Never treat a passing retry as proof the root cause is gone; say what changed
- Never diagnose from a summary line when the full log is available

## Validation

[`references/validation.md`](references/validation.md) records this skill applied
to real failed checks on a public repository: the job log, the classification,
the ownership evidence, the reproduction attempt, and the recommended action.

The first scenario is a transcript from GitHub Copilot CLI, prompted only with
the failing job log, in a checkout where the failing command passes. It returned
the report format below, classified the failure as pipeline, and attributed it to
the parent commit rather than the change under test. Both findings were confirmed
afterwards, and a depth-1 checkout reproduces the failure. The scenario exists to
show the report surviving a green local run instead of collapsing into "cannot
reproduce, probably flaky".

## Limitations

- Log access depends on permissions. Without it, ask for the log instead of guessing
- Private runners and self-hosted infrastructure can fail for reasons the log does not show
- A failure that only reproduces under load or on real hardware may need production-like infrastructure
- This skill diagnoses and recommends. It does not decide whether a check is allowed to be bypassed; that is a policy decision for the repository owner
121 changes: 121 additions & 0 deletions skills/diagnose-ci-gate/references/validation.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
# Validation

Two recorded applications of this skill to real failed jobs in a public
repository. Every run ID, SHA, and command below is public, so each can be
replayed or checked.

## Origin

The seven steps, the four failure classes, the verification checklist, and the
rules are the [`ci-gate-diagnosis` prompt](https://github.com/shauryagangrade/awesome-ai-prompts/blob/main/devops-deploy/ci-gate-diagnosis-prompt.md),
published in `shauryagangrade/awesome-ai-prompts` on 2026-10-24, before this
skill existed. This skill packages that workflow for Copilot and adds the fixed
report block, the base-branch worktree recipe, the `pull_request`-only caveat,
and the validation below.

## Scenario 1: a green local run, a red CI run

This is a run inside GitHub Copilot CLI, on a checkout of the failing commit.
CLI 1.0.105, model `gpt-6-luna` (the CLI's default selection, recorded in its
own usage log), 8 model requests, 2026-11-03. The worktree was a full clone, so
the failing command passed locally before the run started.

**Check:** `Docs structure + em dashes`, run
[40202831763](https://github.com/shauryagangrade/awesome-ai-prompts/actions/runs/40202831763),
head `3ba8bf96`, push to `main`, 2026-10-25 14:33 UTC.

**Log**, trimmed to the failing step:

```text
Job: Docs structure + em dashes
Step: Build all-prompts page (deterministic + in sync)
Run: https://github.com/shauryagangrade/awesome-ai-prompts/actions/runs/40202831763
Commit: 3ba8bf965671e6db8cb05ed089fe3127de9007ad
##[group]Run python3 scripts/build-all.py --check
python3 scripts/build-all.py --check
shell: /usr/bin/bash -e {0}
##[endgroup]
FAIL stale: website/sitemap.xml
run: python3 scripts/build-all.py to regenerate, or delete removed pages
##[error]Process completed with exit code 1.
```

**Prompt:**

```text
A CI check is failing on this repository and I need to know whether my change caused it.
The failed job log is in ./ci-log.txt. Use the diagnose-ci-gate skill in .github/skills/diagnose-ci-gate/SKILL.md and follow it.
Give me the skill's report, in its format. Do not change any files: I want the diagnosis, not a fix.
```

**Reply**, verbatim:

````text
I’ll use the supplied job log first, then compare its SHA and failure against the base branch and recent CI evidence.
The run is a `main` push at the checked-out SHA, not a PR check; I’m checking the exact job log and nearby `main` runs now, including whether the generated sitemap was already stale before this commit.
```text
Check: Docs structure + em dashes on 3ba8bf965671e6db8cb05ed089fe3127de9007ad
First error: FAIL stale: website/sitemap.xml (Build all-prompts page, `python3 scripts/build-all.py --check`)
Class: pipeline — the generator reads Git history for sitemap dates, but CI’s default checkout is shallow.
Ownership: pre-existing to 3ba8: the same failure occurred on main at 1c981e9 ([run](https://github.com/shauryagangrade/awesome-ai-prompts/actions/runs/40202231365)); that commit introduced the Git-history dependency in `scripts/build-all.py:753-768`. 3ba8 changed only `.markdownlint-cli2.jsonc`.
Reproduced: no — it passes locally on macOS with Python 3.14.7 and full Git history; CI used Ubuntu 24.04, and its Python version is not in the log.
Action: fix pipeline — fetch the history the generator requires. The later revert at 64aae52 removed that dependency.
Result: the check passed on the subsequent main run ([40203292949](https://github.com/shauryagangrade/awesome-ai-prompts/actions/runs/40203292949)); no files changed.
```
````

**Checked after the fact:**

- `get_git_lastmod()` is added in `1c981e9` and removed in `64aae52`. The
commit under test, `3ba8bf96`, changes only `.markdownlint-cli2.jsonc`.
- The parent commit `1c981e9` failed the same job in run
[40202231365](https://github.com/shauryagangrade/awesome-ai-prompts/actions/runs/40202231365),
so ownership is pre-existing, as reported.
- A full clone at `3ba8bf96` passes: `OK (144 prompts, 162 files deterministic
and in sync)`. A depth-1 fetch of the same commit, which is what CI's default
checkout does, fails with `FAIL stale: website/sitemap.xml`.
- Run
[40203292949](https://github.com/shauryagangrade/awesome-ai-prompts/actions/runs/40203292949)
at `64aae52` passed.

The report is right on all five points, and the classification is the useful
part: the local check was green, so the skill had to explain the difference
instead of reporting "cannot reproduce, probably flaky". Its own note that it
could not see the CI Python version is also the right level of caution, since
the reproduction was done on macOS.

## Scenario 2: a 404 that re-running cannot fix

Run [40091680340](https://github.com/shauryagangrade/awesome-ai-prompts/actions/runs/40091680340),
job `New external links (PR only)`, head `5ea9cff6`, 2026-10-24 11:53 UTC. The
job checks URLs added by a pull request:

```text
Checking 18 URL(s) added in `git diff origin/main...5ea9cff6`
[X] https://awesome-ai-prompts.vercel.app/prompt/security-performance/secrets-scanning-response (status 404)
17 of 18 links healthy
##[error]Process completed with exit code 1.
```

- **Class:** pipeline. The page was generated correctly in the pull request, but
the URL points at the production deployment, which serves `main`; the page
reached `main` 66 minutes after the run. A pull request cannot make a
production URL exist, so no retry and no edit to the link can turn this green.
- **Ownership:** the URL is new in the pull request. This job only runs on
`pull_request`, so there is no base-branch run to compare against, and the diff
quoted in the log is the ownership evidence.
- **Reproduced:** not as a 404, because the page has since deployed. The
deterministic evidence is that the generated page exists in `5ea9cff6` but not
in `main` before `c283b32`, while the production host serves `main`.
- **Action:** fix the check's target, not the link. Keep the live check on the
scheduled run; on pull requests, resolve the project's own host against the
build output, or skip self-hosted URLs added by the diff.

This scenario is why Step 4 handles jobs that only run on `pull_request`, and why
the pipeline row includes checks that assert a target a pull request cannot
produce.
Loading