Repository navigation
build(ci): pin the Rust toolchain to 1.98.0 - #1620
Merged
Merged
Conversation
Every blocking gate in ci.yml runs under `-D warnings`. CI resolved `stable` at job time, so the moment a runner image rolled forward to 1.98.0, any lint newly warn-by-default in that release turned `main` red with no commit to blame -- and a contributor on 1.97.0 could not reproduce it, or even see it. That happened four times in a row: #1604 (fmt drift, manual_slice_fill, needless_late_init), #1609 (collapsible_if x5 in qmoe.rs from #1602, plus ep-cpu lints), #1615 (collapsible_if in runtime.rs from #1612), and #1603 (chunks_exact_to_as_chunks across 12 crates). Each fixed the symptom; none could stop the next one. Formatting is the self-perpetuating case, since whoever formats next re-flows the file back the other way. Add rust-toolchain.toml pinning channel 1.98.0 -- the exact release CI was already resolving to, `rustc 1.98.0 (88d9e12ae 2026-08-18)`, read out of the job logs -- with clippy, rustfmt and llvm-tools-preview as components. rustup installs the components listed in that file when it materializes the toolchain, and a directory pin takes precedence over the default toolchain for `rustup component add` and `rustup target add` as well, so CI no longer has to install components per-job and can no longer attach them to a different toolchain than the one cargo will use. The eight setup steps in ci.yml therefore collapse to a bare `rustup toolchain install`, which reads the file. The `version=` cache-key output is unchanged and still records the resolved release. An explicit `+toolchain` still wins, so miri.yml's `cargo +nightly` is unaffected. This pins the toolchain, not dependencies: `cargo update` and audit.yml are untouched, so advisories are still surfaced and fixable. The previous policy comment justified tracking `stable` as avoiding "freezing security fixes", which conflated the two -- security fixes arrive via dependencies, while the recurring breakage came from new warn-by-default lints. Also fix the `changes` job, which was gated on the event being pull_request or push. The comment said schedule and workflow_dispatch runs would skip only that job and still get full CI. They did not: every job below is `needs: changes` with a plain `if:`, and GitHub skips a job whose `needs` dependency was skipped regardless of its own `if:`. Gating it skipped the whole workflow, so the nightly cron and every manual dispatch reported success without running a check. The classify step already leaves docs_only=false for any event it does not diff, so removing the gate makes the documented behaviour real. Refs #1600 Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 08760f2f-160f-41e5-828d-9d9b6045c00d
This was referenced Aug 21, 2026
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #1620 +/- ##
==========================================
+ Coverage 81.49% 81.53% +0.03%
==========================================
Files 383 383
Lines 179257 179257
Branches 179257 179257
==========================================
+ Hits 146086 146157 +71
+ Misses 28231 28161 -70
+ Partials 4940 4939 -1
Flags with carried forward coverage won't be shown. Click here to find out more. 🚀 New features to boost your workflow:
|
This was referenced Aug 21, 2026
justinchuby
added a commit
that referenced
this pull request
Aug 21, 2026
`main` is red at `843b0bf7` on `cargo fmt --all -- --check` (exit 1, 2 diffs), which reddens `Fast (Linux x86_64)` and `Rust quality`. Both sites came in with #1644: crates/onnx-genai-engine/src/native_decode/mod.rs:1115 `snapshot_recurrent_state_public` signature folded across three lines; it fits on one at 98 columns. crates/onnx-genai-engine/src/native_decode/tests.rs:1412 `spec.rewind(base_len).expect(...)` on one line at 62 columns; rustfmt's default `use_small_heuristics` breaks a chain over 60. Whitespace only -- `git diff -w` is empty. Verified under the pinned toolchain (`rustfmt 1.9.0-stable (88d9e12ae1 2026-08-18)`, resolved from `rust-toolchain.toml`, no explicit `rustup run`): cargo fmt --all -- --check 1 -> 0 clippy -p onnx-genai-engine -F native-backend --all-targets 0 (unchanged) Reproduced on a clean `origin/main` worktree first, so the diffs are #1644's and not inherited from my tree. One observation, since #1620 pinned the toolchain specifically to stop this: this is not toolchain drift. Both directions here are what 1.98.0's rustfmt produces from a default config, and the pin is being honoured -- the code simply was never run through `cargo fmt`. The pin removed the class where two contributors format the same file two ways; it cannot do anything about code that no formatter has touched. That is a merge-gating question, not a toolchain one: #1644 merged with `Rust quality` red. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 08760f2f-160f-41e5-828d-9d9b6045c00d Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 08760f2f-160f-41e5-828d-9d9b6045c00d
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes the root cause behind the 1.98.0 CI incidents tracked in #1600.
What the failure was
Every blocking gate in
ci.ymlruns under-D warnings— either asRUSTFLAGSor as a trailing-- -D warningson clippy. CI resolvedstableat job time, so when runner images rolled forward torustc 1.98.0 (88d9e12ae 2026-08-18), every lint that release made warn-by-default became an instant failure on code that was clean the day before. No commit to blame, and a contributor on 1.97.0 could not reproduce it — clippy 0.1.97 does not carry those lints at all, so it does not even print them.Four consecutive incidents, all the same cause:
cargo fmtdrift,manual_slice_fill,needless_late_initcollapsible_if×5 inqmoe.rs+ ep-cpu lintscollapsible_ifinruntime.rschunks_exact_to_as_chunks, 12 cratesEach fixed symptoms; none could prevent the next. Formatting is the self-perpetuating one — an unpinned rustfmt means whoever formats next re-flows the file back the other way, so the tree oscillates.
How I reproduced it
I read the version out of a failing job log rather than guessing, then installed it:
That is what turned "unreproducible locally" into reproducible, and it is what made #1609 and #1603 diagnosable at all.
What I changed
rust-toolchain.toml(new) —channel = "1.98.0",profile = "minimal",components = ["clippy", "rustfmt", "llvm-tools-preview"]. Notargetskey:Rust (Windows ARM64)runs natively onwindows-11-armand needs no cross target, andscripts/check_cross_compile.shadds its own.ci.yml— the eight setup steps collapse fromrustup toolchain install stable --profile minimal --component …+rustup default stableto a barerustup toolchain install, which reads the file and installs the declared components. Theversion=cache-key output is unchanged. Policy comment rewritten.ci.yml,changesjob — separate bug, fixed while here. It was gated ongithub.event_name == 'pull_request' || 'push', with a comment claiming schedule andworkflow_dispatchruns would skip only that job and still get full CI. They did not. Every job below isneeds: changeswith a plainif:(noalways()/!cancelled()), and GitHub skips a job whoseneedsdependency was skipped regardless of its ownif:. So the gate skipped the entire workflow: the nightly cron and every manual dispatch reported success without running a single check — a green with no verdict behind it, which is the same class of problem this PR is about. The classify step already leavesdocs_only=falsefor any event it does not diff, so removing the gate makes the documented behaviour real.How I verified it
All local, on this branch, with my rustup default left at 1.97.0 so the file is doing the work:
Negative control — the pin is what changes the resolution:
clippy
0.1.97→0.1.98is precisely the gap that made these failures invisible to contributors.Both gates, run with bare commands (no
+1.98.0), which is the point — a 1.97.0 contributor now gets CI's behaviour by default:cargo fmt --all -- --check→ cleanci.yml~326, including the trailing-- -D warnings→ exit 0Component auto-install:
llvm-toolswas absent from my 1.98.0 install and rustup fetched it on first use inside the repo, so dropping the per-job--componentflags is safe. Confirmed end-to-end withcargo llvm-cov --locked -p onnx-runtime-cpuinfo→ exit 0, which is the one job whose component requirement changed.rustup override semantics, empirically checked (I had this wrong earlier and said so on #1600):
rustup component addandrustup target addrespect the directory pin — I expected them to hit the default toolchain and silently break the coverage and cross-compile jobs. They do not; both landed on 1.98.0. Explicit+toolchainstill beats the file (rustc +stable -Vv→ 1.97.0 inside the repo), so miri'scargo +nightlyis unaffected.YAML: all workflow files parse;
changesconfirmed to have noif:key.What I could not verify
workflow_dispatch/schedulefix. I verified the mechanism by reading the gating (all 8 downstream jobs areneeds: changeswith plainif:), but I have not observed a dispatch run execute the matrix. Worth triggering one after merge to confirm.audit.yml,publish.yml,publish-ep-plugins.yml,wheels.ymlstill sayrustup default stable. They inherit the pin anyway — anycargorun inside the repo resolves through the file — so their behaviour is already correct and their explicit install is merely redundant. I left them rather than widen the blast radius onto release workflows. One exception worth flagging:benchmark.ymlusesdtolnay/rust-toolchain@stable, which setsRUSTUP_TOOLCHAIN— that env var overrides the file, so benchmark is genuinely not pinned. It is non-blocking, but it is a real gap, not an oversight.Related, not fixed here
No CI job runs clippy on macOS.
rust-coveragematrixes macOS but only installs clippy (~line 458) and never runs it; all six clippy-running jobs are Linux/Windows. That means #1609's macOS-only fixes inaccelerate_gemm.rsandmatmul.rs(both#[cfg(target_os = "macos")]) were structurally unverifiable by CI. I ran CI's exact clippy package list on macOS under 1.98.0 → exit 0, so this is a prevention gap rather than an outstanding defect. Filing separately.Conflict risk with #1579
None. This PR touches only
.github/workflows/ci.ymland a new root file. No overlap withcrates/onnx-runtime-ep-cpu,crates/onnx-runtime-ir, orcrates/onnx-genai-engine/src/{decode,native_decode}/.