Skip to content

Commit c2e43ce

Browse files
authored
[ci] Add MSRV minimality check (#2812)
This change adds a new CI script `ci/check_msrv_is_minimal.sh` that verifies that the package's MSRV is strictly lower than any version specified in `package.metadata.build-rs`. This ensures that we don't accidentally bump our MSRV unnecessarily. The check is added to: - `.github/workflows/ci.yml` as a new job. - `githooks/pre-push` to be run locally. The script implementation uses a Python script embedded via heredoc and executed via `python3 -c` for better readability and maintainability.
1 parent 360bb2b commit c2e43ce

File tree

3 files changed

+88
-1
lines changed

3 files changed

+88
-1
lines changed

.github/workflows/ci.yml

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -718,6 +718,19 @@ jobs:
718718
- name: Check crate versions match
719719
run: ./ci/check_versions.sh
720720

721+
check_msrv_is_minimal:
722+
needs: generate_cache
723+
runs-on: ubuntu-latest
724+
name: Check MSRV is minimal
725+
steps:
726+
- uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1
727+
728+
- name: Populate cache
729+
uses: ./.github/actions/cache
730+
731+
- name: Check MSRV is minimal
732+
run: ./ci/check_msrv_is_minimal.sh
733+
721734
generate_cache:
722735
runs-on: ubuntu-latest
723736
name: Generate cache
@@ -833,7 +846,7 @@ jobs:
833846
# https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/collaborating-on-repositories-with-code-quality-features/troubleshooting-required-status-checks#handling-skipped-but-required-checks
834847
if: failure()
835848
runs-on: ubuntu-latest
836-
needs: [build_test, kani, check_be_aarch64, check_avr_artmega, check_fmt, check_readme, check_versions, generate_cache, check-all-toolchains-tested, check-job-dependencies, check-todo, run-git-hooks]
849+
needs: [build_test, kani, check_be_aarch64, check_avr_artmega, check_fmt, check_readme, check_versions, check_msrv_is_minimal, generate_cache, check-all-toolchains-tested, check-job-dependencies, check-todo, run-git-hooks]
837850
steps:
838851
- name: Mark the job as failed
839852
run: exit 1

ci/check_msrv_is_minimal.sh

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
#!/usr/bin/env bash
2+
#
3+
# Copyright 2025 The Fuchsia Authors
4+
#
5+
# Licensed under a BSD-style license <LICENSE-BSD>, Apache License, Version 2.0
6+
# <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT
7+
# license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
8+
# This file may not be copied, modified, or distributed except according to
9+
# those terms.
10+
11+
set -eo pipefail
12+
13+
read -r -d '' PYTHON_SCRIPT <<'EOF' || true
14+
import sys
15+
import json
16+
17+
def parse_version(v):
18+
"""Converts a version string to a tuple of integers."""
19+
return tuple(map(int, v.split(".")))
20+
21+
def main():
22+
"""
23+
Checks that the package's MSRV is strictly lower than any version
24+
specified in `package.metadata.build-rs`.
25+
"""
26+
try:
27+
data = json.load(sys.stdin)
28+
except json.JSONDecodeError as e:
29+
print(f"Error parsing JSON from cargo metadata: {e}", file=sys.stderr)
30+
sys.exit(1)
31+
32+
# Find the zerocopy package
33+
try:
34+
pkg = next(p for p in data["packages"] if p["name"] == "zerocopy")
35+
except StopIteration:
36+
print("Error: zerocopy package not found in metadata", file=sys.stderr)
37+
sys.exit(1)
38+
39+
msrv_str = pkg.get("rust_version")
40+
if not msrv_str:
41+
print("Error: rust-version not found in Cargo.toml", file=sys.stderr)
42+
sys.exit(1)
43+
44+
try:
45+
msrv = parse_version(msrv_str)
46+
except ValueError:
47+
print(f"Error: Invalid MSRV format: {msrv_str}", file=sys.stderr)
48+
sys.exit(1)
49+
50+
build_rs_versions = (pkg.get("metadata") or {}).get("build-rs", {})
51+
52+
failed = False
53+
for name, ver_str in build_rs_versions.items():
54+
try:
55+
ver = parse_version(ver_str)
56+
except ValueError:
57+
print(f"Warning: Skipping invalid version format for {name}: {ver_str}", file=sys.stderr)
58+
continue
59+
60+
# Check that MSRV < Version (strictly lower)
61+
if not (msrv < ver):
62+
print(f"Error: MSRV ({msrv_str}) is not strictly lower than {name} ({ver_str})", file=sys.stderr)
63+
failed = True
64+
65+
if failed:
66+
sys.exit(1)
67+
68+
if __name__ == "__main__":
69+
main()
70+
EOF
71+
72+
cargo metadata --format-version 1 --no-deps | python3 -c "$PYTHON_SCRIPT"

githooks/pre-push

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ echo "Running pre-push git hook: $0"
2020
./ci/check_readme.sh >/dev/null & README_PID=$!
2121
./ci/check_todo.sh >/dev/null & XODO_PID=$!
2222
./ci/check_versions.sh >/dev/null & VERSIONS_PID=$!
23+
./ci/check_msrv_is_minimal.sh >/dev/null & MSRV_PID=$!
2324

2425
# `wait <pid>` exits with the same status code as the job it's waiting for.
2526
# Since we `set -e` above, this will have the effect of causing the entire
@@ -33,6 +34,7 @@ wait $JOB_DEPS_PID
3334
wait $README_PID
3435
wait $XODO_PID
3536
wait $VERSIONS_PID
37+
wait $MSRV_PID
3638

3739
# Ensure that this script calls all scripts in `ci/*`. This isn't a foolproof
3840
# check since it just checks for the string in this script (e.g., it could be in

0 commit comments

Comments
 (0)