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
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]>
90 lines
3.1 KiB
Shell
Executable file
90 lines
3.1 KiB
Shell
Executable file
#!/usr/bin/env bash
|
|
#
|
|
# check-lockfiles.sh — every committed Cargo.lock is current.
|
|
#
|
|
# A lockfile is stale when cargo would change it: a crate's version was bumped,
|
|
# or a dependency was added, and the lock was not regenerated. This tree holds
|
|
# many workspaces that depend on one another by path, so a version bump in one
|
|
# leaves the locks of the others behind. Nothing notices until a job that
|
|
# passes `--locked` fails, for a reason that has nothing to do with what the
|
|
# job tests.
|
|
#
|
|
# For each directory that holds a tracked Cargo.lock this runs
|
|
#
|
|
# cargo update --workspace --locked
|
|
#
|
|
# which resolves the workspace against its lock and fails if the lock would
|
|
# change. It reads the registry index and any git dependency; it downloads no
|
|
# crate and builds nothing.
|
|
#
|
|
# check-lockfiles.sh every tracked Cargo.lock, less the list below
|
|
# check-lockfiles.sh DIR ... exactly these directories
|
|
#
|
|
# Exit 0: every lock is current. Exit 1: at least one is stale, or could not be
|
|
# checked. A lock that could not be checked (no network, say) fails the run too,
|
|
# under its own heading, so nobody goes looking for a stale lock that is not
|
|
# one.
|
|
set -uo pipefail
|
|
|
|
# Directories that hold a Cargo.lock cargo does not read. Each needs a reason,
|
|
# and each must still exist: a stale entry fails the run.
|
|
SKIP=(
|
|
# A vendored crate, patched into jouledesk-rs. Cargo resolves it as part of
|
|
# that workspace, against that workspace's lock; its own lock is the
|
|
# upstream's, kept with the vendored source.
|
|
"jouledesk/jouledesk-rs/vendor/libwebrtc"
|
|
)
|
|
|
|
skipped() { local d; for d in "${SKIP[@]}"; do [ "$d" = "$1" ] && return 0; done; return 1; }
|
|
|
|
if [ $# -gt 0 ]; then
|
|
dirs=("$@")
|
|
else
|
|
cd "$(git rev-parse --show-toplevel)" || exit 1
|
|
for d in "${SKIP[@]}"; do
|
|
if [ ! -f "$d/Cargo.lock" ]; then
|
|
echo "check-lockfiles: the skip list names $d, which holds no Cargo.lock. Remove the entry." >&2
|
|
exit 1
|
|
fi
|
|
done
|
|
dirs=()
|
|
while IFS= read -r l; do
|
|
d=$(dirname "$l")
|
|
skipped "$d" || dirs+=("$d")
|
|
done < <(git ls-files | grep -E '(^|/)Cargo\.lock$')
|
|
fi
|
|
|
|
if [ ${#dirs[@]} -eq 0 ]; then
|
|
echo "check-lockfiles: found no Cargo.lock to check." >&2
|
|
exit 1
|
|
fi
|
|
|
|
stale=(); unchecked=()
|
|
for d in "${dirs[@]}"; do
|
|
out=$( (cd "$d" && cargo update --workspace --locked) 2>&1 ); rc=$?
|
|
if [ $rc -eq 0 ]; then
|
|
continue
|
|
elif printf '%s' "$out" | grep -qE -- '--locked was passed|lock file .* (is missing|needs to be updated)'; then
|
|
stale+=("$d")
|
|
echo "STALE $d"
|
|
printf '%s\n' "$out" | grep -E '^error|^Caused by|^ ' | head -6 | sed 's/^/ /'
|
|
else
|
|
unchecked+=("$d")
|
|
echo "ERROR $d (cargo could not resolve it; this is not a verdict on the lock)"
|
|
printf '%s\n' "$out" | tail -8 | sed 's/^/ /'
|
|
fi
|
|
done
|
|
|
|
if [ ${#stale[@]} -gt 0 ]; then
|
|
echo
|
|
echo "Stale lockfiles. Regenerate each, and commit the result:"
|
|
for d in "${stale[@]}"; do echo " (cd $d && cargo update --workspace)"; done
|
|
fi
|
|
if [ ${#unchecked[@]} -gt 0 ]; then
|
|
echo
|
|
echo "Could not be checked: ${unchecked[*]}"
|
|
fi
|
|
if [ ${#stale[@]} -gt 0 ] || [ ${#unchecked[@]} -gt 0 ]; then
|
|
exit 1
|
|
fi
|
|
echo "check-lockfiles: ${#dirs[@]} lockfiles, all current."
|