From 3ef6cb89191048409b1a3d71d6e37d4a856f9584 Mon Sep 17 00:00:00 2001 From: Piotr Mlocek Date: Tue, 8 Sep 2026 14:45:03 -0700 Subject: [PATCH 1/8] ci(rust): reject stale Cargo lockfiles Signed-off-by: Piotr Mlocek --- .github/workflows/branch-checks.yml | 12 +++++--- tasks/rust.toml | 15 ++++++--- tasks/scripts/check-cargo-lockfiles.sh | 42 ++++++++++++++++++++++++++ 3 files changed, 60 insertions(+), 9 deletions(-) create mode 100755 tasks/scripts/check-cargo-lockfiles.sh diff --git a/.github/workflows/branch-checks.yml b/.github/workflows/branch-checks.yml index 72f8273c1a..a9dbde90b3 100644 --- a/.github/workflows/branch-checks.yml +++ b/.github/workflows/branch-checks.yml @@ -153,6 +153,10 @@ jobs: cache-bin: "false" cmd-format: nix develop .#devShells.${{ matrix.system }}.default -c {0} + - name: Verify Cargo lockfiles + if: matrix.system == 'x86_64-linux' + run: tasks/scripts/check-cargo-lockfiles.sh + - name: Format run: | cargo fmt --all -- --check @@ -162,10 +166,10 @@ jobs: - name: Lint run: | - cargo clippy --workspace --all-targets -- -D warnings - cargo clippy --manifest-path e2e/rust/Cargo.toml --all-targets -- -D warnings - cargo check --manifest-path examples/governance-interceptor/Cargo.toml --all-targets - cargo check --manifest-path examples/supervisor-middleware-content-guard/Cargo.toml --all-targets + cargo clippy --locked --workspace --all-targets -- -D warnings + cargo clippy --locked --manifest-path e2e/rust/Cargo.toml --all-targets -- -D warnings + cargo check --locked --manifest-path examples/governance-interceptor/Cargo.toml --all-targets + cargo check --locked --manifest-path examples/supervisor-middleware-content-guard/Cargo.toml --all-targets - name: Test env: diff --git a/tasks/rust.toml b/tasks/rust.toml index e62e22b3cf..2189da2d53 100644 --- a/tasks/rust.toml +++ b/tasks/rust.toml @@ -5,17 +5,22 @@ ["rust:check"] description = "Check all Rust crates for errors" -run = "cargo check --workspace" +run = "cargo check --locked --workspace" run_windows = "powershell -NoProfile -ExecutionPolicy Bypass -File tasks/scripts/windows-msvc.ps1 check native" hide = true +["rust:lockfiles:check"] +description = "Verify all tracked Cargo lockfiles are current" +run = "tasks/scripts/check-cargo-lockfiles.sh" +hide = true + ["rust:lint"] description = "Lint Rust code with Clippy (deny warnings)" run = [ - "cargo clippy --workspace --all-targets -- -D warnings", - "cargo clippy --manifest-path e2e/rust/Cargo.toml --all-targets -- -D warnings", - "cargo check --manifest-path examples/governance-interceptor/Cargo.toml --all-targets", - "cargo check --manifest-path examples/supervisor-middleware-content-guard/Cargo.toml --all-targets", + "cargo clippy --locked --workspace --all-targets -- -D warnings", + "cargo clippy --locked --manifest-path e2e/rust/Cargo.toml --all-targets -- -D warnings", + "cargo check --locked --manifest-path examples/governance-interceptor/Cargo.toml --all-targets", + "cargo check --locked --manifest-path examples/supervisor-middleware-content-guard/Cargo.toml --all-targets", ] run_windows = "powershell -NoProfile -ExecutionPolicy Bypass -File tasks/scripts/windows-msvc.ps1 lint native" hide = true diff --git a/tasks/scripts/check-cargo-lockfiles.sh b/tasks/scripts/check-cargo-lockfiles.sh new file mode 100755 index 0000000000..db671270e8 --- /dev/null +++ b/tasks/scripts/check-cargo-lockfiles.sh @@ -0,0 +1,42 @@ +#!/usr/bin/env bash +# SPDX-FileCopyrightText: Copyright (c) 2025-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 + +set -euo pipefail + +cd "$(git rev-parse --show-toplevel)" + +found=0 +status=0 + +while IFS= read -r -d '' lockfile; do + found=1 + manifest="${lockfile%Cargo.lock}Cargo.toml" + + if [[ ! -f "$manifest" ]]; then + echo "error: tracked lockfile $lockfile has no adjacent Cargo.toml" >&2 + status=1 + continue + fi + + echo "Checking $lockfile" + if ! cargo metadata \ + --locked \ + --format-version 1 \ + --manifest-path "$manifest" \ + >/dev/null; then + echo "error: $lockfile is out of sync with $manifest" >&2 + status=1 + fi +done < <(git ls-files -z -- ':(glob)**/Cargo.lock') + +if [[ "$found" -eq 0 ]]; then + echo "error: no tracked Cargo.lock files found" >&2 + exit 1 +fi + +if [[ "$status" -ne 0 ]]; then + echo "Refresh the reported lockfiles with Cargo and commit the results." >&2 +fi + +exit "$status" From 7fa562f0809b5f5787aa947531e5ec05c96d53f1 Mon Sep 17 00:00:00 2001 From: Piotr Mlocek Date: Tue, 8 Sep 2026 15:17:01 -0700 Subject: [PATCH 2/8] docs(ci): clarify lockfile validation policy Signed-off-by: Piotr Mlocek --- tasks/scripts/check-cargo-lockfiles.sh | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tasks/scripts/check-cargo-lockfiles.sh b/tasks/scripts/check-cargo-lockfiles.sh index db671270e8..4a3e584e0d 100755 --- a/tasks/scripts/check-cargo-lockfiles.sh +++ b/tasks/scripts/check-cargo-lockfiles.sh @@ -9,6 +9,9 @@ cd "$(git rev-parse --show-toplevel)" found=0 status=0 +# Policy: every tracked Cargo.lock represents an intentionally reproducible +# Cargo workspace and must resolve against its adjacent Cargo.toml. Manifests +# that intentionally do not own a lockfile are outside this check. while IFS= read -r -d '' lockfile; do found=1 manifest="${lockfile%Cargo.lock}Cargo.toml" From 3ea510cbc389522f8eba6ec937743a1297b48139 Mon Sep 17 00:00:00 2001 From: Piotr Mlocek Date: Tue, 8 Sep 2026 15:32:02 -0700 Subject: [PATCH 3/8] refactor(ci): structure and test Cargo lockfile validation Signed-off-by: Piotr Mlocek --- .github/workflows/branch-checks.yml | 3 + TESTING.md | 2 + tasks/scripts/check-cargo-lockfiles.sh | 61 +++++++----- tasks/scripts/check_cargo_lockfiles_test.py | 101 ++++++++++++++++++++ tasks/test.toml | 7 ++ 5 files changed, 148 insertions(+), 26 deletions(-) create mode 100644 tasks/scripts/check_cargo_lockfiles_test.py diff --git a/.github/workflows/branch-checks.yml b/.github/workflows/branch-checks.yml index a9dbde90b3..260729fd60 100644 --- a/.github/workflows/branch-checks.yml +++ b/.github/workflows/branch-checks.yml @@ -252,6 +252,9 @@ jobs: bash tasks/scripts/test-gateway-pull-policy.sh bash tasks/scripts/test-gateway-config.sh + - name: Test Cargo lockfile validation + run: mise run test:cargo-lockfiles + go: name: Go SDK needs: pr_metadata diff --git a/TESTING.md b/TESTING.md index 5d9674dd06..ed02ad7344 100644 --- a/TESTING.md +++ b/TESTING.md @@ -46,6 +46,8 @@ Run Rust tests only: mise run test:rust # cargo test --workspace ``` +Run `mise run rust:lockfiles:check` to validate every tracked Cargo lockfile against its adjacent manifest. Cargo diagnostics explain whether a failure requires refreshing a lockfile or resolving another problem, such as registry access. Run `mise run test:cargo-lockfiles` for the validator's regression tests, which use temporary Git repositories and a stub Cargo command. These tests also run in `mise run test` and the Python branch CI jobs. + ## Python Unit Tests Python unit tests use the `*_test.py` suffix convention (not `test_*` prefix) diff --git a/tasks/scripts/check-cargo-lockfiles.sh b/tasks/scripts/check-cargo-lockfiles.sh index 4a3e584e0d..bd74d8d647 100755 --- a/tasks/scripts/check-cargo-lockfiles.sh +++ b/tasks/scripts/check-cargo-lockfiles.sh @@ -4,42 +4,51 @@ set -euo pipefail -cd "$(git rev-parse --show-toplevel)" - -found=0 -status=0 - -# Policy: every tracked Cargo.lock represents an intentionally reproducible -# Cargo workspace and must resolve against its adjacent Cargo.toml. Manifests -# that intentionally do not own a lockfile are outside this check. -while IFS= read -r -d '' lockfile; do - found=1 - manifest="${lockfile%Cargo.lock}Cargo.toml" +check_lockfile() { + local lockfile="$1" + local manifest="${lockfile%Cargo.lock}Cargo.toml" if [[ ! -f "$manifest" ]]; then - echo "error: tracked lockfile $lockfile has no adjacent Cargo.toml" >&2 - status=1 - continue + printf 'error: tracked lockfile %s has no adjacent Cargo.toml\n' "$lockfile" >&2 + return 1 fi - echo "Checking $lockfile" + printf 'Checking %s\n' "$lockfile" if ! cargo metadata \ --locked \ --format-version 1 \ --manifest-path "$manifest" \ >/dev/null; then - echo "error: $lockfile is out of sync with $manifest" >&2 - status=1 + printf 'error: validation failed for %s\n' "$lockfile" >&2 + return 1 + fi +} + +main() { + local lockfile + local found=0 + local failed=0 + + cd "$(git rev-parse --show-toplevel)" + + # Policy: every tracked Cargo.lock represents an intentionally reproducible + # Cargo workspace and must resolve against its adjacent Cargo.toml. Manifests + # that intentionally do not own a lockfile are outside this check. + while IFS= read -r -d '' lockfile; do + found=1 + check_lockfile "$lockfile" || failed=1 + done < <(git ls-files -z -- ':(glob)**/Cargo.lock') + + if [[ "$found" -eq 0 ]]; then + echo "error: no tracked Cargo.lock files found" >&2 + return 1 fi -done < <(git ls-files -z -- ':(glob)**/Cargo.lock') -if [[ "$found" -eq 0 ]]; then - echo "error: no tracked Cargo.lock files found" >&2 - exit 1 -fi + if [[ "$failed" -ne 0 ]]; then + echo "Resolve the reported errors. If a lockfile needs updating, refresh it with Cargo and commit the result." >&2 + fi -if [[ "$status" -ne 0 ]]; then - echo "Refresh the reported lockfiles with Cargo and commit the results." >&2 -fi + return "$failed" +} -exit "$status" +main "$@" diff --git a/tasks/scripts/check_cargo_lockfiles_test.py b/tasks/scripts/check_cargo_lockfiles_test.py new file mode 100644 index 0000000000..785c8819a9 --- /dev/null +++ b/tasks/scripts/check_cargo_lockfiles_test.py @@ -0,0 +1,101 @@ +# SPDX-FileCopyrightText: Copyright (c) 2025-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 + +import os +import subprocess +from pathlib import Path + +import pytest + +SCRIPT = Path(__file__).with_name("check-cargo-lockfiles.sh") + + +@pytest.fixture +def repo(tmp_path): + subprocess.run(["git", "init", "-q", str(tmp_path)], check=True) + return tmp_path + + +def workspace(repo, directory=".", *, manifest=True, tracked=True): + root = repo / directory + root.mkdir(parents=True, exist_ok=True) + lockfile = root / "Cargo.lock" + lockfile.touch() + if manifest: + (root / "Cargo.toml").touch() + if tracked: + subprocess.run(["git", "add", str(lockfile)], cwd=repo, check=True) + + +def run_check(repo, *, failing_manifest="", cwd=None): + bin_dir = repo / "bin" + bin_dir.mkdir() + cargo = bin_dir / "cargo" + cargo.write_text( + "#!/usr/bin/env bash\n" + "set -euo pipefail\n" + '[[ "$#" -eq 6 && "$1" == metadata && "$2" == --locked && ' + '"$3" == --format-version && "$4" == 1 && "$5" == --manifest-path ]]\n' + 'printf "%s\\0" "$6" >> "$CALL_LOG"\n' + 'if [[ "$6" == "$FAILING_MANIFEST" ]]; then\n' + ' echo "registry unavailable" >&2\n' + " exit 1\n" + "fi\n" + 'echo "metadata output"\n' + ) + cargo.chmod(0o755) + log = repo / "calls" + result = subprocess.run( + ["bash", str(SCRIPT)], + cwd=cwd or repo, + env={ + **os.environ, + "PATH": f"{bin_dir}{os.pathsep}{os.environ['PATH']}", + "CALL_LOG": str(log), + "FAILING_MANIFEST": failing_manifest, + }, + capture_output=True, + text=True, + ) + calls = log.read_bytes().split(b"\0")[:-1] if log.exists() else [] + return result, [entry.decode() for entry in calls] + + +def test_no_tracked_lockfiles(repo): + workspace(repo, tracked=False) + result, calls = run_check(repo) + assert result.returncode == 1 + assert "no tracked Cargo.lock files found" in result.stderr + assert calls == [] + + +def test_missing_manifest_does_not_stop_later_checks(repo): + workspace(repo, "a-missing", manifest=False) + workspace(repo, "z-valid") + result, calls = run_check(repo) + assert result.returncode == 1 + assert "a-missing/Cargo.lock has no adjacent Cargo.toml" in result.stderr + assert calls == ["z-valid/Cargo.toml"] + + +@pytest.mark.parametrize("directory", ["nested workspace", "nested\nworkspace"]) +def test_success_from_subdirectory_with_unusual_path(repo, directory): + workspace(repo) + workspace(repo, directory) + workspace(repo, "untracked", tracked=False) + result, calls = run_check(repo, cwd=repo / directory) + assert result.returncode == 0, result.stderr + assert calls == ["Cargo.toml", f"{directory}/Cargo.toml"] + assert "metadata output" not in result.stdout + + +def test_cargo_failure_preserves_diagnostic_and_continues(repo): + workspace(repo, "a-failing") + workspace(repo, "z-valid") + result, calls = run_check(repo, failing_manifest="a-failing/Cargo.toml") + assert result.returncode == 1 + assert calls == ["a-failing/Cargo.toml", "z-valid/Cargo.toml"] + assert "registry unavailable" in result.stderr + assert "validation failed for a-failing/Cargo.lock" in result.stderr + assert "out of sync" not in result.stderr + assert "If a lockfile needs updating" in result.stderr diff --git a/tasks/test.toml b/tasks/test.toml index 0fa0bd8496..22e0d21f04 100644 --- a/tasks/test.toml +++ b/tasks/test.toml @@ -15,6 +15,7 @@ depends = [ "test:gateway-pull-policy", "test:gateway-config", "test:e2e-parity", + "test:cargo-lockfiles", "test:packaging-assets", "test:codex-security-release-range", "test:docs-website", @@ -26,6 +27,12 @@ description = "Test the docs-website sync script" # dependencies and the script's runtime dependency, which live outside the project env. run = "uv run --no-project --with pytest --with pytest-asyncio --with pyyaml pytest tasks/scripts/sync_docs_website_test.py" +["test:cargo-lockfiles"] +description = "Test Cargo lockfile validation script" +run = "uv run --no-project --with pytest --with pytest-asyncio pytest tasks/scripts/check_cargo_lockfiles_test.py" +run_windows = "echo Skipping test:cargo-lockfiles: the Bash validation script runs on Unix." +hide = true + ["test:sbom"] description = "Run SBOM tooling tests" run = "uv run --no-project --with pytest pytest -o \"python_files=*_test.py\" deploy/sbom/" From 8ff6fc97c00fdcf98dfd2c9d2e5bfde47dc67bfe Mon Sep 17 00:00:00 2001 From: Piotr Mlocek Date: Tue, 8 Sep 2026 15:41:48 -0700 Subject: [PATCH 4/8] chore(ci): remove lockfile validator regression tests Signed-off-by: Piotr Mlocek --- .github/workflows/branch-checks.yml | 4 - TESTING.md | 2 +- tasks/scripts/check_cargo_lockfiles_test.py | 101 -------------------- tasks/test.toml | 7 -- 4 files changed, 1 insertion(+), 113 deletions(-) delete mode 100644 tasks/scripts/check_cargo_lockfiles_test.py diff --git a/.github/workflows/branch-checks.yml b/.github/workflows/branch-checks.yml index 260729fd60..5fde741d10 100644 --- a/.github/workflows/branch-checks.yml +++ b/.github/workflows/branch-checks.yml @@ -251,10 +251,6 @@ jobs: run: | bash tasks/scripts/test-gateway-pull-policy.sh bash tasks/scripts/test-gateway-config.sh - - - name: Test Cargo lockfile validation - run: mise run test:cargo-lockfiles - go: name: Go SDK needs: pr_metadata diff --git a/TESTING.md b/TESTING.md index ed02ad7344..c6541e06eb 100644 --- a/TESTING.md +++ b/TESTING.md @@ -46,7 +46,7 @@ Run Rust tests only: mise run test:rust # cargo test --workspace ``` -Run `mise run rust:lockfiles:check` to validate every tracked Cargo lockfile against its adjacent manifest. Cargo diagnostics explain whether a failure requires refreshing a lockfile or resolving another problem, such as registry access. Run `mise run test:cargo-lockfiles` for the validator's regression tests, which use temporary Git repositories and a stub Cargo command. These tests also run in `mise run test` and the Python branch CI jobs. +Run `mise run rust:lockfiles:check` to validate every tracked Cargo lockfile against its adjacent manifest. Cargo diagnostics explain whether a failure requires refreshing a lockfile or resolving another problem, such as registry access. To refresh a stale lockfile, run `cargo metadata --format-version 1 --manifest-path path/to/Cargo.toml > /dev/null` with the adjacent manifest, review and commit the lockfile changes, then rerun `mise run pre-commit`. ## Python Unit Tests diff --git a/tasks/scripts/check_cargo_lockfiles_test.py b/tasks/scripts/check_cargo_lockfiles_test.py deleted file mode 100644 index 785c8819a9..0000000000 --- a/tasks/scripts/check_cargo_lockfiles_test.py +++ /dev/null @@ -1,101 +0,0 @@ -# SPDX-FileCopyrightText: Copyright (c) 2025-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. -# SPDX-License-Identifier: Apache-2.0 - -import os -import subprocess -from pathlib import Path - -import pytest - -SCRIPT = Path(__file__).with_name("check-cargo-lockfiles.sh") - - -@pytest.fixture -def repo(tmp_path): - subprocess.run(["git", "init", "-q", str(tmp_path)], check=True) - return tmp_path - - -def workspace(repo, directory=".", *, manifest=True, tracked=True): - root = repo / directory - root.mkdir(parents=True, exist_ok=True) - lockfile = root / "Cargo.lock" - lockfile.touch() - if manifest: - (root / "Cargo.toml").touch() - if tracked: - subprocess.run(["git", "add", str(lockfile)], cwd=repo, check=True) - - -def run_check(repo, *, failing_manifest="", cwd=None): - bin_dir = repo / "bin" - bin_dir.mkdir() - cargo = bin_dir / "cargo" - cargo.write_text( - "#!/usr/bin/env bash\n" - "set -euo pipefail\n" - '[[ "$#" -eq 6 && "$1" == metadata && "$2" == --locked && ' - '"$3" == --format-version && "$4" == 1 && "$5" == --manifest-path ]]\n' - 'printf "%s\\0" "$6" >> "$CALL_LOG"\n' - 'if [[ "$6" == "$FAILING_MANIFEST" ]]; then\n' - ' echo "registry unavailable" >&2\n' - " exit 1\n" - "fi\n" - 'echo "metadata output"\n' - ) - cargo.chmod(0o755) - log = repo / "calls" - result = subprocess.run( - ["bash", str(SCRIPT)], - cwd=cwd or repo, - env={ - **os.environ, - "PATH": f"{bin_dir}{os.pathsep}{os.environ['PATH']}", - "CALL_LOG": str(log), - "FAILING_MANIFEST": failing_manifest, - }, - capture_output=True, - text=True, - ) - calls = log.read_bytes().split(b"\0")[:-1] if log.exists() else [] - return result, [entry.decode() for entry in calls] - - -def test_no_tracked_lockfiles(repo): - workspace(repo, tracked=False) - result, calls = run_check(repo) - assert result.returncode == 1 - assert "no tracked Cargo.lock files found" in result.stderr - assert calls == [] - - -def test_missing_manifest_does_not_stop_later_checks(repo): - workspace(repo, "a-missing", manifest=False) - workspace(repo, "z-valid") - result, calls = run_check(repo) - assert result.returncode == 1 - assert "a-missing/Cargo.lock has no adjacent Cargo.toml" in result.stderr - assert calls == ["z-valid/Cargo.toml"] - - -@pytest.mark.parametrize("directory", ["nested workspace", "nested\nworkspace"]) -def test_success_from_subdirectory_with_unusual_path(repo, directory): - workspace(repo) - workspace(repo, directory) - workspace(repo, "untracked", tracked=False) - result, calls = run_check(repo, cwd=repo / directory) - assert result.returncode == 0, result.stderr - assert calls == ["Cargo.toml", f"{directory}/Cargo.toml"] - assert "metadata output" not in result.stdout - - -def test_cargo_failure_preserves_diagnostic_and_continues(repo): - workspace(repo, "a-failing") - workspace(repo, "z-valid") - result, calls = run_check(repo, failing_manifest="a-failing/Cargo.toml") - assert result.returncode == 1 - assert calls == ["a-failing/Cargo.toml", "z-valid/Cargo.toml"] - assert "registry unavailable" in result.stderr - assert "validation failed for a-failing/Cargo.lock" in result.stderr - assert "out of sync" not in result.stderr - assert "If a lockfile needs updating" in result.stderr diff --git a/tasks/test.toml b/tasks/test.toml index 22e0d21f04..0fa0bd8496 100644 --- a/tasks/test.toml +++ b/tasks/test.toml @@ -15,7 +15,6 @@ depends = [ "test:gateway-pull-policy", "test:gateway-config", "test:e2e-parity", - "test:cargo-lockfiles", "test:packaging-assets", "test:codex-security-release-range", "test:docs-website", @@ -27,12 +26,6 @@ description = "Test the docs-website sync script" # dependencies and the script's runtime dependency, which live outside the project env. run = "uv run --no-project --with pytest --with pytest-asyncio --with pyyaml pytest tasks/scripts/sync_docs_website_test.py" -["test:cargo-lockfiles"] -description = "Test Cargo lockfile validation script" -run = "uv run --no-project --with pytest --with pytest-asyncio pytest tasks/scripts/check_cargo_lockfiles_test.py" -run_windows = "echo Skipping test:cargo-lockfiles: the Bash validation script runs on Unix." -hide = true - ["test:sbom"] description = "Run SBOM tooling tests" run = "uv run --no-project --with pytest pytest -o \"python_files=*_test.py\" deploy/sbom/" From 63c71ea98dd13b5f4371b592c1f743beb5b18770 Mon Sep 17 00:00:00 2001 From: Piotr Mlocek Date: Thu, 10 Sep 2026 10:27:42 -0700 Subject: [PATCH 5/8] ci(rust): complete locked validation and lint examples Signed-off-by: Piotr Mlocek --- .github/workflows/branch-checks.yml | 18 +++++++++--------- TESTING.md | 2 +- architecture/build.md | 7 +++++++ tasks/ci.toml | 1 + tasks/rust.toml | 16 ++++++++-------- .../verify-defaults-without-telemetry.sh | 4 ++-- tasks/test.toml | 4 ++-- 7 files changed, 30 insertions(+), 22 deletions(-) diff --git a/.github/workflows/branch-checks.yml b/.github/workflows/branch-checks.yml index 5fde741d10..006a3b8910 100644 --- a/.github/workflows/branch-checks.yml +++ b/.github/workflows/branch-checks.yml @@ -168,22 +168,22 @@ jobs: run: | cargo clippy --locked --workspace --all-targets -- -D warnings cargo clippy --locked --manifest-path e2e/rust/Cargo.toml --all-targets -- -D warnings - cargo check --locked --manifest-path examples/governance-interceptor/Cargo.toml --all-targets - cargo check --locked --manifest-path examples/supervisor-middleware-content-guard/Cargo.toml --all-targets + cargo clippy --locked --manifest-path examples/governance-interceptor/Cargo.toml --all-targets -- -D warnings + cargo clippy --locked --manifest-path examples/supervisor-middleware-content-guard/Cargo.toml --all-targets -- -D warnings - name: Test env: OPENSHELL_TELEMETRY_ENABLED: "false" run: | - cargo nextest run --profile ci --workspace --features openshell-server/test-support + cargo nextest run --locked --profile ci --workspace --features openshell-server/test-support - name: Verify telemetry can be compiled out run: | - cargo build -p openshell-gateway --bin openshell-gateway + cargo build --locked -p openshell-gateway --bin openshell-gateway tasks/scripts/verify-telemetry-compiled-out.sh present target/debug/openshell-gateway - cargo build -p openshell-gateway --bin openshell-gateway --no-default-features --features defaults-without-telemetry + cargo build --locked -p openshell-gateway --bin openshell-gateway --no-default-features --features defaults-without-telemetry tasks/scripts/verify-telemetry-compiled-out.sh absent target/debug/openshell-gateway - cargo build -p openshell-sandbox --bin openshell-sandbox --no-default-features --features defaults-without-telemetry + cargo build --locked -p openshell-sandbox --bin openshell-sandbox --no-default-features --features defaults-without-telemetry tasks/scripts/verify-telemetry-compiled-out.sh absent target/debug/openshell-sandbox - name: Verify selective gateway compute-driver builds @@ -201,12 +201,12 @@ jobs: - name: Verify system CA roots build mode compiles and excludes bundled Mozilla roots run: | - cargo check -p openshell-sandbox --all-targets --no-default-features --features system-ca-roots - if cargo tree -p openshell-sandbox -i webpki-roots --no-default-features --features system-ca-roots 2>/dev/null | grep -q webpki-roots; then + cargo check --locked -p openshell-sandbox --all-targets --no-default-features --features system-ca-roots + if cargo tree --locked -p openshell-sandbox -i webpki-roots --no-default-features --features system-ca-roots 2>/dev/null | grep -q webpki-roots; then echo "ERROR: webpki-roots found in system CA roots build" >&2 exit 1 fi - if cargo tree -p openshell-sandbox -i webpki-root-certs --no-default-features --features system-ca-roots 2>/dev/null | grep -q webpki-root-certs; then + if cargo tree --locked -p openshell-sandbox -i webpki-root-certs --no-default-features --features system-ca-roots 2>/dev/null | grep -q webpki-root-certs; then echo "ERROR: webpki-root-certs found in system CA roots build" >&2 exit 1 fi diff --git a/TESTING.md b/TESTING.md index c6541e06eb..6c5879dc06 100644 --- a/TESTING.md +++ b/TESTING.md @@ -46,7 +46,7 @@ Run Rust tests only: mise run test:rust # cargo test --workspace ``` -Run `mise run rust:lockfiles:check` to validate every tracked Cargo lockfile against its adjacent manifest. Cargo diagnostics explain whether a failure requires refreshing a lockfile or resolving another problem, such as registry access. To refresh a stale lockfile, run `cargo metadata --format-version 1 --manifest-path path/to/Cargo.toml > /dev/null` with the adjacent manifest, review and commit the lockfile changes, then rerun `mise run pre-commit`. +Run `mise run rust:lockfiles:check` to validate every tracked Cargo lockfile against its adjacent manifest. This check also runs through `lint`, including `mise run pre-commit` and `mise run ci`. It resolves dependency metadata without compiling, but may download uncached dependencies. Cargo diagnostics explain whether a failure requires refreshing a lockfile or resolving another problem, such as registry access. To refresh a stale lockfile, run `cargo metadata --format-version 1 --manifest-path path/to/Cargo.toml > /dev/null` with the adjacent manifest, review and commit the lockfile changes, then rerun `mise run pre-commit`. ## Python Unit Tests diff --git a/architecture/build.md b/architecture/build.md index 5f3b913e1b..14ee6d48f0 100644 --- a/architecture/build.md +++ b/architecture/build.md @@ -514,6 +514,13 @@ Published docs live in `docs/`, and Fern site configuration lives in `fern/`. Se ## Validation Expectations +Rust lint tasks and branch checks run Clippy with warnings denied for the +workspace, E2E crate, and the standalone governance-interceptor and +supervisor-middleware-content-guard examples, including all Cargo targets. +The lint task also validates every tracked Cargo lockfile, so pre-commit +and local CI catch stale resolutions in standalone workspaces. Rust validation +commands use `--locked` to prevent implicit lockfile updates. + - Run `mise run pre-commit` before committing. - Run `mise run test` after code changes. - Run `mise run e2e` for sandbox, policy, driver, or deployment changes when the diff --git a/tasks/ci.toml b/tasks/ci.toml index cc4158448f..e2a388e6b1 100644 --- a/tasks/ci.toml +++ b/tasks/ci.toml @@ -54,6 +54,7 @@ description = "Run repository lint checks" depends = [ "license:check", "rust:format:check", + "rust:lockfiles:check", "rust:lint", "python:format:check", "python:lint", diff --git a/tasks/rust.toml b/tasks/rust.toml index 2189da2d53..acb841abe5 100644 --- a/tasks/rust.toml +++ b/tasks/rust.toml @@ -19,8 +19,8 @@ description = "Lint Rust code with Clippy (deny warnings)" run = [ "cargo clippy --locked --workspace --all-targets -- -D warnings", "cargo clippy --locked --manifest-path e2e/rust/Cargo.toml --all-targets -- -D warnings", - "cargo check --locked --manifest-path examples/governance-interceptor/Cargo.toml --all-targets", - "cargo check --locked --manifest-path examples/supervisor-middleware-content-guard/Cargo.toml --all-targets", + "cargo clippy --locked --manifest-path examples/governance-interceptor/Cargo.toml --all-targets -- -D warnings", + "cargo clippy --locked --manifest-path examples/supervisor-middleware-content-guard/Cargo.toml --all-targets -- -D warnings", ] run_windows = "powershell -NoProfile -ExecutionPolicy Bypass -File tasks/scripts/windows-msvc.ps1 lint native" hide = true @@ -59,14 +59,14 @@ description = "Verify telemetry emission code is compiled out with --no-default- run = [ # Positive control: the default (telemetry-on) gateway must contain the # markers, so the absent checks below can never become silently vacuous. - "cargo build -p openshell-gateway --bin openshell-gateway", + "cargo build --locked -p openshell-gateway --bin openshell-gateway", "tasks/scripts/verify-telemetry-compiled-out.sh present target/debug/openshell-gateway", # Guard: telemetry-free builds must contain no telemetry markers. Built # through the `defaults-without-telemetry` alias, which is how the docs tell # operators to produce these artifacts. - "cargo build -p openshell-gateway --bin openshell-gateway --no-default-features --features defaults-without-telemetry", + "cargo build --locked -p openshell-gateway --bin openshell-gateway --no-default-features --features defaults-without-telemetry", "tasks/scripts/verify-telemetry-compiled-out.sh absent target/debug/openshell-gateway", - "cargo build -p openshell-sandbox --bin openshell-sandbox --no-default-features --features defaults-without-telemetry", + "cargo build --locked -p openshell-sandbox --bin openshell-sandbox --no-default-features --features defaults-without-telemetry", "tasks/scripts/verify-telemetry-compiled-out.sh absent target/debug/openshell-sandbox", ] @@ -79,9 +79,9 @@ description = "Verify system CA roots build mode compiles and excludes bundled M run = [ # Check that the sandbox compiles cleanly in system CA roots mode (all # defaults except bundled-ca-roots). - "cargo check -p openshell-sandbox --all-targets --no-default-features --features system-ca-roots", + "cargo check --locked -p openshell-sandbox --all-targets --no-default-features --features system-ca-roots", # Guard: webpki-roots must not appear in the dependency graph. - "bash -c 'if cargo tree -p openshell-sandbox -i webpki-roots --no-default-features --features system-ca-roots 2>/dev/null | grep -q webpki-roots; then echo \"ERROR: webpki-roots found in system CA roots build\" >&2; exit 1; fi'", + "bash -c 'if cargo tree --locked -p openshell-sandbox -i webpki-roots --no-default-features --features system-ca-roots 2>/dev/null | grep -q webpki-roots; then echo \"ERROR: webpki-roots found in system CA roots build\" >&2; exit 1; fi'", # Guard: webpki-root-certs must not appear either (webpki-roots re-exports it). - "bash -c 'if cargo tree -p openshell-sandbox -i webpki-root-certs --no-default-features --features system-ca-roots 2>/dev/null | grep -q webpki-root-certs; then echo \"ERROR: webpki-root-certs found in system CA roots build\" >&2; exit 1; fi'", + "bash -c 'if cargo tree --locked -p openshell-sandbox -i webpki-root-certs --no-default-features --features system-ca-roots 2>/dev/null | grep -q webpki-root-certs; then echo \"ERROR: webpki-root-certs found in system CA roots build\" >&2; exit 1; fi'", ] diff --git a/tasks/scripts/verify-defaults-without-telemetry.sh b/tasks/scripts/verify-defaults-without-telemetry.sh index 1fd7e67dff..8eefdf5082 100755 --- a/tasks/scripts/verify-defaults-without-telemetry.sh +++ b/tasks/scripts/verify-defaults-without-telemetry.sh @@ -32,7 +32,7 @@ if ! command -v jq >/dev/null 2>&1; then exit 2 fi -metadata=$(cargo metadata --no-deps --format-version 1) +metadata=$(cargo metadata --locked --no-deps --format-version 1) failed=0 for crate in "${CRATES[@]}"; do @@ -71,7 +71,7 @@ done # host, and a check that failed for an unrelated reason would make this guard # silently vacuous. for crate in "${CRATES[@]}"; do - output=$(cargo check -p "$crate" --features defaults-without-telemetry 2>&1 || true) + output=$(cargo check --locked -p "$crate" --features defaults-without-telemetry 2>&1 || true) if grep -qF "features \`telemetry\` and \`defaults-without-telemetry\` are mutually exclusive" <<<"$output"; then echo "OK: $crate rejects 'telemetry' + 'defaults-without-telemetry'" diff --git a/tasks/test.toml b/tasks/test.toml index 0fa0bd8496..541c7b101d 100644 --- a/tasks/test.toml +++ b/tasks/test.toml @@ -82,8 +82,8 @@ env = { OPENSHELL_TELEMETRY_ENABLED = "false" } run = [ # Run the workspace once without openshell-server so we can run that crate # with test-only helpers enabled. - "cargo test --workspace --exclude openshell-server", - "cargo test -p openshell-server --features test-support", + "cargo test --locked --workspace --exclude openshell-server", + "cargo test --locked -p openshell-server --features test-support", ] run_windows = "powershell -NoProfile -ExecutionPolicy Bypass -File tasks/scripts/windows-msvc.ps1 test-precommit native" hide = true From 6a186045a2201342dbf7276637edb7228bb4af7d Mon Sep 17 00:00:00 2001 From: Piotr Mlocek Date: Thu, 10 Sep 2026 10:40:49 -0700 Subject: [PATCH 6/8] ci(rust): check lockfile diffs after validation Signed-off-by: Piotr Mlocek --- .github/workflows/branch-checks.yml | 32 ++++++++++--------- TESTING.md | 4 ++- architecture/build.md | 8 +++-- tasks/rust.toml | 24 +++++++------- .../verify-defaults-without-telemetry.sh | 4 +-- tasks/test.toml | 5 +-- 6 files changed, 43 insertions(+), 34 deletions(-) diff --git a/.github/workflows/branch-checks.yml b/.github/workflows/branch-checks.yml index 006a3b8910..2999cf5fc3 100644 --- a/.github/workflows/branch-checks.yml +++ b/.github/workflows/branch-checks.yml @@ -153,10 +153,6 @@ jobs: cache-bin: "false" cmd-format: nix develop .#devShells.${{ matrix.system }}.default -c {0} - - name: Verify Cargo lockfiles - if: matrix.system == 'x86_64-linux' - run: tasks/scripts/check-cargo-lockfiles.sh - - name: Format run: | cargo fmt --all -- --check @@ -166,24 +162,24 @@ jobs: - name: Lint run: | - cargo clippy --locked --workspace --all-targets -- -D warnings - cargo clippy --locked --manifest-path e2e/rust/Cargo.toml --all-targets -- -D warnings - cargo clippy --locked --manifest-path examples/governance-interceptor/Cargo.toml --all-targets -- -D warnings - cargo clippy --locked --manifest-path examples/supervisor-middleware-content-guard/Cargo.toml --all-targets -- -D warnings + cargo clippy --workspace --all-targets -- -D warnings + cargo clippy --manifest-path e2e/rust/Cargo.toml --all-targets -- -D warnings + cargo clippy --manifest-path examples/governance-interceptor/Cargo.toml --all-targets -- -D warnings + cargo clippy --manifest-path examples/supervisor-middleware-content-guard/Cargo.toml --all-targets -- -D warnings - name: Test env: OPENSHELL_TELEMETRY_ENABLED: "false" run: | - cargo nextest run --locked --profile ci --workspace --features openshell-server/test-support + cargo nextest run --profile ci --workspace --features openshell-server/test-support - name: Verify telemetry can be compiled out run: | - cargo build --locked -p openshell-gateway --bin openshell-gateway + cargo build -p openshell-gateway --bin openshell-gateway tasks/scripts/verify-telemetry-compiled-out.sh present target/debug/openshell-gateway - cargo build --locked -p openshell-gateway --bin openshell-gateway --no-default-features --features defaults-without-telemetry + cargo build -p openshell-gateway --bin openshell-gateway --no-default-features --features defaults-without-telemetry tasks/scripts/verify-telemetry-compiled-out.sh absent target/debug/openshell-gateway - cargo build --locked -p openshell-sandbox --bin openshell-sandbox --no-default-features --features defaults-without-telemetry + cargo build -p openshell-sandbox --bin openshell-sandbox --no-default-features --features defaults-without-telemetry tasks/scripts/verify-telemetry-compiled-out.sh absent target/debug/openshell-sandbox - name: Verify selective gateway compute-driver builds @@ -201,16 +197,22 @@ jobs: - name: Verify system CA roots build mode compiles and excludes bundled Mozilla roots run: | - cargo check --locked -p openshell-sandbox --all-targets --no-default-features --features system-ca-roots - if cargo tree --locked -p openshell-sandbox -i webpki-roots --no-default-features --features system-ca-roots 2>/dev/null | grep -q webpki-roots; then + cargo check -p openshell-sandbox --all-targets --no-default-features --features system-ca-roots + if cargo tree -p openshell-sandbox -i webpki-roots --no-default-features --features system-ca-roots 2>/dev/null | grep -q webpki-roots; then echo "ERROR: webpki-roots found in system CA roots build" >&2 exit 1 fi - if cargo tree --locked -p openshell-sandbox -i webpki-root-certs --no-default-features --features system-ca-roots 2>/dev/null | grep -q webpki-root-certs; then + if cargo tree -p openshell-sandbox -i webpki-root-certs --no-default-features --features system-ca-roots 2>/dev/null | grep -q webpki-root-certs; then echo "ERROR: webpki-root-certs found in system CA roots build" >&2 exit 1 fi + - name: Verify Cargo lockfiles unchanged + if: always() + run: | + tasks/scripts/check-cargo-lockfiles.sh + git diff --exit-code HEAD -- ':(glob)**/Cargo.lock' + python: name: Python (${{ matrix.runner }}) needs: pr_metadata diff --git a/TESTING.md b/TESTING.md index 6c5879dc06..5ae487a286 100644 --- a/TESTING.md +++ b/TESTING.md @@ -46,7 +46,9 @@ Run Rust tests only: mise run test:rust # cargo test --workspace ``` -Run `mise run rust:lockfiles:check` to validate every tracked Cargo lockfile against its adjacent manifest. This check also runs through `lint`, including `mise run pre-commit` and `mise run ci`. It resolves dependency metadata without compiling, but may download uncached dependencies. Cargo diagnostics explain whether a failure requires refreshing a lockfile or resolving another problem, such as registry access. To refresh a stale lockfile, run `cargo metadata --format-version 1 --manifest-path path/to/Cargo.toml > /dev/null` with the adjacent manifest, review and commit the lockfile changes, then rerun `mise run pre-commit`. +Run `mise run rust:lockfiles:check` to validate every tracked Cargo lockfile against its adjacent manifest. Local Rust lint, check, and test tasks depend on this guard, so it finishes before those Cargo commands start, including through pre-commit and local CI. It resolves dependency metadata without compiling, but may download uncached dependencies. Cargo diagnostics explain whether a failure requires refreshing a lockfile or resolving another problem, such as registry access. To refresh a stale lockfile, run `cargo metadata --format-version 1 --manifest-path path/to/Cargo.toml > /dev/null` with the adjacent manifest, review and commit the lockfile changes, then rerun `mise run pre-commit`. + +Each Rust CI job ends with lockfile validation and `git diff --exit-code HEAD -- ':(glob)**/Cargo.lock'`. This rejects tracked lockfile changes made during validation, even when the Cargo commands themselves succeed. The final step also runs after earlier failures. Ordinary build and test commands do not need `--locked`; the metadata guard is the single explicit use for this policy. ## Python Unit Tests diff --git a/architecture/build.md b/architecture/build.md index 14ee6d48f0..674d834853 100644 --- a/architecture/build.md +++ b/architecture/build.md @@ -517,9 +517,11 @@ Published docs live in `docs/`, and Fern site configuration lives in `fern/`. Se Rust lint tasks and branch checks run Clippy with warnings denied for the workspace, E2E crate, and the standalone governance-interceptor and supervisor-middleware-content-guard examples, including all Cargo targets. -The lint task also validates every tracked Cargo lockfile, so pre-commit -and local CI catch stale resolutions in standalone workspaces. Rust validation -commands use `--locked` to prevent implicit lockfile updates. +Local Rust lint, check, and test tasks validate every tracked Cargo lockfile +before running, including when invoked through pre-commit or local CI. +Each Rust branch-check job finishes by validating the lockfiles and comparing +them with the checked-out commit. Any tracked lockfile change fails the job, +including changes made by Cargo commands that completed successfully. - Run `mise run pre-commit` before committing. - Run `mise run test` after code changes. diff --git a/tasks/rust.toml b/tasks/rust.toml index acb841abe5..e8c45fd54c 100644 --- a/tasks/rust.toml +++ b/tasks/rust.toml @@ -5,7 +5,8 @@ ["rust:check"] description = "Check all Rust crates for errors" -run = "cargo check --locked --workspace" +depends = ["rust:lockfiles:check"] +run = "cargo check --workspace" run_windows = "powershell -NoProfile -ExecutionPolicy Bypass -File tasks/scripts/windows-msvc.ps1 check native" hide = true @@ -16,11 +17,12 @@ hide = true ["rust:lint"] description = "Lint Rust code with Clippy (deny warnings)" +depends = ["rust:lockfiles:check"] run = [ - "cargo clippy --locked --workspace --all-targets -- -D warnings", - "cargo clippy --locked --manifest-path e2e/rust/Cargo.toml --all-targets -- -D warnings", - "cargo clippy --locked --manifest-path examples/governance-interceptor/Cargo.toml --all-targets -- -D warnings", - "cargo clippy --locked --manifest-path examples/supervisor-middleware-content-guard/Cargo.toml --all-targets -- -D warnings", + "cargo clippy --workspace --all-targets -- -D warnings", + "cargo clippy --manifest-path e2e/rust/Cargo.toml --all-targets -- -D warnings", + "cargo clippy --manifest-path examples/governance-interceptor/Cargo.toml --all-targets -- -D warnings", + "cargo clippy --manifest-path examples/supervisor-middleware-content-guard/Cargo.toml --all-targets -- -D warnings", ] run_windows = "powershell -NoProfile -ExecutionPolicy Bypass -File tasks/scripts/windows-msvc.ps1 lint native" hide = true @@ -59,14 +61,14 @@ description = "Verify telemetry emission code is compiled out with --no-default- run = [ # Positive control: the default (telemetry-on) gateway must contain the # markers, so the absent checks below can never become silently vacuous. - "cargo build --locked -p openshell-gateway --bin openshell-gateway", + "cargo build -p openshell-gateway --bin openshell-gateway", "tasks/scripts/verify-telemetry-compiled-out.sh present target/debug/openshell-gateway", # Guard: telemetry-free builds must contain no telemetry markers. Built # through the `defaults-without-telemetry` alias, which is how the docs tell # operators to produce these artifacts. - "cargo build --locked -p openshell-gateway --bin openshell-gateway --no-default-features --features defaults-without-telemetry", + "cargo build -p openshell-gateway --bin openshell-gateway --no-default-features --features defaults-without-telemetry", "tasks/scripts/verify-telemetry-compiled-out.sh absent target/debug/openshell-gateway", - "cargo build --locked -p openshell-sandbox --bin openshell-sandbox --no-default-features --features defaults-without-telemetry", + "cargo build -p openshell-sandbox --bin openshell-sandbox --no-default-features --features defaults-without-telemetry", "tasks/scripts/verify-telemetry-compiled-out.sh absent target/debug/openshell-sandbox", ] @@ -79,9 +81,9 @@ description = "Verify system CA roots build mode compiles and excludes bundled M run = [ # Check that the sandbox compiles cleanly in system CA roots mode (all # defaults except bundled-ca-roots). - "cargo check --locked -p openshell-sandbox --all-targets --no-default-features --features system-ca-roots", + "cargo check -p openshell-sandbox --all-targets --no-default-features --features system-ca-roots", # Guard: webpki-roots must not appear in the dependency graph. - "bash -c 'if cargo tree --locked -p openshell-sandbox -i webpki-roots --no-default-features --features system-ca-roots 2>/dev/null | grep -q webpki-roots; then echo \"ERROR: webpki-roots found in system CA roots build\" >&2; exit 1; fi'", + "bash -c 'if cargo tree -p openshell-sandbox -i webpki-roots --no-default-features --features system-ca-roots 2>/dev/null | grep -q webpki-roots; then echo \"ERROR: webpki-roots found in system CA roots build\" >&2; exit 1; fi'", # Guard: webpki-root-certs must not appear either (webpki-roots re-exports it). - "bash -c 'if cargo tree --locked -p openshell-sandbox -i webpki-root-certs --no-default-features --features system-ca-roots 2>/dev/null | grep -q webpki-root-certs; then echo \"ERROR: webpki-root-certs found in system CA roots build\" >&2; exit 1; fi'", + "bash -c 'if cargo tree -p openshell-sandbox -i webpki-root-certs --no-default-features --features system-ca-roots 2>/dev/null | grep -q webpki-root-certs; then echo \"ERROR: webpki-root-certs found in system CA roots build\" >&2; exit 1; fi'", ] diff --git a/tasks/scripts/verify-defaults-without-telemetry.sh b/tasks/scripts/verify-defaults-without-telemetry.sh index 8eefdf5082..1fd7e67dff 100755 --- a/tasks/scripts/verify-defaults-without-telemetry.sh +++ b/tasks/scripts/verify-defaults-without-telemetry.sh @@ -32,7 +32,7 @@ if ! command -v jq >/dev/null 2>&1; then exit 2 fi -metadata=$(cargo metadata --locked --no-deps --format-version 1) +metadata=$(cargo metadata --no-deps --format-version 1) failed=0 for crate in "${CRATES[@]}"; do @@ -71,7 +71,7 @@ done # host, and a check that failed for an unrelated reason would make this guard # silently vacuous. for crate in "${CRATES[@]}"; do - output=$(cargo check --locked -p "$crate" --features defaults-without-telemetry 2>&1 || true) + output=$(cargo check -p "$crate" --features defaults-without-telemetry 2>&1 || true) if grep -qF "features \`telemetry\` and \`defaults-without-telemetry\` are mutually exclusive" <<<"$output"; then echo "OK: $crate rejects 'telemetry' + 'defaults-without-telemetry'" diff --git a/tasks/test.toml b/tasks/test.toml index 541c7b101d..8c41e70025 100644 --- a/tasks/test.toml +++ b/tasks/test.toml @@ -78,12 +78,13 @@ run = "bash tasks/scripts/e2e-gpu-build-images.sh" ["test:rust"] description = "Run Rust tests" +depends = ["rust:lockfiles:check"] env = { OPENSHELL_TELEMETRY_ENABLED = "false" } run = [ # Run the workspace once without openshell-server so we can run that crate # with test-only helpers enabled. - "cargo test --locked --workspace --exclude openshell-server", - "cargo test --locked -p openshell-server --features test-support", + "cargo test --workspace --exclude openshell-server", + "cargo test -p openshell-server --features test-support", ] run_windows = "powershell -NoProfile -ExecutionPolicy Bypass -File tasks/scripts/windows-msvc.ps1 test-precommit native" hide = true From 212306ef6d8329498ca0e22c86d4cfa431058442 Mon Sep 17 00:00:00 2001 From: Piotr Mlocek Date: Thu, 10 Sep 2026 10:45:59 -0700 Subject: [PATCH 7/8] docs(build): shorten lockfile validation notes Signed-off-by: Piotr Mlocek --- TESTING.md | 4 +--- architecture/build.md | 10 ++-------- 2 files changed, 3 insertions(+), 11 deletions(-) diff --git a/TESTING.md b/TESTING.md index 5ae487a286..aaad71aa41 100644 --- a/TESTING.md +++ b/TESTING.md @@ -46,9 +46,7 @@ Run Rust tests only: mise run test:rust # cargo test --workspace ``` -Run `mise run rust:lockfiles:check` to validate every tracked Cargo lockfile against its adjacent manifest. Local Rust lint, check, and test tasks depend on this guard, so it finishes before those Cargo commands start, including through pre-commit and local CI. It resolves dependency metadata without compiling, but may download uncached dependencies. Cargo diagnostics explain whether a failure requires refreshing a lockfile or resolving another problem, such as registry access. To refresh a stale lockfile, run `cargo metadata --format-version 1 --manifest-path path/to/Cargo.toml > /dev/null` with the adjacent manifest, review and commit the lockfile changes, then rerun `mise run pre-commit`. - -Each Rust CI job ends with lockfile validation and `git diff --exit-code HEAD -- ':(glob)**/Cargo.lock'`. This rejects tracked lockfile changes made during validation, even when the Cargo commands themselves succeed. The final step also runs after earlier failures. Ordinary build and test commands do not need `--locked`; the metadata guard is the single explicit use for this policy. +Rust validation checks tracked Cargo lockfiles; run `mise run rust:lockfiles:check` to check them directly. If one is stale, refresh it with Cargo using its adjacent manifest, review the diff, and commit the update. ## Python Unit Tests diff --git a/architecture/build.md b/architecture/build.md index 674d834853..d6ad9914a9 100644 --- a/architecture/build.md +++ b/architecture/build.md @@ -514,14 +514,8 @@ Published docs live in `docs/`, and Fern site configuration lives in `fern/`. Se ## Validation Expectations -Rust lint tasks and branch checks run Clippy with warnings denied for the -workspace, E2E crate, and the standalone governance-interceptor and -supervisor-middleware-content-guard examples, including all Cargo targets. -Local Rust lint, check, and test tasks validate every tracked Cargo lockfile -before running, including when invoked through pre-commit or local CI. -Each Rust branch-check job finishes by validating the lockfiles and comparing -them with the checked-out commit. Any tracked lockfile change fails the job, -including changes made by Cargo commands that completed successfully. +Rust CI rejects stale or modified Cargo lockfiles and runs Clippy for the +workspace, E2E crate, and standalone examples. - Run `mise run pre-commit` before committing. - Run `mise run test` after code changes. From 8b216fc5cd8712b3d384073013fae5d63f116a37 Mon Sep 17 00:00:00 2001 From: Piotr Mlocek Date: Thu, 10 Sep 2026 16:46:34 -0700 Subject: [PATCH 8/8] ci(rust): skip lockfile check after failures Signed-off-by: Piotr Mlocek --- .github/workflows/branch-checks.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/branch-checks.yml b/.github/workflows/branch-checks.yml index 2999cf5fc3..7b0c77c8fd 100644 --- a/.github/workflows/branch-checks.yml +++ b/.github/workflows/branch-checks.yml @@ -208,7 +208,6 @@ jobs: fi - name: Verify Cargo lockfiles unchanged - if: always() run: | tasks/scripts/check-cargo-lockfiles.sh git diff --exit-code HEAD -- ':(glob)**/Cargo.lock'