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
4 changes: 3 additions & 1 deletion .github/actions/msrv/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ Compile a crate on its **declared minimum supported Rust version** to catch a de

The action reads `rust-version` from the crate's `Cargo.toml`, builds the toolchain image at *exactly* that Rust version (`image/Dockerfile` on `rust:<msrv>`), and runs `cargo check` inside it, sealed.
Because the container's compiler **is** the declared MSRV, a plain `cargo check` is the MSRV check — there is no separate MSRV tool to install and no toolchain to select.
`command: "test"` runs `cargo test` instead, extending the floor to dev-dependencies and the test suite; the source stays mounted read-only, so tests that write into the checkout fail by design.

**When you need it:** if your main CI already runs the sealed Docker pipeline, set `build-image`'s `rust-version: msrv` instead and the normal `lint-and-test` gate enforces the MSRV across fmt/clippy/test — this action is then redundant. It earns its place when CI runs **natively** or on **stable**: a dedicated, cheap (`cargo check`) floor gate you add as a single job without converting the rest of the pipeline.

Expand Down Expand Up @@ -33,7 +34,8 @@ Set `locked: "true"` to require a committed `Cargo.lock` and check exactly those
| Input | Default | Description |
| --- | --- | --- |
| `package` | `""` | Package to check (`-p`); required for a multi-member workspace. |
| `features` | `""` | Feature flag passed to `cargo check` (e.g. `--features full`). |
| `features` | `""` | Feature flag passed to the cargo command (e.g. `--features full`). |
| `command` | `"check"` | `"check"` compiles; `"test"` also builds and runs the test suite on the MSRV (dev-deps included). |
| `rust-version` | `""` | MSRV to test. Empty reads `rust-version` from `Cargo.toml`. |
| `working-directory` | `.` | Crate/workspace directory (Cargo.toml read from here; mounted read-only). |
| `locked` | `"false"` | `"false"` resolves a fresh lock at the MSRV (in a disposable copy — the checkout is never modified); `"true"` requires a committed `Cargo.lock` and checks exactly that. |
Expand Down
17 changes: 13 additions & 4 deletions .github/actions/msrv/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,13 @@ inputs:
description: Feature flag passed to `cargo check` (e.g. --features full, --all-features).
required: false
default: ""
command:
description: >-
"check" (default) compiles; "test" builds and runs the test suite on the MSRV, so
dev-dependencies and test code are held to the floor too. The source stays mounted
read-only either way — tests that write into the checkout fail by design.
required: false
default: "check"
rust-version:
description: >-
MSRV to test. Empty (default) reads `rust-version` from the crate's Cargo.toml,
Expand Down Expand Up @@ -108,7 +115,7 @@ runs:
CACHE: "false"
run: bash "$GITHUB_ACTION_PATH/../build-image/build-image.sh"

- name: cargo check on the MSRV (sealed)
- name: cargo ${{ inputs.command }} on the MSRV (sealed)
shell: bash
working-directory: ${{ inputs.working-directory }}
env:
Expand All @@ -118,6 +125,7 @@ runs:
OFFLINE: ${{ inputs.offline }}
PACKAGE: ${{ inputs.package }}
FEATURES: ${{ inputs.features }}
COMMAND: ${{ inputs.command }}
LOCKED: ${{ inputs.locked }}
MSRV: ${{ steps.resolve.outputs.msrv }}
ENV_INCLUDE: ${{ inputs.env-include }}
Expand Down Expand Up @@ -210,8 +218,9 @@ runs:
fi

export CICD_DIR="$GITHUB_ACTION_PATH"
# PACKAGE/FEATURES/MSRV aren't CARGO_* (env-include won't forward them); inject them for
# the in-container script. seal_run reads OFFLINE for --network; the check is always --locked.
EXTRA_ENV="$(printf '%s\n%s\n%s' "PACKAGE=$PACKAGE" "FEATURES=$FEATURES" "MSRV=$MSRV")"
# PACKAGE/FEATURES/COMMAND/MSRV aren't CARGO_* (env-include won't forward them); inject
# them for the in-container script. seal_run reads OFFLINE for --network; the run is
# always --locked.
EXTRA_ENV="$(printf '%s\n%s\n%s\n%s' "PACKAGE=$PACKAGE" "FEATURES=$FEATURES" "COMMAND=$COMMAND" "MSRV=$MSRV")"
export EXTRA_ENV
seal_run bash /cicd/msrv.sh
25 changes: 18 additions & 7 deletions .github/actions/msrv/msrv.sh
Original file line number Diff line number Diff line change
@@ -1,18 +1,29 @@
#!/usr/bin/env bash
# Compile the crate inside the MSRV image (its toolchain already IS the declared MSRV, so a
# plain `cargo check` is the MSRV check). PACKAGE / FEATURES (each may be empty) shape the
# command. The lockfile is resolved up front by the action — the source is mounted read-only
# here, so the check always runs --locked and only reads it. OFFLINE=true appends --offline
# (assumes a prior cargo-fetch + the action's --network none). cargo runs in the mounted workdir.
# Compile — or test — the crate inside the MSRV image (its toolchain already IS the declared
# MSRV, so a plain `cargo check` is the MSRV check, and `cargo test` extends the floor to
# dev-dependencies and the test suite). PACKAGE / FEATURES (each may be empty) shape the
# command; COMMAND selects check (default) or test. The lockfile is resolved up front by the
# action — the source is mounted read-only here, so the run is always --locked and only reads
# it. OFFLINE=true appends --offline (assumes a prior cargo-fetch + the action's
# --network none). cargo runs in the mounted workdir.
set -euo pipefail

command="${COMMAND:-check}"
case "$command" in
check | test) ;;
*)
echo "::error::msrv: command must be 'check' or 'test', got '$command'"
exit 1
;;
esac

offline_arg=""
if [ "${OFFLINE:-false}" = "true" ]; then offline_arg="--offline"; fi
pkg_arg=""
if [ -n "${PACKAGE:-}" ]; then pkg_arg="-p ${PACKAGE}"; fi

echo "::group::cargo check on MSRV ${MSRV:-?}"
echo "::group::cargo ${command} on MSRV ${MSRV:-?}"
rustc --version
# shellcheck disable=SC2086 # pkg/offline/FEATURES are intentionally word-split (flag or empty)
cargo check $pkg_arg $offline_arg --locked ${FEATURES:-}
cargo "$command" $pkg_arg $offline_arg --locked ${FEATURES:-}
echo "::endgroup::"
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -247,7 +247,8 @@ See [the action's README](.github/actions/msrv/README.md).
- uses: gronke/rust-ci/.github/actions/msrv@main
with:
package: my-crate # required for a workspace with >1 member
features: "--features full" # optional; the flag passed to cargo check
features: "--features full" # optional; the flag passed to the cargo command
# command: "test" # optional; run the test suite on the MSRV (dev-deps included)
# rust-version: "1.95" # optional override; default reads Cargo.toml
```

Expand Down
Loading