Merge upstream quattro

# Conflicts:
#	README.md
This commit is contained in:
ZacharyZhang-NY committed 2026-10-12 02:58:01 -04:00
commit 24f188a4be
26 files changed
+1955 -66

No files matched your search

+24 -4
View File
@@ -503,16 +503,23 @@ EOF
mcopy -i "$CIDATA_IMG" "$dir"/* ::/
}
# The dev/local ISO installs the -dev packages; a stable ISO the plain ones.
# The edge/dev/local ISO installs the -dev packages, as builder/build-iso.sh
# picks them; a stable ISO the plain ones.
detect_packages() {
RUNTIME_PACKAGE=omarchy-dev
SETTINGS_PACKAGE=omarchy-settings-dev
if [[ $(basename "$ISO") != *dev* && $(basename "$ISO") != *local* && $(basename "$ISO") != *pr* ]]; then
if [[ $(basename "$ISO") != *edge* && $(basename "$ISO") != *dev* && $(basename "$ISO") != *local* && $(basename "$ISO") != *pr* ]]; then
RUNTIME_PACKAGE=omarchy
SETTINGS_PACKAGE=omarchy-settings
fi
}
# The firmware names what it starts on the serial port: the ISO's medium while
# the installer runs, the installed disk's Limine once the install is over.
installed_system_started() {
grep -aq 'starting Boot.*"Limine"' "$1" 2>/dev/null
}
install_phase() {
log "Installing $(basename "$ISO") unattended via cidata (headless)"
@@ -534,7 +541,7 @@ install_phase() {
-device usb-storage,drive=cidata
log "Waiting for the unattended install to finish (timeout ${INSTALL_TIMEOUT}s)"
local waited=0 text progress_name
local waited=0 text progress_name first_boot_at=""
while true; do
# An unattended install reboots on its own; SSH answering means the
# installed system is up (cidata's authorized_keys enables sshd).
@@ -575,7 +582,20 @@ install_phase() {
printf -v progress_name 'success-install-progress-%04ds' "$waited"
capture_console "$progress_name"
fi
((waited % 30 == 0)) && echo " ... installing (${waited}s)"
# Once the installed system has started, the install is over and what is
# being waited for is the first boot: say so, or a hung first boot reads
# as a slow install.
if [[ -z $first_boot_at ]] && installed_system_started "$RUN_DIR/install-serial.log"; then
first_boot_at=$waited
log "Install finished after about ${waited}s. Waiting for the installed system's first boot."
fi
if ((waited % 30 == 0)); then
if [[ -n $first_boot_at ]]; then
echo " ... first boot ($((waited - first_boot_at))s, install took about ${first_boot_at}s)"
else
echo " ... installing (${waited}s)"
fi
fi
sleep 10
((waited += 10))
+244
View File
@@ -0,0 +1,244 @@
#!/bin/bash
#
# The nightly's decisions, tried without a runner: which channels a run makes
# and where they go (test/vm-image/nightly-plan), what it lays out and what
# latest.json then says (test/vm-image/nightly-layout), and two things the
# install test decides from what it is given: which Omarchy packages an ISO
# installs, and when an install is over.
set -euo pipefail
ROOT=$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")/../.." && pwd)
plan="$ROOT/test/vm-image/nightly-plan"
layout="$ROOT/test/vm-image/nightly-layout"
harness="$ROOT/test/integration.d/base-test.sh"
bash -n "$plan"
bash -n "$layout"
tmp=$(mktemp -d)
trap 'rm -rf "$tmp"' EXIT
fail() { echo "FAIL: $*" >&2; exit 1; }
equal() { [[ $2 == "$3" ]] || fail "$1: got '$2', expected '$3'"; }
refused() { # description, command...: it has to fail and say why
local what=$1; shift
if "$@" >"$tmp/refused.out" 2>"$tmp/refused.err"; then fail "$what was accepted"; fi
[[ -s $tmp/refused.err ]] || fail "$what was refused without a word"
}
# ---------------------------------------------------------------- nightly-plan
planned() { "$plan" "$@" 2>/dev/null; }
first=$(planned 2026.10.09 431 1 schedule v4.0.4 "")
equal "a first run makes both channels" "$(jq -r 'map(.channel) | join(",")' <<<"$first")" "edge,stable"
equal "the edge version" "$(jq -r '.[0].version' <<<"$first")" "2026.10.09.431"
equal "the edge path" "$(jq -r '.[0].release' <<<"$first")" "edge/2026.10.09.431"
equal "the stable version is the release's" "$(jq -r '.[1].version' <<<"$first")" "4.0.4"
equal "the stable path has the run number" "$(jq -r '.[1].release' <<<"$first")" "stable/4.0.4/431"
again=$(planned 2026.10.09 431 2 schedule v4.0.4 "")
equal "a run started again has its own edge version" "$(jq -r '.[0].version' <<<"$again")" "2026.10.09.431.2"
equal "a run started again has its own stable path" "$(jq -r '.[1].release' <<<"$again")" "stable/4.0.4/431.2"
[[ $(jq -r '.[].release' <<<"$first" | sort) != "$(jq -r '.[].release' <<<"$again" | sort)" ]] ||
fail "two attempts of one run share a path"
equal "a published release is left out of a scheduled run" \
"$(planned 2026.10.09 432 1 schedule v4.0.4 4.0.4 | jq -r 'map(.channel) | join(",")')" "edge"
equal "a new release is made on the next scheduled run" \
"$(planned 2026.10.09 432 1 schedule v4.0.5 4.0.4 | jq -r '.[1].version')" "4.0.5"
equal "a manual run makes a published release again" \
"$(planned 2026.10.09 432 1 workflow_dispatch v4.0.4 4.0.4 | jq -r 'map(.channel) | join(",")')" "edge,stable"
refused "a release tag that is not a version" "$plan" 2026.10.09 431 1 schedule nightly ""
refused "an empty release tag" "$plan" 2026.10.09 431 1 schedule "" ""
refused "a release tag with a path in it" "$plan" 2026.10.09 431 1 schedule "v4.0.4/../x" ""
refused "a run number that is not a number" "$plan" 2026.10.09 "" 1 schedule v4.0.4 ""
refused "a date in another form" "$plan" 2026-10-09 431 1 schedule v4.0.4 ""
# -------------------------------------------------------------- nightly-layout
sealed() { # directory: what vm-seal leaves
rm -rf "$1"; mkdir -p "$1"
local file
for file in base.qcow2 vmlinuz initrd cmdline; do echo "$file of ${1##*/}" >"$1/$file"; done
echo "sums of the seal" >"$1/SHA256SUMS"
}
export SITE=https://nightly.example ISO_SITE=https://iso.example ISO_COMMIT=0123456789abcdef0123456789abcdef01234567
# Edge. pacman answers for omarchy and omarchy-dev with the one installed
# package, so its line is there twice.
mkdir -p "$tmp/release"
echo "an edge iso" >"$tmp/release/omarchy-2026.10.09-x86_64-edge.iso"
sealed "$tmp/sealed-edge"
printf '%s\n' "omarchy-dev 4.0.0.r6818.gc352b62-2" "omarchy-dev 4.0.0.r6818.gc352b62-2" \
"/usr/lib/modules/7.2.8-5-omarchy-bore/pkgbase is owned by linux-omarchy-bore 7.2.8-5" "7.2.8-5-omarchy-bore" >"$tmp/edge-packages"
"$layout" edge 2026.10.09.431 edge/2026.10.09.431 "$tmp/release/omarchy-2026.10.09-x86_64-edge.iso" \
"$tmp/sealed-edge" "$tmp/edge-packages" "$tmp/out" >/dev/null
json=$tmp/out/edge/latest.json
dir=$tmp/out/edge/2026.10.09.431
field() { jq -r "$1" "$json"; }
equal "edge: files published" "$(cd "$tmp/out" && find . -type f | sort | paste -sd' ')" \
"./edge/2026.10.09.431/omarchy-edge-2026.10.09.431.iso ./edge/2026.10.09.431/omarchy-edge-2026.10.09.431.iso.sha256 ./edge/2026.10.09.431/omarchy-edge-2026.10.09.431.qcow2 ./edge/2026.10.09.431/omarchy-edge-2026.10.09.431.qcow2.sha256 ./edge/2026.10.09.431/unpacked/SHA256SUMS ./edge/2026.10.09.431/unpacked/cmdline ./edge/2026.10.09.431/unpacked/initrd ./edge/2026.10.09.431/unpacked/vm-boot ./edge/2026.10.09.431/unpacked/vmlinuz ./edge/latest.json"
(cd "$dir" && sha256sum -c --quiet ./*.sha256) || fail "edge: a checksum file does not match the file it is for"
equal "edge: the ISO and the image each have a checksum file" "$(cd "$dir" && ls ./*.sha256 | wc -l)" "2"
equal "edge: the image is the sealed disk" "$(cat "$dir/omarchy-edge-2026.10.09.431.qcow2")" "base.qcow2 of sealed-edge"
(cd "$dir/unpacked" && sha256sum -c --quiet SHA256SUMS) || fail "edge: SHA256SUMS does not match the unpacked files"
equal "edge: SHA256SUMS covers every file beside it" \
"$(awk '{ print $2 }' "$dir/unpacked/SHA256SUMS" | sort | paste -sd' ')" "$(cd "$dir/unpacked" && ls | grep -v SHA256SUMS | sort | paste -sd' ')"
cmp -s "$dir/unpacked/vm-boot" "$ROOT/test/vm-image/vm-boot" || fail "edge: the published vm-boot is not the repository's"
equal "edge: version" "$(field .version)" "2026.10.09.431"
equal "edge: channel" "$(field .channel)" "edge"
equal "edge: url" "$(field .url)" "https://nightly.example/edge/2026.10.09.431/omarchy-edge-2026.10.09.431.iso"
equal "edge: sha256 is the ISO's" "$(field .sha256)" "$(sha256sum "$dir/omarchy-edge-2026.10.09.431.iso" | cut -d' ' -f1)"
equal "edge: size is the ISO's" "$(field .size)" "$(stat -c %s "$dir/omarchy-edge-2026.10.09.431.iso")"
equal "edge: iso_commit" "$(field .iso_commit)" "$ISO_COMMIT"
equal "edge: omarchy_version, once" "$(field .omarchy_version)" "4.0.0.r6818.gc352b62-2"
equal "edge: omarchy_commit" "$(field .omarchy_commit)" "c352b62"
equal "edge: kernel" "$(field .kernel)" "7.2.8-5-omarchy-bore"
equal "edge: image address" "$(field .vm.url)" "https://nightly.example/edge/2026.10.09.431/omarchy-edge-2026.10.09.431.qcow2"
equal "edge: image checksum is the image's" "$(field .vm.sha256)" "$(sha256sum "$dir/omarchy-edge-2026.10.09.431.qcow2" | cut -d' ' -f1)"
equal "edge: image size is the image's" "$(field .vm.size)" "$(stat -c %s "$dir/omarchy-edge-2026.10.09.431.qcow2")"
equal "edge: the ISO and the image differ only in their ending" "$(field .url | sed 's/\.iso$//')" "$(field .vm.url | sed 's/\.qcow2$//')"
equal "edge: unpacked folder" "$(field .vm.unpacked)" "https://nightly.example/edge/2026.10.09.431/unpacked/"
equal "edge: every unpacked file listed is published" "$(field '.vm.unpacked_files[]' | sort | paste -sd' ')" "$(cd "$dir/unpacked" && ls | sort | paste -sd' ')"
[[ $(field .built_at) =~ ^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9:]{8}Z$ ]] || fail "edge: built_at is '$(field .built_at)'"
# What a consumer does with the ISO's name: the first run of three or more
# dotted numbers is the version.
[[ $(basename "$(field .url)") =~ [0-9]+(\.[0-9]+){2,} ]] || fail "edge: the ISO's name carries no version"
equal "edge: the version read from the ISO's name" "${BASH_REMATCH[0]}" "2026.10.09.431"
# Stable: the image is published, the released ISO stays where it is.
rm -rf "$tmp/out"
echo "a released iso" >"$tmp/release/omarchy-4.0.4.iso"
sealed "$tmp/sealed-stable"
printf '%s\n' "omarchy 4.0.4-1" "/usr/lib/modules/7.2.5-3-omarchy/pkgbase is owned by linux-omarchy 7.2.5-3" "7.2.5-3-omarchy" >"$tmp/stable-packages"
"$layout" stable 4.0.4 stable/4.0.4/431 "$tmp/release/omarchy-4.0.4.iso" "$tmp/sealed-stable" "$tmp/stable-packages" "$tmp/out" >/dev/null
json=$tmp/out/stable/latest.json
equal "stable: no ISO is published" "$(find "$tmp/out" -name '*.iso*' | wc -l)" "0"
[[ -f $tmp/release/omarchy-4.0.4.iso ]] || fail "stable: the released ISO was moved away"
equal "stable: url is the release's" "$(field .url)" "https://iso.example/omarchy-4.0.4.iso"
equal "stable: sha256 is the ISO's" "$(field .sha256)" "$(sha256sum "$tmp/release/omarchy-4.0.4.iso" | cut -d' ' -f1)"
equal "stable: version" "$(field .version)" "4.0.4"
equal "stable: omarchy_version" "$(field .omarchy_version)" "4.0.4-1"
equal "stable: a release names no commit" "$(field .omarchy_commit)" ""
equal "stable: image address has the run number" "$(field .vm.url)" "https://nightly.example/stable/4.0.4/431/omarchy-4.0.4.qcow2"
equal "stable: unpacked folder" "$(field .vm.unpacked)" "https://nightly.example/stable/4.0.4/431/unpacked/"
(cd "$tmp/out/stable/4.0.4/431" && sha256sum -c --quiet omarchy-4.0.4.qcow2.sha256) || fail "stable: the image's checksum file does not match it"
(cd "$tmp/out/stable/4.0.4/431/unpacked" && sha256sum -c --quiet SHA256SUMS) || fail "stable: SHA256SUMS does not match the unpacked files"
# Nothing half-made is described.
sealed "$tmp/sealed-short"; rm "$tmp/sealed-short/initrd"
refused "a sealed image without its initrd" "$layout" stable 4.0.4 stable/4.0.4/9 "$tmp/release/omarchy-4.0.4.iso" "$tmp/sealed-short" "$tmp/stable-packages" "$tmp/out2"
sealed "$tmp/sealed-x"; : >"$tmp/no-packages"
refused "an image that named no Omarchy package" "$layout" stable 4.0.4 stable/4.0.4/9 "$tmp/release/omarchy-4.0.4.iso" "$tmp/sealed-x" "$tmp/no-packages" "$tmp/out3"
sealed "$tmp/sealed-y"
refused "a released ISO under another version's name" "$layout" stable 4.0.5 stable/4.0.5/9 "$tmp/release/omarchy-4.0.4.iso" "$tmp/sealed-y" "$tmp/stable-packages" "$tmp/out4"
sealed "$tmp/sealed-z"
refused "a channel that does not exist" "$layout" rc 4.0.4 rc/4.0.4 "$tmp/release/omarchy-4.0.4.iso" "$tmp/sealed-z" "$tmp/stable-packages" "$tmp/out5"
# --------------------------------------------------------------- nightly-fetch
# The network is played by three stand-ins: gh lists the artifacts, curl gives
# the signed address, aria2c "downloads" a zip made here.
fetch="$ROOT/test/vm-image/nightly-fetch"
bash -n "$fetch"
if command -v zip >/dev/null && command -v unzip >/dev/null; then
stubs=$tmp/stubs; mkdir -p "$stubs" "$tmp/payload/edge/1"
echo "an image" >"$tmp/payload/edge/1/omarchy-edge-1.qcow2"
echo '{"version": "1"}' >"$tmp/payload/edge/latest.json"
(cd "$tmp/payload" && zip -qr "$tmp/artifact.zip" .)
zip_size=$(stat -c %s "$tmp/artifact.zip")
cat >"$stubs/gh" <<STUB
#!/bin/bash
case "\$*" in
"auth token") echo token ;;
*"/runs/7/artifacts"*) printf '%s\\n' \${FETCH_IDS:-11 12} ;;
*"/artifacts/"*) echo \${FETCH_SIZE:-$zip_size} ;;
esac
STUB
cat >"$stubs/curl" <<'STUB'
#!/bin/bash
echo "${@: -1}" >>"$FETCH_LOG"; printf 'https://storage.example/signed'
STUB
cat >"$stubs/aria2c" <<STUB
#!/bin/bash
echo aria2c >>"\$FETCH_LOG"
if [[ -n \${FETCH_FAIL_ONCE:-} && ! -e $tmp/failed ]]; then touch $tmp/failed; exit 1; fi
for arg in "\$@"; do case \$arg in --dir=*) dir=\${arg#--dir=} ;; --out=*) out=\${arg#--out=} ;; esac; done
cp "$tmp/artifact.zip" "\$dir/\$out"
STUB
chmod +x "$stubs"/*
fetched() { PATH="$stubs:$PATH" TMPDIR="$tmp" FETCH_LOG="$tmp/fetch.log" "$@"; }
: >"$tmp/fetch.log"
fetched "$fetch" omacom/omarchy-iso 7 nightly-edge-7 "$tmp/fetched" >/dev/null
equal "fetch: the files of the artifact" "$(cd "$tmp/fetched" && find . -type f | sort | paste -sd' ')" "./edge/1/omarchy-edge-1.qcow2 ./edge/latest.json"
grep -q "/artifacts/12/zip" "$tmp/fetch.log" || fail "fetch: of two artifacts with one name, the newer was not the one fetched"
equal "fetch: nothing left behind" "$(ls "$tmp" | grep -c 'nightly-fetch\.')" "0"
: >"$tmp/fetch.log"; rm -f "$tmp/failed"
FETCH_FAIL_ONCE=1 fetched "$fetch" omacom/omarchy-iso 7 nightly-edge-7 "$tmp/fetched-again" >/dev/null 2>&1
equal "fetch: a failed download is tried again with a new address" "$(grep -c zip "$tmp/fetch.log")" "2"
refused "an artifact that does not exist" env FETCH_IDS=" " PATH="$stubs:$PATH" TMPDIR="$tmp" FETCH_LOG="$tmp/fetch.log" "$fetch" omacom/omarchy-iso 7 nightly-edge-7 "$tmp/f3"
refused "a download of the wrong size" env FETCH_SIZE=1 PATH="$stubs:$PATH" TMPDIR="$tmp" FETCH_LOG="$tmp/fetch.log" "$fetch" omacom/omarchy-iso 7 nightly-edge-7 "$tmp/f4"
[[ ! -e $tmp/f4/edge ]] || fail "fetch: a download of the wrong size was unpacked"
refused "an artifact larger than the free space" env FETCH_SIZE=9000000000000000 PATH="$stubs:$PATH" TMPDIR="$tmp" FETCH_LOG="$tmp/fetch.log" "$fetch" omacom/omarchy-iso 7 nightly-edge-7 "$tmp/f5"
grep -q "MiB free" "$tmp/refused.err" || fail "fetch: too little room is not what was reported"
else
echo "nightly-fetch tests skipped: no zip or unzip here"
fi
# -------------------------------------------------------------- nightly-rclone
wrapped="$ROOT/test/vm-image/nightly-rclone"
bash -n "$wrapped"
mkdir -p "$tmp/rc"
rclone_says() { # exit status, output lines...: a stand-in rclone
local status=$1; shift
{ echo '#!/bin/bash'; printf 'echo %q >&2\n' "$@"; echo "exit $status"; } >"$tmp/rc/rclone"
chmod +x "$tmp/rc/rclone"
}
rclone_says 0 "Transferred: 3 / 3, 100%"
out=$(PATH="$tmp/rc:$PATH" "$wrapped" copy a b)
[[ $out != *::warning::* ]] || fail "rclone: a clean upload was reported as a retry"
[[ $out == *"Transferred: 3 / 3"* ]] || fail "rclone: its output was not passed through"
rclone_says 0 "<3>ERROR : a.qcow2: Failed to copy: NotImplemented: Not Implemented" \
"<3>ERROR : a.qcow2: Failed to copy: NotImplemented: Not Implemented" \
"<3>ERROR : unpacked/vmlinuz: Failed to copy: NotImplemented: Not Implemented" \
"<3>ERROR : Attempt 2/3 failed with 2 errors" "<3>ERROR : Attempt 3/3 succeeded"
out=$(PATH="$tmp/rc:$PATH" "$wrapped" copy a b)
[[ $out == *"::warning::rclone needed a retry for 2 file(s): a.qcow2 unpacked/vmlinuz"* ]] ||
fail "rclone: a file that failed twice is not counted once: $(grep warning <<<"$out")"
rclone_says 3 "<3>ERROR : a.qcow2: Failed to copy: AccessDenied"
if PATH="$tmp/rc:$PATH" "$wrapped" copy a b >"$tmp/rc/out" 2>&1; then fail "rclone: a failed upload passed"; fi
equal "rclone: its exit status is kept" "$(PATH="$tmp/rc:$PATH" "$wrapped" copy a b >/dev/null 2>&1; echo $?)" "3"
if grep -q '::warning::' "$tmp/rc/out"; then fail "rclone: a failed upload was reported as a retry"; fi
# rclone reads every RCLONE_<FLAG> variable as that flag: RCLONE_VERSION=v1.75.2
# was "--version=v1.75.2" and stopped the publish before it uploaded anything.
# Only its remote's settings, RCLONE_CONFIG_*, belong in a workflow's environment.
flags=$(sed -nE 's/^[[:space:]]+(RCLONE_[A-Z0-9_]+):.*/\1/p' "$ROOT"/.github/workflows/*.yml | grep -v '^RCLONE_CONFIG_' | sort -u | paste -sd' ' || true)
[[ -z $flags ]] || fail "rclone: a workflow sets $flags, which rclone would read as flags"
# ------------------------------------------------------------ the install test
# The harness is a script that starts a VM when it is read; take the two
# functions out of it.
eval "$(sed -n '/^detect_packages() {$/,/^}$/p; /^installed_system_started() {$/,/^}$/p' "$harness")"
declare -F detect_packages installed_system_started >/dev/null || fail "the harness no longer has detect_packages and installed_system_started"
packages_of() { ISO=$1; detect_packages; echo "$RUNTIME_PACKAGE $SETTINGS_PACKAGE"; }
equal "an edge ISO installs the -dev packages" "$(packages_of release/omarchy-2026.10.09-x86_64-edge.iso)" "omarchy-dev omarchy-settings-dev"
equal "a dev ISO installs the -dev packages" "$(packages_of release/omarchy-2026.10.09-x86_64-dev.iso)" "omarchy-dev omarchy-settings-dev"
equal "a released ISO installs the release packages" "$(packages_of release/omarchy-4.0.4.iso)" "omarchy omarchy-settings"
equal "a stable build installs the release packages" "$(packages_of /x/edge/omarchy-2026.10.09-x86_64-stable.iso)" "omarchy omarchy-settings"
printf '%s\r\n' 'BdsDxe: loading Boot0002 "UEFI QEMU DVD-ROM QM00011 " from PciRoot(0x0)/Pci(0x1F,0x2)/Sata(0x5,0xFFFF,0x0)' \
'BdsDxe: starting Boot0002 "UEFI QEMU DVD-ROM QM00011 " from PciRoot(0x0)/Pci(0x1F,0x2)/Sata(0x5,0xFFFF,0x0)' >"$tmp/serial"
if installed_system_started "$tmp/serial"; then fail "the installer's own boot counts as the installed system's"; fi
printf '%s\r\n' 'BdsDxe: loading Boot0005 "Limine" from HD(1,GPT,774175D2,0x800,0x400000)/\EFI\limine\limine_x64.efi' >>"$tmp/serial"
if installed_system_started "$tmp/serial"; then fail "loading Limine counts as having started it"; fi
printf '%s\r\n' 'BdsDxe: starting Boot0005 "Limine" from HD(1,GPT,774175D2,0x800,0x400000)/\EFI\limine\limine_x64.efi' >>"$tmp/serial"
installed_system_started "$tmp/serial" || fail "the installed system's Limine starting is not noticed"
if installed_system_started "$tmp/no-such-log"; then fail "a missing serial log counts as a started system"; fi
echo "nightly tests passed"
+64
View File
@@ -0,0 +1,64 @@
#!/bin/bash
#
# The offline mirror is indexed by several repo-add processes whose databases
# are then joined (builder/index-offline-mirror.sh). The result has to be the
# database one repo-add writes over the same packages, and two versions of one
# package have to be an error, since apart they would both be kept.
set -euo pipefail
ROOT=$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")/../.." && pwd)
index="$ROOT/builder/index-offline-mirror.sh"
bash -n "$index"
if ! command -v repo-add >/dev/null; then
echo "offline mirror index tests skipped: no repo-add here"
exit 0
fi
fixture=$(mktemp -d)
trap 'rm -rf "$fixture"' EXIT
fail() { echo "FAIL: $*" >&2; exit 1; }
package() { # directory name version: the least repo-add accepts as a package
local stage="$fixture/stage"
rm -rf "$stage"; mkdir -p "$stage/usr/share/$2"
echo "$2 $3" >"$stage/usr/share/$2/version"
printf 'pkgname = %s\npkgver = %s\npkgdesc = fixture\narch = any\nsize = 1\n' "$2" "$3" >"$stage/.PKGINFO"
bsdtar -czf "$1/$2-$3-any.pkg.tar.gz" -C "$stage" .PKGINFO usr
}
contents() { # database file -> directory holding its entries
mkdir -p "$2"; bsdtar -xf "$1" -C "$2"
}
mkdir "$fixture/one" "$fixture/many"
for name in alpha bravo charlie delta echo foxtrot golf; do
package "$fixture/one" "$name" 1.0-1
cp "$fixture/one/$name-1.0-1-any.pkg.tar.gz" "$fixture/many/"
done
: >"$fixture/many/alpha-1.0-1-any.pkg.tar.gz.sig" # a signature is not a package
repo-add -q "$fixture/one/offline.db.tar.gz" "$fixture"/one/*.pkg.tar.gz >/dev/null 2>&1
bash "$index" "$fixture/many" 3 >/dev/null || fail "indexing seven packages with three processes failed"
for kind in db files; do
[[ -L $fixture/many/offline.$kind ]] || fail "offline.$kind, the name pacman fetches, is missing"
contents "$fixture/one/offline.$kind.tar.gz" "$fixture/x-one-$kind"
contents "$fixture/many/offline.$kind" "$fixture/x-many-$kind"
diff -r "$fixture/x-one-$kind" "$fixture/x-many-$kind" >/dev/null \
|| fail "the joined $kind database differs from one repo-add's"
done
# More processes than packages, and a second run over an indexed mirror.
bash "$index" "$fixture/many" 64 >/dev/null || fail "more processes than packages failed"
contents "$fixture/many/offline.db" "$fixture/x-again"
diff -r "$fixture/x-one-db" "$fixture/x-again" >/dev/null || fail "indexing an already indexed mirror changed it"
package "$fixture/many" alpha 2.0-1
bash "$index" "$fixture/many" 3 >/dev/null 2>&1 && fail "two versions of one package were indexed"
mkdir "$fixture/empty"
bash "$index" "$fixture/empty" >/dev/null 2>&1 && fail "an empty mirror was indexed"
grep -Fq 'bash /builder/index-offline-mirror.sh "$offline_mirror_dir"' "$ROOT/builder/build-iso.sh" \
|| fail "the build does not use the parallel index"
echo "offline mirror index tests passed"
+2 -2
View File
@@ -82,7 +82,7 @@ class KeyboardConfigurationTest(unittest.TestCase):
)
def test_input_choice_survives_while_console_keymap_stays_real(self):
for method, keymap, layout in (("mozc", "jp106", ""), ("mozc", "us", ""), ("hangul", "us", "kr"), ("pinyin", "us", ""), ("chewing", "us", "")):
for method, keymap, layout in (("mozc", "jp106", ""), ("mozc", "us", ""), ("hangul", "us", "kr"), ("none", "us", "la"), ("pinyin", "us", ""), ("chewing", "us", "")):
with self.subTest(method=method), tempfile.TemporaryDirectory() as directory:
target = self.target(directory)
self.assertTrue(KEYBOARD.configure_keyboard(target, keymap, method, layout))
@@ -104,7 +104,7 @@ class KeyboardConfigurationTest(unittest.TestCase):
KEYBOARD.configure_keyboard(target, "unknown", "pinyin")
def test_invalid_input_preferences_are_rejected_without_writes(self):
for method, layout in (("unknown", ""), ("hangul", "kr\nKEYMAP=ru")):
for method, layout in (("unknown", ""), ("hangul", "kr\nKEYMAP=ru"), ("none", "az")):
with tempfile.TemporaryDirectory() as directory:
target = self.target(directory)
with self.assertRaises(ValueError):
+270
View File
@@ -0,0 +1,270 @@
#!/bin/bash
#
# Takes an installed Omarchy, as a user's machine holds it, moves it to another
# channel the way a user would, reboots it, and checks what came back.
#
# test/upgrade-test <installed_dir> <channel> <evidence_dir>
#
# installed_dir is what test/integration leaves once its install has passed,
# test-runs/<iso>-integration: base.qcow2, OVMF_VARS.4m.fd and id_ed25519. It is
# not written to; the machine runs on an overlay. channel is edge or rc.
#
# The machine boots through the firmware and the boot loader, so the reboot
# after the update starts whatever kernel the update installed. Commands run
# in a login shell, as a user's terminal does: Omarchy's commands need its
# environment.
#
# evidence_dir gets before.png and after.png (the desktop, unlocked), the
# update's output, the facts before and after, and report.md; stuck.png too if
# the reboot did not come back by itself. The exit status is 0 only if every
# check passed.
#
# Needs qemu-system-x86_64, qemu-img, ssh, python3 and a usable /dev/kvm.
# Env: SMP (4), MEM (8G), SSH_PORT (2422), GUEST_PASSWORD (omarchy),
# UPDATE_TIMEOUT (seconds, 1800), EXTRA_MIGRATIONS (migration files to put
# in place before the update, to try a fix that is not released yet).
set -uo pipefail
[[ $# -eq 3 ]] || { sed -n '3,24p' "$0" >&2; exit 2; }
in=$(realpath "$1") channel=$2 out=$(realpath -m "$3")
pw=${GUEST_PASSWORD:-omarchy} port=${SSH_PORT:-2422}
[[ $channel == edge || $channel == rc ]] || { echo "upgrade-test: channel is edge or rc" >&2; exit 2; }
for f in base.qcow2 OVMF_VARS.4m.fd id_ed25519; do
[[ -s $in/$f ]] || { echo "upgrade-test: $in/$f is missing" >&2; exit 1; }
done
[[ -r /dev/kvm && -w /dev/kvm ]] || { echo "upgrade-test: /dev/kvm is not usable" >&2; exit 1; }
for fw in /usr/share/edk2/x64/OVMF_CODE.4m.fd /usr/share/OVMF/OVMF_CODE_4M.fd; do
[[ -f $fw ]] && { fw_code=$fw; break; }
done
: "${fw_code:?no UEFI firmware found}"
mkdir -p "$out"
state=$(mktemp -d "${VM_STATE_DIR:-/var/tmp}/upgrade-test.XXXXXX")
cleanup() {
local status=$? pid
if [[ -f $state/qemu.pid ]]; then
pid=$(cat "$state/qemu.pid")
kill "$pid" 2>/dev/null || true
for _ in $(seq 1 50); do kill -0 "$pid" 2>/dev/null || break; sleep 0.1; done
fi
rm -rf "$state"
exit "$status"
}
trap cleanup EXIT
trap 'exit 130' INT TERM
log() { printf '==> %s\n' "$*"; }
install -m600 "$in/id_ed25519" "$state/key"
ssh_opts=(-i "$state/key" -p "$port" -o BatchMode=yes -o IdentitiesOnly=yes -o StrictHostKeyChecking=no
-o UserKnownHostsFile=/dev/null -o LogLevel=ERROR -o ConnectTimeout=3)
guest() { ssh "${ssh_opts[@]}" omarchy@127.0.0.1 "bash -lc $(printf %q "$1")" </dev/null; }
wait_ssh() { # seconds
local start=$SECONDS
until ssh "${ssh_opts[@]}" omarchy@127.0.0.1 true </dev/null 2>/dev/null; do
kill -0 "$(cat "$state/qemu.pid")" 2>/dev/null || { echo "upgrade-test: qemu exited" >&2; return 1; }
(( SECONDS - start < $1 )) || return 1
sleep 1
done
}
qmp() { # shot <file> | key <qcode>...
python3 - "$state/qmp.sock" "$@" <<'PY'
import json, socket, sys
s = socket.socket(socket.AF_UNIX); s.settimeout(20); s.connect(sys.argv[1]); f = s.makefile("rw"); f.readline()
def run(command):
f.write(json.dumps(command) + "\n"); f.flush()
while "return" not in (reply := json.loads(f.readline())):
if "error" in reply: sys.exit(reply["error"]["desc"])
run({"execute": "qmp_capabilities"})
if sys.argv[2] == "shot":
run({"execute": "screendump", "arguments": {"filename": sys.argv[3], "format": "png"}})
else:
for key in sys.argv[3:]:
run({"execute": "send-key", "arguments": {"keys": [{"type": "qcode", "data": key}]}})
PY
}
# The session starts locked. Type the password, as its owner would, and wait
# for the desktop to draw.
desktop_shot() { # file
local key keys=()
for (( key = 0; key < ${#pw}; key++ )); do keys+=("${pw:key:1}"); done
qmp key "${keys[@]}" ret || true
sleep 8
qmp shot "$1" || echo "upgrade-test: no screenshot" >&2
}
# One fact per line, name=value, the same names before and after.
facts() { # file
guest '
link=~/.local/state/omarchy/current/background; target=$(readlink -f "$link" 2>/dev/null)
echo "omarchy=$(pacman -Qq omarchy omarchy-dev 2>/dev/null | sort -u | xargs -r pacman -Q 2>/dev/null | paste -sd, -)"
echo "channel=$(omarchy-channel-current 2>/dev/null)"
echo "kernel=$(uname -r)"
echo "kernel_is_installed=$([[ -d /usr/lib/modules/$(uname -r)/kernel ]] && echo yes || echo no)"
echo "systemd=$(systemctl --version | sed -n "1s/^systemd \([0-9.]*\).*/\1/p")"
echo "hyprland=$(pacman -Q hyprland 2>/dev/null | cut -d" " -f2)"
echo "system_state=$(systemctl is-system-running 2>/dev/null)"
# A manager that cannot be asked is not a manager with nothing failed.
units=$(systemctl --failed --no-legend --plain 2>/dev/null) && units=$(awk "{print \$1}" <<<"$units" | paste -sd, -) || units="could not ask systemd"
user_units=$(systemctl --user --failed --no-legend --plain 2>/dev/null) && user_units=$(awk "{print \$1}" <<<"$user_units" | paste -sd, -) || user_units="could not ask the user manager"
echo "failed_units=$units"
echo "failed_user_units=$user_units"
echo "hyprland_running=$(pgrep -c -x Hyprland)"
echo "migrations_run=$(find ~/.local/state/omarchy/migrations -maxdepth 1 -name "*.sh" | wc -l)"
echo "migrations_skipped=$(find ~/.local/state/omarchy/migrations/skipped -name "*.sh" 2>/dev/null | wc -l)"
echo "wallpaper=${target##*/}"
echo "wallpaper_exists=$([[ -n $target && -e $target ]] && echo yes || echo no)"
echo "boot_entry_groups=$(sudo grep -c "^/+" /boot/limine.conf 2>/dev/null)"
echo "boot_id=$(cut -c1-8 /proc/sys/kernel/random/boot_id)"
' 2>/dev/null | grep -E '^[a-z_]+=' >"$1"
}
fact() { sed -n "s/^$2=//p" "$1" | head -n 1; }
qemu-img create -qf qcow2 -b "$in/base.qcow2" -F qcow2 "$state/run.qcow2"
cp "$in/OVMF_VARS.4m.fd" "$state/vars.fd"
: >"$out/serial.log"
qemu-system-x86_64 -cpu host -enable-kvm -machine q35,accel=kvm -smp "${SMP:-4}" -m "${MEM:-8G}" \
-drive "if=pflash,format=raw,readonly=on,file=$fw_code" -drive "if=pflash,format=raw,file=$state/vars.fd" \
-drive "file=$state/run.qcow2,format=qcow2,if=none,id=d0" -device virtio-blk-pci,drive=d0 \
-device virtio-vga -device virtio-rng-pci -display none -usb -device usb-kbd -serial "file:$out/serial.log" \
-netdev "user,id=n0,hostfwd=tcp:127.0.0.1:$port-:22" -device virtio-net-pci,netdev=n0 \
-qmp "unix:$state/qmp.sock,server,nowait" -pidfile "$state/qemu.pid" -daemonize
log "Booting the installed system"
wait_ssh 300 || { echo "upgrade-test: the installed system did not come up" >&2; exit 1; }
# The overlay is thrown away: let sudo through without asking, so a long
# update does not stop at a password prompt nobody is there to answer.
# sudo takes the last rule that matches, and reads this folder in name order:
# the name has to sort after the install's own rule for the wheel group.
ssh "${ssh_opts[@]}" omarchy@127.0.0.1 "echo $(printf %q "$pw") | sudo -S -p '' sh -c 'printf \"%s\\n\" \"omarchy ALL=(ALL:ALL) NOPASSWD: ALL\" \"Defaults:omarchy !authenticate\" >/etc/sudoers.d/zzz-upgrade-test'" </dev/null
# "sudo -v" is the hard one: it asks unless every rule for the user lets it
# through, which is why the rule alone is not enough.
ssh "${ssh_opts[@]}" omarchy@127.0.0.1 'sudo -k; sudo -n true && sudo -n -v' </dev/null ||
{ echo "upgrade-test: sudo still asks for a password in the guest" >&2; exit 1; }
guest 'timeout 180 systemctl is-system-running --wait >/dev/null 2>&1 || true'
facts "$out/before.txt"
desktop_shot "$out/before.png"
log "Before: $(fact "$out/before.txt" omarchy), kernel $(fact "$out/before.txt" kernel), channel $(fact "$out/before.txt" channel)"
for migration in ${EXTRA_MIGRATIONS:-}; do
log "Putting $(basename "$migration") in place before the update"
ssh "${ssh_opts[@]}" omarchy@127.0.0.1 "sudo tee /usr/share/omarchy/migrations/$(basename "$migration") >/dev/null" <"$migration"
done
# A channel that offers what the machine already has, or something older, is
# no upgrade. Say so now: the release's own updater, run with nothing to do,
# ends at a prompt nobody is there to answer.
case $channel in edge) package=omarchy-dev ;; *) package=omarchy ;; esac
# A server that cannot be reached, or does not answer in time, is not a channel
# with nothing on offer: that is a failure of its own, said as one.
if ! offered=$(guest "set -o pipefail; curl -fsSL --connect-timeout 20 --max-time 120 --retry 2 https://pkgs.omarchy.org/$channel/\$(uname -m)/omarchy.db | bsdtar -xOf - '$package-[0-9]*/desc' | sed -n '/^%VERSION%\$/{n;p;}' | head -n 1" 2>"$out/probe.log") || [[ -z $offered ]]; then
{
echo "**The $channel channel could not be asked what it offers.** The test did not run."
echo
echo '```'
tail -n 5 "$out/probe.log"
echo '```'
} >"$out/report.md"
cat "$out/report.md"
exit 1
fi
installed=$(guest "pacman -Q $package 2>/dev/null | cut -d' ' -f2" 2>/dev/null)
log "The $channel channel offers $package $offered; installed: ${installed:-none}"
# pacman's own ordering: 0 for the same version, below 0 for an older offer.
newer=1
[[ -z $installed ]] || newer=$(guest "vercmp $(printf %q "$offered") $(printf %q "$installed")" 2>/dev/null)
if (( ${newer:-0} <= 0 )); then
{
echo "**Nothing to upgrade to.** The $channel channel offers \`$package $offered\`, and the machine has \`$(fact "$out/before.txt" omarchy)\`."
echo
echo "The test did not run: point it at a channel that holds a newer Omarchy."
} >"$out/report.md"
cat "$out/report.md"
exit 1
fi
log "omarchy-channel-set $channel"
update_start=$SECONDS
guest "timeout ${UPDATE_TIMEOUT:-1800} omarchy-channel-set $channel" >"$out/update.log" 2>&1
update_status=$?
update_seconds=$(( SECONDS - update_start ))
sed -i 's/\x1b\[[0-9;?]*[A-Za-z]//g; s/\r/\n/g' "$out/update.log"
migrations_in_update=$(grep -c '^Running migration' "$out/update.log" || true)
log "The update exited $update_status after $update_seconds s, $migrations_in_update migrations"
log "Rebooting"
guest 'sudo systemctl reboot' >/dev/null 2>&1 || true
# Wait for the old boot to go away first: its sshd answers for a moment yet.
for _ in $(seq 1 90); do
ssh "${ssh_opts[@]}" -o ConnectTimeout=2 omarchy@127.0.0.1 true </dev/null 2>/dev/null || break
sleep 1
done
rebooted=no
if wait_ssh 150; then
rebooted=yes
else
# A boot that sits there until a key is pressed is a failure, and a known
# kind: keep what the screen showed, then press Enter to find out whether
# that was it, and to have a system to collect the rest from.
qmp shot "$out/stuck.png" || true
qmp key ret || true
if wait_ssh 150; then rebooted="only after a key was pressed"; fi
fi
if [[ $rebooted != no ]]; then
guest 'timeout 180 systemctl is-system-running --wait >/dev/null 2>&1 || true'
facts "$out/after.txt"
desktop_shot "$out/after.png"
else
: >"$out/after.txt"
qmp shot "$out/after.png" || true
fi
log "After: $(fact "$out/after.txt" omarchy), kernel $(fact "$out/after.txt" kernel), channel $(fact "$out/after.txt" channel)"
failures=0
rows=()
check() { # description, command...
local what=$1; shift
if "$@"; then rows+=("| ✅ | $what |"); else rows+=("| ❌ | $what |"); failures=$((failures + 1)); fi
}
b() { fact "$out/before.txt" "$1"; }
a() { fact "$out/after.txt" "$1"; }
check "The update finished without an error (exit $update_status)" test "$update_status" = 0
check "No migration was skipped ($(a migrations_skipped) skipped)" test "$(a migrations_skipped)" = 0
check "The system came back from the reboot by itself (came back: $rebooted)" test "$rebooted" = yes
check "It is a new boot (boot ID $(b boot_id) → $(a boot_id))" test -n "$(a boot_id)" -a "$(a boot_id)" != "$(b boot_id)"
check "It is on the $channel channel (got: $(a channel))" test "$(a channel)" = "$channel"
# A channel that holds what the machine already had upgrades nothing, and
# every other check would pass on a machine that was only rebooted.
check "Omarchy itself changed ($(b omarchy) → $(a omarchy))" test -n "$(a omarchy)" -a "$(a omarchy)" != "$(b omarchy)"
check "The running kernel is an installed one ($(a kernel))" test "$(a kernel_is_installed)" = yes
check "systemd reports the system running (got: $(a system_state))" test "$(a system_state)" = running
failed="$(a failed_units) $(a failed_user_units)"
failed=$(xargs <<<"$failed")
check "No failed units (${failed:-none})" test -z "$failed"
check "The desktop is up (Hyprland processes: $(a hyprland_running))" test "$(a hyprland_running)" = 1
# The same picture, whatever format it is kept in now: an update may convert
# the bundled images, and may not swap the one the user chose for another.
before_wallpaper=$(b wallpaper) after_wallpaper=$(a wallpaper)
check "The wallpaper is the one the user had, and exists ($before_wallpaper → $after_wallpaper)" \
test "$(a wallpaper_exists)" = yes -a -n "$after_wallpaper" -a "${after_wallpaper%.*}" = "${before_wallpaper%.*}"
check "The boot menu has one Omarchy group ($(a boot_entry_groups))" test "$(a boot_entry_groups)" = 1
row() { printf '| %s | %s | %s |\n' "$1" "$(b "$2")" "$(a "$2")"; }
{
if (( failures )); then echo "**$failures of ${#rows[@]} checks failed.**"; else echo "**All ${#rows[@]} checks passed.**"; fi
echo
echo "| | Before | After the update and a reboot |"
echo "| --- | --- | --- |"
row "Omarchy" omarchy
row "Channel" channel
row "Kernel running" kernel
row "systemd" systemd
row "Hyprland" hyprland
row "Migrations run" migrations_run
row "Wallpaper" wallpaper
echo
echo "The update took $update_seconds s and ran $migrations_in_update migrations."
echo
echo "| | Check |"
echo "| --- | --- |"
printf '%s\n' "${rows[@]}"
} >"$out/report.md"
cat "$out/report.md"
(( failures == 0 ))
+56
View File
@@ -0,0 +1,56 @@
#!/bin/bash
# Fetches a run's artifact for the publish job, and fast.
#
# nightly-fetch <owner/repo> <run_id> <artifact_name> <out_dir>
#
# The download action takes a multi-gigabyte artifact over a few connections,
# and GitHub's storage limits each one to a few megabytes a second: an 11 GB
# release would outlast the job. An artifact is one zip at a signed address,
# so this asks the API for that address and takes it over 16 connections.
#
# The zip goes to TMPDIR and is deleted once unpacked, so there has to be room
# for the artifact twice: point TMPDIR at a disk, not at a /tmp held in memory.
#
# Needs gh (with GH_TOKEN allowed to read the run's artifacts), curl, aria2c
# and unzip. A run started again keeps the artifacts of its earlier attempts
# under the same name: the newest is the one fetched.
set -euo pipefail
[[ $# -eq 4 ]] || { sed -n '2,16p' "$0" >&2; exit 2; }
repo=$1 run=$2 name=$3 out=$4
fail() { echo "nightly-fetch: $*" >&2; exit 1; }
id=$(gh api "repos/$repo/actions/runs/$run/artifacts" --paginate \
--jq ".artifacts[] | select(.name == \"$name\" and .expired == false) | .id" | sort -n | tail -n 1)
[[ -n $id ]] || fail "run $run has no artifact named $name"
size=$(gh api "repos/$repo/actions/artifacts/$id" --jq .size_in_bytes)
echo "nightly-fetch: artifact $id, $((size / 1048576)) MiB"
zip=$(mktemp -u "${TMPDIR:-/tmp}/nightly-fetch.XXXXXX.zip")
mkdir -p "$out"
for place in "$(dirname "$zip")" "$out"; do
free=$(( $(df --output=avail -B1 "$place" | tail -n 1) ))
(( free > size )) || fail "$place has $((free / 1048576)) MiB free, the artifact is $((size / 1048576)) MiB"
done
trap 'rm -f "$zip" "$zip.aria2"' EXIT
started=$(date +%s)
# The address is signed for a few minutes. A try that fails asks for a new one
# and carries on from what is already there.
for attempt in 1 2 3; do
url=$(curl -fsS -o /dev/null -w '%{redirect_url}' \
-H "Authorization: Bearer $(gh auth token)" -H "Accept: application/vnd.github+json" \
"https://api.github.com/repos/$repo/actions/artifacts/$id/zip")
[[ $url == https://* ]] || fail "the API gave no download address for artifact $id"
if aria2c --quiet --continue --max-connection-per-server=16 --split=16 --min-split-size=16M \
--file-allocation=none --dir="$(dirname "$zip")" --out="$(basename "$zip")" "$url"; then
break
fi
(( attempt < 3 )) || fail "the download failed three times"
echo "nightly-fetch: attempt $attempt failed, trying again" >&2
sleep 10
done
[[ $(stat -c %s "$zip") == "$size" ]] || fail "downloaded $(stat -c %s "$zip") bytes, the artifact is $size"
seconds=$(( $(date +%s) - started ))
echo "nightly-fetch: downloaded in $seconds s, $(( size / 1048576 / (seconds > 0 ? seconds : 1) )) MiB/s"
unzip -q "$zip" -d "$out"
echo "nightly-fetch: $(find "$out" -type f | wc -l) files in $out"
+112
View File
@@ -0,0 +1,112 @@
#!/bin/bash
# Lays out what one channel of a nightly run publishes and writes the
# latest.json that describes it.
#
# nightly-layout <channel> <version> <release> <iso> <sealed_dir> <vm_packages> <out_dir>
#
# release the path under the site, from nightly-plan
# iso the ISO that was installed
# sealed_dir what vm-seal made
# vm_packages what the sealed image answered to: pacman -Q of its Omarchy
# package, pacman -Qo of its kernel's pkgbase, uname -r
#
# Env: SITE (https://nightly.omarchy.org), ISO_SITE (https://iso.omarchy.org),
# ISO_COMMIT (the omarchy-iso commit, default: HEAD of this checkout).
#
# out_dir gets, under <release>/:
#
# omarchy-<...>.qcow2 and .qcow2.sha256 the VM image: one file, which boots
# by itself through UEFI
# unpacked/ its kernel, initramfs and kernel
# arguments for booting it directly,
# vm-boot, and their SHA256SUMS
# omarchy-edge-<version>.iso and .sha256 edge only
#
# and <channel>/latest.json. The released ISO already has its place:
# latest.json points there and the ISO stays where it is.
#
# The ISO and the image are moved, not copied: they are gigabytes.
set -euo pipefail
[[ $# -eq 7 ]] || { sed -n '2,12p' "$0" >&2; exit 2; }
channel=$1 version=$2 release=$3 iso_file=$4 sealed=$5 packages=$6 out=$7
here=$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)
site=${SITE:-https://nightly.omarchy.org}
iso_site=${ISO_SITE:-https://iso.omarchy.org}
iso_commit=${ISO_COMMIT:-$(git -C "$here" rev-parse HEAD)}
fail() { echo "nightly-layout: $*" >&2; exit 1; }
[[ $channel == edge || $channel == stable ]] || fail "'$channel' is not a channel"
[[ -f $iso_file ]] || fail "no ISO at $iso_file"
unpacked=(vmlinuz initrd cmdline)
for file in base.qcow2 "${unpacked[@]}"; do
[[ -s $sealed/$file ]] || fail "the sealed image has no $file"
done
omarchy=$(awk '$1 == "omarchy" || $1 == "omarchy-dev" { print $2; exit }' "$packages")
kernel=$(tail -n 1 "$packages")
[[ -n $omarchy ]] || fail "$packages names no omarchy package"
[[ $kernel =~ ^[0-9]+\.[0-9] ]] || fail "$packages does not end with a kernel release"
# An edge package's version carries the commit it was built from.
omarchy_commit=$(sed -nE 's/.*\.g([0-9a-f]+)-.*/\1/p' <<<"$omarchy")
dir=$out/$release
mkdir -p "$dir/unpacked" "$out/$channel"
if [[ $channel == edge ]]; then
name=omarchy-$channel-$version
iso=$name.iso
iso_url=$site/$release/$iso
mv "$iso_file" "$dir/$iso"
(cd "$dir" && sha256sum "$iso" >"$iso.sha256")
iso_sha256=$(cut -d' ' -f1 "$dir/$iso.sha256") iso_size=$(stat -c %s "$dir/$iso")
else
name=omarchy-$version
iso=$name.iso
[[ ${iso_file##*/} == "$iso" ]] || fail "the released ISO is $iso, not ${iso_file##*/}"
iso_url=$iso_site/$iso
iso_sha256=$(sha256sum "$iso_file" | cut -d' ' -f1) iso_size=$(stat -c %s "$iso_file")
fi
# The image has the ISO's name, so the two are told apart by their endings.
image=$name.qcow2
mv "$sealed/base.qcow2" "$dir/$image"
(cd "$dir" && sha256sum "$image" >"$image.sha256")
for file in "${unpacked[@]}"; do mv "$sealed/$file" "$dir/unpacked/$file"; done
cp "$here/vm-boot" "$dir/unpacked/vm-boot"
unpacked+=(vm-boot)
(cd "$dir/unpacked" && sha256sum "${unpacked[@]}" >SHA256SUMS)
latest=$out/$channel/latest.json
jq -n \
--arg version "$version" --arg channel "$channel" --arg release "$site/$release" --arg image "$image" \
--arg built_at "$(date -u +%Y-%m-%dT%H:%M:%SZ)" \
--arg url "$iso_url" --arg sha256 "$iso_sha256" --argjson size "$iso_size" \
--arg iso_commit "$iso_commit" --arg omarchy_version "$omarchy" --arg omarchy_commit "$omarchy_commit" \
--arg kernel "$kernel" \
--arg vm_sha256 "$(cut -d' ' -f1 "$dir/$image.sha256")" --argjson vm_size "$(stat -c %s "$dir/$image")" \
--args '{
version: $version, channel: $channel, built_at: $built_at,
url: $url, sha256: $sha256, size: $size,
iso_commit: $iso_commit, omarchy_version: $omarchy_version, omarchy_commit: $omarchy_commit,
kernel: $kernel,
vm: {
url: "\($release)/\($image)", sha256: $vm_sha256, size: $vm_size,
unpacked: "\($release)/unpacked/", unpacked_files: ($ARGS.positional + ["SHA256SUMS"]),
user: "omarchy", password: "omarchy",
ssh: "keys only; vm-boot makes one for each boot"
}
}' "${unpacked[@]}" >"$latest"
# What is about to be published has to say what it should: one value in every
# field, and checksums that are checksums.
jq -e --arg channel "$channel" '
def one_line: type == "string" and test("^[^\n]+$");
def sha: type == "string" and test("^[0-9a-f]{64}$");
(.version | one_line) and .channel == $channel
and (.url | test("^https://[^\n ]+\\.iso$")) and (.sha256 | sha) and .size > 0
and (.iso_commit | test("^[0-9a-f]{40}$"))
and (.omarchy_version | one_line) and (.omarchy_commit | test("^[0-9a-f]*$")) and (.kernel | one_line)
and (.vm.url | test("^https://[^\n ]+\\.qcow2$")) and (.vm.sha256 | sha) and .vm.size > 0
and (.vm.unpacked | test("^https://[^\n ]+/unpacked/$")) and (.vm.unpacked_files | length) == 5
' "$latest" >/dev/null || { cat "$latest" >&2; fail "latest.json does not say what it should"; }
cat "$latest"
+42
View File
@@ -0,0 +1,42 @@
#!/bin/bash
# Says which channels a nightly run makes, under which version, and where
# each one is published. It decides; the workflow fetches what it needs to
# know and passes it in, so every case can be tried without a runner.
#
# nightly-plan <date> <run_number> <run_attempt> <event> <release_tag> [published_stable]
#
# date today, as YYYY.MM.DD
# event what started the run: schedule, workflow_dispatch
# release_tag omacom/omarchy's latest release, such as v4.0.4
# published_stable the version stable/latest.json names now, if any
#
# Prints a JSON list of {channel, version, release}; release is the path
# under the site.
#
# An edge version is the date and the run number. A stable version is the
# release's own, and on a scheduled run a release already published is left
# out: it is done once. Two builds are never the same bytes and a published
# file is never replaced, so no path is used twice: a stable image has the run
# number in its path, and a run started again adds its attempt to the number.
set -euo pipefail
[[ $# -eq 5 || $# -eq 6 ]] || { sed -n '2,12p' "$0" >&2; exit 2; }
date=$1 run=$2 attempt=$3 event=$4 tag=$5 published=${6:-}
fail() { echo "nightly-plan: $*" >&2; exit 1; }
[[ $date =~ ^[0-9]{4}\.[0-9]{2}\.[0-9]{2}$ ]] || fail "'$date' is not a date like 2026.10.09"
[[ $run =~ ^[1-9][0-9]*$ ]] || fail "'$run' is not a run number"
[[ $attempt =~ ^[1-9][0-9]*$ ]] || fail "'$attempt' is not a run attempt"
stable=${tag#v}
[[ $stable =~ ^[0-9]+(\.[0-9]+)+$ ]] || fail "the latest release is '$tag', not a version"
build=$run
[[ $attempt == 1 ]] || build+=.$attempt
channels=$(jq -cn --arg v "$date.$build" '[{channel: "edge", version: $v, release: "edge/\($v)"}]')
if [[ $event == schedule && $published == "$stable" ]]; then
echo "nightly-plan: stable $stable is already published" >&2
else
channels=$(jq -c --arg v "$stable" --arg build "$build" \
'. + [{channel: "stable", version: $v, release: "stable/\($v)/\($build)"}]' <<<"$channels")
fi
echo "$channels"
+19
View File
@@ -0,0 +1,19 @@
#!/bin/bash
# Runs rclone for the publish job and says when it only got there on a retry.
#
# nightly-rclone <rclone arguments...>
#
# rclone tries a failed transfer again by itself, and a run that passes on the
# second attempt looks like any other. This passes rclone's output and exit
# status through, and adds a warning for the run's page naming the files that
# failed on an earlier attempt.
set -uo pipefail
log=$(mktemp)
trap 'rm -f "$log"' EXIT
rclone "$@" 2>&1 | tee "$log"
status=${PIPESTATUS[0]}
files=$(sed -nE 's/^.*ERROR : (.*): Failed to copy: .*$/\1/p' "$log" | sort -u)
if [[ $status -eq 0 && -n $files ]]; then
echo "::warning::rclone needed a retry for $(wc -l <<<"$files") file(s): $(paste -sd' ' <<<"$files")"
fi
exit "$status"
+86
View File
@@ -0,0 +1,86 @@
#!/bin/bash
# Boots a sealed Omarchy image (vm-seal) as a throwaway machine.
#
# vm-boot <image> boot, print how to log in, run until Ctrl-C
# vm-boot <image> <command...> boot, run the command over SSH, power off;
# exits with the command's status
#
# <image> is a downloaded disk, omarchy-<...>.qcow2, with vmlinuz, initrd and
# cmdline in the same directory as this script, as in a published "unpacked"
# folder. Or it is a directory as vm-seal leaves it, holding base.qcow2 and
# those three files.
#
# Nothing is written to the image: the machine runs on a copy-on-write overlay
# that is deleted on exit. Each boot gets a new SSH key and a new machine ID;
# the image itself holds no key and its SSH takes no password.
#
# Needs qemu-system-x86_64, qemu-img, ssh and a usable /dev/kvm.
# Env: SMP (4), MEM (4G), SSH_PORT (random), VM_UUID (random), APPEND (more
# kernel arguments), QEMU_EXTRA (more qemu arguments, split on spaces),
# VM_STATE_DIR (/var/tmp; holds the overlay, so it needs room to grow).
set -euo pipefail
[[ $# -ge 1 ]] || { sed -n '2,21p' "$0" >&2; exit 2; }
image=$(realpath "$1"); shift
if [[ -d $image ]]; then
base=$image disk=$image/base.qcow2
else
base=$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd) disk=$image
fi
[[ -s $disk ]] || { echo "vm-boot: there is no disk image at $disk" >&2; exit 1; }
for f in vmlinuz initrd cmdline; do
[[ -s $base/$f ]] || { echo "vm-boot: $base/$f is missing" >&2; exit 1; }
done
[[ -r /dev/kvm && -w /dev/kvm ]] || { echo "vm-boot: /dev/kvm is not usable" >&2; exit 1; }
state=$(mktemp -d "${VM_STATE_DIR:-/var/tmp}/vm.XXXXXX")
cleanup() {
local status=$? pid
if [[ -f $state/qemu.pid ]]; then
pid=$(cat "$state/qemu.pid")
kill "$pid" 2>/dev/null || true
for _ in $(seq 1 50); do kill -0 "$pid" 2>/dev/null || break; sleep 0.1; done
fi
rm -rf "$state"
exit "$status"
}
trap cleanup EXIT
trap 'exit 130' INT TERM
port=${SSH_PORT:-$(( 20000 + RANDOM % 10000 ))}
uuid=${VM_UUID:-$(cat /proc/sys/kernel/random/uuid)}
# A key made for this boot only, handed in through the firmware tables as a
# systemd credential that writes authorized_keys.
ssh-keygen -q -t ed25519 -N '' -C vm-boot -f "$state/id_ed25519"
keys=$(printf 'd /home/omarchy/.ssh 0700 omarchy omarchy -\nf+ /home/omarchy/.ssh/authorized_keys 0600 omarchy omarchy - %s\n' \
"$(cat "$state/id_ed25519.pub")" | base64 -w0)
ssh_opts=(-i "$state/id_ed25519" -p "$port" -o BatchMode=yes -o IdentitiesOnly=yes
-o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -o LogLevel=ERROR)
qemu-img create -qf qcow2 -b "$disk" -F qcow2 "$state/run.qcow2"
t0=$(date +%s%N)
# shellcheck disable=SC2086
qemu-system-x86_64 -cpu host -enable-kvm -machine q35,accel=kvm -smp "${SMP:-4}" -m "${MEM:-4G}" \
-kernel "$base/vmlinuz" -initrd "$base/initrd" -append "$(cat "$base/cmdline")${APPEND:+ $APPEND}" \
-uuid "$uuid" \
-drive "file=$state/run.qcow2,format=qcow2,if=none,id=d0" -device virtio-blk-pci,drive=d0 \
-smbios "type=11,value=io.systemd.credential.binary:tmpfiles.extra=$keys" \
-device virtio-vga -device virtio-rng-pci -display none \
-netdev "user,id=n0,hostfwd=tcp:127.0.0.1:$port-:22" -device virtio-net-pci,netdev=n0 \
-qmp "unix:$state/qmp.sock,server,nowait" -pidfile "$state/qemu.pid" -daemonize ${QEMU_EXTRA:-}
# </dev/null: the probe must not eat a script meant for the command below.
until ssh "${ssh_opts[@]}" -o ConnectTimeout=1 omarchy@127.0.0.1 true </dev/null 2>/dev/null; do
kill -0 "$(cat "$state/qemu.pid")" 2>/dev/null || { echo "vm-boot: qemu exited before ssh came up" >&2; exit 1; }
(( ($(date +%s%N) - t0) / 1000000 < 300000 )) || { echo "vm-boot: no ssh after 300s" >&2; exit 1; }
sleep 0.2
done
echo "vm-boot: ssh up after $(( ($(date +%s%N) - t0) / 1000000 )) ms, machine ID ${uuid//-/}" >&2
if [[ $# -gt 0 ]]; then
# Stdin passes through, so `vm-boot dir bash -s <script` works.
ssh "${ssh_opts[@]}" omarchy@127.0.0.1 "$@"
else
echo "ssh ${ssh_opts[*]} omarchy@127.0.0.1"
echo "Desktop and sudo password: omarchy. QMP socket: $state/qmp.sock. Ctrl-C powers it off."
while kill -0 "$(cat "$state/qemu.pid")" 2>/dev/null; do sleep 1; done
fi
+148
View File
@@ -0,0 +1,148 @@
#!/bin/bash
# Turns an installed Omarchy disk (test/integration's base image) into an image anyone can
# download and boot: every boot is its own machine, nothing of the build is
# left in it, and it boots straight into its kernel, so a boot takes seconds.
#
# vm-seal <installed_dir> <sealed_dir>
#
# installed_dir holds base.qcow2, OVMF_VARS.4m.fd and id_ed25519, which is
# what test/integration leaves in test-runs/<iso>-integration once its install
# has passed. sealed_dir gets a standalone, zstd-compressed base.qcow2, which
# boots by itself through UEFI, and the UKI's vmlinuz, initrd and cmdline for
# booting it directly. It holds no key: each boot is handed one (see vm-boot).
#
# The image keeps the installer's user and password (GUEST_PASSWORD, default
# omarchy) for the desktop and sudo. SSH takes keys only.
set -euo pipefail
[[ $# -eq 2 ]] || { echo "Usage: vm-seal <installed_dir> <sealed_dir>" >&2; exit 2; }
in=$(realpath "$1") out=$(realpath -m "$2")
pw=${GUEST_PASSWORD:-omarchy}
for fw in /usr/share/edk2/x64/OVMF_CODE.4m.fd /usr/share/OVMF/OVMF_CODE_4M.fd; do
[[ -f $fw ]] && { fw_code=$fw; break; }
done
: "${fw_code:?no OVMF firmware found}"
state=$(mktemp -d /var/tmp/seal.XXXXXX)
cleanup() {
local status=$? pid
if [[ -f $state/qemu.pid ]]; then
pid=$(cat "$state/qemu.pid")
kill "$pid" 2>/dev/null || true
for _ in $(seq 1 50); do kill -0 "$pid" 2>/dev/null || break; sleep 0.1; done
fi
rm -rf "$state"
exit "$status"
}
trap cleanup EXIT
port=$(( 30000 + RANDOM % 5000 ))
ssh_vm() {
ssh -i "$in/id_ed25519" -p "$port" -o BatchMode=yes -o IdentitiesOnly=yes \
-o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null \
-o ConnectTimeout=2 -o LogLevel=ERROR omarchy@127.0.0.1 "$@"
}
# Runs a script as root in the guest and fails if any line of it fails. The
# password goes to sudo on stdin, never into a command line.
root() {
printf '%s\n' "$pw" | ssh_vm "sudo -S -p '' bash -ec $(printf %q "trap 'echo \"vm-seal: failed in the guest at: \$BASH_COMMAND\" >&2' ERR
$1")"
}
qemu-img create -qf qcow2 -b "$in/base.qcow2" -F qcow2 "$state/edit.qcow2"
cp "$in/OVMF_VARS.4m.fd" "$state/vars.fd"
qemu-system-x86_64 -cpu host -enable-kvm -machine q35,accel=kvm -smp 4 -m 4G \
-drive if=pflash,format=raw,readonly=on,file="$fw_code" \
-drive if=pflash,format=raw,file="$state/vars.fd" \
-drive "file=$state/edit.qcow2,format=qcow2,if=virtio,discard=unmap" -display none \
-netdev "user,id=n0,hostfwd=tcp:127.0.0.1:$port-:22" -device virtio-net-pci,netdev=n0 \
-pidfile "$state/qemu.pid" -daemonize
for i in $(seq 1 150); do
ssh_vm true 2>/dev/null && break
(( i < 150 )) || { echo "vm-seal: no ssh on the installed disk" >&2; exit 1; }
sleep 2
done
# Let first-boot work finish before taking it apart.
ssh_vm 'timeout 180 systemctl is-system-running --wait >/dev/null 2>&1 || true'
mkdir -p "$out"
# The kernel that is running: edge installs linux-omarchy-bore where stable
# installs linux-omarchy, and the boot entry, not the UKI, may hold the
# command line.
kernel=$(ssh_vm 'cat "/usr/lib/modules/$(uname -r)/pkgbase"')
root "cat /boot/EFI/Linux/omarchy_$kernel.efi" >"$state/uki.efi"
ssh_vm 'cat /proc/cmdline' >"$state/cmdline"
root '
# The ISO writes autologin only for encrypted installs; a test has nobody at
# SDDM, and a desktop check that skips for want of a session reads as a pass.
printf "[Autologin]\nUser=omarchy\nSession=omarchy.desktop\n" >/etc/sddm.conf.d/autologin.conf
# The image is public and its password is too, so SSH takes keys only. sshd
# keeps the first value it reads, hence a name that sorts first.
printf "PasswordAuthentication no\nKbdInteractiveAuthentication no\nAuthenticationMethods publickey\n" \
>/etc/ssh/sshd_config.d/00-omarchy-vm.conf
ssh-keygen -A >/dev/null # sshd -T needs host keys to parse; they go below
sshd -T | grep -qix "passwordauthentication no"
sshd -T | grep -qix "authenticationmethods publickey"
# Empty, not "uninitialized": that string marks a first boot, and a first boot
# applies unit presets, which on Arch disable everything not listed. Empty lets
# systemd take the VM SMBIOS UUID (qemu -uuid) as this boot machine ID.
# Host keys come back from sshdgenkeys.service before sshd starts.
: >/etc/machine-id
rm -f /var/lib/dbus/machine-id /etc/ssh/ssh_host_*
rm -f /home/omarchy/.ssh/authorized_keys /home/omarchy/.bash_history /root/.bash_history
# The factory snapshot the installer took carries the same machine ID.
mkdir -p /run/seal-top
mount -o subvolid=5 "$(findmnt -no SOURCE / | sed "s/\[.*//")" /run/seal-top
if [ -f /run/seal-top/@factory/etc/machine-id ]; then
ro=$(btrfs property get -ts /run/seal-top/@factory ro)
[ "$ro" = ro=false ] || btrfs property set -ts /run/seal-top/@factory ro false
: >/run/seal-top/@factory/etc/machine-id
[ "$ro" = ro=false ] || btrfs property set -ts /run/seal-top/@factory ro true
fi
umount /run/seal-top
# Stopping the unit saves a seed; with it stopped, shutdown saves none.
systemctl stop systemd-random-seed.service
rm -f /var/lib/systemd/random-seed /var/lib/systemd/credential.secret
# Leases and the key NetworkManager derives stable addresses from.
systemctl stop NetworkManager.service
rm -f /var/lib/NetworkManager/*.lease /var/lib/NetworkManager/secret_key \
/var/lib/NetworkManager/seen-bssids /var/lib/NetworkManager/timestamps \
/var/lib/NetworkManager/NetworkManager.state
# Vacuuming leaves the active journal. Send journald to /run, then the
# build logs on disk can go, and shutdown writes nothing back.
journalctl --relinquish-var
rm -rf /var/log/journal/*
test ! -s /etc/machine-id
test -z "$(ls /etc/ssh/ssh_host_* /var/lib/NetworkManager/*.lease /var/log/journal/* 2>/dev/null)"
test ! -e /home/omarchy/.ssh/authorized_keys
test ! -e /var/lib/systemd/random-seed
sync
# Hand freed blocks back to the disk image, so the copy skips them.
fstrim -av >/dev/null
(sleep 1; systemctl poweroff) >/dev/null 2>&1 &'
# The key that let us in is gone, so the poweroff above was the last word.
pid=$(cat "$state/qemu.pid")
for _ in $(seq 1 120); do kill -0 "$pid" 2>/dev/null || break; sleep 1; done
if kill -0 "$pid" 2>/dev/null; then echo "vm-seal: the VM did not power off" >&2; exit 1; fi
rm -f "$state/qemu.pid"
# Direct boot skips the firmware and Limine, which spend most of a boot reading
# and hashing the UKI. resume= points at the image's own swap, so drop it.
objcopy -O binary --only-section=.linux "$state/uki.efi" "$out/vmlinuz"
objcopy -O binary --only-section=.initrd "$state/uki.efi" "$out/initrd"
tr -d '\0' <"$state/cmdline" | tr ' ' '\n' | { grep -vE '^(resume|resume_offset)=|^$' || true; } | paste -sd' ' >"$out/cmdline"
[[ -s $out/vmlinuz && -s $out/initrd && -s $out/cmdline ]] || { echo "vm-seal: the UKI gave no kernel, initrd or cmdline" >&2; exit 1; }
# zstd clusters: QEMU reads them as they are, so the download boots as it is.
qemu-img convert -c -O qcow2 -o compression_type=zstd -m 16 -W "$state/edit.qcow2" "$out/base.qcow2"
( cd "$out" && sha256sum base.qcow2 vmlinuz initrd cmdline >SHA256SUMS )
echo "sealed: $out ($(du -sh "$out/base.qcow2" | cut -f1)); cmdline: $(cat "$out/cmdline")"
+49
View File
@@ -0,0 +1,49 @@
#!/bin/bash
# Boots a sealed image once, as a throwaway machine, and checks that it is
# what vm-seal promises: a desktop that comes up, nothing of the build left
# in it, and SSH that takes keys only. Exits non-zero on any failed check.
#
# vm-verify <sealed_dir>
set -euo pipefail
[[ $# -eq 1 ]] || { echo "Usage: vm-verify <sealed_dir>" >&2; exit 2; }
here=$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)
base=$(realpath "$1")
( cd "$base" && sha256sum --quiet -c SHA256SUMS )
uuid=$(cat /proc/sys/kernel/random/uuid)
export VM_UUID=$uuid SSH_PORT=$(( 20000 + RANDOM % 10000 ))
VM_PW=${GUEST_PASSWORD:-omarchy} "$here/vm-boot" "$base" "WANT_ID=${uuid//-/} PW=${GUEST_PASSWORD:-omarchy} bash -s" <<'GUEST'
fail=0
check() { # description, then a command that must succeed
local what=$1; shift
if "$@" >/dev/null 2>&1; then echo "ok $what"; else echo "FAIL $what"; fail=1; fi
}
root() { printf '%s\n' "$PW" | sudo -S -p '' "$@"; }
booted=$(( $(date +%s) - $(cut -d. -f1 /proc/uptime) - 5 ))
newer() { [ "$(root stat -c %Y "$1")" -ge "$booted" ]; } # written by this boot
check "the system reaches running or degraded" \
sh -c 's=$(timeout 120 systemctl is-system-running --wait); [ "$s" = running ] || [ "$s" = degraded ]'
check "no unit failed" sh -c '[ -z "$(systemctl --failed --no-legend)" ]'
check "a desktop session is logged in" sh -c 'for i in $(seq 1 60); do pgrep -x Hyprland && exit 0; sleep 0.5; done; exit 1'
check "the machine ID is the one this boot was given" [ "$(cat /etc/machine-id)" = "$WANT_ID" ]
check "the journal holds this machine only" [ "$(root ls /var/log/journal | tr '\n' ' ')" = "$WANT_ID " ]
check "SSH refuses passwords" sh -c "printf '%s\n' '$PW' | sudo -S -p '' sshd -T | grep -qix 'passwordauthentication no'"
check "SSH requires a key" sh -c "printf '%s\n' '$PW' | sudo -S -p '' sshd -T | grep -qix 'authenticationmethods publickey'"
# Asking with no method makes sshd list the ones it would take.
check "sshd offers a key as the only way in" \
sh -c 'ssh -o PreferredAuthentications=none -o BatchMode=yes -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null omarchy@127.0.0.1 true 2>&1 | grep -qF "Permission denied (publickey)."'
check "authorized_keys holds one key, this boot's" [ "$(grep -c . ~/.ssh/authorized_keys)" = 1 ]
check "SSH host keys were made by this boot" newer /etc/ssh/ssh_host_ed25519_key
check "NetworkManager's key was made by this boot" newer /var/lib/NetworkManager/secret_key
check "one DHCP lease, this boot's" [ "$(root sh -c 'ls /var/lib/NetworkManager/*.lease | wc -l')" = 1 ]
check "no shell history" sh -c '! [ -e ~/.bash_history ]'
check "the package cache is empty" [ -z "$(ls /var/cache/pacman/pkg)" ]
root mkdir -p /run/top && root mount -o subvolid=5,ro "$(findmnt -no SOURCE / | sed 's/\[.*//')" /run/top
check "the factory snapshot has no machine ID" sh -c "! printf '%s\n' '$PW' | sudo -S -p '' test -s /run/top/@factory/etc/machine-id"
check "the factory snapshot holds no SSH login key" sh -c "! printf '%s\n' '$PW' | sudo -S -p '' sh -c 'ls /run/top/@factory/root/.ssh/authorized_keys /run/top/@factory/home/*/.ssh/authorized_keys' 2>/dev/null | grep -q ."
check "the factory snapshot has no SSH host keys" sh -c "[ -z \"\$(printf '%s\n' '$PW' | sudo -S -p '' sh -c 'ls /run/top/@factory/etc/ssh/ssh_host_* 2>/dev/null')\" ]"
check "no snapshots besides the current system" [ -z "$(root ls /.snapshots)" ]
echo "omarchy $(pacman -Q omarchy 2>/dev/null | cut -d' ' -f2), kernel $(uname -r), $(systemd-analyze | head -1)"
exit $fail
GUEST