diff --git a/.github/workflows/arxiv-attributions-guard.yml b/.github/workflows/arxiv-attributions-guard.yml index 93d7564b0c..f40ab7b354 100644 --- a/.github/workflows/arxiv-attributions-guard.yml +++ b/.github/workflows/arxiv-attributions-guard.yml @@ -25,7 +25,11 @@ name: arXiv attributions guard # Le filtre de chemins ne fait qu'éviter des runs inutiles : registry / # script / tests / workflow (self-cover #8822) + les notebooks enregistrés. # Une entrée NOUVELLE passe par le registre (dans paths) donc déclenche son -# propre contrôle. Le nocturne 03:47 UTC est le filet : un rename dont le +# propre contrôle -- mais son NOTEBOOK doit aussi entrer dans paths, sinon +# une PR qui ne touche que ce notebook esquive la garde : mesure 2026-09-29, +# #18320 a décalé les cellules d'ICT-37 (passe 6, #17622) sans déclencher ce +# workflow, et main est resté rouge jusqu'à #18343. La couverture est tenue par +# test_workflow_paths_cover_every_registry_notebook. Le nocturne 03:47 UTC est le filet : un rename dont le # diff ne montre que le nouveau chemin esquive le filtre per-PR ; la sweep # suivante le voit (RENAMED/FAIL) sur main. # @@ -41,6 +45,10 @@ on: - 'scripts/tests/test_check_arxiv_attributions.py' - '.github/workflows/arxiv-attributions-guard.yml' - 'MyIA.AI.Notebooks/GameTheory/GameTheory-13b-Safe-Subgame-Solving-Python.ipynb' + - 'MyIA.AI.Notebooks/GenAI/PostTraining/PT_15_controle_interpretabilite.ipynb' + - 'MyIA.AI.Notebooks/GenAI/PostTraining/PT_16_vericoding_formal_verification.ipynb' + - 'MyIA.AI.Notebooks/IIT/ICT-Series/ICT-37-FLens-BeliefState.ipynb' + - 'MyIA.AI.Notebooks/ML/DataScienceWithAgents/02-ML-Cours/2.9d-Features-Circulaires-Helice-Nombres.ipynb' - 'MyIA.AI.Notebooks/ML/DataScienceWithAgents/03-DeepLearning/3.5-Phenomenes-de-Generalisation.ipynb' - 'MyIA.AI.Notebooks/ML/DataScienceWithAgents/Track2-GoogleADK/Day4-Foundations/Lab8-ADK-Introduction.ipynb' - 'MyIA.AI.Notebooks/QuantConnect/ML-Training-Pipeline/research_l4_decision_transformer.ipynb' diff --git a/scripts/tests/test_check_arxiv_attributions.py b/scripts/tests/test_check_arxiv_attributions.py index 6d06684433..12207831cb 100644 --- a/scripts/tests/test_check_arxiv_attributions.py +++ b/scripts/tests/test_check_arxiv_attributions.py @@ -600,3 +600,37 @@ def test_real_registry_lives_against_main_repo() -> None: ) # Exit code 0 (tout PASS en mode strict) assert result.returncode == 0 + + +def test_workflow_paths_cover_every_registry_notebook() -> None: + """Chaque notebook du registre REEL figure dans le filtre `paths:` de + `arxiv-attributions-guard.yml`. + + Sans cela, une PR qui ne modifie qu'un notebook enregistre (cellules + inserees, citation reecrite) n'active pas la garde bloquante : la derive + n'apparait qu'apres merge, sur main. Mesure fondatrice (2026-09-29) : + #18320 a decale les cellules d'ICT-37, ajoute au registre par la passe 6 + (#17622) sans que le filtre suive ; main est reste rouge sur Scripts Tests + jusqu'a #18343. + """ + import yaml + + real_reg = REPO_ROOT / "arxiv_attributions_registry.yaml" + workflow = REPO_ROOT / ".github" / "workflows" / "arxiv-attributions-guard.yml" + if not real_reg.exists() or not workflow.exists(): + pytest.skip("Registre ou workflow absent") + + with real_reg.open(encoding="utf-8") as f: + entries = yaml.safe_load(f).get("attributions", []) + with workflow.open(encoding="utf-8") as f: + wf = yaml.safe_load(f) + # PyYAML lit la cle `on` comme le booleen True. + triggers = wf.get("on", wf.get(True, {})) + paths = set(triggers["pull_request"]["paths"]) + + missing = sorted({e["notebook"] for e in entries} - paths) + assert not missing, ( + "Notebooks du registre absents du filtre paths: de " + f"arxiv-attributions-guard.yml : {missing}. Les ajouter au filtre, " + "sinon une PR qui ne touche que ces notebooks esquive la garde." + )