Repository navigation
CI: l'organe bloquant fast-lane rougit sur "Could not read <sha> / no merge base" sans lire le diff (clone partiel blob:none, course avec main) #15553
Description
Activity
Acceptance 1 : la course est établie, pas supposée.
Test décisif passé sur #15455, tête inchangée (
43b6f5be8812), aucune modification de la PR entre les deux runs :Run Organe Verdict Fin 34557939760Always-on guardsfailure — Could not read 8f5211eb23c6/no merge base2026-09-11T03:29:32Z 34558546728Always-on guards(rerun--failed)success 2026-09-11T03:48:15Z Même head, même diff, même workflow : seul le temps a changé. La cause est donc bien transitoire et située dans la résolution du commit de base par le clone partiel, pas dans le contenu de la PR ni dans
fast_lane.py. Le rapprochement temporel relevé plus haut —mainavançant à03:30:06Z, 34 s après la fin du run rouge — est cohérent avec cette lecture.Ce que la mesure ne dit pas, et qui reste à la charge du correctif : elle démontre que relancer suffit, pas que la fenêtre de course est fermée. Tant que le fetch reste celui d'aujourd'hui, le rouge se reproduira à chaque merge concomitant. L'acceptance 2 (un diff illisible doit être distinguable d'un diff fautif) et l'acceptance 3 (robustesse du fetch) restent entières — ce ticket n'est pas soldé par ce vert.
Propagation : relance des mêmes organes lancée sur les PRs de la ligne « merge-base » du tableau de rayon — #15442, #15443, #15446 — plus
Always-on metadata guardsde #15455, qui portait 5 occurrences de la même signature et n'était pas couvert par la première relance.Grain: MED/guard — lane myia-po-2025:CoursIA-2 — prev: MED/tooling #15498
[CLAIMED] lane myia-po-2025:CoursIA-2 -- paths: scripts/ci/fast_lane.py, scripts/tests/test_fast_lane_merge_base.py
Implémentation bornée à l’organe et à son contrôle négatif, sans toucher les workflows actuellement en collision avec #15538. Le moteur tentera un refetch ciblé/refspec explicite après un premier diff illisible, restera fail-closed si la seconde lecture échoue, et distinguera explicitement cette panne d’infrastructure d’un verdict mesuré et fautif.
Data point pour la course (diagnostic #15531 fait ce matin, même famille) : l'organe Scripts Tests (CPU) vient de tomber sur la même signature sur un runner
myia-po-2024-linux-docker-7(run 34565760760, 05:23Z, PR #15561) :test_twin_registry_integrity.py::test_audit_shas_exist_in_file_history→RuntimeError: HISTORY_WALK_INCOMPLETE (#15387) : git log -m --raw a terminé avec le code 128 ; stderr=error: Could not read f4aa35182f47ea3137bafc9ba21c1293c96a9191f4aa3518…est un commit, présent dans le dépôt (vérifiégit cat-file -ten local) → le clone CI était tronqué (objet jamais arrivé), pas un objet inexistant.- Même test PASS 1 h plus tôt sur
myia-po-2024-linux-docker-3(run 34562227344, 04:26Z), diff identique. - Contexte pool : la même fenêtre nocturne 09-11 a produit des runs ML Pipeline Tests 3-4× ralentis sur docker-9/-10 (diagnostic complet sur feat(ml,#15294): matrice baseline d'accessibilite — mode baseline probe + 4/6 mesures (dapo en cours) #15531, issuecomment-5630153666) — les hôtes po-2024 chargés voient à la fois leur CPU contentionné ET leurs transferts git échouer partiellement.
Si la course de #15553 couvre le fast-lane, ce cas montre que l'organe Scripts Tests (marche d'historique complète
git log -m --raw) expose la même défaillance — à considérer dans le remède (retry au niveau step vs checkout intégral vs ignorer les organes à marche d'historique sur pool contended).
Symptôme
L'organe bloquant
fastlanedealways-on-guards.yml(step « Fast lane (verdicts par garde absorbe) »,python scripts/ci/fast_lane.py --shadow) échoue sans rien mesurer :L'agrégat rend alors
Organes bloquants en echec : fastlane, le job sort enexit 1, et lePR gatesuit. Une PR dont le contenu est sain est retenue par un organe qui n'a pas pu lire son diff.Ce qui est mesuré, et ce qui ne l'est pas
Les SHA « illisibles » existent, et ce sont des commits récents de
main. C'est le point qui écarte l'hypothèse d'un objet orphelin :8f5211eb23c6docs(ml,#15294): veille bornée datasets RL calibrés 0.8-2B416712faf348feat(qc,#15539): 3-arm Kelly sizing test on HAR-RV-JLe runner ne peut donc pas résoudre des commits présents sur l'origine. Le checkout est un clone partiel blobless :
Corrélation temporelle relevée sur l'occurrence de #15455 : le run se termine à
03:29:32Z, etmainavance à03:30:06Z(merge de #15484). Les deux SHA illisibles sont des commits demainde la même heure. L'hypothèse de travail est une course entre legit fetch origin "$base_ref"du step et l'avancée demainpendant le run, le fetch promisor du clone partiel échouant à résoudre un commit atteignable seulement depuis la tête plus récente. C'est une hypothèse, pas une conclusion — elle se teste (§ Acceptance).Rayon de souffle — mesuré, et à ne pas gonfler
Balayage des 60 PRs ouvertes les plus récentes (
gh pr list --json number,statusCheckRollup) :PR gateAlways-on guards -- 12 organes, 1 checkoutAlways-on metadata guards -- 3 organes, 1 checkout18 PRs sur 60 portent un rouge
Always-on. Mais l'échantillon des annotations montre que ce ticket ne les couvre pas toutes, et les confondre serait le défaut à éviter :fastlanefastlaneperimeteradjacencyprev_guardLes quatre dernières lignes sont des rouges légitimes appartenant à leur lane : elles ne doivent pas être absorbées dans ce ticket ni servir à en gonfler l'urgence.
Le même
Could not read <sha>apparaît 5 fois dansAlways-on metadata guardssur le head de #15455 — même classe, organe différent, donc la cause est probablement dans le checkout partagé, pas dansfast_lane.py.Pourquoi ça compte
fastlaneest bloquant. Un organe bloquant qui échoue faute de pouvoir lire son entrée est le pire cas pour une CI : indiscernable, pour qui lit le rollup, d'un vrai défaut de la PR. J'ai moi-même d'abord attribué le rouge de #15455 à une assertion de périmètre de son body — c'était un vrai défaut, corrigé, mais pas celui-là, etperimeterétait vert pendant tout ce temps. Le coût de la confusion est une PR retenue et un diagnostic à refaire.Acceptance
mainavance, ou démontrer que la relance suffit (cause transitoire) — si un simple rerun repasse au vert, la course est établie et le remède porte sur la robustesse du fetch, pas surfast_lane.py.unknown/neutral) avec message explicite, soit il réessaie — mais il ne doit pas rendre « bloquant en échec » sur une entrée qu'il n'a pas lue. Fail-closed reste acceptable, à condition que le message nomme la cause au lecteur du rollup.git fetch --filter=blob:none origin +refs/heads/<base>:refs/remotes/origin/<base>explicite, ou un--unshallow/refetch ciblé sur échec de merge-base, plutôt que legit fetch origin "$base_ref" -qactuel.Portée
Coordinateur (capacité de digestion). N'appartient à aucune lane de contenu : l'organe est partagé par les cinq workflows absorbés.