Files
src/scripts/check-source-locks.sh
T
2026-08-04 17:59:44 +01:00

198 lines
6.4 KiB
Bash
Executable File

#!/bin/sh
set -eu
script_dir=$(CDPATH= cd -- "$(dirname -- "$0")" && pwd)
repo_dir=$(dirname "$script_dir")
lock_dir="$repo_dir/release"
temporary=$(mktemp -d "${TMPDIR:-/tmp}/mouse-source-lock-check.XXXXXX")
cleanup() {
rm -rf "$temporary"
}
trap cleanup EXIT HUP INT TERM
MOUSE_VALIDATE_ONLY=1 "$script_dir/fetch-sources.sh"
awk 'NF && $1 !~ /^#/ { print $3 }' \
"$lock_dir/toolchain.lock" \
"$lock_dir/kernel.lock" \
"$lock_dir/facilities.lock" \
"$lock_dir/storage.lock" \
"$lock_dir/software.lock" |
LC_ALL=C sort -u >"$temporary/locked"
awk '$1 == "extract" { print $2 }' "$script_dir/static-base"/*.sh |
LC_ALL=C sort -u >"$temporary/referenced-archives"
sed -n 's/.*"$source_dir\/\([^"$]*\)".*/\1/p' \
"$script_dir/static-base"/*.sh \
"$script_dir/build-boot-disk.sh" |
LC_ALL=C sort -u >"$temporary/referenced-files"
cat "$temporary/referenced-archives" "$temporary/referenced-files" |
LC_ALL=C sort -u >"$temporary/referenced"
if ! diff -u "$temporary/locked" "$temporary/referenced"; then
printf '%s\n' "source locks do not match static-base component inputs" >&2
exit 1
fi
toolchain_count=$(awk 'NF && $1 !~ /^#/ { count++ } END { print count + 0 }' \
"$lock_dir/toolchain.lock")
kernel_count=$(awk 'NF && $1 !~ /^#/ { count++ } END { print count + 0 }' \
"$lock_dir/kernel.lock")
if [ "$toolchain_count" -ne 1 ] || \
! awk 'NF && $1 !~ /^#/ { print $3 }' "$lock_dir/toolchain.lock" |
grep -Eq '^llvm-project-[^/]+$'
then
printf '%s\n' "toolchain.lock must contain exactly the LLVM source" >&2
exit 1
fi
if [ "$kernel_count" -ne 1 ] || \
! awk 'NF && $1 !~ /^#/ { print $3 }' "$lock_dir/kernel.lock" |
grep -Eq '^linux-[^/]+$'
then
printf '%s\n' "kernel.lock must contain exactly the Linux source" >&2
exit 1
fi
pkgsrc_count=$(awk 'NF && $1 !~ /^#/ { count++ } END { print count + 0 }' \
"$lock_dir/pkgsrc.lock")
if [ "$pkgsrc_count" -ne 1 ] || \
! awk 'NF && $1 !~ /^#/ { print $3 }' "$lock_dir/pkgsrc.lock" |
grep -Eq '^pkgsrc-[0-9]{4}Q[1-4]\.tar\.gz$'
then
printf '%s\n' "pkgsrc.lock must contain exactly one stable pkgsrc archive" >&2
exit 1
fi
firmware_count=$(awk 'NF && $1 !~ /^#/ { count++ } END { print count + 0 }' \
"$lock_dir/firmware.lock")
if [ "$firmware_count" -ne 1 ] || \
! awk 'NF && $1 !~ /^#/ { print $3 }' "$lock_dir/firmware.lock" |
grep -Eq '^ovmf-[^/]+\.apk$'
then
printf '%s\n' "firmware.lock must contain exactly one OVMF package" >&2
exit 1
fi
storage_count=$(awk 'NF && $1 !~ /^#/ { count++ } END { print count + 0 }' \
"$lock_dir/storage.lock")
if [ "$storage_count" -lt 1 ] || \
! awk 'NF && $1 !~ /^#/ { print $3 }' "$lock_dir/storage.lock" |
grep -Eq '^btrfs-progs-[^/]+$'
then
printf '%s\n' "storage.lock must contain the btrfs-progs source" >&2
exit 1
fi
if awk 'NF && $1 !~ /^#/ { print $3 }' "$lock_dir/software.lock" |
grep -Eq '^(llvm-project|linux|btrfs-progs|less|mandoc|iproute2|nftables)-'
then
printf '%s\n' "software.lock contains a source owned by another cache domain" >&2
exit 1
fi
if awk 'NF && $1 !~ /^#/ { print $3 }' "$lock_dir/facilities.lock" |
grep -Eq '^(llvm-project|linux|btrfs-progs)-'
then
printf '%s\n' "facilities.lock contains a kernel, toolchain, or storage source" >&2
exit 1
fi
awk '
/^FROM toolchain AS kernel-builder$/ { in_kernel = 1; next }
/^FROM / && in_kernel { exit }
in_kernel { print }
' "$repo_dir/Containerfile" >"$temporary/kernel-stage"
if ! grep -Fq 'COPY --from=kernel-sources ' "$temporary/kernel-stage"; then
printf '%s\n' "kernel-builder does not import kernel-sources" >&2
exit 1
fi
if grep -Eq 'COPY --from=(toolchain|storage|software)-sources ' \
"$temporary/kernel-stage"
then
printf '%s\n' "kernel-builder imports an unrelated source domain" >&2
exit 1
fi
if grep -Fq 'tests/fixtures' "$temporary/kernel-stage"; then
printf '%s\n' "production kernel stage imports test fixtures" >&2
exit 1
fi
awk '
/^FROM kernel-builder AS kernel-ready$/ { in_marker = 1; next }
/^FROM / && in_marker { exit }
in_marker { print }
' "$repo_dir/Containerfile" >"$temporary/kernel-ready-stage"
if ! grep -Fq 'RUN install -m 0444 /dev/null /kernel-ready' \
"$temporary/kernel-ready-stage"
then
printf '%s\n' "kernel-ready does not create its completion marker" >&2
exit 1
fi
for stage_script in \
static-base-bootstrap:bootstrap.sh \
static-base-libraries:libraries-and-accounts.sh \
static-base-system:system-services.sh \
static-base-facilities:facilities.sh \
static-base-toolchain:native-toolchain.sh \
static-base-storage:storage.sh \
static-base-builder:finish.sh
do
stage=${stage_script%%:*}
component=${stage_script#*:}
awk -v heading="AS $stage" '
/^FROM / {
if (active) exit
active = index($0, heading) != 0
next
}
active { print }
' "$repo_dir/Containerfile" >"$temporary/$stage"
if ! grep -Fq \
"COPY mouse-src/scripts/static-base/$component " \
"$temporary/$stage"
then
printf '%s\n' \
"$stage does not own static-base component $component" >&2
exit 1
fi
if [ "$(grep -Fc \
"COPY mouse-src/scripts/static-base/$component " \
"$repo_dir/Containerfile")" -ne 1 ]
then
printf '%s\n' \
"$component must enter exactly one container cache stage" >&2
exit 1
fi
done
if ! grep -Fq \
'COPY --from=kernel-ready /kernel-ready /tmp/kernel-ready' \
"$temporary/static-base-bootstrap"
then
printf '%s\n' "static-base build does not wait for kernel completion" >&2
exit 1
fi
for production_stage in image-commands-builder rootfs-builder; do
awk -v heading="AS $production_stage" '
/^FROM / {
if (active) exit
active = index($0, heading) != 0
next
}
active { print }
' "$repo_dir/Containerfile" >"$temporary/$production_stage"
if grep -Fq 'tests/fixtures' "$temporary/$production_stage"; then
printf '%s\n' "$production_stage imports test fixtures" >&2
exit 1
fi
done
for test_stage in kernel-test-builder test-fixtures-builder rootfs-test-builder; do
if ! grep -Fq "AS $test_stage" "$repo_dir/Containerfile"; then
printf '%s\n' "missing isolated test stage: $test_stage" >&2
exit 1
fi
done
printf '%s\n' "source lock and cache-boundary checks passed"