Synthèse automatique
Diagnostique les échecs de pipelines GitLab CI et durcit le fichier .gitlab-ci.yml en confrontant les symptômes à une taxonomie propre au dépôt des classes de pannes récurrentes.
Points forts
- Part des faits du pipeline en direct (ID du pipeline, jobs en échec, trace du job) via l’API GitLab plutôt que de deviner à partir du diff de commit.
- Fournit une taxonomie concrète symptôme → cause racine (jobs de tag jamais exercés, succès silencieux, dérive des chemins d’artefacts, câblage manquant de release:gate).
- Encode des règles CI propres au dépôt, comme le fait qu’une ancre YAML ne traverse pas les fichiers inclus, d’où l’usage obligatoire de extends ou !reference.
- Documente les particularités d’authentification et de branche avec glab et l’API brute.
Limites
- Codé en dur pour le projet GitLab futo-notes/futo-notes et son organisation ci/<group>.yml.
- Nécessite un accès réseau et un GITLAB_TOKEN valide ; le texte fourni semble par ailleurs tronqué au milieu d’une entrée.
- La taxonomie est historique et peut manquer des modes de panne réellement nouveaux.
À utiliser lorsqu’un pipeline GitLab échoue, qu’un job de publication/tag n’a rien publié, ou avant de modifier .gitlab-ci.yml ou de poser un tag de release.
À éviter pour des CI autres que GitLab, ou pour une simple revue de syntaxe YAML sans lien avec le comportement du pipeline de ce dépôt.
Analyse de sécurité
PrudenceNo destructive, obfuscated, or exfiltrating actions: the only secret use is an env-var token sent to the legitimate GitLab API endpoint for the repo, and nothing is piped to curl|sh or decoded. It does rely on Bash, network calls, and Edit of CI config, and contemplates pushing a throwaway branch, so it belongs in 'caution' rather than 'safe', but it is a legitimate diagnostics workflow with explicit guardrails (no silent green, ask before tagging).
- •Uses Bash/curl with a private GitLab token (`$GITLAB_TOKEN` via `PRIVATE-TOKEN` header) against a remote API; the token is read from the environment rather than hardcoded, which is correct, but the skill does exercise authenticated network access.
- •Step 4 suggests pushing a temporary branch with a `rules:` override to dry-run tag-only jobs, i.e. it expects the agent to commit/push to the real remote; it does caution to revert before merge and to ask the user before any retag.
- •Grants Edit on `.gitlab-ci.yml`/`ci/*.yml` and guides CI/publish pipeline changes — high-impact configuration surface, though changes are reviewable and the skill repeatedly insists on verification and ask-first for publishing.
- •Skill routinely makes authenticated network calls to the GitLab API (gitlab.futo.org) using a personal access token from $GITLAB_TOKEN, and prints job traces — traces could contain secrets if run verbatim on hostile logs, though nothing here exfiltrates data off-site.
- •Guidance to edit .gitlab-ci.yml and, in Step 4, to temporarily push branch-scoped rule overrides that make tag-only jobs run on a throwaway branch; legitimate but modifies release/publish configuration, so changes must be reverted as instructed.
- •Suggests ad-hoc shell loops (watch_pipeline, curl | jq, tail on traces) that are read-only, but the skill assumes the token has broad API scope with no least-privilege note.
Exemples
The pipeline on main is red. Get the latest pipeline, list the failed jobs, and show me the tail of the trace for the first failure before proposing a fix.publish:android failed on the v1.2.0 tag build — check the job trace, classify the failure against our known CI failure classes, and patch .gitlab-ci.yml if needed.I'm about to tag a release. Run the pre-tag check against the current .gitlab-ci.yml and flag any release-gate or artifact-path issues.name: ci-doctor description: Diagnose and fix GitLab CI/pipeline failures, and harden .gitlab-ci.yml against this repo's recurring failure classes. Use when the user says "pipeline failed", "CI is red", "the tag build failed", "publish:android/publish:ios failed", "check the pipeline", "why didn't the release go out", "harden CI", or before tagging a release ("pre-tag check"). Also load this BEFORE editing .gitlab-ci.yml for any reason — it encodes the hard rules that past pipeline breakage taught. allowed-tools: Bash, Read, Edit, Grep, Glob
CI Doctor
.gitlab-ci.yml is the most-churned file in this repo — CI firefighting is the largest recurring
time cost. This skill turns the historical failure classes into a triage procedure so a red
pipeline costs minutes, not an afternoon of push-and-watch.
The root .gitlab-ci.yml holds default, variables, workflow, stages, and an include:
list; the jobs live in ci/<group>.yml. A YAML anchor (&x/*x) does not resolve across
included files, so a template used from another file goes through extends: or !reference.
Text checks read the whole pipeline through scripts/lib/gitlab-ci.mjs.
Project: futo-notes/futo-notes on gitlab.futo.org. The curl calls below use $GITLAB_TOKEN,
which always works. glab is usually also present, but whether it can authenticate is per-machine
and per-shell — see the auth gotcha in docs/agents/issue-tracker.md before blaming a read.
Step 1 — Get the facts (never guess from the commit diff alone)
API="https://gitlab.futo.org/api/v4/projects/futo-notes%2Ffuto-notes"
H='--header PRIVATE-TOKEN:'"$GITLAB_TOKEN"
# Latest pipelines for a ref (branch or tag)
curl -s $H "$API/pipelines?ref=main&per_page=5" | jq '.[] | {id, status, ref, sha: .sha[0:8], web_url}'
# Jobs in a pipeline — find the failures
curl -s $H "$API/pipelines/<PIPELINE_ID>/jobs?per_page=100" \
| jq '.[] | select(.status=="failed" or .status=="canceled") | {id, name, stage, status, allow_failure}'
# The job log (the tail is where the truth is)
curl -s $H "$API/jobs/<JOB_ID>/trace" | tail -80
glab ci status / glab ci view work for quick looks; use the raw API when you need job traces
or to script a watch loop.
For pipelines on the current branch, glab ci list -b <branch> may parse the branch as a date and
fail. Use the encoded project path through glab api:
BRANCH=$(git branch --show-current)
glab api "projects/futo-notes%2Ffuto-notes/pipelines?ref=$BRANCH"
Read the log tail FIRST, then the failing job's script: in its ci/*.yml file, then the diff of
the commit that broke it (git log --oneline -5 -- .gitlab-ci.yml ci/).
Step 2 — Classify against the known failure taxonomy
Match the symptom before inventing a novel diagnosis. These classes account for most historical red pipelines here:
| Class | Symptom | Root cause pattern |
|---|---|---|
| First-contact tag job | A publish/release job fails on its first real run at tag time | Job only executes on tags, so it was never exercised: secrets not propagated (especially into nested VMs like Cirrus), cold caches hitting timeouts, wrong artifact lookup paths |
| CWD/path assumption | A step "succeeds" but its effect didn't happen; later step fails mysteriously | GitLab preserves cd across script lines; relative path resolved elsewhere; -f/|| true masked it |
| Silent green | "Job succeeded" but nothing was published/uploaded | An error branch special-cased to exit 0 |
| Missing release-gate wiring | A test failed but the release published anyway | New test job absent from release:gate.needs (deliberate exceptions: test:audit, test:localization-audit, test:quality-report — see rule 3) |
| Artifact-path drift | No files to upload / downstream job can't find inputs | Workspace layout changed; artifacts:paths/lookup globs didn't |
| Cache death spiral | Retries keep timing out at the same wall | Caches upload only on_success, so every retry starts cold |
| Flake | Same job passes on retry with no change | Fixed timeout or exact-string assertion in a cross-platform test |
| Environment skew | Works locally, fails in CI image | Tool version differs (strip/binutils, glibc, NDK, Xcode) — check the job's image:/runner tag |
Step 3 — Fix by the hard rules
Apply the rule for the class; do not just patch the symptom:
- Absolute paths only in CI scripts — anchor on
$CI_PROJECT_DIR. Never rely on acdfrom an earlier line. After any destructive/cleanup line, verify the effect (ls,test -f) rather than trusting-f. - No silent green. Every error path exits non-zero. If a failure is genuinely acceptable,
model it as
allow_failure: trueon the JOB (visible in the UI), never asexit 0in the script. Assert outcomes: artifact exists, upload count > 0, store accepted the bundle. - Every new test job goes into
release:gate.needsin the same commit. Publish jobs start as soon as their ownneedssucceed, so a red test job that is missing from that list does not hold anything back — that is how v1.4.0 twice came within one job of publishing past a failed test (therelease:gate.needscomment inci/publish.ymlnames both). Deliberate exceptions:test:audit,test:localization-audit, andtest:quality-reportareallow_failure: trueand left out on purpose (docs/architecture-gates.md) — adding one would turn a reporter into a release blocker. - Secrets into nested environments are passed explicitly (Cirrus VM, docker-in-docker). Never assume a CI variable propagates one level down.
- Caches upload
when: alwaysso a timed-out job doesn't doom every retry to a cold start. - Flakes get root-caused — wait on conditions/events, not durations; don't assert exact user-facing strings. One commented timeout bump is the ceiling; a second bump on the same job means find the real cause.
- Keep MR-blocking vs
allow_failure/manual intent explicit inrules:— don't accidentally promote a manual job to blocking or vice versa.
Step 4 — Verify without burning a tag
- MR-scoped jobs: push a branch/MR and watch that pipeline.
- Tag-only jobs: never verify by tagging. Options, in order of preference:
- Run the job's script locally with the same inputs (most publish scripts are
scripts/*.py|mjs|sh— they run outside CI). - Push a temp branch with a one-commit rule override making the job run on that branch
(
rules: - if: $CI_COMMIT_BRANCH == "ci-dryrun-x"); revert before merge. - For the updater path specifically:
node scripts/release-build.mjs e2erehearses build→sign→serve→verify end-to-end with localdev keys.
- Run the job's script locally with the same inputs (most publish scripts are
- After a failed tag: fix on main first. Then ask the user before any retag/new tag (publishing is an ask-first action). Repo convention favors bumping the patch version over deleting tags; release creation is retag-safe but partially-published artifacts from the failed run must be accounted for.
Watch loop after pushing a fix (jobs run 10–60 min; poll accordingly):
watch_pipeline() {
curl -s $H "$API/pipelines/$1" | jq -r '"\(.status) \(.web_url)"'
curl -s $H "$API/pipelines/$1/jobs?per_page=100" \
| jq -r '.[] | "\(.status | .[0:7])\t\(.stage)\t\(.name)"' | sort
}
Pre-tag checklist (run when asked for a "pre-tag check" or before /release tags)
- [ ]
just checkgreen locally - [ ] Last main pipeline fully green (not "green with failed-but-allowed jobs you care about")
- [ ]
.gitlab-ci.ymldiff since the last tag reviewed against the rules above (git diff $(git describe --tags --abbrev=0) -- .gitlab-ci.yml ci/) - [ ] Any NEW tag-only job since the last tag has been exercised (Step 4)
- [ ]
release:gate.needsstill lists every test job except the threeallow_failurereporters (test:audit,test:localization-audit,test:quality-report), non-blocking by design (grep -A30 'release:gate' ci/publish.yml) - [ ]
test:auditwas yellow because it FOUND something, not because it never ran — its log has noAUDIT-DID-NOT-RUNline (allow_failurerenders both the same) - [ ] Updater artifacts: signing is the LAST touch on bytes (mesa patch / notarize / Authenticode
all happen before
.sig) — seedocs/release/updater.md
Report format
State: pipeline + failing job(s) with links · the class from the taxonomy · root cause (quote the log line) · the fix and which hard rule it enforces · how it was verified (pipeline link or local run output) · any follow-up risk (e.g. "publish:ios remains unexercised until next tag").
Du fichier au premier essai
Le téléchargement contient exactement le contenu affiché sur cette fiche. Cette copie peut différer de la dernière version du dépôt source.
Consulter la source et ses fichiers annexesCe téléchargement contient uniquement SKILL.md. Les scripts, références, modèles et dépendances éventuels ne sont pas inclus. Récupérez les fichiers nécessaires depuis la source en conservant leur arborescence avant de poursuivre.
1. Télécharger le fichier
Télécharger SKILL.mdDepuis la racine d’un projet de test, enregistrez le fichier sous .skill-downloads/gitlab-ci-doctor-mvj1oc4k/SKILL.md, ou utilisez la commande suivante. Ce dossier sert à examiner la skill avant son installation.
Commande pour macOS/Linux ou WSL : un shell POSIX et curl sont nécessaires. Sous Windows sans WSL, utilisez le bouton de téléchargement et créez le dossier manuellement.
mkdir -p '.skill-downloads/gitlab-ci-doctor-mvj1oc4k' && curl --fail --show-error --location 'https://skills-guides.com/api/skills/gitlab-ci-doctor-mvj1oc4k/download' --output '.skill-downloads/gitlab-ci-doctor-mvj1oc4k/SKILL.md.part' && mv '.skill-downloads/gitlab-ci-doctor-mvj1oc4k/SKILL.md.part' '.skill-downloads/gitlab-ci-doctor-mvj1oc4k/SKILL.md'2. Vérifier les prérequis
Lisez SKILL.md avant de l’utiliser. Si le fichier cite des scripts ou services externes, examinez-les et préparez les accès nécessaires dans votre environnement de test.
Outils déclarés par l’auteur (à vérifier dans votre agent) : Bash, Read, Edit, Grep, Glob
Aucune section de prérequis reconnue dans ce fichier. Cela ne signifie pas qu’il est autonome : les bibliothèques, outils et accès peuvent être cités ailleurs dans le contenu ou dans le dépôt source.
Les plateformes de la fiche sont des indications du catalogue. Les chemins ci-dessous suivent la documentation des outils ; ils ne prouvent pas que cette skill y a été exécutée. Aucune version minimale de ces outils n’est attestée pour cette fiche.
3. Charger la skill
Après vérification, copiez le dossier complet dans le projet avec l’une des commandes ci-dessous, puis ouvrez une nouvelle session de l’outil. La commande s’arrête si un dossier du même nom existe déjà : comparez les fichiers avant de le remplacer.
Claude Code
test -f '.skill-downloads/gitlab-ci-doctor-mvj1oc4k/SKILL.md' && test -s '.skill-downloads/gitlab-ci-doctor-mvj1oc4k/SKILL.md' && mkdir -p '.claude/skills' && test ! -e '.claude/skills/ci-doctor' && cp -R '.skill-downloads/gitlab-ci-doctor-mvj1oc4k' '.claude/skills/ci-doctor'OpenSkills
OpenSkills doit déjà être installé. La procédure locale install/read est contrôlée avec OpenSkills 1.5.0, qui exige Node.js ≥ 20.6.0. Aucun slug du catalogue n’est résolu automatiquement.
Installation officielle d’OpenSkillsopenskills install './.skill-downloads/gitlab-ci-doctor-mvj1oc4k'openskills read 'gitlab-ci-doctor-mvj1oc4k'La lecture doit afficher le contenu du fichier installé et son dossier de base. Elle ne lance ni la skill ni ses dépendances.
Pour un agent qui lit AGENTS.md, synchronisez ensuite l’index. Cette commande modifie AGENTS.md : relisez le diff avant de l’utiliser.
openskills syncMode manuel ou autre outil : joignez SKILL.md à une conversation, ou ouvrez-le dans un agent capable de lire les fichiers. Ajoutez les ressources annexes nécessaires. Il n’existe pas de dossier universel reconnu par tous les outils.
4. Faire un premier essai
Utilisez une entrée courte et fictive : un endpoint d’API, un petit document ou un brief d’interface. Dans une nouvelle conversation, joignez le fichier ou donnez son chemin à l’agent, puis adaptez cette demande :
Lis .skill-downloads/gitlab-ci-doctor-mvj1oc4k/SKILL.md et applique ses instructions à cet exemple : [décrire une entrée de test]. Indique les fichiers, dépendances ou accès qui manquent. Produis le résultat demandé par la skill sans inventer de données ni exécuter de script non examiné.Résultat attendu : une sortie correspondant aux instructions de la skill, ou une liste précise des prérequis manquants. Une simple confirmation de lecture ne valide pas le premier usage. Si une ressource externe est indisponible, ce parcours reste à tester.
Configurer un canal de discussion avec SecretRefs
DevOps
Configurez des canaux de discussion avec des commandes non interactives, les secrets étant uniquement des SecretRefs. Couvre les étapes de collecte, modification, réparation et vérification.
Enquêter sur les échecs CI de ClickHouse
DevOps
Investigue un échec CI de ClickHouse de bout en bout à partir d'une URL de PR ou de rapport S3. Récupère les tests échoués, classe flaky vs vraie régression, et cherche des issues/fixes existants.
Revue de PR Ansible
DevOps
Examine une PR Ansible selon le processus standardisé du projet, incluant la validation des changelogs, la couverture de tests et le suivi des commentaires.