Skip to content

fix(coverage): install the base-pinned Rust release in the coverage image - #2524

Merged
seonghobae merged 3 commits into
mainfrom
seonghobae/coverage-rust-toolchain
Sep 29, 2026
Merged

seonghobae merged 3 commits into
mainfrom
seonghobae/coverage-rust-toolchain

Conversation

@seonghobae

@seonghobae seonghobae commented Sep 29, 2026 •

Copy link
Copy Markdown
Contributor

Why

The coverage image installs Debian's rustc 1.85. fast-mlsirm pins 1.97.1, and its dependency graph needs at least 1.90 (ordered-float, time, wgpu/naga). So maturin build --offline fails, _core never imports, and every fast-mlsirm coverage run sits near 68% against its 100% gate. For example, fast-mlsirm#2256 coverage-evidence job 109519410203. As a result, no fast-mlsirm PR can reach an APPROVED review.

What changes

  • scripts/ci/resolve_base_rust_toolchain.py reads rust-toolchain(.toml) from the base SHA only.
    • An exact 1.x.y pin is used as-is.
    • stable, nightly-*, custom path and unparsable files all fall back to the central 1.97.1.
    • With no pin, the output is empty and the image is unchanged.
  • The image build installs that release from rustup-init 1.29.1, SHA-256 verified, with --profile minimal --component llvm-tools-preview.
    • cargo and rustc are symlinked to the toolchain binaries, so no rustup proxy runs inside --network=none.
  • Rust coverage accepts exactly two reviewed LLVM pairs: Debian llvm-19, or /usr/local/libexec/opencode-rust/* from the same rustc release.
  • Rollback: if the pinned layer's build fails, the job rebuilds the previous Debian image.

Verification

  • Contract tests: tests/test_resolve_base_rust_toolchain.py and tests/test_opencode_rust_coverage_toolchain_contract.py. The REVIEW_DISPATCH_BLOB_SHA pin is updated.
  • scripts/ci/test_strix_quick_gate.sh passes. The target tests pass both plain and with GITHUB_ACTIONS=true.
  • Local container checks, with the layer text extracted verbatim:
    • amd64 with the exact digest: the sha check and the install of all 4 components pass. rustc can't execute under qemu-user.
    • arm64 native, with only the triple and sha swapped, under --network=none as a non-root UID: pyo3 0.29.2 from fast-mlsirm's base vendor dir builds offline with maturin and imports, and cargo llvm-cov reports 100%.
    • The unpinned image has no rustup layer.
  • fast-mlsirm#2157's tree with 1.97.1 and its base vendor dir builds offline with maturin; _core imports and the backend resolves to rust.
  • Pending: a native amd64 run on the s1 host (coordinator).

🤖 Generated with Claude Code

https://claude.ai/code/session_01PtgtJk1WjqieqvLDb1w8uW

Addendum: the second root cause (commit 2c90c58)

fast-mlsirm's pytest config sets pythonpath = [".", "python"], so the test suite imports the source tree's python/fast_mlsirm first. A _core that exists only in user site-packages is shadowed, and the same cannot import name '_core' error persists even after a successful build. scripts/ci/place_maturin_extension.py copies only the wheel's compiled extension into the tool.maturin.python-source package, as maturin develop does, and rejects paths that leave the project. Reproduced on fast-mlsirm#2157's tree: collection ImportError before placement → 17 passed after.

Known follow-up (not in this PR)

On my host (M-series, 4 jobs), cargo llvm-cov --workspace --all-features took 3366 s over fast-mlsirm#2157's tree. The sandbox's per-command cap is 900 s, so a Rust-changing fast-mlsirm PR will likely time out in Rust coverage. The timeout, the test scope, and the repo-owned minimum_lines metadata need a separate decision.

seonghobae and others added 2 commits September 30, 2026 04:44
…mage

Debian's rustc 1.85 is older than fast-mlsirm's pinned 1.97.1 (its graph
needs >=1.90), so the offline maturin build failed, _core never imported,
and every fast-mlsirm coverage run fell below its 100% gate.

When the validated base commit pins an exact 1.x.y release, the trusted
image installs it from a SHA-256-verified rustup-init (minimal profile +
llvm-tools-preview) and binds Rust coverage to that release's LLVM tools.
Unpinned repositories keep the Debian image; a failed pinned layer rebuilds
the previous image.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PtgtJk1WjqieqvLDb1w8uW
The head-lock intake contract executes the workflow block that ends at the
Dockerfile heredoc with a python3 stub; resolving the toolchain inside that
block overwrote its argument receipt.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PtgtJk1WjqieqvLDb1w8uW
@coderabbitai

coderabbitai Bot commented Sep 29, 2026 •

Copy link
Copy Markdown
Contributor

Warning

Review limit reached

Next included review available in 57 minutes.

Check out review usage here.

View limit details

Limit details: You’ve used the included review currently available.

You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository.

Learn how review limits work.

Review configuration:

⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Advanced

Run ID: 69760634-373a-4af9-af4a-eb76f8a41369

📥 Commits

Reviewing files that changed from the base of the PR and between 9ca2353 and 2c90c58.

📒 Files selected for processing (10)
  • .github/workflows/agent-review-runtime-quality-ci.yml
  • .github/workflows/opencode-review-dispatch.yml
  • CHANGELOG.d/20260930-coverage-base-pinned-rust.md
  • docs/doctoring/opencode-rust-coverage-runtime-boundary.md
  • scripts/ci/place_maturin_extension.py
  • scripts/ci/resolve_base_rust_toolchain.py
  • tests/test_opencode_rust_coverage_toolchain_contract.py
  • tests/test_place_maturin_extension.py
  • tests/test_pr_review_autofix_nvidia_nim_contract.py
  • tests/test_resolve_base_rust_toolchain.py

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

fast-mlsirm's pytest pythonpath puts python/ first, so the source-tree
package shadowed the wheel installed into user site-packages and _core
stayed unimportable even after a successful offline build. Copy only the
wheel's compiled extension members into the tool.maturin.python-source
package, as maturin develop does, rejecting paths that leave the project.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PtgtJk1WjqieqvLDb1w8uW
@seonghobae
seonghobae marked this pull request as ready for review September 29, 2026 23:15
@seonghobae
seonghobae merged commit 00e84cf into main Sep 29, 2026
23 of 31 checks passed
@seonghobae
seonghobae deleted the seonghobae/coverage-rust-toolchain branch September 29, 2026 23:15
@seonghobae

Copy link
Copy Markdown
Contributor Author

Bypass merge record (merge 00e84cf7, head 2c90c581d)

  • Reason: every fast-mlsirm opencode verdict was structurally blocked at coverage-evidence (Debian rustc 1.85 < MSRV 1.90, plus _core shadowing), which blocked the late-life stage-B release PRs. The central review queue for this PR is saturated, so its own checks are still queued.
  • Direct diff review: 10 files, +481/-20. The Rust layer applies only to repositories whose base commit pins an exact 1.x.y; unpinned repositories keep the previous image, and a failed layer rebuilds it. The extension copy rejects python-source and wheel members that escape the project.
  • Local verification:
    • scripts/ci/test_strix_quick_gate.sh PASS.
    • Target tests (82) pass, both plain and with GITHUB_ACTIONS=true.
    • arm64 container (--network=none, non-root): maturin + import + llvm-cov OK.
  • amd64 verification (coordinator, s1 host, fast-mlsirm#2157 4eb6a4c0, toolchain 1.97.1): offline wheel build, extension placement, pytest 17 passed, _core import OK rust — 4 of 5 criteria pass. The remaining criterion is llvm-cov runtime: 56 min locally. Handling that runtime against the sandbox's 900 s cap is a separate follow-up.
  • Rollback: revert the merge commit. Repositories without a pin were never affected.

@seonghobae

Copy link
Copy Markdown
Contributor Author

Correction: the description said "coverage sits near 68% against its 100% gate". That was wrong. The 68.1% in the log is the docstring-coverage advisory (interrogate, "minimum 100.0%, actual 68.1%", and that step is recorded as PASS), not a gate. The gate failure itself was the configured pytest suite exiting 2 on the _core ImportError at collection (#2256 coverage log, L4597–L4956). The two root causes this PR fixes (Rust 1.85 < MSRV, _core shadowing) are unchanged. I fix the changelog wording in the follow-up PR.

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