open-standards/scripts/check-lockfiles-selftest.sh
Transaction Science e22955434f
All checks were successful
standards workspaces build + test / jouleclaw-rs (pull_request) Successful in 2m24s
standards workspaces build + test / joule-code-rs (pull_request) Successful in 1m28s
standards workspaces build + test / joulecontract-rs (pull_request) Successful in 53s
standards workspaces build + test / aac-rs (pull_request) Successful in 2m37s
standards workspaces build + test / map-rs (pull_request) Successful in 56s
standards workspaces build + test / mesh-rs (pull_request) Successful in 51s
standards workspaces build + test / openpay (pull_request) Successful in 3m25s
standards workspaces build + test / jouledesk-rs (pull_request) Successful in 52s
standards workspaces build + test / macOS energy backends (pull_request) Successful in 4m4s
lockfiles / every Cargo.lock is current (pull_request) Successful in 44s
standards workspaces build + test / arl-rs (pull_request) Successful in 1m22s
standards workspaces build + test / eoc-rs (pull_request) Successful in 2m7s
standards workspaces build + test / joule-ui-rs (pull_request) Successful in 1m13s
standards workspaces build + test / jcp-rs (pull_request) Successful in 2m51s
standards workspaces build + test / joulehook-rs (pull_request) Successful in 1m17s
standards workspaces build + test / proof-rs (pull_request) Successful in 1m22s
standards workspaces build + test / sense-rs (pull_request) Successful in 1m14s
standards workspaces build + test / sandbox-rs (pull_request) Successful in 2m23s
workflow hygiene / every workflow supersedes its own queue (pull_request) Successful in 4s
standards workspaces build + test / smart-byte-rs (pull_request) Successful in 3m51s
ci: every committed Cargo.lock is current
The workspaces here depend on one another by path, so a version bump in one
leaves its dependents' lockfiles behind. Only jobs that pass --locked notice,
and they fail on changes that never touched them. This job resolves each
workspace against its lock on every push (cargo update --workspace --locked:
no crate is downloaded and nothing is built) and names the stale ones with the
command that fixes each. A self-test shows the check fails on a bumped path
dependency, an added dependency, a missing lock and an unparseable manifest.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-12 20:16:43 -04:00

58 lines
2.9 KiB
Shell
Executable file

#!/usr/bin/env bash
#
# check-lockfiles-selftest.sh — check-lockfiles.sh can fail.
#
# A check that cannot fail is decoration. This builds a scratch workspace of two
# crates, one depending on the other by path, and asserts that the check
# 1. passes when the lock is current;
# 2. fails when the dependency's version is bumped and the lock is not
# regenerated (the case this check exists for);
# 3. fails when a dependency is added and the lock is not regenerated;
# 4. fails when the lock is missing;
# 5. fails, and says it could not check, when the manifest does not parse:
# an error is never read as "current".
# The scratch crates have no registry dependency, so nothing here needs a
# network.
set -uo pipefail
here=$(cd "$(dirname "$0")" && pwd)
check="$here/check-lockfiles.sh"
tmp=$(mktemp -d)
trap 'rm -rf "$tmp"' EXIT
mk() {
rm -rf "$tmp/ws"; mkdir -p "$tmp/ws/a/src" "$tmp/ws/b/src" "$tmp/ws/c/src"
printf '[workspace]\nmembers = ["a", "b"]\nresolver = "2"\n' > "$tmp/ws/Cargo.toml"
printf '[package]\nname = "selftest-a"\nversion = "0.1.0"\nedition = "2021"\n\n[dependencies]\nselftest-b = { path = "../b" }\n' > "$tmp/ws/a/Cargo.toml"
printf '[package]\nname = "selftest-b"\nversion = "0.1.0"\nedition = "2021"\n' > "$tmp/ws/b/Cargo.toml"
printf '[package]\nname = "selftest-c"\nversion = "0.1.0"\nedition = "2021"\n' > "$tmp/ws/c/Cargo.toml"
: > "$tmp/ws/a/src/lib.rs"; : > "$tmp/ws/b/src/lib.rs"; : > "$tmp/ws/c/src/lib.rs"
(cd "$tmp/ws" && cargo generate-lockfile --offline) >/dev/null 2>&1 || { echo "selftest: could not make the scratch lockfile" >&2; exit 2; }
}
fails=0
expect() { # expect <pass|fail> <what> [text the output must hold]
local want=$1 what=$2 needle=${3:-} out rc
out=$("$check" "$tmp/ws" 2>&1); rc=$?
if [ "$want" = pass ] && [ $rc -ne 0 ]; then echo "FAIL $what: the check failed"; printf '%s\n' "$out" | sed 's/^/ /'; fails=$((fails+1)); return; fi
if [ "$want" = fail ] && [ $rc -eq 0 ]; then echo "FAIL $what: the check passed"; fails=$((fails+1)); return; fi
if [ -n "$needle" ] && ! printf '%s' "$out" | grep -q -- "$needle"; then echo "FAIL $what: the output does not say '$needle'"; printf '%s\n' "$out" | sed 's/^/ /'; fails=$((fails+1)); return; fi
echo "ok $what"
}
mk; expect pass "a current lock passes"
mk; sed -i.bak 's/^version = "0.1.0"/version = "0.2.0"/' "$tmp/ws/b/Cargo.toml"
expect fail "a bumped path dependency with the old lock fails" "STALE"
mk; printf 'selftest-c = { path = "../c" }\n' >> "$tmp/ws/a/Cargo.toml"
expect fail "an added dependency with the old lock fails" "STALE"
mk; rm "$tmp/ws/Cargo.lock"
expect fail "a missing lock fails" "STALE"
mk; printf 'this is not toml\n' >> "$tmp/ws/a/Cargo.toml"
expect fail "a manifest that does not parse fails as unchecked, not as current" "ERROR"
if [ $fails -ne 0 ]; then echo "check-lockfiles-selftest: $fails failure(s)"; exit 1; fi
echo "check-lockfiles-selftest: the check passes a current lock and fails each broken one."