Skip to content

fix(ci,#17253): un fetch promisor en echec ne rougit plus Scripts Tests (CPU) - #17254

Merged
myia-ai-01 merged 2 commits into
mainfrom
fix/17253-promisor-fetch-red
Sep 23, 2026
Merged

myia-ai-01 merged 2 commits into
mainfrom
fix/17253-promisor-fetch-red

Conversation

@jsboige

@jsboige jsboige commented Sep 21, 2026

Copy link
Copy Markdown
Owner

Grain: LIGHT/test -- lane myia-po-2026:CoursIA -- prev: LIGHT/docs #17252

Quoi: Scripts Tests (CPU) etait rouge sur main sur un seul test, parce qu'un fetch promisor en echec pendant l'extraction d'un arbre historique sortait en 128 — et le test jetait le message de git, rendant le rouge opaque. Le helper remonte desormais le stderr et traduit la seule classe « objet non materialisable » en test non jouable ; tout le reste reste un echec dur.
Preuve: mecanisme reproduit avec controle negatif (4 bras ci-dessous) ; Closes #17253.
Perimetre: 1 fichier de test, +56/−17. Hors scope : la cause racine (saturation du quota d'installation), et les 2 rouges PR gate de mes PRs en vol (#17230/#17233/#17237) qui sont un 403 et non du contenu.

Le rouge, et pourquoi il se lisait mal

Scripts Tests (CPU) sur main :

run head date verdict
35600494275 dc0ccbfd 12:36:15Z success
35612584784 54d510f0 14:30:12Z failure

Aucun commit ne touche ce test entre les deux : le rouge depend de l'etat du workdir du runner, pas du contenu. Le log CI ne portait que :

E   subprocess.CalledProcessError: Command '['git', ..., 'checkout-index', '-a', '--prefix=...']'
    returned non-zero exit status 128.
= 1 failed, 14439 passed, 97 skipped, 8 xfailed

fatal: could not fetch <sha> from promisor remote — la cause — etait avalee par check=True, capture_output=True. C'est ce qui a fait classer ce rouge « herite de la base » et l'a laisse plusieurs heures sans diagnostic.

Le mecanisme, mesure

Le checkout des workflows est un clone partiel (scripts-tests.yml L195-205 : fetch-depth: 0 + filter: blob:none) : tous les commits sont presents — donc le skipif(_commit_exists(...)) du test ne se declenche pas — mais aucun blob. Le test extrait l'arbre PRE-consolidation par read-tree + checkout-index, ce qui exige les blobs historiques.

Sur un clone blob:none reel, remote promisor rendu injoignable :

read-tree       rc=0
checkout-index  rc=128
fatal: could not fetch d06f30f2942d7bf6a9df426a92e9c7a1fab697e7 from promisor remote

checkout-index n'est pas fautif — il est bien fetch-aware : sur le meme clone avec un remote qui repond, il materialise 2364 fichiers (rc=0). Le docstring du test supposait cette voie sure ; elle l'est, sauf quand le remote ne repond pas. C'est le fetch qui echoue.

Deux victimes pour un seul quota

Le fetch promisor du runner utilise le meme token d'installation dont le quota renvoyait, au meme moment, API rate limit exceeded for installation (HTTP 403) a l'agregateur PR gate (mesure 15:47Z sur #17249 et 15:52Z sur #17252). Un seul quota sature faisait donc deux degats : l'agregateur du gate, et le fetch paresseux des blobs — le second sous la forme d'un rouge de check requis, avec une imputation fausse (le test, pas le quota).

Validation — 4 bras, dont un controle negatif

# arbre fichier promisor resultat
1 clone blob:none d'origine casse FAILED exit 128 — reproduit la CI a l'identique
2 clone blob:none corrige casse 1 skipped, cause reelle dans le motif
3 clone blob:none corrige sain (blobs froids) 8 passed — le garde mord toujours
4 clone complet corrige n/a 8 passed — chemin nominal intact

Le bras 1 est le controle qui qualifie le correctif : meme clone, meme panne, seul le fichier change. Le bras 3 est celui qui interdit de lire ce correctif comme un affaiblissement : quand les objets sont materialisables, les assertions du controle retroactif s'executent normalement.

Ce qui change dans le code

  • _run_git() : lance git et, sur echec, remonte le stderr — plus aucun exit status N nu ;
  • PromisorObjectUnavailable : levee quand git rapporte promisor remote (cause d'infrastructure) ;
  • le test traduit exactement cette classe en pytest.skip motive. Une revision invalide, un arbre corrompu ou une assertion du scanner restent des echecs durs — fail-closed preserve.

Portee

Un seul test du depot materialise des objets git ainsi (grep sur checkout-index / read-tree / GIT_INDEX_FILE dans scripts/) : la classe est d'un seul membre, le correctif la couvre entierement. Tout test futur qui extrairait un arbre historique sur un checkout blob:none devra traiter la meme classe.

Cause racine hors perimetre : la saturation du quota d'installation GitHub n'est pas traitee ici. Ce correctif empeche qu'elle se transforme en rouge de check requis et en imputation fausse — il ne l'empeche pas d'arriver.

Closes #17253

🤖 Generated with Claude Code

…ts (CPU)

Scripts Tests (CPU) etait rouge sur main (run 35612584784, 14:30Z) sur un seul
test : test_retroactive_control_sees_third_pair_pre_consolidation, en
"checkout-index ... returned non-zero exit status 128". Le test extrait un arbre
HISTORIQUE via read-tree + checkout-index, sur le checkout partiel des workflows
du depot (scripts-tests.yml L195-205 : fetch-depth 0 + filter blob:none).

Mecanisme reproduit avec controle negatif sur un clone blob:none reel, remote
promisor rendu injoignable :
    read-tree       rc=0
    checkout-index  rc=128
    fatal: could not fetch <sha> from promisor remote

checkout-index n'est PAS en cause : il est bien fetch-aware (2364 fichiers
extraits du meme clone quand le remote repond). C'est le FETCH qui echoue -- et
sur le runner il echoue sous le meme quota d'installation dont le 403 saturait
l'agregateur PR gate au meme moment (15:47Z / 15:52Z). Un seul quota sature
avait donc deux victimes, et la seconde se lisait comme une regression du
scanner.

D'ou l'imputation fausse : check=True + capture_output=True avalait le stderr de
git, ne laissant dans le log CI qu'un "exit status 128" nu -- invisible a qui ne
dispose que du check. Flaky par construction : vert a 12:36Z (head dc0ccbf),
rouge a 14:30Z (head 54d510f), sans aucun commit sur ce test entre les deux
(workdir promisor chaud vs froid).

Le correctif :
- _run_git() remonte le stderr de git dans tous les chemins d'echec ;
- PromisorObjectUnavailable est levee quand git rapporte un fetch promisor en
  echec ("promisor remote") ;
- le test traduit EXACTEMENT cette classe en pytest.skip motive (non jouable),
  et rien d'autre : revision invalide, arbre corrompu ou assertion du scanner
  restent des echecs durs (fail-closed preserve).

Validation, 4 bras :
- controle (fichier d'origine, clone blob:none, promisor casse) : FAILED exit
  128 -- reproduit la CI a l'identique ;
- fichier corrige, meme clone, promisor casse : 1 skipped, cause reelle dans le
  motif ;
- fichier corrige, promisor retabli (blobs froids) : 8 passed -- le garde mord
  toujours ;
- clone complet : 8 passed.

Portee : un seul test du depot materialise des objets git ainsi (grep sur
checkout-index / read-tree / GIT_INDEX_FILE) -- la classe est d'un seul membre.
Cause racine (saturation du quota d'installation) hors perimetre.

Closes #17253

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@github-actions

Copy link
Copy Markdown
Contributor

Trivial-diff advisory (#15740, non bloquant).
genre test dans la famille META (docs/guard/ledger/readme/test) + diff de 73 lignes changees (<= 100) + aucune exception ecrite dans le body : le litmus de la trivialite (une douzaine d'instances scannees a la suite) est credible. Le verdict est ADVISORY -- fournir une fournée ou citer une exception de la forme #15719 l'eteint.
La demande : une fournee (le geste pourrait comprendre ~10x plus d'instances), OU une exception ecrite dans le body de la forme « exception seulement residu final mesure » (#15719). Editer le body re-deroule cet organe et retire le label.

@github-actions

github-actions Bot commented Sep 21, 2026 •

Copy link
Copy Markdown
Contributor

Path-collision (organ #13359) — résolue

La collision de chemins signalée sur #17254 n'existe plus au passage du 2026-09-23T01:47Z : aucune autre PR ouverte ne partage désormais de chemin de fichier avec elle. Note laissée en place de l'avertissement (retraction non destructive).

@jsboige

jsboige commented Sep 22, 2026 •

Copy link
Copy Markdown
Owner Author

[ADJOINT PREFLIGHT]
schema: 1
lane: myia-po-2026:CoursIA-3
pr: 17254
head: c1e5d30
complete: true
body: read
comments-reviewed: 3
reviews-reviewed: 0
threads-reviewed: 0
threads-unresolved: 0
surfaces-sha256: 3706bbfc5f626d59a1e7e2bf25ebf6fc2c7f45580e67b6c44132ecc9229cc985
diff-files: 1
diff-additions: 56
diff-deletions: 17
checks: BLOCKED
b0: blocked
scope: pass
domain: pass
verdict: BLOCKED
[/ADJOINT PREFLIGHT]

[Tell c.81 - BLOCKED-WITH-SUBSTANCE] PR gate FAIL (Scripts Tests CPU failure). Cycle 12 hub secretaire.

@github-actions

Copy link
Copy Markdown
Contributor

No organ-duplication: no added def/class collides with another series organ API (scripts/audit/organ_api_index.yaml).

Detector: python scripts/audit/detect_organ_duplication.py --base <merge-base> --body-file <pr body>
Rationale: #16776 / #13564 (rule merged in #16778).

@github-actions github-actions Bot added the variation-light-cap-reached Lane ayant deja merge une LIGHT aujourd'hui (cap G-VAR-2 atteint) label Sep 23, 2026
@github-actions

Copy link
Copy Markdown
Contributor

G-VAR-2 light cap reached (advisory, non bloquant).
La lane myia-po-2026:CoursIA a deja consomme son budget LIGHT du jour (axe genre G-VAR-2/3 (light-genre, quel que soit le tier declare) : #17275 (MED/guard, merge a 2026-09-23T00:03:57Z), #17272 (MED/guard, merge a 2026-09-23T00:11:26Z), #17432 (MED/guard, merge a 2026-09-23T00:23:00Z), #17384 (LIGHT/notebook, merge a 2026-09-23T00:59:13Z), #17414 (MED/guard, merge a 2026-09-23T01:15:48Z), #17247 (LIGHT/test, merge a 2026-09-23T01:24:30Z), #17382 (LIGHT/notebook, merge a 2026-09-23T04:12:48Z), #17285 (MED/guard, merge a 2026-09-23T06:30:29Z), #17368 (MED/guard, merge a 2026-09-23T10:06:27Z), #17447 (MED/guard, merge a 2026-09-23T10:07:49Z), #17502 (MED/guard, merge a 2026-09-23T10:09:47Z), #17393 (MED/guard, merge a 2026-09-23T10:15:23Z)).
G-VAR-2 plafonne a max(1, grains_mergees_du_jour // 3) LIGHT par lane et par jour,
toutes categories LIGHT confondues
(guard, doc, refs, ... partagent un seul budget) :
c'est un RATIO, pas un plafond plat. La decision de merge reste au coordinateur.

@github-actions github-actions Bot added variation-tier-inflation declared LIGHT << effective LIGHT-genre (#10020, advisory) variation-genre-cap-exceeded light_genre > cap partage G-VAR-2 (#10020, advisory) labels Sep 23, 2026
@github-actions

Copy link
Copy Markdown
Contributor

G-VAR-2/3 GENRE signals (advisory, non bloquant, #10020).
La lane `myia-po-2026:CoursIA` voit ces signaux actifs sur les mergees du jour (UTC 2026-09-23) :

  • TIER-INFLATION : declared LIGHT << effective LIGHT-genre (tally : declared=3 genre=12 cap=9)
  • CAP-EXCEEDED-BY-GENRE : light_genre > cap partage G-VAR-2 (tally : declared=3 genre=12 cap=9)

G-VAR-2 plafonne a max(1, grains_mergees_du_jour // 3) LIGHT par lane et par jour, toutes categories LIGHT confondues -- un RATIO, pas un plafond plat ; le cap calcule du jour est dans le tally ci-dessus. G-VAR-3 interdit deux genres LIGHT consecutifs. Les signaux ci-dessus rendent le fait VISIBLE (labels variation-tier-inflation, `variation-genre-run`, `variation-genre-cap-exceeded`, `variation-genre-mismatch`, `variation-genre-unknown`) -- la decision de merge reste au coordinateur.

@github-actions github-actions Bot added the trivial-diff-advisory Diff trivial : grain META mecanique sans fournee ni exception ecrite (#15740) label Sep 23, 2026
@jsboige

jsboige commented Sep 23, 2026

Copy link
Copy Markdown
Owner Author

[ADJOINT PREFLIGHT]
schema: 1
lane: myia-po-2025:CoursIA-2
pr: 17254
head: 20adb72
complete: true
body: read
comments-reviewed: 6
reviews-reviewed: 0
threads-reviewed: 0
threads-unresolved: 0
surfaces-sha256: 318f2c00cf853c994b847a9308fa2de6ca79d4a89e401645b8f1df0e19950423
diff-files: 1
diff-additions: 56
diff-deletions: 17
checks: latest-wins-green
b0: clear
scope: pass
domain: pass
verdict: READY
[/ADJOINT PREFLIGHT]

Lecture complète à la tête 20adb723d4 (fusion de main sans contenu d'auteur sur c1e5d30077) : un seul fichier, scripts/audit/tests/test_scan_duplicate_test_pairs.py. _run_git remonte le stderr, seule la classe promisor remote devient pytest.skip motivé, tout autre échec git reste un échec dur ; le fichier n'a pas bougé sur main depuis la base, git merge-tree propre. Scripts Tests (CPU) vert à 13:12Z, PR gate: PASS à 13:52Z. Pour l'arbitrage d'ai-01 : l'advisory G-VAR-2 5795279306 signale le budget LIGHT de la lane myia-po-2026:CoursIA consommé ce jour ; ce dossier atteste l'état de la PR, pas la décision de budget.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

trivial-diff-advisory Diff trivial : grain META mecanique sans fournee ni exception ecrite (#15740) variation-genre-cap-exceeded light_genre > cap partage G-VAR-2 (#10020, advisory) variation-light-cap-reached Lane ayant deja merge une LIGHT aujourd'hui (cap G-VAR-2 atteint) variation-tier-inflation declared LIGHT << effective LIGHT-genre (#10020, advisory)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants