ci
Monitor the CI pipeline for the current branch via a background Monitor script (GitHub or GitLab), reacting to pass, fail, and manual-gate states. Use when the user says 'watch CI', 'monitor the pipeline', 'is CI green', or after pushing a branch or creating a PR/MR.
Install
npx skills add https://github.com/domengabrovsek/agent-config/tree/main/skills/ci
claude plugin marketplace add https://llmmart.ai/marketplace.json && claude plugin install domengabrovsek-claude@llmmart
git clone https://github.com/domengabrovsek/agent-config.git
The skills CLI installs just this skill, for any of its supported agents. Claude Code installs the whole domengabrovsek/claude collection as a plugin from our marketplace. Git is the plain clone.
Skill manifest
Monitor CI Pipeline
Workflow
why-no-hook: skill workflow guidance; each step requires understanding the surrounding context (repo, task shape, prior state).
- Detect VCS platform:
.gitlab-ci.yml-> glab,.github/-> gh(review-time: see section note) - Start a Monitor with the matching script:
(review-time: see section note)- GitHub:
bash scripts/gh-ci-monitor.sh, resolved inside this skill's own directory(review-time: see section note) - GitLab:
bash scripts/glab-ci-monitor.sh, resolved inside this skill's own directory(review-time: see section note) - Use
timeout_ms: 1800000, the Monitor maximum of 30 minutes(review-time: see section note) - Description: "CI pipeline on
- GitHub:
- React to Monitor notifications:
(review-time: see section note)- Monitor expiry before a
completed|*status: re-arm the same script, since CI pipelines can outlast 30 minutes. The restarted script re-emits the current status(review-time: see section note) no-runs|<branch>: no CI runs found for this branch - inform the user and stop(review-time: see section note)error|persistent-failure: the monitor script hit 5 consecutive errors - report and stop(review-time: see section note)- Status change (e.g.,
in_progress|null→completed|success): acknowledge briefly(review-time: see section note) - Pipeline passes (
completed|success):(review-time: see section note)- Run
~/.agents/scripts/notify.sh "CI passed - <branch-name>"(review-time: see section note) - Report success
(review-time: see section note)
- Run
- Pipeline awaiting manual action (
completed|manual, GitLab only):(review-time: see section note)- All automatic jobs completed; the pipeline is paused on a manual gate and will not progress without user action
(review-time: see section note) - Run
~/.agents/scripts/notify.sh "CI awaiting manual action - <branch-name>"(review-time: see section note) - Report status and stop watching - do NOT trigger the manual job automatically
(review-time: see section note)
- All automatic jobs completed; the pipeline is paused on a manual gate and will not progress without user action
- Pipeline fails (
completed|failureor any non-success conclusion):(review-time: see section note)- Fetch the job log:
- GitLab:
glab ci trace <job-id>(review-time: see section note) - GitHub:
gh run view <run-id> --log-failed(review-time: see section note)
- GitLab:
- Do NOT pipe output through head, tail, grep, or any other command - run the commands directly
- Analyze the root cause - identify the specific failure (test, lint, type check, build, coverage, etc.)
- Classify the failure as transient or real before proposing any change - transient = infra outage, rate limit, queued/timed-out runner, auth/network flake, registry or dependency propagation delay; real = a test/lint/type/build/coverage failure caused by the code under change. State the classification
(review-time: see section note) - If transient: re-run the failed job (
gh run rerun <run-id> --failed/glab ci retry <job-id>) and keep monitoring - do NOT edit code for a transient failure. Escalate to the user only if it recurs after a re-run(review-time: see section note) - Run
~/.agents/scripts/notify.sh "CI failed - <failure-summary>" - If real, fix it: make the change, run
/verify-done, commit with a descriptive message, push, and keep monitoring(review-time: see section note) - Report what failed and what changed in the same message as the next action
(review-time: see section note)
- Fetch the job log:
- Monitor expiry before a
How it works
The monitor scripts poll CI status every 30 seconds but only emit a line when the status changes. This means:
- Zero token cost while the pipeline is running and status hasn't changed
(review-time: see section note) - Claude reacts within ~30s of a status change (vs up to 2 min with /loop)
(review-time: see section note) - No CronDelete cleanup needed - the script exits on terminal state, ending the Monitor
(review-time: see section note) - If
gh/glabfails 5 times in a row (auth expired, network down), the script exits with an error notification(review-time: see section note)
Important: Non-interactive commands only
These commands require a TTY and will NOT work - never use them:
glab ci view(interactive TUI)(review-time: see section note)gh run watch(interactive watcher)(review-time: see section note)- Any command with
--webflag (opens browser)(review-time: see section note)
Safe commands to use:
glab ci status,glab ci list,glab ci trace <job-id>(review-time: see section note)gh pr checks,gh run list,gh run view <run-id> --log-failed(review-time: see section note)
Guardrails
- After 3 consecutive failures on the same issue, stop and escalate - something structural is wrong
(review-time: see section note) - Never weaken tests, skip linting, or lower coverage thresholds to make CI pass
(review-time: see section note) - Never use
--no-verifyor skip hooks(review-time: see section note) - A failure unrelated to your changes (flaky test, infra issue) is transient: re-run it per step e, and do not edit code for it
(review-time: see section note)
Files (claude)
-
scripts
-
gh-ci-monitor.sh 2.5 KB
#!/usr/bin/env bash # Monitor GitHub CI status for the current branch. # Uses `gh pr checks` to aggregate ALL checks for the PR. # Falls back to `gh run list` (all runs, not just one) when no PR exists. # Emits a line to stdout ONLY when status changes. # Exits when the pipeline reaches a terminal state. set -uo pipefail # Note: no -e - gh pr checks uses non-standard exit codes (8 = pending) # that would terminate the script under errexit branch=$(git branch --show-current) pr_number=$(gh pr view --json number --jq '.number' 2>/dev/null) || pr_number="" prev="" error_count=0 while true; do if [ -n "$pr_number" ]; then # Primary path: aggregate all PR checks via gh pr checks gh pr checks "$pr_number" >/dev/null 2>&1 ec=$? case $ec in 0) cur="completed|success" ;; 1) cur="completed|failure" ;; 8) cur="in_progress|null" ;; *) cur="error|exit-$ec" ;; esac else # Fallback: no PR yet - check ALL runs for the branch, not just one lines=$(gh run list --branch "$branch" --json status,conclusion \ --jq '.[] | "\(.status)|\(.conclusion)"' 2>/dev/null) || lines="" if [ -z "$lines" ]; then echo "no-runs|$branch" exit 0 fi # Aggregate: any in_progress → in_progress; any failure → failure; all success → success has_pending=false has_failure=false all_completed=true while IFS='|' read -r status conclusion; do if [ "$status" != "completed" ]; then all_completed=false has_pending=true elif [ "$conclusion" != "success" ] && [ "$conclusion" != "skipped" ]; then has_failure=true fi done <<< "$lines" if [ "$all_completed" = true ] && [ "$has_failure" = true ]; then cur="completed|failure" elif [ "$all_completed" = true ]; then cur="completed|success" elif [ "$has_pending" = true ]; then cur="in_progress|null" else cur="error|unknown" fi # Re-check for PR in case it was created after push pr_number=$(gh pr view --json number --jq '.number' 2>/dev/null) || pr_number="" fi # Track consecutive errors if [[ "$cur" == error* ]]; then error_count=$((error_count + 1)) if [ "$error_count" -ge 5 ]; then echo "error|persistent-failure" exit 1 fi else error_count=0 fi if [ "$cur" != "$prev" ]; then echo "$cur" prev="$cur" # Exit on any completed status regardless of conclusion if [[ "$cur" == completed\|* ]]; then exit 0 fi fi sleep 30 done -
glab-ci-monitor.sh 1.7 KB
#!/usr/bin/env bash # Monitor GitLab CI status for the current branch. # Emits a line to stdout ONLY when status changes. # Exits when the pipeline reaches a terminal state. set -euo pipefail prev_state="" prev_first="" error_count=0 while true; do raw=$(glab ci status 2>/dev/null) || raw="" if [ -z "$raw" ]; then error_count=$((error_count + 1)) if [ "$error_count" -ge 5 ]; then echo "error|persistent-failure" exit 1 fi sleep 30 continue fi error_count=0 # Source of truth: the trailing "Pipeline state: <state>" line. # `glab ci status` lists jobs above it; the first job line can be a # `manual`/`skipped` outlier that does not reflect overall progress. # Take the LAST match via awk's END block (no SIGPIPE risk under # pipefail) and strip the label prefix so we tolerate extra fields. state_line=$(awk '/^Pipeline state:/ { line = $0 } END { print line }' <<<"$raw") state="${state_line##*: }" first="${raw%%$'\n'*}" if [ "$first" != "$prev_first" ]; then echo "$first" prev_first="$first" fi if [ "$state" != "$prev_state" ] && [ -n "$state" ]; then case "$state" in success|failed|canceled|skipped|manual) # Terminal from the monitor's POV: nothing more will happen # automatically. `manual` means all automatic jobs completed and # the pipeline is paused on a manual gate awaiting human action, # so treat it as semi-done and stop watching. # Emit a structured marker so the consumer can branch on outcome # without re-parsing glab's free-form job lines. Mirrors the # `completed|<conclusion>` contract of gh-ci-monitor.sh. echo "completed|$state" exit 0 ;; esac prev_state="$state" fi sleep 30 done
-
-
SKILL.md 5.5 KB
--- name: ci description: "Monitor the CI pipeline for the current branch via a background Monitor script (GitHub or GitLab), reacting to pass, fail, and manual-gate states. Use when the user says 'watch CI', 'monitor the pipeline', 'is CI green', or after pushing a branch or creating a PR/MR." --- # Monitor CI Pipeline ## Workflow **why-no-hook:** skill workflow guidance; each step requires understanding the surrounding context (repo, task shape, prior state). 1. **Detect VCS platform**: `.gitlab-ci.yml` -> glab, `.github/` -> gh `(review-time: see section note)` 2. **Start a Monitor** with the matching script: `(review-time: see section note)` - GitHub: `bash scripts/gh-ci-monitor.sh`, resolved inside this skill's own directory `(review-time: see section note)` - GitLab: `bash scripts/glab-ci-monitor.sh`, resolved inside this skill's own directory `(review-time: see section note)` - Use `timeout_ms: 1800000`, the Monitor maximum of 30 minutes `(review-time: see section note)` - Description: "CI pipeline on <branch-name>" `(review-time: see section note)` 3. **React to Monitor notifications**: `(review-time: see section note)` - Monitor expiry before a `completed|*` status: re-arm the same script, since CI pipelines can outlast 30 minutes. The restarted script re-emits the current status `(review-time: see section note)` - `no-runs|<branch>`: no CI runs found for this branch - inform the user and stop `(review-time: see section note)` - `error|persistent-failure`: the monitor script hit 5 consecutive errors - report and stop `(review-time: see section note)` - Status change (e.g., `in_progress|null` → `completed|success`): acknowledge briefly `(review-time: see section note)` - **Pipeline passes** (`completed|success`): `(review-time: see section note)` - Run `~/.agents/scripts/notify.sh "CI passed - <branch-name>"` `(review-time: see section note)` - Report success `(review-time: see section note)` - **Pipeline awaiting manual action** (`completed|manual`, GitLab only): `(review-time: see section note)` - All automatic jobs completed; the pipeline is paused on a manual gate and will not progress without user action `(review-time: see section note)` - Run `~/.agents/scripts/notify.sh "CI awaiting manual action - <branch-name>"` `(review-time: see section note)` - Report status and stop watching - do NOT trigger the manual job automatically `(review-time: see section note)` - **Pipeline fails** (`completed|failure` or any non-success conclusion): `(review-time: see section note)` a. Fetch the job log: - GitLab: `glab ci trace <job-id>` `(review-time: see section note)` - GitHub: `gh run view <run-id> --log-failed` `(review-time: see section note)` b. Do NOT pipe output through head, tail, grep, or any other command - run the commands directly c. Analyze the root cause - identify the specific failure (test, lint, type check, build, coverage, etc.) d. **Classify the failure as transient or real before proposing any change** - transient = infra outage, rate limit, queued/timed-out runner, auth/network flake, registry or dependency propagation delay; real = a test/lint/type/build/coverage failure caused by the code under change. State the classification `(review-time: see section note)` e. **If transient**: re-run the failed job (`gh run rerun <run-id> --failed` / `glab ci retry <job-id>`) and keep monitoring - do NOT edit code for a transient failure. Escalate to the user only if it recurs after a re-run `(review-time: see section note)` f. Run `~/.agents/scripts/notify.sh "CI failed - <failure-summary>"` g. **If real, fix it**: make the change, run `/verify-done`, commit with a descriptive message, push, and keep monitoring `(review-time: see section note)` h. Report what failed and what changed in the same message as the next action `(review-time: see section note)` ## How it works The monitor scripts poll CI status every 30 seconds but only emit a line when the status **changes**. This means: - Zero token cost while the pipeline is running and status hasn't changed `(review-time: see section note)` - Claude reacts within ~30s of a status change (vs up to 2 min with /loop) `(review-time: see section note)` - No CronDelete cleanup needed - the script exits on terminal state, ending the Monitor `(review-time: see section note)` - If `gh`/`glab` fails 5 times in a row (auth expired, network down), the script exits with an error notification `(review-time: see section note)` ## Important: Non-interactive commands only These commands require a TTY and will NOT work - never use them: - `glab ci view` (interactive TUI) `(review-time: see section note)` - `gh run watch` (interactive watcher) `(review-time: see section note)` - Any command with `--web` flag (opens browser) `(review-time: see section note)` Safe commands to use: - `glab ci status`, `glab ci list`, `glab ci trace <job-id>` `(review-time: see section note)` - `gh pr checks`, `gh run list`, `gh run view <run-id> --log-failed` `(review-time: see section note)` ## Guardrails - After 3 consecutive failures on the **same issue**, stop and escalate - something structural is wrong `(review-time: see section note)` - Never weaken tests, skip linting, or lower coverage thresholds to make CI pass `(review-time: see section note)` - Never use `--no-verify` or skip hooks `(review-time: see section note)` - A failure unrelated to your changes (flaky test, infra issue) is transient: re-run it per step e, and do not edit code for it `(review-time: see section note)`
Comments (0)
Sign in to join the conversation.
Reviews (0)
No reviews yet.
No comments yet.