| name | ci-prep |
| description | Prepares the current branch for CI by running the exact same steps locally and fixing issues. If CI is already failing, fetches the GH Actions logs first to diagnose. Use before pushing, when CI is red, or when the user says "fix ci". |
| argument-hint | [--failing] [optional job name to focus on] |
CI Prep
Prepare the current state for CI. If CI is already failing, fetch and analyze the logs first.
Arguments
--failing — Indicates a GitHub Actions run is already failing. When present, you MUST execute Step 1 before doing anything else.
- Any other argument is treated as a job name to focus on (but all failures are still reported).
If --failing is NOT passed, skip directly to Step 2.
Step 1 — Fetch failed CI logs (only when --failing)
You MUST do this before any other work.
BRANCH=$(git branch --show-current)
PR_JSON=$(gh pr list --head "$BRANCH" --state open --json number,title,url --limit 1)
If the JSON array is empty, stop immediately:
No open PR found for branch $BRANCH. Create a PR first.
Otherwise fetch the logs:
PR_NUMBER=$(echo "$PR_JSON" | jq -r '.[0].number')
gh pr checks "$PR_NUMBER"
RUN_ID=$(gh run list --branch "$BRANCH" --limit 1 --json databaseId --jq '.[0].databaseId')
gh run view "$RUN_ID"
gh run view "$RUN_ID" --log-failed
Read every line of --log-failed output. For each failure note the exact file, line, and error message. If a job name argument was provided, prioritize that job but still report all failures.
Step 2 — Analyze the CI workflow
- Find the CI workflow file:
.github/workflows/ci.yml. Also check codeql.yml and any other workflow triggered on pull_request.
- Read the workflow file completely. Parse every job and every step.
- Extract the ordered list of commands the CI actually runs. In this repo
ci.yml currently runs, in order: make fmt CHECK=1 → make lint → deslop . → make test → make corpus example → make build. Verify that against the file — do not trust this list if the workflow has changed.
- Note any environment variables, matrix strategies, or conditional steps that affect execution.
ci.yml's security job and all of codeql.yml are gated on the repo being public, so they are skipped while the repo is private.
Do NOT assume the steps. Extract what the CI actually does. If you find extra public targets beyond the standard vocabulary in [MAKE-TARGETS] (e.g. make fmt-check, make coverage-check), flag them in your final report — they should be consolidated by the agent-pmo skill.
Release workflow blocker scan
If .github/workflows/release.yml exists, scan it before broad local CI. These are critical blockers
and must be fixed before release work is considered CI-ready:
- Tag-triggered jobs checking out
ref: main instead of the tagged SHA.
- Any
git commit, git push, branch mutation, or tag mutation during release.
- Version bump commits after the tag already exists.
- Ad hoc
sed version stamping of structured files instead of a first-class stamper/build input.
- Missing tests that pass a test version into the same stamper used by release.
- Publish jobs that do not
needs: the gated CodeQL job (uses: ./.github/workflows/codeql.yml with gate: true) — a release that a security finding cannot stop is a blocker.
Step 3 — Run each CI step locally, in order
Work through failures in this priority order:
- Formatting — run auto-formatters first to clear noise (
make fmt)
- Compilation errors — must compile before lint/test
- Lint violations — fix the code pattern (
make lint)
- Runtime / test failures — fix source code to satisfy the test (
make test, then make corpus example for the Dart end-to-end gate)
For each command extracted from the CI workflow:
- Run the command exactly as CI would run it (adjusting only for local environment differences like not needing
actions/checkout).
- If the step fails, stop and fix the issues before continuing to the next step.
- After fixing, re-run the same step to confirm it passes.
- Move to the next step only after the current one succeeds.
Hard constraints
- NEVER modify test files — fix the source code, not the tests
- NEVER add suppressions — no
#[allow(...)] in Rust, no // ignore_for_file: in Dart
- NEVER weaken a type to silence an error — no
dynamic, no as casts, no ! in Dart; no unwrap()/expect() bolted on to make Rust compile
- NEVER delete or ignore failing tests
- NEVER remove assertions
- NEVER hand-edit generated Dart (
example/lib, tests/golden/*.dart regions) to make a check pass — fix the template or the context builder and regenerate
If stuck on the same failure after 5 attempts, ask the user for help.
Step 4 — Report
- List every step that was run and its result (pass/fail/fixed).
- If any step could not be fixed, report what failed and why.
- Confirm whether the branch is ready to push.
Step 5 — Remote CI follow-up (only when --failing)
Once all CI steps pass locally:
- Report the local fixes and exact commands that now pass.
- Do not commit or push. The user owns source-control writes.
- If the user pushes, monitor the new run until completion or failure.
- Upon failure, go back to Step 1.
Rules
- Always read the CI workflow first. Never assume what commands CI runs.
- Do not commit or push from this skill.
- Fix issues found in each step before moving to the next
- Never skip steps or suppress errors
- If the CI workflow has multiple jobs, run all of them (respecting dependency order)
- Skip steps that are CI-infrastructure-only (checkout,
dtolnay/rust-toolchain, dart-lang/setup-dart, cache steps, artifact uploads) — focus on the actual build/test/lint commands
Success criteria
- Every command that CI runs has been executed locally and passed
- All fixes are applied to the working tree
- The CI passes successfully (if you are correcting an existing failure)