* Move the unit tests under test/unit test/ is growing an integration suite; the fast, VM-free tests get their own directory so the two kinds cannot be confused. test/all keeps its role as the aggregate runner for everything that needs no built ISO. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * Add an integration suite that boots ISO scenarios in QEMU test/integration installs an ISO once — unattended, from a generated cidata drive — and saves a reusable base image; each scenario in test/integration.d/ then boots a throwaway overlay with its own copy of the firmware vars. Shared machinery (VM lifecycle, QMP screendump + OCR console driving, virtual keystrokes, guest SSH, the cidata build) lives in base-test.sh, so a new scenario is one file. The first scenario proves omarchy-system-factory-reset hands a machine on without destroying a shared ESP: a Windows entry and a foreign Linux with its own machine-id, boot directory, and UKIs must survive both the staged reset and the first-boot provisioning that follows. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * Let omarchy-iso-make keep the host package cache Purging /var/cache/pacman/pkg needs interactive sudo, which blocks unattended builds. --keep-pkg-cache skips the purge so test rigs and agents can build an ISO without a prompt. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> --------- Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
171 lines
4.6 KiB
Bash
Executable File
171 lines
4.6 KiB
Bash
Executable File
#!/bin/bash
|
|
|
|
set -e
|
|
|
|
NO_CACHE=""
|
|
KEEP_PKG_CACHE=""
|
|
LOCAL_OMARCHY_PATH=""
|
|
LOCAL_PKGS_PATH=""
|
|
while [[ $# -gt 0 ]]; do
|
|
case $1 in
|
|
--no-cache)
|
|
NO_CACHE=1
|
|
shift
|
|
;;
|
|
--keep-pkg-cache)
|
|
KEEP_PKG_CACHE=1
|
|
shift
|
|
;;
|
|
--no-boot-offer)
|
|
NO_BOOT_OFFER=1
|
|
shift
|
|
;;
|
|
--debug)
|
|
OMARCHY_INSTALL_DEBUG=1
|
|
shift
|
|
;;
|
|
--edge)
|
|
OMARCHY_ISO_REF=edge
|
|
OMARCHY_MIRROR=edge
|
|
shift
|
|
;;
|
|
--local-source)
|
|
LOCAL_OMARCHY_PATH="${2:-}"
|
|
LOCAL_PKGS_PATH="${3:-}"
|
|
if [[ -z $LOCAL_OMARCHY_PATH || -z $LOCAL_PKGS_PATH ]]; then
|
|
echo "Error: --local-source requires two args: <omarchy-checkout> <pkgs-checkout>" >&2
|
|
exit 1
|
|
fi
|
|
OMARCHY_MIRROR=edge
|
|
OMARCHY_ISO_REF=local
|
|
shift 3
|
|
;;
|
|
--dev)
|
|
OMARCHY_ISO_REF=dev
|
|
OMARCHY_MIRROR=edge
|
|
shift
|
|
;;
|
|
--quattro)
|
|
OMARCHY_INSTALLER_REF=quattro
|
|
OMARCHY_MIRROR=edge
|
|
shift
|
|
;;
|
|
--rc)
|
|
OMARCHY_ISO_REF=rc
|
|
OMARCHY_MIRROR=rc
|
|
shift
|
|
;;
|
|
*)
|
|
echo "Unknown option: $1"
|
|
echo "Usage: $0 [--no-cache] [--keep-pkg-cache] [--no-boot-offer] [--debug] [--edge] [--dev|--rc] [--local-source <omarchy-checkout> <pkgs-checkout>]"
|
|
exit 1
|
|
;;
|
|
esac
|
|
done
|
|
|
|
if [[ -n $LOCAL_OMARCHY_PATH ]]; then
|
|
[[ -d $LOCAL_OMARCHY_PATH ]] || { echo "Error: Omarchy checkout not found at $LOCAL_OMARCHY_PATH" >&2; exit 1; }
|
|
[[ -d $LOCAL_PKGS_PATH ]] || { echo "Error: pkgs checkout not found at $LOCAL_PKGS_PATH" >&2; exit 1; }
|
|
LOCAL_OMARCHY_PATH=$(realpath "$LOCAL_OMARCHY_PATH")
|
|
LOCAL_PKGS_PATH=$(realpath "$LOCAL_PKGS_PATH")
|
|
fi
|
|
|
|
lint_file_permissions() {
|
|
local profiledef="configs/profiledef.sh"
|
|
local -A declared=()
|
|
local missing=()
|
|
|
|
while IFS= read -r path; do
|
|
[[ -n $path ]] && declared["$path"]=1
|
|
done < <(grep -oP '^\s*\["\K[^"]+(?="\])' "$profiledef" || true)
|
|
|
|
while IFS= read -r f; do
|
|
[[ -f $f ]] || continue
|
|
|
|
local rel="${f#configs/airootfs}"
|
|
local mode
|
|
mode=$(git ls-files --stage -- "$f" | awk '{print $1}')
|
|
|
|
if [[ $mode != 100755 && $(head -c 2 "$f") != "#!" ]]; then
|
|
continue
|
|
fi
|
|
|
|
if [[ -z ${declared[$rel]+x} ]]; then
|
|
missing+=("$rel")
|
|
fi
|
|
done < <(find configs/airootfs/usr/local/bin configs/airootfs/root -type f 2>/dev/null)
|
|
|
|
if (( ${#missing[@]} > 0 )); then
|
|
echo "ERROR: the following executable files are missing from $profiledef file_permissions:" >&2
|
|
printf ' %s\n' "${missing[@]}" >&2
|
|
echo "Add entries like [\"<path>\"]=\"0:0:755\" to profiledef.sh and retry." >&2
|
|
exit 1
|
|
fi
|
|
}
|
|
|
|
lint_file_permissions
|
|
|
|
# Purging the host package cache needs interactive sudo; --keep-pkg-cache
|
|
# skips it so unattended builds (test rigs, agents) can run without a prompt.
|
|
if [[ -z $KEEP_PKG_CACHE ]]; then
|
|
sudo rm -rf /var/cache/pacman/pkg/*
|
|
fi
|
|
git submodule update --init --recursive --jobs=8
|
|
|
|
BUILD_SCRIPT="builder/build-iso.sh"
|
|
BUILD_ROOT=$(realpath "${BASH_SOURCE[0]%/*}/..")
|
|
BUILD_RELEASE_PATH="$BUILD_ROOT/release"
|
|
mkdir -p "$BUILD_RELEASE_PATH"
|
|
|
|
OMARCHY_ISO_REF="${OMARCHY_ISO_REF:-quattro}"
|
|
OMARCHY_MIRROR="${OMARCHY_MIRROR:-stable}"
|
|
|
|
DOCKER_ARGS=(
|
|
--rm
|
|
--privileged
|
|
-e "OMARCHY_ISO_REF=$OMARCHY_ISO_REF"
|
|
-e "OMARCHY_MIRROR=$OMARCHY_MIRROR"
|
|
-e "OMARCHY_INSTALL_DEBUG=${OMARCHY_INSTALL_DEBUG:-}"
|
|
-e "HOST_UID=$(id -u)"
|
|
-e "HOST_GID=$(id -g)"
|
|
-v "$BUILD_RELEASE_PATH/:/out/"
|
|
-v "$BUILD_ROOT/$BUILD_SCRIPT:/$BUILD_SCRIPT:ro"
|
|
-v "$BUILD_ROOT/archiso:/archiso:ro"
|
|
-v "$BUILD_ROOT/builder:/builder:ro"
|
|
-v "$BUILD_ROOT/configs:/configs:ro"
|
|
)
|
|
|
|
if [[ -n $LOCAL_OMARCHY_PATH ]]; then
|
|
DOCKER_ARGS+=(
|
|
-v "$LOCAL_OMARCHY_PATH:/omarchy-source:ro"
|
|
-v "$LOCAL_PKGS_PATH:/omarchy-pkgs:ro"
|
|
)
|
|
fi
|
|
|
|
if [[ -d /var/cache/pacman/pkg ]]; then
|
|
DOCKER_ARGS+=(-v "/var/cache/pacman/pkg:/var/cache/pacman/pkg")
|
|
fi
|
|
|
|
# Mount the build cache directory where packages are downloaded. Channels use
|
|
# different package snapshots and must never share an offline mirror cache.
|
|
if [[ -z "$NO_CACHE" ]]; then
|
|
OFFLINE_REPO_BUILD_CACHE_DIR="$HOME/.cache/omarchy/iso_${OMARCHY_MIRROR}/airootfs/var/cache/omarchy"
|
|
mkdir -p "$OFFLINE_REPO_BUILD_CACHE_DIR"
|
|
DOCKER_ARGS+=(-v "$OFFLINE_REPO_BUILD_CACHE_DIR:/var/cache/airootfs/var/cache/omarchy")
|
|
else
|
|
# The locally cached :latest image is a cache too — docker run never
|
|
# re-checks the registry for it, so refresh it when building cold.
|
|
DOCKER_ARGS+=(--pull=always)
|
|
fi
|
|
|
|
docker run "${DOCKER_ARGS[@]}" archlinux/archlinux:latest /$BUILD_SCRIPT
|
|
|
|
latest_iso=$(\ls -t "$BUILD_RELEASE_PATH"/*.iso | head -n1)
|
|
iso_ref="${latest_iso%.*}-$OMARCHY_ISO_REF.iso"
|
|
mv -f "$latest_iso" "$iso_ref"
|
|
|
|
if [[ -z "${NO_BOOT_OFFER:-}" ]]; then
|
|
echo
|
|
gum confirm "Boot $iso_ref?" && "$BUILD_ROOT/bin/omarchy-iso-boot" "$iso_ref"
|
|
fi
|