Skip to content

CI routing : 32 des 124 workflows self-hosted n'ont AUCUN besoin local, dont pr-gate — un gate ne doit pas dependre du parc qu'il mesure #17397

Description

@myia-ai-01

Mandat

Arbitrage user du 2026-09-22, verbatim : « Mon mandat, c'est d'équilibrer pour l'efficacité maximale (en se posant la question de quelle lane à quel endroit pour que le CI soit le plus performant et robuste) ».

Et la correction qui l'accompagne : le « mandat de consommer les runs conteneurisés » n'est pas un mandat user. Voir la section « Attribution fabriquée » plus bas.

Mesure

124 workflows ciblent self-hosted. Classés par ce dont ils ont réellement besoin (grep sur secrets.*, docker, cuda|gpu, lake|elan|mathlib, dotnet, papermill|jupyter|.ipynb, conda, wsl) :

workflows
au moins un besoin local 92
aucun besoin local détecté 32

Raisons de rester self-hosted, par fréquence : notebook 61 · secrets 36 · lean 11 · docker 8 · dotnet 8 · wsl 4 · gpu 4 · conda 3.

Les 32 sans besoin local

adjacency-stale-sweep · catalog-cron · check-resync-only · concurrency-conj-guard · docs-link-check · exercise-leak-ci · fast-lane-shadow · harness-coauthor-guard · hooks-parity · ict-tests-profile · label-paths-guard · linux-runner-version-pin-advisory · machine-dep-timing-inventory · manifest-description-visuelle-gate · owui-playwright-check · perimeter-review-guard · pr-gate-rerun · pr-gate-sweep-health-advisory · pr-gate · pr-path-collision-advisory · qc-research-monitor · repeated-prose-advisory · repo-size-advisory · series-naming-gate · slides-composition-pr-relay · slow-lane · split-reading-advisory · stale-guard-red-sweep · testpaths-coverage-guard · translation-hot-drift-advisory · twin-parity-drift-audit · workflow-path-filter-audit

L'argument de robustesse, qui pèse plus que celui de capacité

pr-gate.yml n'a aucun besoin local, et c'est l'organe qui décide si une PR est mergeable. Il tourne aujourd'hui sur le parc dont il est censé rapporter l'état.

Conséquence mesurée sur le cycle du 2026-09-22 : sur 80 candidates, 27 refusées pour rouge CI, et PR gate figure parmi les checks fautifs d'une vingtaine d'entre elles — alors que la cause était la saturation du parc. Quand le parc dégrade, l'organe qui le mesure dégrade en même temps, et la file qu'il devrait débloquer grossit exactement au moment où il en est le moins capable.

Le même fichier pr-gate-stale-sweep.yml le décrit déjà, sans en tirer la conséquence : « the waiters are held by the aggregators this sweep must unblock ». Le pool coursia-waiter — 28 slots (16 ai-01 + 12 po-2024) — existe presque uniquement pour héberger ces agrégateurs en long-poll, chacun occupant un slot 9 à 12 minutes pour interroger une API.

Sur ai-01, ces 16 waiters pèsent 16 processus Runner.Listener et 4 des 24 vCPU du budget CI — exactement la marge qui manque (cf. #17390 et la mesure de capacité : 24 demandés contre 24 accordés, zéro marge).

Principe proposé

Un job va sur self-hosted uniquement s'il a besoin de quelque chose qui n'existe que là. Tout le reste va sur GitHub-hosted. Et les organes qui gatent un merge y vont par exigence de robustesse, pas seulement de capacité : un gate ne doit pas dépendre du parc qu'il mesure.

Ce principe ne coupe aucune capacité. Il libère du self-hosted pour ce qui en a un besoin réel — notebooks, secrets, Lean, .NET, GPU — et rend les gates immunisés à la saturation locale.

Attribution fabriquée à corriger

pr-gate-stale-sweep.yml:116 porte : # GitHub-hosted stays out (mandat: consume the containerized runs; #12728.

Vérifié firsthand : #12728 ne contient ni le mot « mandat », ni « containerized », ni « hosted », ni dans son body ni dans ses commentaires. Elle argumente même l'inverse en esprit — router un workflow précis vers self-hosted pour fuir la file GitHub contendue de l'époque, en notant que « contre-intuitivement, ce ne sont pas les suites lourdes qu'il faut migrer en premier : ce sont les petits jobs fréquents dont la valeur s'effondre avec le délai ».

Deux défauts distincts, et le second est le plus coûteux :

  1. un arbitrage lié à une mesure s'est durci en « mandat » ;
  2. la prémisse s'est inversée depuis — la file saturée, aujourd'hui, est la nôtre, pas celle de GitHub. Le raisonnement de CI: l'organe qui repare les PR gates perimes est annule 19 fois sur 30 — 2 min d'execution, 2 h de file #12728, appliqué aux conditions actuelles, conclut dans l'autre sens.

La phrase n'a essaimé nulle part ailleurs (1 seule occurrence dans tout le dépôt) : elle se corrige à peu de frais, maintenant.

Découpage proposé

Aucune de ces étapes ne réduit la capacité CI.

  • Étape 0 — corriger le commentaire fabriqué de pr-gate-stale-sweep.yml:116 (commentaire seul, zéro changement de comportement).
  • Étape 1 — router pr-gate.yml vers ubuntu-latest. C'est le plus fort ratio : aucun besoin local, agrégateur pur, et il découple le gate du parc qu'il mesure. Mesurer avant/après : délai run-created → job-started, durée totale, et occupation du pool coursia-waiter.
  • Étape 2 — si l'étape 1 tient, router les autres agrégateurs et sweeps sans besoin local (pr-gate-rerun, pr-gate-sweep-health-advisory, stale-guard-red-sweep, adjacency-stale-sweep).
  • Étape 3 — redimensionner coursia-waiter sur ai-01 une fois la charge réellement partie, et rendre le vCPU libéré à coursia-runner : c'est là que se crée la marge qui manque.
  • Étape 4 — les 27 restants des 32, au cas par cas, en vérifiant que le grep ne rate pas un besoin implicite (cache chaud, accès réseau interne, durée).

Limites de cette mesure — à ne pas surinterpréter

  • La classification est un grep sur le texte du workflow, pas une analyse d'exécution. Un workflow sans motif détecté peut avoir un besoin implicite : cache chaud, accès réseau interne, durée dépassant les limites GitHub-hosted. L'étape 4 existe pour ça ; les étapes 1-2 ne portent que sur des agrégateurs dont l'absence de besoin est lisible directement.
  • Le grep peut aussi sur-accuser : un docker cité en commentaire compte comme un besoin. Les 92 « avec besoin » sont donc un majorant, et les 32 un minorant — ce qui va dans le sens prudent.
  • Non mesuré : le coût GitHub-hosted en minutes pour un dépôt public, et les éventuelles limites de concurrence du plan. À vérifier avant l'étape 2.

Lane : myia-ai-01:CoursIA. Voir #17390 (double fetch du gate) et #17394 (contrat du cycle de merge) — même chantier de fiabilisation.

Activity

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