Skip to content
27 changes: 15 additions & 12 deletions .github/workflows/always-on-metadata-guards.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
17 changes: 16 additions & 1 deletion .github/workflows/enrich-quality-gate.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
44 changes: 36 additions & 8 deletions .github/workflows/notebook-execution-required.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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 }}
Expand Down Expand Up @@ -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
Expand Down
16 changes: 15 additions & 1 deletion .github/workflows/notebook-validation.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
10 changes: 9 additions & 1 deletion .github/workflows/quarto-render-list-freshness.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
28 changes: 28 additions & 0 deletions scripts/ci/check_self_hosted_runner_policy.py
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
Loading