Skip to content

1.14: pin Rust toolchain to 1.99.0 - #51

Open
cunninghamcard-bit wants to merge 9 commits into
exp/restartfrom
exp/1.14-pin-toolchain
Open

cunninghamcard-bit wants to merge 9 commits into
exp/restartfrom
exp/1.14-pin-toolchain

Conversation

@cunninghamcard-bit

@cunninghamcard-bit cunninghamcard-bit commented Oct 12, 2026 •

Copy link
Copy Markdown
Owner

What (unit 1.14)

  • rust-toolchain.toml: channel = "stable" → "1.99.0"; components = ["rustfmt", "clippy"] kept.
  • .github/workflows/ci.yml (11) and release.yml (9): every dtolnay/rust-toolchain@stable → @1.99.0. With @stable the action installed stable and added targets: to stable, while cargo in the repo used the toml toolchain; now both are 1.99.0, so cross targets land on the pinned toolchain. No other rustup/toolchain usage besides rustup target add in release.yml android job, which runs in the repo and so honours the toml.
  • ci.yml rust-test job prints rustup show && cargo --version for log evidence.

Local evidence

rustup show in the repo: 1.99.0-x86_64-unknown-linux-gnu, active because overridden by rust-toolchain.toml. cargo fmt --all --check OK, cargo clippy --workspace --all-targets -D warnings OK.

Upgrades

Toolchain upgrades go in a separate PR that bumps rust-toolchain.toml and all workflow refs together.

CI evidence (run 38194851398, job "Rust core" 114635145063: success)

1.99.0-x86_64-unknown-linux-gnu installed - rustc 1.99.0 (b940084d7 2026-09-28)
name: 1.99.0-x86_64-unknown-linux-gnu
active because: overridden by '/home/runner/work/aimux/aimux/rust-toolchain.toml'
cargo 1.99.0 (5f94df478 2026-08-27)

fmt, clippy, doc, test steps green on 1.99.0. Failing jobs are the same set failing on exp/restart head 8455db9 (run 38111665412), and none of them come from the toolchain:

  • Flutter binding: flutter analyze reports two unused_element_parameter warnings at bindings/flutter/test/typed_model_test.dart:130:10 / :131:10 (base job 114388336001, this run 114635145229).
  • Python binding: test_decision.py KeyErrors, 'decision_result' (recording test) and 'input_tokens' (4 usage cases).
  • Node binding ×4: decision.test.ts:60:36, the missing/null usage test reads usage.input_tokens.
    All three are fixed in 1.15: binding CI green (flutter analyze, decision usage shape, recording key) #52 (unit 1.15).

Toolchain pin check (94d3667, b597f7d, aa6051e)

scripts/check_toolchain_pin.sh, run by a new "Workflow toolchain refs match rust-toolchain.toml" step in the Rust core job. It fails with file:line when any dtolnay/rust-toolchain reference in .github/workflows/*.yml has a ref other than the rust-toolchain.toml channel: a wrong version, a non-version (@stable, @master), or no @ref at all. It also fails on any toolchain: input, and when no reference is found. The 20 existing @1.99.0 refs are untouched.

Local mutations (each reverted, then baseline toolchain pin OK: 20 dtolnay/rust-toolchain steps use 1.99.0, rc 0):

mutation result
ci.yml:23 → @stable rc 1, ci.yml:23: dtolnay/rust-toolchain@stable is not a version
release.yml:53 → @master + with: toolchain: 1.99.0 rc 1, release.yml:53 ... @master is not a version and release.yml:55: ... 'toolchain:' input overrides the pin
release.yml:53 → @1.98.0 rc 1, release.yml:53: ... @1.98.0 does not match rust-toolchain.toml channel 1.99.0
ci.yml:23 → bare dtolnay/rust-toolchain rc 1, ci.yml:23: dtolnay/rust-toolchain without @1.99.0
all 20 → another action rc 1, no dtolnay/rust-toolchain@ steps found
The mutations were not pushed to CI; local results only.

Case-insensitive match (5a35008)

The grep and the ref extraction are now case-insensitive (grep -in, sed s///I), because GitHub resolves action owner/repo names case-insensitively. Mutation ci.yml:23 → DTolnay/Rust-Toolchain@stable: rc 1, ci.yml:23: ... @stable is not a version. I re-ran the five earlier mutations and all are still red (stable, master+toolchain:, 1.98.0, bare, zero matches). Baseline is OK with 20.

All .github yml/yaml and flow-style keys (dc86fa8)

  • The check now scans every .github/**/*.yml and *.yaml, including composite actions under .github/actions/**/action.yml, not just workflows/*.yml. It also fails if there are no such files.
  • Any toolchain: key fails, in block, flow (with: { toolchain: x }) or quoted form, anywhere on the line.

release.yml gate job (4201ba3)

Jobs run in parallel, so the step dc86fa8 added inside rust-publish gated nothing; it is removed. A dedicated check-toolchain job (checkout, then bash scripts/check_toolchain_pin.sh) now gates the release. The eight root jobs needs: check-toolchain: rust-publish, node-build, python-release, go-build, ffi-build, console-build, flutter-ffi-mobile, jvm-publish. node-publish, flutter-publish and github-release reach it through their existing needs.

Verified by parsing release.yml with PyYAML and walking needs transitively: every job except check-toolchain reaches it (UNGATED: []). Mutation: dropping jvm-publish's needs gives UNGATED: ['jvm-publish'].

release.yml runs only on push/tags and workflow_dispatch, not on PRs, so neither the gate job nor the needs graph has run in CI. ci.yml's Rust core job runs the same script.

Mutations (local, each reverted; baseline toolchain pin OK: 20 ..., rc 0; the count stays at 20 because the gate job names no dtolnay/rust-toolchain):

mutation result
new .github/workflows/extra.yaml with @stable rc 1, extra.yaml:4: ... @stable is not a version
new composite .github/actions/x/action.yml with @stable rc 1, action.yml:4: ... @stable is not a version
ci.yml with: { toolchain: stable } rc 1, ci.yml:24: ... 'toolchain:' input overrides the pin
DTolnay/Rust-Toolchain@stable rc 1
@stable rc 1
@master + toolchain: rc 1 (two lines flagged)
@1.98.0 rc 1
bare, no @ rc 1
zero matches rc 1

Release gate check (a9602e9, 5a21291)

scripts/check_release_gate.py parses release.yml with PyYAML. It fails, listing what it found, when:

  • any job does not transitively need check-toolchain (lists the UNGATED jobs);
  • the check-toolchain job is missing, or no jobs parse;
  • any job's if: uses always(), cancelled() / !cancelled() or failure(), since each of these runs a job past a failed gate;
  • continue-on-error is set on any job or on any check-toolchain step;
  • PyYAML can't be imported.

It runs in ci.yml's Rust core step after check_toolchain_pin.sh, and in release.yml's check-toolchain job. Both steps install python3-yaml via apt only if import yaml fails. (a9602e9 was a stdlib-only first version; 5a21291 replaced it.)

Mutations (local, each reverted; baseline release gate OK: all 11 release.yml jobs transitively need check-toolchain, rc 0):

mutation result
remove jvm-publish needs rc 1, UNGATED jobs ...: jvm-publish
remove the check-toolchain job rc 1, job 'check-toolchain' is missing
jvm-publish if: always() && (...) rc 1, job 'jvm-publish' if: ... bypasses a failed 'check-toolchain'
node-publish if: ${{ !cancelled() && (...) }} / failure() / cancelled() rc 1 each
continue-on-error: true on the check-toolchain job rc 1
continue-on-error: true on a check-toolchain step rc 1, step 1 has continue-on-error
PyYAML missing (python3 -S) rc 1, cannot import PyYAML
workflow with no jobs rc 1, no jobs parsed

rust-toolchain.toml channel stable -> 1.99.0 (components unchanged);
every dtolnay/rust-toolchain step in ci.yml and release.yml uses @1.99.0
so installed targets land on the pinned toolchain; ci prints rustup show.
scripts/check_toolchain_pin.sh fails with file:line for any
dtolnay/rust-toolchain@<v> that differs from the pinned channel; the
Rust core job runs it.
Also fails when no dtolnay/rust-toolchain@ step is found.
…vely

GitHub resolves action owners/repos case-insensitively, so
DTolnay/Rust-Toolchain@stable must not slip past the check.
…lchain keys

Scan .github/**/*.yml and *.yaml (incl. composite actions), reject any
toolchain: key anywhere on a line (block, flow, quoted), and run the
check first in release.yml's rust-publish job.
Jobs run in parallel, so a step inside rust-publish gated nothing. A
dedicated check-toolchain job now runs the pin check and the eight root
jobs need it; node-publish, flutter-publish and github-release reach it
through their existing needs.
scripts/check_release_gate.py (stdlib only) walks release.yml needs
transitively and fails listing UNGATED jobs, or when check-toolchain is
missing. Runs next to check_toolchain_pin.sh in ci.yml's Rust core step
and in release.yml's check-toolchain job.
check_release_gate.py now parses with PyYAML (fails if it can't import
it, or if no jobs parse), and fails on any job if: using always(),
cancelled()/!cancelled() or failure(), and on continue-on-error on any
job or check-toolchain step. CI installs python3-yaml if missing.
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.

1 participant