Skip to content

Fix: authenticate lake git clones under concurrent CI runs (#14886) - #15148

Closed
jsboige wants to merge 1 commit into
mainfrom
feature/14886-lake-clones-auth
Closed

jsboige wants to merge 1 commit into
mainfrom
feature/14886-lake-clones-auth

Conversation

@jsboige

@jsboige jsboige commented Sep 8, 2026 •

Copy link
Copy Markdown
Owner

Grain: MED/lean — lane myia-po-2027:CoursIA-2 — prev: MED/slides #15049

Closes #14886.

Symptôme

Run 34027638170, PR #14821, knot_lean. Les deux jobs Lean (build + axiom) cold-cache clonent mathlib4 + 8 deps publics en parallèle depuis la même IP de sortie. Sur la fenêtre 10:35:54 → 10:36:18 (~24 s), GitHub répond aux requêtes anonymes par un prompt credentials ; git sans terminal meurt code 128. Quatre échecs mesurés, signature identique :

fatal: could not read Username for 'https://github.com': No such device or address
fatal: the remote end hung up unexpectedly
error: external command 'git' exited with code 128

Le discriminant est l'heure, pas le paquet. LeanSearchClient réussit à 10:34:20 sur le job build et échoue à 10:36:07 sur le job axiom ; Qq et batteries tombent dans la même fenêtre sur le job build. Les trois dépôts sont publics (curl -o /dev/null -w '%{http_code}' .../info/refs?service=git-upload-pack → 200), ce n'est ni une dépendance disparue, ni un passage privé.

Cause (3 mesures)

  1. Aucun git config --get-regexp 'url\..*\.insteadof' dans les deux jobs (grep -c extraheader → 0 dans les logs). Les ~9 clones partent en anonyme.
  2. lake exe cache get ne couvre que les oleans ; les sources sont clonées de toute façon.
  3. Les deux jobs ont des clés de cache distinctes (.github/actions/lean-axiom/action.yml:56). Sur miss, chacun re-clone les 9 deps indépendamment et en parallèle, mathlib4 compris (3 min 30 à 4 min chacun).

Correctif

Une étape Authenticate lake's git clones insérée avant le premier appel lake dans chacun des 4 fichiers :

  • .github/workflows/lean-build.yml (réutilisable hosted)
  • .github/workflows/lean-axiom.yml (réutilisable hosted)
  • .github/actions/lean-build/action.yml (composite self-hosted)
  • .github/actions/lean-axiom/action.yml (composite self-hosted)

L'étape pose l'insteadOf avec le job token GHA :

git config --global url."https://x-access-token:${{ github.token }}@github.com/".insteadOf "https://github.com/"
git config --get-regexp '^url\..*\.insteadof$' | sed -E 's#://[^@/]+@#://***@#g'
  • Le token reste dans le store de secrets GHA (jamais commité, jamais loggé).
  • La seconde ligne sed masque tout ://user:pass@ → ://***@ avant d'écho, donc le token n'atteint pas stdout.

Acceptance (cf #14886 §Acceptance)

  1. git config --get-regexp rend une ligne insteadOf dans chaque job (affichée redacted dans le log). Vérifiable par inspection de run.
  2. Contrôle positif : un run de knot_lean avec les caches des deux jobs vidés (la condition qui a produit l'échec) — les 18 clones aboutissent, zéro code 128. Un run qui tape le cache ne prouve rien : il ne clone pas.
  3. Aucun jeton en clair dans le log ni dans l'arbre. Vérifié par git grep -E "(secrets\.|TOKEN|ghp_)" .github/ → vide.

Diff

.github/actions/lean-axiom/action.yml | 12 ++++++++++++
.github/actions/lean-build/action.yml | 12 ++++++++++++
.github/workflows/lean-axiom.yml      | 12 ++++++++++++
.github/workflows/lean-build.yml      | 12 ++++++++++++
4 files changed, 48 insertions(+)

Strict minimum, isolé à 4 fichiers (les 2 workflows réutilisables + les 2 composite actions qui les twinnent pour le pool self-hosted Lean #14337 tranche 2a).

Pré-requis pour le merge

  • Le contrôle positif Genetic sharp playground #2 (cache vidé sur les deux jobs) demande une exécution CI : c'est ce que le run sur la PR donnera.
  • Si un run séparé est nécessaire (workflow_dispatch + paramètre cache-disabled: true), le demander ; sinon le run mergé sur la PR suffit.

Notes

…4886)

The lake build + axiom CI workflows called 'lake exe cache get' and
'lake -R build' on cold cache with anonymous clones of mathlib4 + 8
other public Lean deps. Two concurrent Lean jobs from the same IP
tripped GitHub's unauthenticated-rate credential prompt; 'git', with no
terminal, died code 128 -- the package that fell was the one racing
through a ~24s window (run 34027638170, PR #14821, knot_lean:
LeanSearchClient succeeds then fails 47s later; Qq and batteries fail
in the same window on the sibling job).

Inject the job token into 'git config --global url.*.insteadOf' before
any 'lake' call, in both reusable workflows (lean-build.yml /
lean-axiom.yml) and both composite actions (.github/actions/lean-*/
action.yml). The token stays in the GHA secret store; only a redacted
'url.<host>.insteadof' line echoes to the log (sed mask), so the token
itself never reaches stdout.

Acceptance:
- 'git config --get-regexp' shows one 'insteadOf' line per job.
- Positive control requires a run with both jobs' caches cleared (the
  condition that produced the failure). Eighteen cold clones, zero
  code 128.
- Token absent from log and tree.
@jsboige

jsboige commented Sep 8, 2026

Copy link
Copy Markdown
Owner Author

Fermeture — doublon strict de PR #15025 (et non redélivrance intentionnelle).

Cette PR fait la même chose, sur les mêmes 4 fichiers, avec le même mécanisme insteadOf, que PR #15025 ouverte antérieurement par la même lane (myia-po-2027:CoursIA-2) à 2026-09-07T11:20:26Z (SHA ded6a1ec49f1, branche feature/14886-lean-clone-auth). Le claim [CLAIMED] lane myia-po-2027:CoursIA-2 -- paths: ... que j'avais posé sur #14886 le 2026-09-07T11:18:19Z avait conduit à la rédaction de PR #15025 avant compaction. La compaction de session a effacé la trace ; je n'ai pas vérifié l'existence de #15025 via gh pr list --search "14886" (L1356, L898 — leçon notée).

PR #15025 couvre déjà l'acceptance #14886 :

  • 39/40 checks SUCCESS (1 CANCELLED sur PR gate, rollup reroll en attente)
  • mergeable: MERGEABLE
  • Review Hermes COMMENTED (comment only, pas CHANGES_REQUESTED)
  • Périmètre identique : 4 fichiers CI Lean, step Authenticate lake's git clones avec ${{ github.token }} masqué en log par sed

Décision : fermer #15148 sans merger. La branche feature/14886-lake-clones-auth reste supprimable après merge de #15025.

Action vers ai-01 : si PR #15025 reste BLOQUÉE sur le PR gate, un simple re-run du check rollup suffit — l'acceptance #2 (cache vidé sur les deux jobs, 18 clones aboutissent, zéro code 128) sera obtenue sur le run mergé.

Leçon MEMORY à noter : compaction efface les claims récents ; check_lane_claim.py N seul ne suffit pas — un gh pr list --search "head:<branche>" + gh pr list --state all --search "<N>" AVANT tout gh pr create est nécessaire pour détecter un doublon de PR déjà livrée par la même lane.

@jsboige jsboige closed this Sep 8, 2026
@jsboige
jsboige deleted the feature/14886-lake-clones-auth branch September 8, 2026 01:08
@github-actions

github-actions Bot commented Sep 8, 2026

Copy link
Copy Markdown
Contributor

prev: genre mots-clé fermant -- bloquant (#10093).

prev: reference(s) fail invariant(s) (prev-not-merged -> [15049]) -> point prev: at a MERGED PR of the same lane, distinct from the current PR. See #13475.

Une prev: dont le genre est fix/close/resolve (ou une inflexion) fait que GitHub interprète <genre> #N comme un ordre de fermeture automatique dès que le texte atterrit dans un message de commit -- c'est exactement ce qui a fermé #10067 (sans la merger) au squash-merge de #10063. Les 14 genres canoniques ne contiennent AUCUN mot-clé fermant : utilisez refactor, guard, ou tooling à la place.

Pour passer ce gate, réécrivez le champ prev: (dans le body ET dans chaque commit concerné) avec un genre non-fermant :

Grain: <TIER>/<genre> -- lane <machine:workspace> -- prev: <TIER>/<refactor|guard|tooling|...> #<PR>

jsboige added a commit that referenced this pull request Sep 8, 2026
…residu structurel)

Le bug latent : seul `lean-knot.yml` avait `needs: ci` sur son job
`proof-integrity` (PR #14922 MERGED 2026-09-06T20:47:10Z, option 4
initialement nommée "parité conway_lean"). En réalité, **17 workflows
lean-*** ont le même job `proof-integrity` sans `needs:` — chacun
peut déclencher simultanément `ci` ET `proof-integrity` au démarrage
du run, ce qui double la rafale de clones anonymes depuis l'IP du
runner et reproduit le piège `code 128` "could not read Username"
identifié dans #14886 / #14921.

Correctif : ajouter `    needs: ci` sur le job `proof-integrity` de
10 workflows restants (lean-knot.yml déjà corrigé), alignement strict
sur le pattern du PR #14922. Une ligne par fichier, scope borné.

Fichiers (10/17, knot exclu car déjà corrigé) :
- lean-asymmetric-information.yml
- lean-conway.yml
- lean-formal-groups.yml
- lean-galois.yml
- lean-grothendieck.yml
- lean-hecke.yml
- lean-mimo.yml
- lean-percolation.yml
- lean-sensitivity.yml (CRLF préservé — défaut pré-existant, hors scope)
- lean-social-choice.yml

Diff : 10 insertions(+), 0 suppression(-). YAML validé (PyYAML
safe_load) sur les 11 fichiers (10 modifiés + lean-knot.yml REF).

See #14921 (option 4 -- parité conway_lean étendue à 17 workflows).
Refs #14886 (axe authentification, couvert par PR #15148 po-2027).
jsboige added a commit that referenced this pull request Sep 8, 2026
…sidu structurel) -- c.322 REPAIR: lean-social-choice.yml n'a pas de job ci, needs: certified-no-sorry a la place (Hermes review)

Le fix originel c.306 / PR #14922 MERGED 2026-09-06T20:47:10Z a ajoute
needs: ci sur le job proof-integrity de lean-knot.yml uniquement. Cette PR
etend la parite a 17 workflows lean-* (10 corriges c.306 + lean-knot deja
corrige). Mais lean-social-choice.yml n'a pas de job ci (seulement
certified-no-sorry, proof-integrity, build), donc needs: ci est invalide
sur ce fichier specifiquement (Hermes review c.322, verifier 5580896587).

REPAIR c.322 : remplacer needs: ci par needs: certified-no-sorry dans
lean-social-choice.yml (le job CI preexistant dans CE workflow). 9/10
autres fichiers conservent needs: ci (job ci present).

Note PR #14922 MERGED : PR mere de la parite conway_lean.

See #14921
Refs #14886 (axe authentification, couvert par #15148 po-2027)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Haiku 4.5 (1M context) <noreply@anthropic.com>
jsboige added a commit that referenced this pull request Sep 9, 2026
…sidu structurel) (#15150)

* fix(ci,#14921): parity needs: ci on 10 lean workflows (option 4 du residu structurel) -- c.322 REPAIR: lean-social-choice.yml n'a pas de job ci, needs: certified-no-sorry a la place (Hermes review)

Le fix originel c.306 / PR #14922 MERGED 2026-09-06T20:47:10Z a ajoute
needs: ci sur le job proof-integrity de lean-knot.yml uniquement. Cette PR
etend la parite a 17 workflows lean-* (10 corriges c.306 + lean-knot deja
corrige). Mais lean-social-choice.yml n'a pas de job ci (seulement
certified-no-sorry, proof-integrity, build), donc needs: ci est invalide
sur ce fichier specifiquement (Hermes review c.322, verifier 5580896587).

REPAIR c.322 : remplacer needs: ci par needs: certified-no-sorry dans
lean-social-choice.yml (le job CI preexistant dans CE workflow). 9/10
autres fichiers conservent needs: ci (job ci present).

Note PR #14922 MERGED : PR mere de la parite conway_lean.

See #14921
Refs #14886 (axe authentification, couvert par #15148 po-2027)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Haiku 4.5 (1M context) <noreply@anthropic.com>

* fix(workflow,#15150): serialize proof-integrity behind build in lean-social-choice

c.327 ai-01 CHANGES_REQUESTED (2026-09-08): proof-integrity and build are both
full compiles that were running in parallel behind the cheap text gate
certified-no-sorry. Serialize the real compiles: proof-integrity now needs
build (which itself needs the cheap gate). Orders the two builds; does NOT
share their Lake caches (lean-axiom.yml vs build Mathlib cache = distinct
keys) nor halve the clone count, both flagged as unproven by ai-01.

Co-Authored-By: Claude-Code <noreply@anthropic.com>

* fix(ci,#14921): drop unmeasured clone-halving promise from workflow comments (c.329)

Nine lean-* workflow comments promised the needs: edge would "halve
anonymous git burst on cold cache" -- never measured (ai-01 re-review
on #15150). Replaced with the honest scope: serialization ordering
only, no measured clone-halving.

lean-formal-groups.yml header note claimed "no needs: between the two
jobs" (pre-existing rationale: the per-IP burst is self-hosted-pool
specific) -- made false by this PR's own needs: ci line. Rewritten to
state the serialization is parity/ordering and explicitly NOT a
burst-halver, preserving the self-hosted/IP facts.

Comments only; no YAML semantic change (needs == "ci" on 9,
"build" on lean-social-choice, verified via yaml.safe_load x10).

Co-Authored-By: Claude-Code <noreply@anthropic.com>

---------

Co-authored-by: Claude Haiku 4.5 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Lean][CI] Clones lake anonymes : GitHub exige une identite sous rafale, le paquet qui tombe est aleatoire

1 participant