Diagnostiquer les goulots d'étranglement CI et fusion
L'analytics d'ingénierie traite une pull request comme l'analytics produit traite un utilisateur : une PR se déplace dans un pipeline
(opened → CI → review → merged → deployed) et le but est de trouver où elle ralentit. La surface se compose de trois
outils MCP nommés — tu les appelles, tu n'écris pas SQL. Testé en dogfooding sur PostHog/posthog ; les mêmes outils servent
des agents autonomes (par ex. PostHog Code) qui raisonnent sur leurs propres PRs.
Les outils
pull-requests— le cheval de bataille des PR. PRs ouvertes plus tout ce qui a été fusionné ou fermé depuisdate_from(par défaut-30d), les plus récentes d'abord. Chaque ligne porteauthor(objet imbriqué :handle,display_name,is_bot),repo(imbriqué :owner,name),state,is_draft,labels,open_to_merge_seconds, et un rollupci(runs/passing/failing/pending) à partir de la jointure head-SHA. Répond à la plupart des questions au niveau PR : quelles PRs ont un CI en échec ou en attente, lesquelles sont bloquées ouvertes le plus longtemps, triage par auteur ou par repo, et statistiques de temps-à-fusion (agrègeopen_to_merge_secondssur les lignes fusionnées renvoyées toi-même — médiane et p95, jamais une moyenne).workflow-health— santé CI par workflow sur une fenêtre (date_from/date_to, par défaut les 30 derniers jours) :run_count,success_rate,p50_seconds,p95_seconds,last_failure_at. Répond à « est-ce que CI devient plus rapide ou plus lent » et « quel workflow est le long pole lent ou instable ». Il n'y a pas de tendance intégrée — appelle-le sur deux fenêtres adjacentes et compare.success_rate/p50_seconds/p95_secondscouvrent les exécutions complétées uniquement et sontnullquand une fenêtre n'a pas d'exécutions complétées — garde une protection contre null avant de comparer deux fenêtres (un workflow peut avoir des exécutions dans l'une et aucune dans l'autre).pr-lifecycle— la chronologie d'une seule PR : un en-tête plus événements ordonnés — ouvert, puis une paire CI started/finished par workflow run (nombreux sur un repo multi-workflow, entrelacés par le temps), puis fusionné/fermé. Répond à « où la PR N est-elle bloquée ».metric_qualityestpartial.
Il n'y a pas d'outil de temps-à-fusion agrégé et pas d'outil « counts » — dérive-les à partir de pull-requests (les counts bloqués/en échec, les percentiles de temps-à-fusion).
Les réserves que tu dois porter dans chaque réponse
Ce sont des limites structurelles des données snapshot d'aujourd'hui — énonce-les, ne les occulte pas.
open_to_merge_secondsest grossier. Il fusionne le temps draft et le temps ready-for-review en une seule figure. Rapporte-le comme « open to merge », jamais « cycle time » ou « review time ». Signale-le quand les drafts durables gonflent un nombre.- Le statut CI peut être obsolète. La source CI se synchronise sur un watermark et ne rafraîchit pas une exécution qui se termine après
que des exécutions plus récentes arrivent (jusqu'à ce que le webhook
workflow_runsoit livré). Traite un comptependingcomme non réglé, pas comme un échec réglé ; mène avec le statut, pas un verdict. - Le CI pour une PR est la jointure head-SHA, rien d'autre. Le rollup
cireflète uniquement les exécutions du dernier commit. Il n'y a aucun autre lien entre une PR et ses vérifications. - Pas encore d'avis, d'approbations, de per-check/job, ou de déploiements. N'en déduis pas le comportement de review ou les métriques DORA de leur absence ;
ces données ne sont pas arrivées.
pr-lifecycleestpartialpour la même raison. - Les bots et drafts sont présents dans la sortie
pull-requests, exclus par convention. Filtreauthor.is_bot(imbriqué sousauthor, pas un champ au niveau ligne) etis_draftpour les questions de débit / temps-à-fusion ; conserve-les pour les questions d'impact bot. pull-requestsretourne une page plafonnée. Au maximumlimitlignes (les plus récentes d'abord) ;truncatedesttruequand d'autres correspondent, et il n'y a aucun filtre repo ou limit pour affiner l'appel. Quandtruncatedesttrue, tout percentile ou count que tu dérives couvre uniquement la page la plus récente — pas la fenêtre entière — donc dis-le et réduisdate_fromjusqu'à ce que l'ensemble réel tienne sous le plafond.
Choisir un outil
| La question | Outil | Comment |
|---|---|---|
| Est-ce que CI devient plus lent ? Quel workflow est le long pole ? | workflow-health |
Appelle sur deux fenêtres adjacentes (par ex. date_from=-14d, puis date_from=-28d date_to=-14d) ; compare p50_seconds et p95_seconds par workflow. Mène avec la médiane mais vérifie toujours p95 séparément — ils bougent indépendamment. |
| Quelles PRs ouvertes ont un CI en échec ou en attente ? | pull-requests |
Garde les lignes où ci.failing > 0 ou ci.pending > 0. pending signifie non réglé (ou obsolète) — pas un échec réglé. |
| Quelles PRs sont bloquées ouvertes le plus longtemps ? | pull-requests |
Garde state = open, pas is_draft, pas author.is_bot ; trie par created_at croissant (les plus anciennes d'abord). |
| Combien de temps les PRs prennent-elles à se fusionner ? Par auteur ? | pull-requests |
Sur les lignes fusionnées (merged_at défini, pas bot, pas draft), agrège open_to_merge_seconds — médiane et p95. Groupe par author.handle pour un contexte de cohorte, pas un classement (la surveillance per-développeur est un objectif explicitement exclus). Tends-le en appelant avec deux fenêtres date_from. |
| Où la PR N est-elle bloquée ? | pr-lifecycle |
Parcours les événements triés : opened → first CI started, l'étendue CI (first start → last finish ; une paire par workflow), last CI finished → merged. Le plus grand écart est le goulot. Un long open→merge avec CI rapide pointe vers le temps de review/idle que les données partial ne peuvent pas encore détailler — dis-le. |
La chaîne haute valeur
Miroir comment un humain enquête : signal agrégé → confirmer → PR concrète.
workflow-health (trouver le workflow long-pole lent/instable)
→ pull-requests (confirmer qu'il traîne le temps-à-fusion ; lister les PRs affectées)
→ pr-lifecycle (ouvrir une PR bloquée représentative et montrer l'écart)
« La médiane CI a augmenté parce que e2e-playwright p95 a doublé ; ce workflow est le long pole sur la PR #1234, qui a attendu 47m dans
CI avant de fusionner. »
Attentes de sortie
- Mène avec le verdict en une ligne, puis les chiffres justificatifs.
- Porte la réserve grossier / partial / obsolescence chaque fois que la distinction compte.
- Pour les comparaisons multi-fenêtre ou multi-workflow, un court tableau bat la prose. Rapporte la médiane et p95 côte à côte — ne les effondre jamais en une « moyenne ».
Ce qu'il ne faut PAS faire
- N'appelle pas
open_to_merge_secondscycle time ou review time — c'est grossier open-to-merge. - Ne rapporte pas un compte CI comme un échec réglé quand
pending > 0— il peut être non réglé ou obsolète. - N'en déduis pas les avis, les approbations, les counts per-check, ou les déploiements — cette donnée n'est pas ingérée yet.
- Ne transforme pas les buckets par auteur en un classement — ils servent à trouver le travail bloqué, pas à classer les gens.
- N'utilise pas ces outils pour récupérer les contenus PR bruts ou les diffs — ils font surface au signal pipeline, pas au fil PR.