| name | ci-monitoring |
| description | Use after creating PR - monitor CI pipeline, resolve failures cyclically until green or issue is identified as unresolvable |
CI Monitoring
Overview
Monitor CI pipeline and resolve failures until green.
CRITICAL: CI is validation, not discovery.
If CI finds a bug you didn't find locally, your local testing was insufficient.
Before blaming CI, ask yourself:
- Did you run all tests locally?
- Did you test against local services (postgres, redis)?
- Did you run the same checks CI runs?
- Did you run integration tests, not just unit tests with mocks?
CI should only fail for: environment differences, flaky tests, or infrastructure issues—never for bugs you could have caught locally.
Core principle: CI failures are blockers. But they should never be surprises.
Announce at start: "I'm monitoring CI and will resolve any failures."
The CI Loop
PR Created
│
▼
┌─────────────┐
│ Wait for CI │
└──────┬──────┘
│
▼
┌─────────────┐
│ CI Status? │
└──────┬──────┘
│
┌───┴───┐
│ │
Green Red/Failed
│ │
▼ ▼
┌─────────┐ ┌─────────────┐
│ MERGE │ │ Diagnose │
│ THE PR │ │ failure │
└────┬────┘ └──────┬──────┘
│ │
▼ ▼
┌─────────┐ ┌─────────────┐
│ Continue│ │ Fixable? │
│ to next │ └──────┬──────┘
│ issue │ │
└─────────┘ ┌────┴────┐
│ │
Yes No
│ │
▼ ▼
┌─────────┐ ┌─────────────┐
│ Fix and │ │ Document as │
│ push │ │ unresolvable│
└────┬────┘ └─────────────┘
│
└────► Back to "Wait for CI"
CRITICAL: Green CI = Merge Immediately
When CI passes, you MUST merge the PR and continue working.
Do NOT:
- Stop and report "CI is green, ready for review"
- Wait for user confirmation
- Summarize and ask what to do next
DO:
- Merge the PR immediately:
gh pr merge [PR_NUMBER] --squash --delete-branch
- Mark the linked issue as Done
- Continue to the next issue in scope
gh pr merge [PR_NUMBER] --squash --delete-branch
gh issue edit [ISSUE_NUMBER] --remove-label "status:in-review" --add-label "status:done"
The only exception: PRs with do-not-merge label require explicit user action.
Checking CI Status
Using GitHub CLI
gh pr checks [PR_NUMBER]
gh pr checks [PR_NUMBER] --watch
gh pr view [PR_NUMBER] --json statusCheckRollup
Expected Output
All checks were successful
0 failing, 0 pending, 5 passing
CHECKS
✓ build 1m23s
✓ lint 45s
✓ test 3m12s
✓ typecheck 1m05s
✓ security-scan 2m30s
Handling Failures
Step 1: Identify the Failure
gh pr checks [PR_NUMBER]
gh run view [RUN_ID] --log-failed
Step 2: Diagnose the Cause
Common failure types:
| Type | Symptoms | Cause |
|---|
| Test failure | FAIL in test output | Code bug or test bug |
| Build failure | Compilation errors | Type errors, syntax errors |
| Lint failure | Style violations | Formatting, conventions |
| Typecheck failure | Type errors | Missing types, wrong types |
| Timeout | Job exceeded time limit | Performance issue or stuck test |
| Flaky test | Passes locally, fails CI | Race condition, environment difference |
Step 3: Fix the Issue
Test Failures
pnpm test
pnpm test --grep "test name"
Build Failures
pnpm build
Lint Failures
pnpm lint
pnpm lint:fix
Type Failures
pnpm typecheck
Step 4: Push Fix and Wait
git add .
git commit -m "fix(ci): Resolve test failure in user validation"
git push
gh pr checks [PR_NUMBER] --watch
Step 5: Repeat Until Green
Loop through diagnose → fix → push → wait until all checks pass.
Flaky Tests
Identifying Flakiness
Test passes locally
Test fails in CI
Test passes on retry in CI
Handling Flakiness
- Don't just retry - Find the root cause
- Check for race conditions - Timing-dependent code
- Check for environment differences - Paths, env vars, services
- Check for state pollution - Tests affecting each other
await saveData();
await delay(100);
const result = await loadData();
await saveData();
await waitFor(() => dataExists());
const result = await loadData();
Unresolvable Failures
Sometimes failures can't be fixed in the current PR:
Legitimate Unresolvable Cases
| Case | Example |
|---|
| CI infrastructure issue | Service down, rate limited |
| Pre-existing flaky test | Not introduced by this PR |
| Upstream dependency issue | External API changed |
| Requires manual intervention | Needs secrets, permissions |
Process for Unresolvable
- Document the issue
gh pr comment [PR_NUMBER] --body "## CI Issue
The \`security-scan\` check is failing due to a known issue with the scanner service (see #999).
This is not related to changes in this PR. The scan passes when run locally.
Requesting bypass approval from @maintainer."
- Create issue if new
gh issue create \
--title "CI: Security scanner service timeout" \
--body "The security scanner is timing out in CI..."
- Request bypass if appropriate
Some teams allow merging with known infrastructure failures.
- Do NOT merge with real failures
If the failure is from your code, it must be fixed.
CI Best Practices
Run Locally First (MANDATORY)
CI is the last resort, not the first check.
Before pushing, run EVERYTHING CI will run:
pnpm lint
pnpm typecheck
pnpm test
pnpm test:integration
pnpm build
docker-compose up -d postgres
pnpm migrate
If your project has docker-compose services:
- Start them before testing:
docker-compose up -d
- Run integration tests against real services
- Verify migrations apply to real database
- Don't rely on mocks alone
Skill: local-service-testing
Commit Incrementally
Don't push 10 commits at once. Push smaller changes:
git push
gh pr checks --watch
Monitor Actively
Don't "push and forget":
gh pr checks [PR_NUMBER] --watch
Checklist
For each CI run:
When CI is green:
For unresolvable issues:
Integration
This skill is called by:
issue-driven-development - Step 13
autonomous-orchestration - Main loop and bootstrap
This skill follows:
This skill completes:
- The PR lifecycle - merge is the final step, not "verification-before-merge"
This skill may trigger:
error-recovery - If CI reveals deeper issues