ci: install test on every pull request
Builds the ISO a pull request produces, installs it unattended in a KVM guest on a GitHub-hosted runner, boots the installed system again, and writes the install time per phase plus first-boot and everyday-boot systemd-analyze to the job summary. Every later installer change is measured against these numbers in its own PR. Locally against the 2026-10-04 quattro ISO: install 51.3 s (42.9 s of it pacstrap), first boot 12.1 s, everyday boot 11.7 s with ~6 s in the loader, systemd running, no failed units. A disk check replaces a cleanup step: the runner has ~86 GB free, so the 2-minute "Free Disk Space" action the nightly uses is not needed.
This commit is contained in:
1 parent
e7774eeeaf
commit
1ad8872146
1 file changed
+105
@@ -0,0 +1,105 @@
|
||||
name: Install test
|
||||
|
||||
# Builds the ISO a pull request produces, installs it unattended in a KVM
|
||||
# guest, boots the installed system again, and reports how long the install
|
||||
# and both boots took. Every later change to the installer is measured
|
||||
# against these numbers in its own PR.
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
concurrency:
|
||||
group: install-test-${{ github.event.pull_request.number || github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
install:
|
||||
runs-on: ubuntu-24.04
|
||||
timeout-minutes: 75
|
||||
steps:
|
||||
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5
|
||||
|
||||
# The hosted runner has far more disk than the build needs (145 GB,
|
||||
# ~86 GB free); fail early and loudly if that ever changes.
|
||||
- name: Check disk space
|
||||
run: |
|
||||
df -h /
|
||||
avail_gb=$(df -BG --output=avail / | tail -1 | tr -dc 0-9)
|
||||
[ "$avail_gb" -ge 40 ] || { echo "::error::only ${avail_gb} GB free, the ISO build and install test need ~40 GB"; exit 1; }
|
||||
|
||||
- name: Prepare the runner for KVM guests
|
||||
run: |
|
||||
sudo apt-get update -qq
|
||||
sudo apt-get install -y -qq --no-install-recommends \
|
||||
qemu-system-x86 qemu-utils ovmf socat imagemagick \
|
||||
tesseract-ocr tesseract-ocr-eng mtools dosfstools jq openssh-client
|
||||
# test/integration installs its tools through Omarchy's Arch helper;
|
||||
# they are installed above.
|
||||
printf '#!/bin/sh\nexit 0\n' | sudo tee /usr/local/bin/omarchy-pkg-add >/dev/null
|
||||
sudo chmod 0755 /usr/local/bin/omarchy-pkg-add
|
||||
# Keep the harness's Arch paths: map Ubuntu's OVMF files onto them.
|
||||
sudo install -d /usr/share/edk2/x64
|
||||
sudo ln -sf "$(find /usr/share -name 'OVMF_CODE_4M.fd' -print -quit)" /usr/share/edk2/x64/OVMF_CODE.4m.fd
|
||||
sudo ln -sf "$(find /usr/share -name 'OVMF_VARS_4M.fd' -print -quit)" /usr/share/edk2/x64/OVMF_VARS.4m.fd
|
||||
# Ubuntu's ImageMagick 6 is `convert`; the harness calls `magick`.
|
||||
command -v magick >/dev/null || sudo ln -sf "$(command -v convert)" /usr/local/bin/magick
|
||||
sudo chmod 0666 /dev/kvm
|
||||
nproc; free -h; qemu-system-x86_64 --version | head -1
|
||||
|
||||
- uses: docker/setup-buildx-action@37fe631027851001ddb9b187196cc803df7f5f0e # v4
|
||||
|
||||
- name: Build the ISO
|
||||
run: NO_BOOT_OFFER=1 ./bin/omarchy-iso-make
|
||||
|
||||
- name: Install unattended, then boot the installed system
|
||||
env:
|
||||
OMARCHY_INTEGRATION_DISK_CACHE: none
|
||||
run: ./test/integration release/*.iso boot --no-preview --memory 8192 --timeout 1800
|
||||
|
||||
- name: Report times
|
||||
if: always()
|
||||
run: |
|
||||
base=$(ls -d test-runs/*-integration 2>/dev/null | head -1)
|
||||
[ -n "$base" ] || { echo "No test run to report" >> "$GITHUB_STEP_SUMMARY"; exit 0; }
|
||||
{
|
||||
echo "## Install test"
|
||||
echo
|
||||
if [ -f "$base/omarchy-install-timing.json" ]; then
|
||||
jq -r '"**Install:** \((.finished_at - .started_at) * 10 | round / 10) s across \(.phases | length) phases"' "$base/omarchy-install-timing.json"
|
||||
echo
|
||||
echo "| Phase | Seconds |"
|
||||
echo "| --- | ---: |"
|
||||
jq -r '.phases[] | "| \(.name) | \(.elapsed * 10 | round / 10) |"' "$base/omarchy-install-timing.json"
|
||||
echo
|
||||
fi
|
||||
if [ -f "$base/first-boot-systemd-analyze.txt" ]; then
|
||||
echo "**First boot:** $(head -1 "$base/first-boot-systemd-analyze.txt")"
|
||||
echo
|
||||
fi
|
||||
boot_dir=$(ls -d "$base"/runs/*-boot 2>/dev/null | tail -1)
|
||||
if [ -n "$boot_dir" ] && [ -f "$boot_dir/systemd-analyze.txt" ]; then
|
||||
echo "**Everyday boot:** $(head -1 "$boot_dir/systemd-analyze.txt")"
|
||||
echo
|
||||
echo "System state: $(jq -r .system_state "$boot_dir/boot-timing.json" 2>/dev/null)"
|
||||
fi
|
||||
} >> "$GITHUB_STEP_SUMMARY"
|
||||
|
||||
- name: Upload test artifacts
|
||||
if: always()
|
||||
uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6
|
||||
with:
|
||||
name: install-test-${{ github.run_id }}-${{ github.run_attempt }}
|
||||
path: |
|
||||
test-runs/*/omarchy-install-timing.json
|
||||
test-runs/*/omarchy-install.log
|
||||
test-runs/*/first-boot-systemd-analyze.txt
|
||||
test-runs/*/runs/**/*.png
|
||||
test-runs/*/runs/**/*.txt
|
||||
test-runs/*/runs/**/*.json
|
||||
test-runs/*/runs/**/*.log
|
||||
if-no-files-found: ignore
|
||||
retention-days: 14
|
||||
Reference in new issue
Block a user