63614382d6
warm-cargo-offline-cache.sh: builds run cargo with --offline --locked, so
resolution comes from the sparse-index CACHE, which only an online cargo
run refreshes. A lockfile can pin a version whose .crate is already
downloaded while the index cache does not list it, producing
error: failed to select a version for the requirement quinn = ^0.11.1
(locked to 0.11.11)
candidate versions found which didn't match: 0.11.9
on a dependency that is in fact present. 13 lockfiles were missing 42
crates this way. --check reports offending manifests without fetching.
test-sddm-virgl-qemu.sh: boots redbear-full on virtio-gpu-gl with
egl-headless so the guest takes the accelerated redox-drm -> Mesa (virgl)
-> Wayland path, captures the serial console and classifies each boot
marker independently rather than collapsing to pass/fail.
127 lines
4.2 KiB
Bash
Executable File
127 lines
4.2 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# warm-cargo-offline-cache.sh — make every Rust recipe/fork resolvable OFFLINE.
|
|
#
|
|
# WHY THIS EXISTS
|
|
#
|
|
# Red Bear builds are offline by default (COOKBOOK_OFFLINE=true), so the
|
|
# cookbook invokes cargo with `--offline --locked`. In that mode cargo resolves
|
|
# dependencies purely from the local registry, and — critically — from the
|
|
# *sparse index cache* under
|
|
# ~/.cargo/registry/index/<registry>/.cache/. That cache is only refreshed by an
|
|
# ONLINE cargo invocation.
|
|
#
|
|
# The failure mode is silent and confusing: a Cargo.lock can pin a version that
|
|
# is present in ~/.cargo/registry/cache as a .crate file, while the index cache
|
|
# entry is older and does not list it. Cargo then reports
|
|
#
|
|
# error: failed to select a version for the requirement `quinn = "^0.11.1"`
|
|
# (locked to 0.11.11)
|
|
# candidate versions found which didn't match: 0.11.9
|
|
#
|
|
# even though quinn-0.11.11.crate is sitting in the cache. The build fails on a
|
|
# dependency that is, in fact, already downloaded.
|
|
#
|
|
# Running this script once while online makes every lockfile-pinned version
|
|
# visible to the offline resolver. Run it after any lockfile change, after
|
|
# `bump-release.sh`, or when provisioning a new build host.
|
|
#
|
|
# It is READ-ONLY with respect to the repo: `cargo fetch --locked` populates
|
|
# ~/.cargo but never edits Cargo.lock (--locked makes cargo fail rather than
|
|
# update a lockfile).
|
|
|
|
set -uo pipefail
|
|
|
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
PROJECT_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
|
|
cd "$PROJECT_ROOT"
|
|
|
|
usage() {
|
|
cat <<'USAGE'
|
|
Usage: warm-cargo-offline-cache.sh [--check] [--timeout SECONDS]
|
|
|
|
--check Do not fetch; only report which manifests FAIL to resolve
|
|
offline. Exits non-zero if any do. Safe with no network.
|
|
--timeout SECONDS Per-manifest timeout (default 300).
|
|
|
|
Covers every Cargo.toml that the build drives directly:
|
|
local/sources/*/ (Cat 2 upstream forks)
|
|
local/recipes/*/*/source/ (Cat 1 in-house crates + vendored Rust)
|
|
USAGE
|
|
}
|
|
|
|
check_only=0
|
|
per_timeout=300
|
|
while [[ $# -gt 0 ]]; do
|
|
case "$1" in
|
|
--help|-h) usage; exit 0 ;;
|
|
--check) check_only=1 ;;
|
|
--timeout) shift; per_timeout="${1:?--timeout requires seconds}" ;;
|
|
--timeout=*) per_timeout="${1#*=}" ;;
|
|
*) echo "ERROR: unsupported argument $1" >&2; usage >&2; exit 1 ;;
|
|
esac
|
|
shift
|
|
done
|
|
|
|
mapfile -t manifests < <(
|
|
{
|
|
find local/sources -maxdepth 2 -name Cargo.toml 2>/dev/null
|
|
find local/recipes -maxdepth 4 -path '*/source/Cargo.toml' 2>/dev/null
|
|
} | sort -u
|
|
)
|
|
|
|
if [[ "${#manifests[@]}" -eq 0 ]]; then
|
|
echo "ERROR: no Cargo manifests found under local/sources or local/recipes" >&2
|
|
exit 1
|
|
fi
|
|
|
|
echo ">>> ${#manifests[@]} Rust manifest(s) to verify"
|
|
failed=0
|
|
fixed=0
|
|
skipped=0
|
|
|
|
for m in "${manifests[@]}"; do
|
|
# A manifest with no lockfile is resolved as part of a parent workspace;
|
|
# fetching it standalone is meaningless.
|
|
lock_dir="$(dirname "$m")"
|
|
if [[ ! -f "$lock_dir/Cargo.lock" ]]; then
|
|
skipped=$((skipped + 1))
|
|
continue
|
|
fi
|
|
|
|
if timeout "$per_timeout" cargo metadata --offline --locked \
|
|
--manifest-path "$m" --format-version 1 >/dev/null 2>&1; then
|
|
continue
|
|
fi
|
|
|
|
if [[ "$check_only" -eq 1 ]]; then
|
|
echo " OFFLINE-FAIL $m"
|
|
failed=$((failed + 1))
|
|
continue
|
|
fi
|
|
|
|
echo " warming $m"
|
|
if timeout "$per_timeout" cargo fetch --locked --manifest-path "$m" >/dev/null 2>&1 \
|
|
&& timeout "$per_timeout" cargo metadata --offline --locked \
|
|
--manifest-path "$m" --format-version 1 >/dev/null 2>&1; then
|
|
fixed=$((fixed + 1))
|
|
else
|
|
echo " STILL-FAIL $m"
|
|
failed=$((failed + 1))
|
|
fi
|
|
done
|
|
|
|
echo ">>> skipped (no own lockfile): $skipped"
|
|
if [[ "$check_only" -eq 1 ]]; then
|
|
if [[ "$failed" -gt 0 ]]; then
|
|
echo ">>> $failed manifest(s) will FAIL an offline build."
|
|
echo ">>> Fix: run this script without --check while online."
|
|
exit 1
|
|
fi
|
|
echo ">>> All manifests resolve offline."
|
|
exit 0
|
|
fi
|
|
|
|
echo ">>> warmed: $fixed, still failing: $failed"
|
|
[[ "$failed" -eq 0 ]] || exit 1
|
|
echo ">>> Offline cargo resolution is complete for every Rust manifest."
|