Skip to content

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

@myia-ai-01

Symptôme

L'organe bloquant fastlane de always-on-guards.yml (step « Fast lane (verdicts par garde absorbe) », python scripts/ci/fast_lane.py --shadow) échoue sans rien mesurer :

[fast-lane] impossible de calculer le diff contre origin/main : error: Could not read 8f5211eb23c6848aab9f3676e940cbf592aebeda
fatal: origin/main...HEAD: no merge base
##[error]Process completed with exit code 1.

L'agrégat rend alors Organes bloquants en echec : fastlane, le job sort en exit 1, et le PR gate suit. 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 :

SHA Existe sur le remote Date Sujet
8f5211eb23c6 oui 2026-09-11T02:35:48Z docs(ml,#15294): veille bornée datasets RL calibrés 0.8-2B
416712faf348 oui 2026-09-11T02:04:33Z feat(qc,#15539): 3-arm Kelly sizing test on HAR-RV-J

Le runner ne peut donc pas résoudre des commits présents sur l'origine. Le checkout est un clone partiel blobless :

- uses: actions/checkout@v4
  with:
    fetch-depth: 0
    filter: blob:none

Corrélation temporelle relevée sur l'occurrence de #15455 : le run se termine à 03:29:32Z, et main avance à 03:30:06Z (merge de #15484). Les deux SHA illisibles sont des commits de main de la même heure. L'hypothèse de travail est une course entre le git fetch origin "$base_ref" du step et l'avancée de main pendant 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) :

Check rouge PRs
PR gate 41
Always-on guards -- 12 organes, 1 checkout 17
Always-on metadata guards -- 3 organes, 1 checkout 8

18 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 :

PR Organe en échec Signature
#15443, #15446, #15455 fastlane merge-base — ce ticket
#15442 fastlane probable (annotations tronquées, à confirmer)
#15448, #15506 perimeter défaut réel de la PR
#15546 adjacency défaut réel de la PR
#15483 prev_guard défaut réel de la PR

Les 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 dans Always-on metadata guards sur le head de #15455 — même classe, organe différent, donc la cause est probablement dans le checkout partagé, pas dans fast_lane.py.

Pourquoi ça compte

fastlane est 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à, et perimeter était vert pendant tout ce temps. Le coût de la confusion est une PR retenue et un diagnostic à refaire.

Acceptance

  1. Établir la cause plutôt que la supposer : reproduire en relançant un run sur un head inchangé pendant que main avance, 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 sur fast_lane.py.
  2. Rendre l'échec distinguable : un diff illisible ne doit pas produire le même verdict qu'un diff mesuré et fautif. Soit l'organe rend un statut propre (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.
  3. Robustesse du fetch : évaluer 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 le git fetch origin "$base_ref" -q actuel.
  4. Contrôle négatif : un test qui prouve que l'organe rend bien un verdict bloquant quand le diff est lisible et réellement fautif — sans quoi le remède pourrait rendre l'organe silencieux, ce qui serait pire que le rouge.
  5. Re-mesurer le rayon après correctif et relancer nommément les PRs de la ligne « merge-base » du tableau.

Portée

Coordinateur (capacité de digestion). N'appartient à aucune lane de contenu : l'organe est partagé par les cinq workflows absorbés.

Activity

  1. myia-ai-01 commented on Sep 11, 2026

    @myia-ai-01
    CollaboratorAuthor

    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
    34557939760 Always-on guards failure — Could not read 8f5211eb23c6 / no merge base 2026-09-11T03:29:32Z
    34558546728 Always-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 — main avanç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 guards de #15455, qui portait 5 occurrences de la même signature et n'était pas couvert par la première relance.

  2. jsboigeEpita commented on Sep 11, 2026

    @jsboigeEpita
    Contributor

    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.

  3. jsboige commented on Sep 11, 2026

    @jsboige
    Owner

    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 f4aa35182f47ea3137bafc9ba21c1293c96a9191

    • f4aa3518… est un commit, présent dans le dépôt (vérifié git cat-file -t en 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).

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions