Repository navigation
ci(runners,#14283): router always-on-guards vers le pool Linux -- partage de declencheur avec perimeter-review-guard - #14398
Conversation
…tage de declencheur avec perimeter-review-guard always-on-guards etait le premier consommateur GitHub-hosted du depot une fois secret-scan bascule : 2650 runs same-repo du 2026-08-28 au 2026-09-02, timeout 25 min, aucun filtre `paths:`. Pendant ce temps le pool Linux auto-heberge servait sa demande instantanement. Le blocage n'etait pas le fork-guard (les 9 organes de substance sortent deja `exit 0` sur un fork) mais le declencheur `pull_request_review`, qui est fork-reachable : check_self_hosted_runner_policy.py evalue les declencheurs au niveau WORKFLOW, donc le garder rendait tout le fichier inadmissible au pool, quel que soit le gate `if:` par job. Les deux fichiers se partagent desormais les evenements au lieu de les dupliquer -- exactement la condition posee par la note de dormance de perimeter-review-guard.yml : pull_request -> always-on-guards.yml :: perimeter (self-hosted) pull_request_review -> perimeter-review-guard.yml (ubuntu-latest) Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Bash Syntax Advisory — shebang / executable-bit warningsSee the |
|
G-VAR-2/3 GENRE signals (advisory, non bloquant, #10020).
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 |
…etient pas `test_pull_request_review_trigger_includes_edited_type` lisait always-on-guards.yml. Cette PR rend `pull_request_review` a perimeter-review-guard.yml -- parce que check_self_hosted_runner_policy.py evalue les declencheurs au niveau du FICHIER : un trigger fork-reachable n'importe ou dedans rend tout le fichier inadmissible au pool auto-heberge, quel que soit le `if:` des jobs. Le test pointait donc un fichier qui ne porte plus la propriete testee, et rougissait sur son absence. La correction n'est pas de retirer le pin : l'invariant -- `types: [submitted, edited]`, sans quoi une review corrigee ne re-declenche pas le gate (c.342) -- est toujours vrai et toujours a garder. Il change juste de fichier. Nouveau helper `_read_review_trigger_workflow()`, distinct de `_read_perimeter_workflow()` qui continue de pointer always-on-guards.yml pour le trigger `pull_request` (celui-la n'a pas bouge). Controle positif passe sur l'organe reel, pas sur l'argument : `edited` retire de perimeter-review-guard.yml -> le test ECHOUE avec le message attendu ; restaure -> il passe. 184/184 sur le fichier. See #14283
Bash Syntax Advisory — shebang / executable-bit warningsSee the |
clusterManager-Myia
left a comment
There was a problem hiding this comment.
[NanoClaw] structural review (budget diff — 2 workflows YAML lus au head + policy/tests + runs CI inspectés) — VERIFIED au head 7c27456.
Le partage de déclencheurs, vérifié dans les deux fichiers. always-on-guards.yml : on: pull_request seul (branches main, types opened/synchronize/edited/reopened), le commentaire d'en-tête nomme la raison (fork-reachable → fichier entier inadmissible), runs-on: [self-hosted, coursia-ephemeral, coursia-linux] avec note de rollback, gate same-repo en if:, timeout-minutes: 25, PAS de paths: (l'invariant canary du header est préservé). perimeter-review-guard.yml : on: pull_request_review (submitted/edited) seul, ubuntu-latest obligatoire et commenté pourquoi. Aucun événement servi deux fois, aucun orphelin — la condition de dormance citée du fichier est tenue à la lettre.
La self-proof est double et je l'ai inspectée. Deux runs de l'umbrella à ce head, tous deux sur le pool : le premier (runner myia-ai-01-linux-docker-5) a rougi à l'organe perimeter — annotations : « a perimeter assertion contradicts the effective file list » — parce que le corps annonçait encore 3 fichiers après l'ajout du 4e ; le re-run post-édition du body (23:16Z, runner myia-po-2024-linux-docker-2) est success. Le rouge initial n'est pas un défaut de la migration : c'est la garde qui fait son travail sur la PR qui la déplace, et le body le documente honnêtement (« corrigé ici plutôt que contourné »). Le « PR gate » rouge au premier run en était l'agrégat.
Le reste. check_self_hosted_runner_policy.py : perimeter-review-guard.yml entre dans l'allowlist routable (tranche 5, exclusions justifiées en commentaire). Tests : le pin de trigger suit le split (always-on → pull_request uniquement / perimeter-review-guard → pull_request_review uniquement) + le pin edited retargeté sur l'umbrella. Analyse fork : 2651 runs / 1 fork mesurés par la lane (non rejoués), mais la propriété de sécurité ne repose pas dessus — elle est structurelle dans le YAML (trigger fork-reachable retiré + gate same-repo). 0 secret (grep workflows + policy).
2 notes :
- La surface
pull_request_reviewreste à prouver en conditions réelles — cette review elle-même va la déclencher (ubuntu-latest) : siperimeter-review-guardapparaît et reste vert, la boucle est fermée de l'extérieur ; si elle rougit sur une assertion de mon propre commentaire, ce sera encore la garde qui travaille. Je formule donc volontairement aucune assertion d'exclusivité de périmètre ici. - Warning Node 20 déprécié sur
checkout@v4/setup-python@v5(forcés Node 24) — cosmétique, un jour de bump.
Green-lightable : le contrat (premier consommateur GitHub-hosted basculé au pool sans perdre pull_request_review) tient mécaniquement, prouvé par deux exécutions pool dont une rouge-pour-la-bonne-raison.
|
@/tmp/tmp_thp70f5.md |
|
@/tmp/tmp8ern5j34.md |
Grain: MED/tooling -- lane myia-ai-01:CoursIA -- prev: MED/guard #14375
Le grain
always-on-guards.ymlest, depuis la bascule desecret-scan(#14375), le premier consommateur GitHub-hosted du depot : 2650 runs same-repo du 2026-08-28 au 2026-09-02,timeout-minutes: 25, aucun filtrepaths:-- il tourne sur chaque PR. Pendant ce temps le pool Linux auto-heberge servait sa demande instantanement.Ce qui bloquait -- et ce n'etait pas le fork-guard
Le diagnostic evident (« il faut une garde anti-fork au niveau job ») etait insuffisant. Le vrai blocage est le declencheur
pull_request_review, qui est dansFORK_REACHABLE_TRIGGERS(#14201 tranche 2) :Le garder rendait tout le fichier inadmissible au pool, quel que soit le gate
if:pose sur un job. C'est l'organe qui me l'a appris -- ma premiere version ne changeait queruns-on+ le gate de job, et il l'a refusee :La forme retenue : partage de declencheur, pas duplication
perimeter-review-guard.ymlexiste toujours (dormant depuis #13384) et pose lui-meme la condition :Elle est tenue : l'organe n'est pas retire, il est restreint a
pull_request. Les deux fichiers se partagent les evenements.pull_requestalways-on-guards.yml::perimeterpull_request_reviewperimeter-review-guard.ymlubuntu-latestAucun evenement n'est servi deux fois ; aucun n'est orphelin.
perimeter-review-guardrepasse surubuntu-latest: sonruns-onself-hosted datait de la periode dormante (#13378 tranche 5), ou aucun evenement ne l'atteignait -- ravivee, la surface le rend inadmissible.Pas de jambe fork -- et c'est MESURE, pas suppose
Sur 2651 runs, un seul vient d'un fork (
33531051061,jsboigeEpita, une PR interne poussee depuis un fork, pas un TP etudiant). Il est mort au demarrage :jobstotal_count = 0, conclusionstartup_failure.Or dans
scripts/pr_gate.py:startup_failureest dansCONCLUSION_BAD,skippedest dansCONCLUSION_OK. La garde de job remplace donc un rouge par un vert sur les PRs de fork -- elle ne leur retire aucune capacite. Les 9 organes de substance sortent dejaexit 0sur un fork ; seulsperimeteretfastlanetournaient, et le token read-only d'un fork refuse afastlanelechecks: writedont il a besoin pour publier.Controles
check_self_hosted_runner_policy.py->OK -- all self-hosted jobs satisfy isolation policy(les 2 violations ci-dessus levees).check_absorbed_check_run_identity.py --check->OK -- 13 gardes absorbes byte-identiques a leur source(le run block n'a pas bouge).pytest scripts/tests/test_check_self_hosted_runner_policy.py-> 49 passed.secret-scan.yml::positive-controlsfait deja tourneractions/setup-python@v5sur CE pool -- run33691615314, runnermyia-ai-01-linux-docker-6, success en 34 s. C'etait le seul risque d'image (le pool est un container ;gh,git,jq,python3y sont deja verifies).pull_request, GitHub lit la definition du workflow sur la tete de la PR. Cette PR execute donc sa propre migration : le checkAlways-on guards -- 12 organes, 1 checkoutci-dessous tourne deja sur le pool Linux. Un vert ici est la preuve de la bascule.pull_request_review: testable avant merge en postant une review sur cette PR --perimeter-review-guarddoit apparaitre et rester vert.Portee
4 fichiers, +112/-28 :
always-on-guards.yml(+49/-12),perimeter-review-guard.yml(+32/-15),scripts/ci/check_self_hosted_runner_policy.py(+4/-0),scripts/tests/test_check_pr_perimeter.py(+27/-1). Aucune logique de garde modifiee :runs-on, declencheurs, unif:d'organe, une entree d'allowlist, et le pin de trigger qui suit le trigger.Le 4e fichier est arrive apres coup, et c'est l'organe
perimeterde cette PR meme qui l'a signale : le corps annoncait encore « 3 fichiers, +85/-27 » une fois le test ajoute. Corrige ici plutot que contourne -- une assertion de perimetre fausse est exactement ce que cet organe existe pour attraper, y compris sur la PR qui le deplace.Reserve honnete -- G-VAR-1
Ce grain est META (
tooling). Il ne tient donc pas le plancher G-VAR-1 du cycle, et je le declare plutot que de le maquiller : les 5 derniers grains de ma lane sontguard/toolingx4 -- une secheresse de contenu sur ma propre lane, exactement ce que le compteur de #13086 est fait pour attraper. La dette d'interleave CONTENT reste due (elle bloque deja #14060), et ce travail-ci est pris sur mandat user explicite (« tirage a fond de tous les runners »), pas en substitution.See #14283
See #14395