diff --git a/.github/workflows/always-on-metadata-guards.yml b/.github/workflows/always-on-metadata-guards.yml index f8dd754e0a7..7278037df92 100644 --- a/.github/workflows/always-on-metadata-guards.yml +++ b/.github/workflows/always-on-metadata-guards.yml @@ -78,28 +78,31 @@ jobs: always-on-metadata-guards: name: "Always-on metadata guards -- 3 organes, 1 checkout" # Routage #14283 tranche 3c (ai-01 2026-09-02) : jambe Linux auto-hebergee. - # Garde anti-fork au niveau job + runs-on STATIQUE (une expression leverait - # DYNAMIC_RUNS_ON dans check_self_hosted_runner_policy.py). - # Retour arriere = remettre `runs-on: ubuntu-latest` + retrait de l'allowlist. + # Garde anti-fork au niveau job + runs-on sous la FORME HYBRIDE AUDITEE + # (une expression non auditee leverait DYNAMIC_RUNS_ON dans + # check_self_hosted_runner_policy.py). # Rapatrie sur l'offre GitHub le 2026-10-25 (#17397, consigne user : le CI local pallie # les limites de l'offre hebergee, il ne la remplace pas). Mesure : 3 jobs heberges en # cours pour un plafond d'environ 20, 42 jobs sur 42 en file sur coursia-linux. # L'entree reste dans SELF_HOSTED_WORKFLOW_ALLOWLIST : retour = remettre le label. - # - # #22937 (volet (d), 2026-10-28) : la garde REJOINT LA COHORTE -- forme - # hybride auditee de `check_self_hosted_runner_policy.py` (#22461) : - # PR meme-depot ET `vars.CI_OVERFLOW_LOCAL == 'true'` -> jambe Linux - # locale ; tout le reste (fork, variable absente ou fausse, - # `workflow_dispatch`) retombe sur `ubuntu-latest`. La garde same-repo - # reste en place au niveau job (elle ne gene pas la forme hybride : - # l'organe ne l'exige plus pour une jambe hybride, il ne l'interdit pas). + # #22937 (forme hybride, phase A puis vague 2 ; 2026-10-27 puis + # 2026-10-28) : PR meme-depot ET `vars.CI_OVERFLOW_LOCAL == 'true'` -> + # jambe Linux locale ; tout le reste (variable absente ou fausse, + # forks, push/schedule/dispatch) retombe sur `ubuntu-latest`. La garde + # same-repo reste en place au niveau job (elle ne gene pas la forme + # hybride : l'organe ne l'exige plus pour une jambe hybride, il ne + # l'interdit pas). # Ce qui a change depuis le retour arriere du 25/10 (#17397) : le # checkout sur le parc local ne coute plus 80-148 s mais **3,9 s** # (volume `_work` persistant par slot, #14285, remesure du 18/10 : le # checkout local est plus rapide que l'heberge a 40-51 s). La saturation # du parc local par les checkouts, qui motivait le retour arriere, a # donc disparu. - # Retour arriere = remettre `runs-on: ubuntu-latest`. + # Bascule : `gh variable set CI_OVERFLOW_LOCAL --body true|false --repo + # jsboige/CoursIA`. Retour arriere = variable a `false` ou supprimee : + # routage 100 % heberge, sans toucher ce fichier. + # Limite : runs-on se resout a la creation du job, les runs deja en + # file ne bougent pas. runs-on: ${{ (github.event.pull_request.head.repo.full_name == github.repository && vars.CI_OVERFLOW_LOCAL == 'true') && fromJSON('["self-hosted","coursia-ephemeral","coursia-linux"]') || 'ubuntu-latest' }} if: github.event.pull_request.head.repo.full_name == null || github.event.pull_request.head.repo.full_name == github.repository timeout-minutes: 10 diff --git a/.github/workflows/enrich-quality-gate.yml b/.github/workflows/enrich-quality-gate.yml index c2e255ae7bd..ca5324f2ca0 100644 --- a/.github/workflows/enrich-quality-gate.yml +++ b/.github/workflows/enrich-quality-gate.yml @@ -56,7 +56,22 @@ permissions: jobs: enrich-quality: name: "No enrich-quality regression in changed notebooks" - runs-on: ubuntu-latest + # 2026-10-27 (#22937 vague 2, phase A) : forme hybride de debordement -- + # PR meme-depot ET vars.CI_OVERFLOW_LOCAL == 'true' -> jambe Linux locale ; + # tout le reste (variable absente ou fausse, forks, push/schedule/ + # dispatch) retombe sur ubuntu-latest (l'etat du 27/10). Bascule : + # `gh variable set CI_OVERFLOW_LOCAL --body true|false --repo jsboige/CoursIA`. + # Retour arriere = variable a `false` ou supprimee : routage 100 % + # heberge, sans toucher ce fichier. Limite : runs-on se resout a la + # creation du job, les runs deja en file ne bougent pas. + runs-on: ${{ (github.event.pull_request.head.repo.full_name == github.repository && vars.CI_OVERFLOW_LOCAL == 'true') && fromJSON('["self-hosted","coursia-ephemeral","coursia-linux"]') || 'ubuntu-latest' }} + + # Borne de duree (#23016, review 5677732011) : sans `timeout-minutes`, un + # job herite de 360 min et peut figer un slot ephemere du parc local -- + # 16 slots sur 18 ont ete tenus pendant des heures le 15/10. La borne vaut + # ~3x la duree mesuree (0-1 min sur les 8 derniers succes), plus la marge + # d'un clone froid. + timeout-minutes: 10 steps: - name: Checkout diff --git a/.github/workflows/notebook-execution-required.yml b/.github/workflows/notebook-execution-required.yml index 6792895c55c..7ddd45cd6dd 100644 --- a/.github/workflows/notebook-execution-required.yml +++ b/.github/workflows/notebook-execution-required.yml @@ -53,12 +53,26 @@ jobs: detect-changes: name: Detect notebook changes # Routage #14283 tranche 3c (ai-01 2026-09-02) : jambe Linux auto-hebergee. - # Garde anti-fork au niveau job + runs-on STATIQUE (une expression leverait - # DYNAMIC_RUNS_ON dans check_self_hosted_runner_policy.py). - # Retour arriere = remettre `runs-on: ubuntu-latest` + retrait de l'allowlist. + # Garde anti-fork au niveau job + runs-on sous la FORME HYBRIDE AUDITEE + # (une expression non auditee leverait DYNAMIC_RUNS_ON dans + # check_self_hosted_runner_policy.py). # Offre GitHub d'abord (#17397, consigne user du 2026-10-25) : le CI local pallie ses limites. Retour = remettre le label. - runs-on: ubuntu-latest + # 2026-10-27 (#22937 vague 2, phase A) : forme hybride de debordement -- + # PR meme-depot ET vars.CI_OVERFLOW_LOCAL == 'true' -> jambe Linux locale ; + # tout le reste (variable absente ou fausse, forks, push/schedule/ + # dispatch) retombe sur ubuntu-latest (l'etat du 27/10). Bascule : + # `gh variable set CI_OVERFLOW_LOCAL --body true|false --repo jsboige/CoursIA`. + # Retour arriere = variable a `false` ou supprimee : routage 100 % + # heberge, sans toucher ce fichier. Limite : runs-on se resout a la + # creation du job, les runs deja en file ne bougent pas. + runs-on: ${{ (github.event.pull_request.head.repo.full_name == github.repository && vars.CI_OVERFLOW_LOCAL == 'true') && fromJSON('["self-hosted","coursia-ephemeral","coursia-linux"]') || 'ubuntu-latest' }} if: github.event.pull_request.head.repo.full_name == null || github.event.pull_request.head.repo.full_name == github.repository + # Borne de duree (#23016, review 5677732011) : sans `timeout-minutes`, un + # job herite de 360 min et peut figer un slot ephemere du parc local -- + # 16 slots sur 18 ont ete tenus pendant des heures le 15/10. La borne vaut + # ~3x la duree mesuree (0-1 min sur les 8 derniers succes), plus la marge + # d'un clone froid. + timeout-minutes: 5 outputs: notebooks: ${{ steps.detect.outputs.notebooks }} has_notebooks: ${{ steps.detect.outputs.has_notebooks }} @@ -98,13 +112,27 @@ jobs: validate-static: name: Static validation (H.1/H.3/C.1) # Routage #14283 tranche 3c (ai-01 2026-09-02) : jambe Linux auto-hebergee. - # Garde anti-fork au niveau job + runs-on STATIQUE (une expression leverait - # DYNAMIC_RUNS_ON dans check_self_hosted_runner_policy.py). - # Retour arriere = remettre `runs-on: ubuntu-latest` + retrait de l'allowlist. + # Garde anti-fork au niveau job + runs-on sous la FORME HYBRIDE AUDITEE + # (une expression non auditee leverait DYNAMIC_RUNS_ON dans + # check_self_hosted_runner_policy.py). # Offre GitHub d'abord (#17397, consigne user du 2026-10-25) : le CI local pallie ses limites. Retour = remettre le label. - runs-on: ubuntu-latest + # 2026-10-27 (#22937 vague 2, phase A) : forme hybride de debordement -- + # PR meme-depot ET vars.CI_OVERFLOW_LOCAL == 'true' -> jambe Linux locale ; + # tout le reste (variable absente ou fausse, forks, push/schedule/ + # dispatch) retombe sur ubuntu-latest (l'etat du 27/10). Bascule : + # `gh variable set CI_OVERFLOW_LOCAL --body true|false --repo jsboige/CoursIA`. + # Retour arriere = variable a `false` ou supprimee : routage 100 % + # heberge, sans toucher ce fichier. Limite : runs-on se resout a la + # creation du job, les runs deja en file ne bougent pas. + runs-on: ${{ (github.event.pull_request.head.repo.full_name == github.repository && vars.CI_OVERFLOW_LOCAL == 'true') && fromJSON('["self-hosted","coursia-ephemeral","coursia-linux"]') || 'ubuntu-latest' }} needs: detect-changes if: (github.event.pull_request.head.repo.full_name == null || github.event.pull_request.head.repo.full_name == github.repository) && needs.detect-changes.outputs.has_notebooks > 0 + # Borne de duree (#23016, review 5677732011) : sans `timeout-minutes`, un + # job herite de 360 min et peut figer un slot ephemere du parc local -- + # 16 slots sur 18 ont ete tenus pendant des heures le 15/10. La borne vaut + # ~3x la duree mesuree (1 min sur les 8 derniers succes), plus la marge + # d'un clone froid. + timeout-minutes: 10 steps: - uses: actions/checkout@v4 diff --git a/.github/workflows/notebook-validation.yml b/.github/workflows/notebook-validation.yml index c1bf971930c..e9b54f73548 100644 --- a/.github/workflows/notebook-validation.yml +++ b/.github/workflows/notebook-validation.yml @@ -28,8 +28,22 @@ jobs: # saute les PRs de fork (pr_gate.py compte `skipped` comme OK) : aucun code de # fork n'atteint le runner. Retour arriere = revert de la PR. # Offre GitHub d'abord (#17397, consigne user du 2026-10-25) : le CI local pallie ses limites. Retour = remettre le label. - runs-on: ubuntu-latest + # 2026-10-27 (#22937 vague 2, phase A) : forme hybride de debordement -- + # PR meme-depot ET vars.CI_OVERFLOW_LOCAL == 'true' -> jambe Linux locale ; + # tout le reste (variable absente ou fausse, forks, push/schedule/ + # dispatch) retombe sur ubuntu-latest (l'etat du 27/10). Bascule : + # `gh variable set CI_OVERFLOW_LOCAL --body true|false --repo jsboige/CoursIA`. + # Retour arriere = variable a `false` ou supprimee : routage 100 % + # heberge, sans toucher ce fichier. Limite : runs-on se resout a la + # creation du job, les runs deja en file ne bougent pas. + runs-on: ${{ (github.event.pull_request.head.repo.full_name == github.repository && vars.CI_OVERFLOW_LOCAL == 'true') && fromJSON('["self-hosted","coursia-ephemeral","coursia-linux"]') || 'ubuntu-latest' }} if: github.event.pull_request.head.repo.full_name == null || github.event.pull_request.head.repo.full_name == github.repository + # Borne de duree (#23016, review 5677732011) : sans `timeout-minutes`, un + # job herite de 360 min et peut figer un slot ephemere du parc local -- + # 16 slots sur 18 ont ete tenus pendant des heures le 15/10. La borne vaut + # ~3x la duree mesuree (4-6 min sur les 8 derniers succes), plus la marge + # d'un clone froid. + timeout-minutes: 20 steps: - uses: actions/checkout@v4 diff --git a/.github/workflows/quarto-render-list-freshness.yml b/.github/workflows/quarto-render-list-freshness.yml index a9b93a692f0..5ec166f361b 100644 --- a/.github/workflows/quarto-render-list-freshness.yml +++ b/.github/workflows/quarto-render-list-freshness.yml @@ -77,7 +77,15 @@ jobs: # regeneration de _quarto.yml -- exactement le conflit que ce garde veut # eteindre (arbitrage ai-01, review 5469480925 sur #19901). name: _quarto.yml render list freshness (advisory) - runs-on: ubuntu-latest + # 2026-10-27 (#22937 vague 2, phase A) : forme hybride de debordement -- + # PR meme-depot ET vars.CI_OVERFLOW_LOCAL == 'true' -> jambe Linux locale ; + # tout le reste (variable absente ou fausse, forks, push/schedule/ + # dispatch) retombe sur ubuntu-latest (l'etat du 27/10). Bascule : + # `gh variable set CI_OVERFLOW_LOCAL --body true|false --repo jsboige/CoursIA`. + # Retour arriere = variable a `false` ou supprimee : routage 100 % + # heberge, sans toucher ce fichier. Limite : runs-on se resout a la + # creation du job, les runs deja en file ne bougent pas. + runs-on: ${{ (github.event.pull_request.head.repo.full_name == github.repository && vars.CI_OVERFLOW_LOCAL == 'true') && fromJSON('["self-hosted","coursia-ephemeral","coursia-linux"]') || 'ubuntu-latest' }} timeout-minutes: 5 steps: - name: Checkout diff --git a/scripts/ci/check_self_hosted_runner_policy.py b/scripts/ci/check_self_hosted_runner_policy.py index 438bf7d320c..cd204d2bb05 100644 --- a/scripts/ci/check_self_hosted_runner_policy.py +++ b/scripts/ci/check_self_hosted_runner_policy.py @@ -648,6 +648,34 @@ "translation-drift.yml", "twin-parity.yml", "unique-check-run-names-guard.yml", + # 2026-10-27 (#22937 vague 2, lane myia-ai-01:CoursIA-2) : meme forme + # hybride de debordement que la phase A (#22461), appliquee aux + # workflows a fort volume qui n'etaient PAS dans la phase A. + # Les trois autres fichiers de la vague 2 + # (notebook-execution-required.yml, always-on-metadata-guards.yml, + # notebook-validation.yml) sont deja dans l'allowlist -- ils y etaient + # depuis la tranche 3c (#14283), avant leur deport Q35 du 27/10. + # `twin-parity.yml` y est aussi, mais il est porte par une PR + # dediee (#22944) : les deux PRs ne peuvent pas toucher le meme + # workflow, et le perimetre accorde est « 5 workflows par volume + # decroissant ». + # Perimetre : 5 workflows, 6 jobs. Exclus, avec leur motif : + # - codeql.yml : le setup par defaut de GitHub-heberge le job, la + # ligne `runs-on` du fichier n'est pas honoree ; + # - lean-ci-matrix.yml : la toolchain Lean vit dans une image distincte + # (label `coursia-lean`), pas dans le pool `coursia-linux` ; + # - local-path-waiver-guard.yml et perimeter-review-guard.yml : + # declencheurs `issue_comment` et `pull_request_review`, classes + # FORK_REACHABLE par l'instrument (default-deny) ; + # - les deux starvation-advisory : un chien de garde de la file ne + # doit pas occuper la file qu'il observe ; + # - ict-tests.yml : venv + pyphi/numpy/scipy, 8,1 min medianes -- le + # debordement absorbe d'abord les jobs courts ; + # - quarto-pages-deploy.yml : `build` et `deploy` dependent du + # service GitHub Pages (upload-pages-artifact, deploy-pages + OIDC) ; + # seul `validate-pr` est portable (Quarto par tarball curl). + "quarto-render-list-freshness.yml", + "enrich-quality-gate.yml", } GITHUB_HOSTED_LABELS = { "ubuntu-latest",