You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
CI : dédoublonner les runs d'une même tête (8 052 premières tentatives redondantes en 48 h) #22467
Part of #22461 (audit d'optimisation du CI, levier 4).
Mesure (48 h, du 2026-10-23T07:00Z au 2026-10-25T07:00Z)
33 383 runs pour 1 250 têtes de commit, soit 26,7 runs par tête.
8 052 runs sont une première tentative supplémentaire du même workflow sur la même tête. Ce ne sont pas des re-runs (760 à part) : ce sont des déclenchements répétés, par edited, labeled ou synchronize à SHA égal.
9 683 runs annulés (29 %). Sur 471 annulés échantillonnés, 52 seulement avaient consommé du calcul : la plupart meurent dans la file. Le coût porte sur la file et sur l'API, pas sur les runners.
Recenser les workflows qui écoutent pull_request: types: [..., edited, ...] alors que leur verdict ne dépend pas du titre ni du body. Les wrappers Lean, par exemple, écoutent edited avec un filtre paths : sur une PR qui touche le lake une fois, chaque édition de body relance le build.
Pour chacun, soit retirer edited, soit ajouter une garde de job qui saute quand seul le body a changé (github.event.changes.body sans base).
Mesurer avant et après : runs par tête et premières tentatives redondantes, sur 24 h, avec scripts/ci/measure_runner_demand.py ou la méthode de l'audit.
Critère de sortie : moins de 2 000 premières tentatives redondantes par 48 h, à charge de PRs comparable.
[CLAIMED] lane myia-po-2028:CoursIA-2 -- paths: .github/workflows/lean-knot.yml, .github/workflows/lean-conway.yml, scripts/ci/list_edited_trigger_workflows.py, scripts/ci/tests/test_edited_trigger_census.py
Tranche : famille Lean (wrappers lean-knot.yml / lean-conway.yml). Le census des 37 workflows qui ecoutent pull_request: types: [edited] est mesure au repo ; l'organe de reference scripts/ci/body_consuming_guards.py sert de source pour distinguer un verdict dependant du body d'un verdict de contenu. Les wrappers lean-ci-matrix.yml et lean-mimo.yml sont hors perimetre de cette tranche : ils sont occupes par des PRs ouvertes d'autres lanes (#24046, #23579).
[CLAIMED-AMEND] lane myia-po-2028:CoursIA-2 -- paths: .github/workflows/lean-knot.yml, .github/workflows/lean-conway.yml, scripts/ci/list_edited_trigger_workflows.py, scripts/ci/measure_redundant_runs.py, scripts/ci/tests/test_edited_trigger_census.py
Ajout d'un cinquieme chemin : scripts/ci/measure_redundant_runs.py (organe de mesure des premieres tentatives redondantes, cree apres le premier claim). Le perimetre reste borne aux deux wrappers Lean claims et aux trois organes CI de la famille.
Sixieme chemin ajoute : scripts/ci/body_consuming_guards.py (detecteur canonique des consommateurs de body d'une PR).
Motif : le census construit son verdict body sur l'inventaire de cet organe, et cet inventaire etait aveugle sur la forme gh pr view --json body,reviews,author (une seule chaine a virgules) -- 8 consommateurs reels echappaient a la detection, dont scripts/check_pr_perimeter.py, le script du garde perimeter-review-guard qui lit le body de la PR et DOIT rejouer sur edited. Sans la correction du detecteur, le census aurait recommande de retirer edited a ce workflow : une regression.
La correction porte sur le detecteur (decoupe des champs JSON sur la virgule) et sur la table REFERENCE de l'organe (les 8 consommateurs nouvellement decouverts sont declares). Le gate --check de l'organe repasse au vert (REFERENCE a jour : inventaire conforme), et aucun PR ouverte ne touche ce fichier au moment de l'amendement.
Livraison de la tranche « census + mesure » de cette issue. Le PR est #24120.
Le census (point 1) — le levier du retrait est indisponible
python scripts/ci/list_edited_trigger_workflows.py --json classe chaque workflow qui ecoute pull_request: edited sur quatre axes de dependance — body, title, base, et paths (le filtre paths: est evalue sur le diff base-relative : changer la base change la liste des fichiers qui matchent, donc change le verdict).
Le recit en trois etapes, parce que chaque etape eliminait une famille de faux candidats :
axes retenus
CONTENT_ONLY restant
body + title + base
22
+ detection body corrigee
1
+ axe paths
0
Les 22 du premier palier lisaient le diff par un filtre paths: : c'est cet axe, et lui seul, qui rend leur verdict dependant de la base.
Une correction de doctrine que je dois signaler sur cette issue. Mon premier commit retirait edited aux deux wrappers Lean (lean-knot.yml, lean-conway.yml). C'etait une regression : le defaut #15652 est documente dans le depot (lean-knot.yml, l. 68-81) — un workflow PR qui combine branches: [main] + paths: + une cle types:sansedited rate systematiquement les PR empilees, parce que le retarget de l'enfant emet un base_ref_changed que ces workflows ignorent. Le commit de retour a1f2d33f0 restaure les deux fichiers a l'identique de main ; le diff final de la branche ne touche aucun fichier .github/. Le pin de test qui echoue si quelqu'un re-enleve edited a ces deux wrappers fait partie du lot.
Le trou du detecteur canonique. Le census s'appuie sur scripts/ci/body_consuming_guards.py pour l'axe body. Ce detecteur reconnaissait gh pr view --json body, mais pas la forme gh pr view --json body,reviews,author (une seule chaine, champs separes par une virgule) : 8 consommateurs reels echappaient a l'inventaire, dont scripts/check_pr_perimeter.py — le script du garde perimeter-review-guard, qui lit le body et doit rejouer sur edited (son en-tete documente ce relyat pour #21922). La correction porte sur le detecteur canonique (decoupe sur la virgule), et les 8 consommateurs sont desormais declares dans sa table REFERENCE. Sans cette correction, le census aurait recommande de retirer edited a ce workflow : une regression de plus.
La mesure (point 3) — 48 h, collecte workflow par workflow
Fenetre 2026-10-31T02:00Z -> 2026-11-02T02:00Z, forme canonique created=<debut>..<fin> (les formes created=>=X et created<=Y sont ignorees par l'API, qui rend alors toute l'historique).
mesure
valeur
runs collectes
18 444
tetes de commit
1 421
premieres tentatives redondantes
3 854
dont classe SAME_HEAD_PULL_REQUEST
626
dont classe MIXED_EVENT
0
dont classe WITHOUT_LINKED_PR
3 228
corroborees par un evenement base_ref_changed lisible
5
Quatre workflows touchent le plafond de 1000 runs de l'endpoint (always-on-guards-body, always-on-metadata-guards, coursia-waiter-starvation-advisory, linux-runner-starvation-advisory) : leurs lignes sont un minimum, et l'organe le signale dans son rapport.
Une precision de methode. Ma premiere version attribuait chaque redondance a un evenement edited lu sur la timeline d'issue. Cet axe est structurellement aveugle : la timeline REST n'expose aucune entree edited (verifie : 0 entree pour #24102, dont le body a ete republie a 01:33Z). Le chiffre « 0 redondance imputable a edited » etait un faux zero — l'absence de lecture, pas l'absence de cause. L'organe classe desormais la cause (SAME_HEAD_PULL_REQUEST / MIXED_EVENT / WITHOUT_LINKED_PR) et corrobore par le seul evenement lisible, base_ref_changed. Le compteur redundant_without_linked_pr existe pour qu'un zero ne soit jamais lu comme une absence de cause.
Famille Lean (workflows Lean actifs) : lean-ci-matrix 9 redondantes sur 76 runs, lean-visibility-advisory 6 sur 42, lean-conway 1 sur 17, lean-knot 1 sur 13, lean-i18n-drift 0 sur 40. Les tetes Lean dupliquees sont toutes de classe pull_request sur la meme tete ; une seule est corroboree par un retarget.
Ce que cette tranche ne fait pas, et pourquoi
Le critere de sortie de cette issue (« moins de 2 000 premieres tentatives redondantes par 48 h ») n'est pas atteint : la mesure en donne 3 854. Cette tranche ne retire aucun declencheur — il n'y en a pas de retirable sur l'axe edited — donc elle ne peut pas reduire cette masse. Le PR porte See #22467, pas Closes.
Le levier restant est dans d'autres familles de declencheurs : 3 228 des 3 854 redondances se produisent dans des groupes de runs dont aucun ne porte de PR liee — des workflows declenches par workflow_run ou issue_comment, qui rejouent sur l'evenement d'un autre workflow ou sur chaque commentaire d'une PR. Issue de suivi ouverte pour ce lever : #24121.
Je laisse #24121non claimee : les chemins concernes (scripts/ci/list_edited_trigger_workflows.py, scripts/ci/measure_redundant_runs.py) sont encore portes par le PR #24120, qui n'est pas merge ; une seconde branche de la meme lane sur les memes fichiers serait une collision.
Activity
jsboige commentedon Nov 2, 2026
[CLAIMED] lane myia-po-2028:CoursIA-2 -- paths: .github/workflows/lean-knot.yml, .github/workflows/lean-conway.yml, scripts/ci/list_edited_trigger_workflows.py, scripts/ci/tests/test_edited_trigger_census.py
Tranche : famille Lean (wrappers
lean-knot.yml/lean-conway.yml). Le census des 37 workflows qui ecoutentpull_request: types: [edited]est mesure au repo ; l'organe de referencescripts/ci/body_consuming_guards.pysert de source pour distinguer un verdict dependant du body d'un verdict de contenu. Les wrapperslean-ci-matrix.ymletlean-mimo.ymlsont hors perimetre de cette tranche : ils sont occupes par des PRs ouvertes d'autres lanes (#24046, #23579).jsboige commentedon Nov 2, 2026
[CLAIMED-AMEND] lane myia-po-2028:CoursIA-2 -- paths: .github/workflows/lean-knot.yml, .github/workflows/lean-conway.yml, scripts/ci/list_edited_trigger_workflows.py, scripts/ci/measure_redundant_runs.py, scripts/ci/tests/test_edited_trigger_census.py
Ajout d'un cinquieme chemin : scripts/ci/measure_redundant_runs.py (organe de mesure des premieres tentatives redondantes, cree apres le premier claim). Le perimetre reste borne aux deux wrappers Lean claims et aux trois organes CI de la famille.
Fix(ci,#22467): les wrappers Lean gardent `edited` -- le retrait re-o…
Fix(ci,#22467): census des workflows qui ecoutent `edited`, avec l'ax…
jsboige commentedon Nov 2, 2026
[CLAIMED-AMEND] lane myia-po-2028:CoursIA-2 -- paths: .github/workflows/lean-knot.yml, .github/workflows/lean-conway.yml, scripts/ci/list_edited_trigger_workflows.py, scripts/ci/measure_redundant_runs.py, scripts/ci/tests/test_edited_trigger_census.py, scripts/ci/body_consuming_guards.py
Sixieme chemin ajoute :
scripts/ci/body_consuming_guards.py(detecteur canonique des consommateurs de body d'une PR).Motif : le census construit son verdict
bodysur l'inventaire de cet organe, et cet inventaire etait aveugle sur la formegh pr view --json body,reviews,author(une seule chaine a virgules) -- 8 consommateurs reels echappaient a la detection, dontscripts/check_pr_perimeter.py, le script du gardeperimeter-review-guardqui lit le body de la PR et DOIT rejouer suredited. Sans la correction du detecteur, le census aurait recommande de retirerediteda ce workflow : une regression.La correction porte sur le detecteur (decoupe des champs JSON sur la virgule) et sur la table
REFERENCEde l'organe (les 8 consommateurs nouvellement decouverts sont declares). Le gate--checkde l'organe repasse au vert (REFERENCE a jour : inventaire conforme), et aucun PR ouverte ne touche ce fichier au moment de l'amendement.jsboige commentedon Nov 2, 2026
Livraison de la tranche « census + mesure » de cette issue. Le PR est #24120.
Le census (point 1) — le levier du retrait est indisponible
python scripts/ci/list_edited_trigger_workflows.py --jsonclasse chaque workflow qui ecoutepull_request: editedsur quatre axes de dependance —body,title,base, etpaths(le filtrepaths:est evalue sur le diff base-relative : changer la base change la liste des fichiers qui matchent, donc change le verdict).Le recit en trois etapes, parce que chaque etape eliminait une famille de faux candidats :
CONTENT_ONLYrestantbody+title+basebodycorrigeepathsLes 22 du premier palier lisaient le diff par un filtre
paths:: c'est cet axe, et lui seul, qui rend leur verdict dependant de la base.Une correction de doctrine que je dois signaler sur cette issue. Mon premier commit retirait
editedaux deux wrappers Lean (lean-knot.yml,lean-conway.yml). C'etait une regression : le defaut #15652 est documente dans le depot (lean-knot.yml, l. 68-81) — un workflow PR qui combinebranches: [main]+paths:+ une cletypes:sanseditedrate systematiquement les PR empilees, parce que le retarget de l'enfant emet unbase_ref_changedque ces workflows ignorent. Le commit de retoura1f2d33f0restaure les deux fichiers a l'identique demain; le diff final de la branche ne touche aucun fichier.github/. Le pin de test qui echoue si quelqu'un re-enleveediteda ces deux wrappers fait partie du lot.Le trou du detecteur canonique. Le census s'appuie sur
scripts/ci/body_consuming_guards.pypour l'axebody. Ce detecteur reconnaissaitgh pr view --json body, mais pas la formegh pr view --json body,reviews,author(une seule chaine, champs separes par une virgule) : 8 consommateurs reels echappaient a l'inventaire, dontscripts/check_pr_perimeter.py— le script du gardeperimeter-review-guard, qui lit le body et doit rejouer suredited(son en-tete documente ce relyat pour #21922). La correction porte sur le detecteur canonique (decoupe sur la virgule), et les 8 consommateurs sont desormais declares dans sa tableREFERENCE. Sans cette correction, le census aurait recommande de retirerediteda ce workflow : une regression de plus.La mesure (point 3) — 48 h, collecte workflow par workflow
Fenetre
2026-10-31T02:00Z->2026-11-02T02:00Z, forme canoniquecreated=<debut>..<fin>(les formescreated=>=Xetcreated<=Ysont ignorees par l'API, qui rend alors toute l'historique).SAME_HEAD_PULL_REQUESTMIXED_EVENTWITHOUT_LINKED_PRbase_ref_changedlisibleQuatre workflows touchent le plafond de 1000 runs de l'endpoint (
always-on-guards-body,always-on-metadata-guards,coursia-waiter-starvation-advisory,linux-runner-starvation-advisory) : leurs lignes sont un minimum, et l'organe le signale dans son rapport.Une precision de methode. Ma premiere version attribuait chaque redondance a un evenement
editedlu sur la timeline d'issue. Cet axe est structurellement aveugle : la timeline REST n'expose aucune entreeedited(verifie : 0 entree pour #24102, dont le body a ete republie a 01:33Z). Le chiffre « 0 redondance imputable aedited» etait un faux zero — l'absence de lecture, pas l'absence de cause. L'organe classe desormais la cause (SAME_HEAD_PULL_REQUEST/MIXED_EVENT/WITHOUT_LINKED_PR) et corrobore par le seul evenement lisible,base_ref_changed. Le compteurredundant_without_linked_prexiste pour qu'un zero ne soit jamais lu comme une absence de cause.Famille Lean (workflows Lean actifs) :
lean-ci-matrix9 redondantes sur 76 runs,lean-visibility-advisory6 sur 42,lean-conway1 sur 17,lean-knot1 sur 13,lean-i18n-drift0 sur 40. Les tetes Lean dupliquees sont toutes de classepull_requestsur la meme tete ; une seule est corroboree par un retarget.Ce que cette tranche ne fait pas, et pourquoi
Le critere de sortie de cette issue (« moins de 2 000 premieres tentatives redondantes par 48 h ») n'est pas atteint : la mesure en donne 3 854. Cette tranche ne retire aucun declencheur — il n'y en a pas de retirable sur l'axe
edited— donc elle ne peut pas reduire cette masse. Le PR porteSee #22467, pasCloses.Le levier restant est dans d'autres familles de declencheurs : 3 228 des 3 854 redondances se produisent dans des groupes de runs dont aucun ne porte de PR liee — des workflows declenches par
workflow_runouissue_comment, qui rejouent sur l'evenement d'un autre workflow ou sur chaque commentaire d'une PR. Issue de suivi ouverte pour ce lever : #24121.Je laisse #24121 non claimee : les chemins concernes (
scripts/ci/list_edited_trigger_workflows.py,scripts/ci/measure_redundant_runs.py) sont encore portes par le PR #24120, qui n'est pas merge ; une seconde branche de la meme lane sur les memes fichiers serait une collision.[DELIVERED] lane myia-po-2028:CoursIA-2 -- PR #24120 -- paths: .github/workflows/lean-knot.yml, .github/workflows/lean-conway.yml, scripts/ci/list_edited_trigger_workflows.py, scripts/ci/measure_redundant_runs.py, scripts/ci/tests/test_edited_trigger_census.py, scripts/ci/body_consuming_guards.py
Fix(ci,#22467): l'inventaire de body couvre deux formes de plus, et l…
Fix(ci,#22467): census des workflows qui ecoutent `edited` et mesure …