Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 11 additions & 2 deletions .github/workflows/mutation-cargo.yml
Original file line number Diff line number Diff line change
Expand Up @@ -213,10 +213,19 @@ jobs:
CARGO_MUTANTS_VERSION: ${{ inputs.cargo-mutants-version }}
run: |
set -euo pipefail
# `--locked` is forwarded to the source-build fallback that
# cargo-binstall runs when no prebuilt binary matches the runner.
# Without it the fallback resolves cargo-mutants' dependency tree
# to the newest permitted versions, which can pull in a transitive
# crate whose MSRV exceeds the pinned nightly toolchain (e.g.
# cargo-platform 0.3.3 requiring rustc 1.91) and fail the install.
# Building against the crate's committed Cargo.lock keeps the
# install reproducible against the pinned toolchain (issue #364).
# Mirrors the cargo-nextest install in the generate-coverage action.
if [[ -n "${CARGO_MUTANTS_VERSION}" ]]; then
cargo binstall --no-confirm "cargo-mutants@${CARGO_MUTANTS_VERSION}"
cargo binstall --no-confirm --locked "cargo-mutants@${CARGO_MUTANTS_VERSION}"
else
cargo binstall --no-confirm cargo-mutants
cargo binstall --no-confirm --locked cargo-mutants
fi

- name: Run setup commands
Expand Down
29 changes: 29 additions & 0 deletions workflow_scripts/tests/test_mutation_workflow_shape.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,35 @@ def _step_names(steps: list[dict[str, object]]) -> list[object]:
return [step.get("name") for step in steps]


def test_cargo_mutants_install_is_locked() -> None:
"""The cargo-mutants install pins its dependency resolution with --locked.

``cargo binstall`` falls back to a source build when no prebuilt binary
matches the runner. Without ``--locked`` that fallback resolves the
dependency tree to the newest permitted versions and can pull in a
transitive crate whose MSRV exceeds the pinned nightly toolchain, failing
the install before any mutant runs (issue #364).
"""
steps = [
step
for job in _jobs("mutation-cargo.yml").values()
for step in _steps(job)
if step.get("name") == "Install cargo-mutants"
]
assert steps, "mutation-cargo.yml must install cargo-mutants"
for step in steps:
run = step.get("run")
assert isinstance(run, str), "install step must have a run block"
binstall_lines = [line for line in run.splitlines() if "cargo binstall" in line]
assert binstall_lines, "install step must invoke cargo binstall"
for line in binstall_lines:
assert "--locked" in line, (
f"cargo binstall must pass --locked so the source-build "
f"fallback honours the committed Cargo.lock (issue #364): "
f"{line.strip()!r}"
)


@pytest.mark.parametrize("workflow_name", WORKFLOW_NAMES)
def test_every_workflow_checkout_is_followed_by_relocation(
workflow_name: str,
Expand Down
Loading