#!/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"