Repository navigation
CI: pin floating toolchain versions (#1645) - #1647
Mikola Lysenko (mikolalysenko) wants to merge 4 commits into
Conversation
Assisted-by: Claude Code:claude-opus-5-5
The e2e, yarn-classic, test, coverage and hosted-e2e jobs installed Node '24.x', Python '3.12.x' and Go '1.24'. Any upstream release then changed what CI ran with no commit here, which is how uv 0.13.2 turned main red and stalled the merge queue for 2.7 h on 10-20. Pin them to exact releases: Node 24.21.0 (already used by the vlt legs), Go 1.24.13, and Python 3.12.10, the newest 3.12 that actions/python-versions builds for Windows and macOS as well as Linux. Later 3.12 patches are source-only, so '3.12.x' already resolved to 3.12.10 on those runners. Refs #1645 Assisted-by: Claude Code:claude-opus-5-5
pin-check only made `uses:` references immutable. Nothing stopped a setup step from taking the latest tool, so a new upstream release could break the merge queue until someone landed a pin. Add scripts/check-tool-pins.py and run it from pin-check on ci.yml, the only workflow that gates PRs and the merge queue. It fails when setup-uv has no `version:`, or when a uv, node, python or go version is not an exact X.Y.Z, including literal fallbacks and the matrix values an expression reads. The pin-check job moves to the Depot runner mapping with the DISABLE_DEPOT_RUNNERS switch. Fixes #1645 Assisted-by: Claude Code:claude-opus-5-5
Review follow-up. The pin lint imported PyYAML, which the runner's python3 may not have; on such a runner the new test module would break the required lint-ecosystems job. The lint now scans the workflow as text with the standard library, like the other ci.yml tests do. The pin-check step is dropped. lint-ecosystems already runs every scripts/tests module on each PR, so the repository test gates ci.yml with no new step or job, and pin-check is back to its main version. The lint also now rejects expressions that read vars/env/inputs, skips comparison operands such as `!= ''`, and matches setup-uv regardless of case. Assisted-by: Claude Code:claude-opus-5-5
|
BugBot review Generated by Claude Code |
There was a problem hiding this comment.
✅ Bugbot reviewed your changes and found no new issues!
Comment @cursor review or bugbot run to trigger another review on this PR
Reviewed by Cursor Bugbot for commit 4c5f403. Configure here.
|
Burn-down agent: labeled Ready for review at
Slack announcement not sent: this run has no Slack send tool. Generated by Claude Code |
|
Labeled Ready for review (burn-down agent).
Generated by Claude Code |
Final review brief (final reviewer agent)What it does. Pins the Node ( Risk: low. CI-only; no Rust or shipped code changes. The one behavior change is that Linux Python legs drop from the latest 3.12 patch to 3.12.10, the last patch with Windows and macOS builds. Those legs only use Python to host uv, poetry, pdm and hatch. A full-tier dispatch ran on the new pins and passed. Look here
Verified
Changes I made: none. Open questions: none blocking. The PR description lists what's out of scope: php/java/dotnet majors and package-manager versions in hosted-e2e. Auto-merge is armed, so approving sends this straight to the merge queue. Generated by Claude Code |
LLM Description written by Claude Code:claude-opus-5-5
Fixes #1645
Problem
ci.ymlinstalled several oracle toolchains at floating versions:node-version: '24.x'(e2e pnpm legs, yarn-classic matrix, hosted-e2e),python-version: '3.12.x'(e2e Python legs, hosted-e2e) andgo-version: '1.24'(test, coverage, hosted-e2e). Any upstream release could then change what CI runs without a commit here. That is how uv 0.13.2 turned main red on 10-20 and stalled the merge queue for 2 h 44 min (about 4.3k job-min wasted; see #1645).pin-check.ymlonly enforced SHA pins onuses:, so nothing caught it.Root cause
Nothing required tool versions to be exact. The uv pin itself already landed on main via #1605 (
version: "0.13.1"). This PR pins the remaining runtimes and adds a lint so the next floating version is caught in review instead of in the merge queue.Changes
ci.yml, each with a "bump deliberately (CI perf: floating toolchain versions in ci.yml e2e — upstream uv 0.13.2 red-mained the merge queue for 2.7 h (~4.3k job-min wasted on 10-20; ~0.45k min/day amortized) #1645)" comment:24.x→24.21.0. The vlt legs already use it; it was released 2026-09-07.1.24→1.24.13, the last 1.24 patch.3.12.x→3.12.10. 3.12.11–3.12.15 are source-only security releases, andactions/python-versionsbuilds them for Linux only. On the Windows and macOS e2e legs,3.12.xalready resolved to 3.12.10, so pinning a newer patch would break those legs. Linux Python legs move from the latest 3.12 patch to 3.12.10. They use Python only to host uv, poetry, pdm and hatch.scripts/check-tool-pins.py, standard library only. It scans a workflow as text, the same way the otherscripts/testsmodules readci.yml. It fails when:astral-sh/setup-uv(matched case-insensitively) has noversion:;version, or anynode-version/python-version/go-versioninput, is not an exactX.Y.Z(.x, bare major or major.minor,latest, ranges);matrix.*(for examplevars.*,env.*orinputs.*), yields a non-exact quoted value (comparison operands such as!= ''are skipped), or reads amatrix.<key>with a non-exact value in that job's matrix. AfromJSONmatrix can't be resolved statically and is left to review.scripts/tests/test_check_tool_pins.py. The leanlint-ecosystemsjob already runspython3 -B -m unittest discover -s scripts/testson every PR, soRepository.test_ci_yml_has_no_floating_toolchainsblocks a floating version inci.ymlwith no new job or step. It coversci.ymlonly, the one workflow that gates PRs and the merge queue. The disabled compatibility workflows are untouched; the script flags their floatingpython-version: '3.12'if run on them by hand.pin-check.ymlis unchanged.Out of scope, same as the issue:
php-version: '8.2'(setup-php only takes major.minor),java-versionmajors,dotnet-version: N.0.x,npm install -g pnpm@10in the e2e pnpm legs, and the package managers hosted-e2e installs by major (pnpm@10,bun@1, unpinneduv). hosted-e2e tracks current releases on purpose and runs only in the full tier. Optional item 4 in the issue (a fail-fast "base is red" summary) is not done here.Runner usage (lean PR run)
lint-ecosystemsruns 21 more unit tests, which take about 20 ms.ci-okandclippynames and theci-okaggregation are unchanged.Test evidence
python3 scripts/check-tool-pins.pyonorigin/main'sci.yml: exit 1, flagging exactly the 8 floating lines (403, 620, 1422, 1428, 2241, 2637, 2682, 2702). On this branch: exit 0.origin/main'sci.ymlcopied in,test_ci_yml_has_no_floating_toolchainsandtest_main_exit_codesFAIL. With this branch'sci.yml, all 21 tests pass.python3 -B -m unittest discover -s scripts/tests(what lint-ecosystems runs): 368 tests OK, 6 skipped. Neither file imports anything outside the standard library.actionlint1.7.7 onci.yml: the same findings as main, none new.zizmor --offline: the same 61 findings as main, none new.fromJSONmatrix changed, and no Rust code changed.4c5f403: lean PR run green (87 checks,lint-ecosystemsran the new gate). One full-scope dispatch, run 39499480887: success, 246 jobs, including the Windows and macOS e2e legs and hosted-e2e on the new Node, Python and Go pins.4c5f403: no issues./code-review high
Fixed: the PyYAML dependency (the lint is now stdlib only), the duplicate pin-check step (dropped), the unchecked
vars/env/inputsexpressions, comparison operands flagged as versions, and the case-sensitive setup-uv match.Not fixed, with reasons:
if: matrix.<key> != ''(for example Setup Bun and Setup Deno), so flagging them would produce false positives. The three checked keys use no matrix expressions today.Per-issue checklist:
ci.yml; gate and regression tests inscripts/tests/test_check_tool_pins.pyGenerated by Claude Code