Skip to content

Install Rust explicitly in the development version tests - #211

Open
garrison wants to merge 3 commits into
mainfrom
rust-toolchain
Open

Install Rust explicitly in the development version tests#211
garrison wants to merge 3 commits into
mainfrom
rust-toolchain

Conversation

@garrison

Copy link
Copy Markdown
Member

Occasionally, the development version tests will fail because the runner uses an image that does not include a Rust compiler. This is an attempt at fixing that issue.

This is based on Qiskit/qiskit#16731.

Occasionally, the development version tests will fail because the runner
uses an image that does not include a Rust compiler.  This is an attempt
at fixing that issue.

This is based on Qiskit/qiskit#16731.
@garrison garrison added the ci-cd Related to CI/CD pipeline label Aug 12, 2026
@garrison
garrison marked this pull request as ready for review August 20, 2026 22:18
@coveralls

coveralls commented Aug 20, 2026

Copy link
Copy Markdown

Coverage Report for CI Build 32529557299

Warning

Build has drifted: This PR's base is out of sync with its target branch, so coverage data may include unrelated changes.
Quick fix: rebase this PR. Learn more →

Coverage remained the same at 96.524%

Details

  • Coverage remained the same as the base build.
  • Patch coverage: No coverable lines changed in this PR.
  • No coverage regressions found.

Uncovered Changes

No uncovered changes found.

Coverage Regressions

No coverage regressions found.


Coverage Stats

Coverage Status
Relevant Lines: 1640
Covered Lines: 1583
Line Coverage: 96.52%
Coverage Strength: 0.97 hits per line

💛 - Coveralls

The intermittent development-version failures are not caused by the
runner image lacking a Rust compiler -- rustup is present on all of the
relevant images.  What actually happens is visible in the failing logs,
partway through `python -m build --wheel`:

    running build_rust
    info: syncing channel updates for 1.87-x86_64-unknown-linux-gnu
    info: recovering from a partially installed toolchain
    info: removing previous version of component rustc
    ...
    error: failed to install component:
           'clippy-preview-x86_64-unknown-linux-gnu',
           detected conflict: 'bin/cargo-clippy'
    error: can't find Rust compiler

Qiskit's rust-toolchain.toml pins a channel and requests `clippy` and
`rustfmt` as components, so setuptools-rust triggers an on-demand rustup
install of that toolchain.  When the runner image already carries a
partially-installed copy of it, rustup's recovery path removes `rustc`
and then aborts on a `bin/cargo-clippy` conflict, leaving no compiler
behind.  The "can't find Rust compiler" line is the symptom, not the
cause, which is why the failure looked like a missing toolchain.  It is
intermittent because it depends on which runner image generation the job
lands on.

The previous version of this step could not help, because
`rustup toolchain install` with no toolchain argument installs the
*active* toolchain, and "active" depends on the working directory:

    $ cd /tmp                       # no rust-toolchain.toml in scope
    $ rustup show active-toolchain
    stable-x86_64-unknown-linux-gnu (default)

    $ cd qiskit
    $ rustup show active-toolchain
    1.89-x86_64-unknown-linux-gnu (overridden by '.../rust-toolchain.toml')

That step ran before the clone existed, so it installed `stable` while
the build went on to need the pinned channel.  This differs from
Qiskit/qiskit#16731, which this was based on: there, every such step runs
inside a checkout of the repository that owns rust-toolchain.toml, so the
bare command resolves the pinned toolchain.  Here the toolchain-defining
repository is a nested clone created mid-job, so the same command means
something different.

So split the clone into its own step and run the installation inside it,
first uninstalling the pinned channel to clear any partial copy.  The
uninstall is what addresses the conflict; it is a no-op (exit 0) when
nothing is installed.  Note that `--force` does *not* help here, despite
being documented as forcing an update -- it still aborts on the same
component conflict.

`--profile minimal` is retained.  It does not suppress the `clippy` and
`rustfmt` components that rust-toolchain.toml requests explicitly, but it
does drop `rust-docs`, which rustup would otherwise download for a job
that never reads it.

Verified locally by reproducing the exact CI error against a staged
partial toolchain, and confirming the new sequence recovers from it.
@garrison

Copy link
Copy Markdown
Member Author

This comment was generated by Claude Opus 5 under my guidance.


I went back through the failing logs across the addon repos before pushing 473f075, and the diagnosis in the original PR description turns out to be wrong in a way that made the fix a no-op. Summarizing here for the record.

The failure is not a missing Rust compiler

Over the last ~100 development-version runs, the Build Qiskit SDK development wheel step failed 9 times: 2× sqd, 4× obp, 2× mpf, 1× aqc-tensor. (None in this repo — its 2 failures in that window were both in Test using tox environment, which is why this is easy to miss when only looking here.)

All 9 are the same failure, and rustup is present on the image:

running build_rust
info: syncing channel updates for 1.87-x86_64-unknown-linux-gnu
info: recovering from a partially installed toolchain
info: removing previous version of component rustc
...
error: failed to install component: 'clippy-preview-x86_64-unknown-linux-gnu', detected conflict: 'bin/cargo-clippy'
error: can't find Rust compiler

Qiskit's rust-toolchain.toml pins a channel and lists clippy/rustfmt in components, so setuptools-rust triggers an on-demand rustup install. When the image carries a partially installed copy of that toolchain, rustup's recovery path removes rustc and then aborts on a bin/cargo-clippy conflict — leaving no compiler. can't find Rust compiler is the symptom, not the cause. It's intermittent because it depends on which image generation the job lands on.

Why the original step couldn't help

rustup toolchain install with no toolchain argument installs the active toolchain, and "active" is directory-dependent:

$ cd /tmp                        # no rust-toolchain.toml in scope
$ rustup show active-toolchain
stable-x86_64-unknown-linux-gnu (default)

$ cd qiskit
$ rustup show active-toolchain
1.89-x86_64-unknown-linux-gnu (overridden by '.../rust-toolchain.toml')

The step ran before git clone, so it installed stable while the build needed the pinned channel. The failing on-demand install then happened later inside qiskit/, unchanged.

This is the structural difference from Qiskit/qiskit#16731: there, those steps run inside a checkout of the repo that owns rust-toolchain.toml, so the bare command resolves the pin. Here the toolchain-defining repo is a nested clone created mid-job — same command, different meaning.

What changed

Clone is now its own step, and the install runs inside it, preceded by an uninstall of the pinned channel to clear any partial copy. The uninstall is the part that actually addresses the conflict, and it's a no-op (exit 0) when nothing is installed.

Two findings worth recording, both from testing rather than reasoning:

  • --force does not work, despite being documented as "force an update, even if some components are missing". Against a staged conflict it fails identically. I had initially recommended it; that was wrong.
  • --profile minimal is worth keeping. It doesn't suppress clippy/rustfmt — the file requests those explicitly and the sets are unioned — but it does drop rust-docs, which rustup otherwise downloads for a job that never reads it.

Verification and caveat

I reproduced the exact CI error locally by staging a partial toolchain (a stray bin/cargo-clippy under ~/.rustup/toolchains/<pinned>/), confirmed --force still fails against it, and confirmed the uninstall-then-install sequence recovers.

The caveat: this failure depends on runner-image state, so green CI on this PR is not evidence of a fix — the last several weeks are green everywhere, including on main without the change. The local reproduction is the real evidence.

Since these repos share this workflow, it's probably worth propagating once we're satisfied — the failures cluster in sqd/obp/mpf/aqc-tensor rather than here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ci-cd Related to CI/CD pipeline

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants