A fast, offline gate for a stale harness/opfs-contract lock (improvise-zs2r)
This commit is contained in:
@@ -56,6 +56,7 @@ deleted worktree. Tidying history before the PR is fine; losing it is not.
|
||||
|
||||
```
|
||||
direnv exec . ./scripts/fmt-workspaces.sh # NOT cargo fmt --all; exit 2 = the gate did not run
|
||||
direnv exec . ./scripts/check-harness-lock.sh # offline; a Cargo.toml change can stale harness/opfs-contract's lock
|
||||
direnv exec . cargo clippy --workspace --all-targets -- -D warnings
|
||||
direnv exec . cargo test --workspace --no-fail-fast
|
||||
direnv exec . python3 scripts/check-comment-runs.py --self-test
|
||||
|
||||
@@ -144,6 +144,10 @@ jobs:
|
||||
# roots. Exit 2 here is a usage error, never a verdict (improvise-b4ks).
|
||||
- name: Every workspace root is formatted
|
||||
run: ./scripts/fmt-workspaces.sh
|
||||
# A manifest-only change to a crate the harness reaches by path stales
|
||||
# its own lock, which only the slow `build` job saw (improvise-zs2r).
|
||||
- name: The harness lock matches the manifests it resolves against
|
||||
run: ./scripts/check-harness-lock.sh --allow-network
|
||||
- run: cargo clippy --workspace --all-targets -- -D warnings
|
||||
- run: cargo test --workspace
|
||||
# The comment cap and the test-evidence keys (improvise-9c8c); without
|
||||
@@ -281,9 +285,10 @@ jobs:
|
||||
# fmt-workspaces is here because its own failure mode is the bug it
|
||||
# exists for: a usage error wearing a formatting failure's exit code.
|
||||
# bd-audit-ids is the dead-ID audit, whose recipe once read a bd that
|
||||
# never ran as a clean audit (improvise-52eq).
|
||||
# never ran as a clean audit (improvise-52eq). check-harness-lock must
|
||||
# never read "could not resolve" as "stale" (improvise-zs2r).
|
||||
- name: The remaining checkers refuse what they claim to
|
||||
run: ./scripts/checkers.sh pr-watch release-preflight pr-reviews fmt-workspaces bd-audit-ids
|
||||
run: ./scripts/checkers.sh pr-watch release-preflight pr-reviews fmt-workspaces bd-audit-ids check-harness-lock
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Lints the one crate the `test` job cannot reach.
|
||||
|
||||
@@ -706,3 +706,51 @@ configuration.** A script may declare `#!/usr/bin/env bash`, pass the gate, and
|
||||
still be handed to dash by whatever invokes it. The only defence there is
|
||||
reading, which is how this one was found — by grepping for the *call* after
|
||||
fixing the *declaration*, rather than stopping at the gate going green.
|
||||
|
||||
## 6. The harness lock gate (improvise-zs2r)
|
||||
|
||||
`harness/opfs-contract` declares its own `[workspace]`, so it has its own
|
||||
`Cargo.lock`. It reaches `improvise-io`, and through it `improvise-core` and
|
||||
`improvise-formula`, by path. So a change to one of those crates' manifests,
|
||||
such as removing a dependency or a feature, can stale that lock while the root
|
||||
lock is updated and every host gate stays green. Before this gate, the only
|
||||
thing that noticed was `harness/build.sh`'s `cargo metadata --locked`, in the
|
||||
slow `build` job, and #214 and #224 both found out that way.
|
||||
|
||||
`scripts/check-harness-lock.sh` runs that same `cargo metadata --locked`
|
||||
against the harness manifest. It runs in the `test` job (with
|
||||
`--allow-network`) and locally, where it is **offline** by default.
|
||||
|
||||
**Why offline is sound, measured rather than assumed.** `--locked --offline`
|
||||
resolves from the local registry cache and fails on a real mismatch with its
|
||||
own message: "cannot update the lock file … because --locked was passed". A
|
||||
dependency missing from the cache fails differently, with a resolution error
|
||||
naming the index ("location searched: crates.io index"). Both were measured:
|
||||
a manifest-only change to `improvise-formula` produced the first, and an empty
|
||||
`CARGO_HOME` produced the second. So the script can tell the two apart, and it
|
||||
does:
|
||||
|
||||
- exit 0: the lock is current;
|
||||
- exit 1: stale, and the fix is named;
|
||||
- exit 2: the gate did not run.
|
||||
|
||||
That follows `fmt-workspaces.sh`'s rule that "did not run" is never collapsed
|
||||
into a verdict. Offline, then, it never needs the network and never lies:
|
||||
- a developer whose cache is warm, which is anyone who has built the root
|
||||
workspace, gets a real answer;
|
||||
- one whose cache is cold is told the gate did not run, not that the lock is
|
||||
stale.
|
||||
|
||||
**The one residual, stated.** A manifest change that adds a crate never
|
||||
downloaded is, offline, a resolution failure. So it reads as exit 2, not
|
||||
exit 1. The developer is still stopped, but told the gate did not run rather
|
||||
than that the lock is stale. CI runs with `--allow-network` and answers it
|
||||
properly.
|
||||
|
||||
`scripts/check-harness-lock-test.sh` pins the three answers against path-only
|
||||
fixture workspaces, which need no registry at all. The fixtures have the same
|
||||
shape as the harness: a root that reaches a crate by path, whose manifest then
|
||||
changes. Two rivals were run:
|
||||
- reading every failure as stale fails the offline case (exit 1, wanted 2);
|
||||
- dropping `--locked` fails the stale case (exit 0, wanted 1). Without
|
||||
`--locked`, cargo quietly rewrites the lock and reports success.
|
||||
|
||||
Executable
+77
@@ -0,0 +1,77 @@
|
||||
#!/usr/bin/env bash
|
||||
# check_the_checker for scripts/check-harness-lock.sh (improvise-zs2r). The
|
||||
# fixtures are path-only crates, so every case runs offline with no cache.
|
||||
set -uo pipefail
|
||||
|
||||
here="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
RUN="$here/check-harness-lock.sh"
|
||||
work="$(mktemp -d)"
|
||||
trap 'rm -rf "$work"' EXIT
|
||||
|
||||
pass=0; fail=0
|
||||
ok() { printf ' ok %s\n' "$1"; pass=$((pass+1)); }
|
||||
bad() { printf ' FAIL %s (exit %s, wanted %s)\n' "$1" "$2" "$3"; fail=$((fail+1)); }
|
||||
|
||||
# $1 name, $2 expected exit, $3 expected stderr substring ("" for none), rest: args
|
||||
run_case() {
|
||||
local name="$1" want="$2" says="$3"; shift 3
|
||||
local err
|
||||
err="$("$RUN" "$@" 2>&1 >/dev/null)"
|
||||
local got=$?
|
||||
if [ "$got" != "$want" ]; then
|
||||
bad "$name" "$got" "$want"
|
||||
printf '%s\n' "$err" | sed 's/^/ /'
|
||||
elif [ -n "$says" ] && [[ "$err" != *"$says"* ]]; then
|
||||
bad "$name: stderr did not say $says" "$got" "$want"
|
||||
else
|
||||
ok "$name"
|
||||
fi
|
||||
}
|
||||
|
||||
# $1 dir, $2 crate name, $3 extra [dependencies] lines, $4 "workspace" or ""
|
||||
crate() {
|
||||
mkdir -p "$1/src"
|
||||
: > "$1/src/lib.rs"
|
||||
{
|
||||
printf '[package]\nname = "%s"\nversion = "0.0.0"\nedition = "2021"\n' "$2"
|
||||
[ "${4:-}" = workspace ] && printf '\n[workspace]\n'
|
||||
printf '\n[dependencies]\n%s' "$3"
|
||||
} > "$1/Cargo.toml"
|
||||
}
|
||||
|
||||
# A two-crate workspace shaped like the harness: `app` is its own root and
|
||||
# reaches `lib` by path, so `lib`'s manifest is one the lock resolves against.
|
||||
fixture() {
|
||||
local root="$1"
|
||||
crate "$root/lib" lib ""
|
||||
crate "$root/extra" extra ""
|
||||
crate "$root/app" app 'lib = { path = "../lib" }
|
||||
' workspace
|
||||
cargo generate-lockfile --offline --manifest-path "$root/app/Cargo.toml" 2>/dev/null
|
||||
}
|
||||
|
||||
fixture "$work/current"
|
||||
run_case "a current lock passes" 0 "" "$work/current/app/Cargo.toml"
|
||||
|
||||
# The shape improvise-zs2r names: only a PATH DEPENDENCY's manifest changed.
|
||||
fixture "$work/stale"
|
||||
crate "$work/stale/lib" lib 'extra = { path = "../extra" }
|
||||
'
|
||||
run_case "a manifest-only change to a path dependency is stale" 1 "STALE" \
|
||||
"$work/stale/app/Cargo.toml"
|
||||
|
||||
# Offline and unresolvable is NOT a stale lock: the gate did not run.
|
||||
fixture "$work/cold"
|
||||
crate "$work/cold/lib" lib 'zs2r-no-such-crate-anywhere = "1"
|
||||
'
|
||||
run_case "an offline resolution failure is not a verdict" 2 "did not run" \
|
||||
"$work/cold/app/Cargo.toml"
|
||||
|
||||
run_case "a missing manifest is a usage error" 2 "no manifest" \
|
||||
"$work/nowhere/Cargo.toml"
|
||||
run_case "two manifests is a usage error" 2 "" \
|
||||
"$work/current/app/Cargo.toml" "$work/stale/app/Cargo.toml"
|
||||
run_case "an unknown option is a usage error" 2 "unknown option" --bogus
|
||||
|
||||
printf '\ncheck-harness-lock: %d passed, %d failed\n' "$pass" "$fail"
|
||||
[ "$fail" = 0 ]
|
||||
Executable
+73
@@ -0,0 +1,73 @@
|
||||
#!/usr/bin/env bash
|
||||
# Fails in seconds when harness/opfs-contract/Cargo.lock no longer matches the
|
||||
# manifests it resolves against. Reasoning: context/code/tooling.md, "The
|
||||
# harness lock gate" (improvise-zs2r).
|
||||
set -uo pipefail
|
||||
|
||||
usage() {
|
||||
cat >&2 <<'EOF'
|
||||
usage: check-harness-lock.sh [--allow-network] [manifest]
|
||||
|
||||
manifest the Cargo.toml whose lock is checked; defaults to
|
||||
harness/opfs-contract/Cargo.toml beside this script
|
||||
--allow-network resolve without --offline (CI); the default never
|
||||
touches the network
|
||||
|
||||
exit 0 the lock is current
|
||||
exit 1 the lock is stale: a manifest it resolves against changed
|
||||
exit 2 the gate did not run: usage error, no cargo, or cargo could not
|
||||
resolve at all (offline, with a dependency missing from the local
|
||||
cache). NO verdict was produced. Never collapse 2 into 1.
|
||||
EOF
|
||||
}
|
||||
|
||||
main() {
|
||||
local network=0 manifest=""
|
||||
while [ $# -gt 0 ]; do
|
||||
case "$1" in
|
||||
--allow-network) network=1 ;;
|
||||
-h|--help) usage; return 2 ;;
|
||||
-*) printf 'check-harness-lock: unknown option %s\n' "$1" >&2; usage; return 2 ;;
|
||||
*)
|
||||
if [ -n "$manifest" ]; then usage; return 2; fi
|
||||
manifest="$1" ;;
|
||||
esac
|
||||
shift
|
||||
done
|
||||
if [ -z "$manifest" ]; then
|
||||
manifest="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)/harness/opfs-contract/Cargo.toml"
|
||||
fi
|
||||
if [ ! -f "$manifest" ]; then
|
||||
printf 'check-harness-lock: no manifest at %s\n' "$manifest" >&2
|
||||
return 2
|
||||
fi
|
||||
if ! command -v cargo >/dev/null 2>&1; then
|
||||
echo 'check-harness-lock: no cargo on PATH' >&2
|
||||
return 2
|
||||
fi
|
||||
|
||||
local -a args=(metadata --locked --format-version 1 --manifest-path "$manifest")
|
||||
if [ "$network" = 0 ]; then args+=(--offline); fi
|
||||
|
||||
local err rc
|
||||
err="$(cargo "${args[@]}" 2>&1 >/dev/null)"
|
||||
rc=$?
|
||||
if [ "$rc" = 0 ]; then
|
||||
printf 'check-harness-lock: %s is current\n' "${manifest%Cargo.toml}Cargo.lock"
|
||||
return 0
|
||||
fi
|
||||
# The one message that means "resolution succeeded and disagrees with the lock".
|
||||
if printf '%s' "$err" | grep -q 'cannot update the lock file .* because --locked was passed'; then
|
||||
printf 'check-harness-lock: STALE: %s\n' "${manifest%Cargo.toml}Cargo.lock" >&2
|
||||
printf ' Run: cargo update -w --manifest-path %s, and commit the lock.\n' "$manifest" >&2
|
||||
return 1
|
||||
fi
|
||||
printf 'check-harness-lock: the gate did not run; cargo could not resolve:\n%s\n' "$err" >&2
|
||||
if [ "$network" = 0 ]; then
|
||||
echo ' Offline, this is usually a dependency missing from the local cache.' >&2
|
||||
echo ' Retry with --allow-network, or fetch once and rerun.' >&2
|
||||
fi
|
||||
return 2
|
||||
}
|
||||
|
||||
main "$@"
|
||||
Reference in New Issue
Block a user