Skip to content

fix(ci): check_c2_compliance --json viole son contrat sur cible vide -> un rouge indiscernable d'un defaut de carnet #20198

Closed

Description

@jsboige

Sans parent : residuel du garde introduit par #14799 (ferme) ; c'est le volet depot de l'episode runner dont le volet infra vit sur #20174.

Le defaut

check_c2_compliance.py --json ne respecte pas son contrat --json quand la liste de cibles est vide : il imprime une chaine humaine et sort en 0.

# scripts/notebook_tools/check_c2_compliance.py:313-317
    targets = get_target_notebooks(args)
    if not targets:
        print("No notebooks to check.")
        return 0

Le garde CI du workflow notebook-validation.yml (l.102-113) redirige cette sortie dans /tmp/c2_results.json et la parse comme du JSON :

python scripts/notebook_tools/check_c2_compliance.py --json > /tmp/c2_results.json || C2_EXIT=$?
VIOLATIONS=$(python -c "import json; data=json.load(open('/tmp/c2_results.json')); ...")
if ! VIOLATIONS=$(... 2>/tmp/c2_parse.err); then
  echo "::error::C.2 results not parseable as JSON — scanner wrote non-JSON or truncated output (#14799)"
  exit 1
fi

Resultat : un return 0 (succes du scanner) devient un exit 1 du job, avec un message qui nomme un carnet et un fichier de resultats, jamais la cause.

Pourquoi ce n'est pas qu'un detail cosmetique

Mesure firsthand du 2026-10-10, sur #19590 (tete 8eed473259), job validate-notebooks (run 38005462188) :

##[error]C.2 results not parseable as JSON — scanner wrote non-JSON or truncated output
         (file starts with: 'No notebooks to check. ') (#14799)

Cette PR modifie bien un carnet (MyIA.AI.Notebooks/IIT/ICT-Series/ICT-23-PersonaCatastrophe-Python.ipynb, +28/-6). En local, meme tete, arbre propre : --json rend un JSON valide commencant par [, et le carnet y figure.

Le vrai declencheur est un arbre de travail ampute cote runner (cause racine sparse-checkout herite, suivie sur #20174) : le catalogue commite est lu, mais aucun des carnets qu'il liste n'existe sur le disque, donc targets == []. Sur un arbre sain, c'est impossible — le catalogue absent fait basculer sur rglob("*.ipynb"), qui rend des centaines de carnets.

Le cout est un cycle de diagnostic par lane : le rouge est indiscernable d'un defaut de contenu. Une lane qui ne rejoue pas l'organe en local conclut a tort que son carnet est casse, corrige un diff qui n'a rien, ou re-diagnostique la meme cause que ses voisines.

Proposition de correction (minimale, deux fichiers)

  1. check_c2_compliance.py — en mode --json, toujours emettre du JSON. Cible vide -> []. Le contrat est verifie par un test.
  2. notebook-validation.yml — traiter la cible vide comme une erreur explicite et nommee, jamais comme un succes : quand len(results) == 0, sortir en 1 avec un message qui dit la cause probable (checkout incomplet : le catalogue liste N carnets, aucun n'est present sur le disque).

Le point 2 est indispensable : sans lui, le point 1 masque le defaut d'environnement ([] -> 0 notebooks, 0 cells -> le else du workflow imprime « All notebooks C.2 compliant. »). Le contrat JSON et la distinction vide/panne sont les deux moities de la meme correction, et aucune ne doit partir seule.

Criteres d'acceptation

  • python scripts/notebook_tools/check_c2_compliance.py --json sur une cible vide rend une sortie parseable (rc a definir explicitement, et ce choix teste).
  • Un test couvre le cas « cible vide » et affirme le contrat JSON.
  • Le workflow notebook-validation rougit sur cible vide avec un message qui nomme la cause probable, et ne peut plus presenter ce cas comme un succes.
  • Aucun changement de verdict sur une cible non vide (non-regression : le comportement nominal est inchange).

Contexte de decouverte

Remonte par la lane myia-po-2023:CoursIA-2 (cycle c.1241) en drainant sa file de reparation P0. Le diagnostic complet et les cinq organes mesures a la tete exacte sont sur #19590 (commentaire 6092628798), et l'escalade fleet est sur le dashboard global, avec la cause racine chez #20174.

Activity

  1. jsboige commented on Oct 10, 2026

    @jsboige
    OwnerAuthor

    [CLAIMED] lane myia-po-2023:CoursIA-2 -- fix du contrat --json du scanner C.2 sur cible vide + erreur nommee dans le workflow (2 fichiers, tests)

  2. jsboige commented on Oct 10, 2026

    @jsboige
    OwnerAuthor

    [INFO] lane myia-po-2023:CoursIA-2 — correction livree en branche feature/20198-c2-json-empty-target (commit d9b7947766), PR differee au lever du plafond WIP de la lane (27/15, consigne coordinateur).

    • check_c2_compliance.py : en --json, cible vide -> [] parseable, rc 0 explicite (le vide est un resultat de scan valide ; la distinction vide/panne appartient a l'appelant).
    • notebook-validation.yml : liste vide apres parse = ::error:: nomme (checkout incomplet : le scanner n'a trouve AUCUN carnet (catalogue lu mais fichiers absents du disque ?)) et exit 1 — le cas ne peut plus s'afficher « All notebooks C.2 compliant. ».
    • Tests : 3 nouveaux (contrat JSON vide, message humain inchange, non-regression cible non vide) — suite 65 passed.
    • Simulation des deux branches du workflow : cible vide -> scanner rc=0 + [], le garde rend 0 => le bloc sort en 1 avec l'erreur nommee ; cible reelle (1 carnet) -> garde rend 1 => verdict C.2 normal inchange.
    • YAML du workflow re-valide (yaml.safe_load OK) ; diff : 3 fichiers, +56/-1.
  3. added a commit that references this issue on Oct 11, 2026
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