Guest-boot CI
Optional GitHub Actions lanes that start a real QEMU Workload. They live in
.github/workflows/guest-boot.yml and
are never a required status check. Required PR gates stay in
ci.yml (lint, build, test, linux-build).
A Device still runs if other Devices in the Home are unreachable. Local SQLite owns Workload runtime. These lanes only prove guest boot on one Linux Device; they do not invent a second control plane.
What runs
Section titled “What runs”| Lane | Runner | When | What |
|---|---|---|---|
| Tier 1 blank | ubuntu-24.04 | every PR and push to main | Probe /dev/kvm. If usable, install QEMU + OVMF, run scripts/guest-boot-bdd.sh blank. Else SKIP (exit 0). Never TCG. |
| Tier 1 REAL_GUEST | ubuntu-24.04 | nightly schedule, run-guest-boot PR label, or workflow_dispatch with real_guest | Same probe, then scripts/guest-boot-bdd.sh real (Ubuntu cloud image + SSH). |
| Tier 2 blank | [self-hosted, linux, kvm] | only if repo variable KVM_RUNNER_ENABLED=true | Blank-disk smoke. Missing runners never hang PRs because the job if: is false when the variable is unset. |
| Tier 2 REAL_GUEST | [self-hosted, linux, kvm] | KVM_RUNNER_ENABLED=true and nightly / label / dispatch | Cloud-image + SSH smoke on the operator’s KVM Device. |
Smoke logs (server.log under BARKVISOR_DATA_DIR) upload as Actions
artifacts on every run, including failures.
mise run prepush stays lint + Swift tests + frontend tests. Do not add
guest-boot to the default push gate. Local opt-in remains:
mise run guest-smoke # blank diskmise run guest-smoke-real # REAL_GUEST=1Do not make this required
Section titled “Do not make this required”Do not add Guest Boot (or any job name from guest-boot.yml) to
branch-protection required checks until the lanes have been stable for a
while and an operator explicitly asks. A missing /dev/kvm on
GitHub-hosted runners must stay a skip, not a red required check.
Repo variable: KVM_RUNNER_ENABLED
Section titled “Repo variable: KVM_RUNNER_ENABLED”GitHub → Settings → Secrets and variables → Actions → Variables:
| Name | Value | Effect |
|---|---|---|
KVM_RUNNER_ENABLED | true | Queue the self-hosted jobs. |
| unset / anything else | — | Self-hosted jobs are skipped. PRs never wait for a runner. |
Set the variable only after a runner with labels linux and kvm is
online. If the variable is true and the runner is offline, GitHub will
wait for it.
Register a self-hosted runner
Section titled “Register a self-hosted runner”Use a dedicated Linux Device (x86_64 or aarch64) with hardware
virtualization. One process ↔ one Device ↔ one data directory still
applies: give Actions an ephemeral working directory, not the
production BARKVISOR_DATA_DIR.
1. Packages
Section titled “1. Packages”Ubuntu / Debian:
sudo apt-get updatesudo DEBIAN_FRONTEND=noninteractive apt-get install -y \ qemu-system-x86 qemu-system-arm qemu-utils ovmf \ genisoimage jq python3 curl ca-certificates \ libcurl4-openssl-dev libxml2-dev libsqlite3-dev \ swtpmFedora / RHEL-family: qemu-kvm, edk2-ovmf, genisoimage, jq, swtpm.
swtpm is optional for these Linux smokes and required later for Windows
guests with TPM.
2. KVM access
Section titled “2. KVM access”ls -l /dev/kvmsudo usermod -aG kvm "$USER"# log out and back in so the group appliestest -r /dev/kvm && test -w /dev/kvm && echo "kvm ok"The Actions user must be able to read and write /dev/kvm.
3. Swift
Section titled “3. Swift”./scripts/install-swift-linux.shecho /opt/swift/usr/bin >> ~/.profileThe workflow also runs that script when swift is not on PATH.
4. GitHub runner labels
Section titled “4. GitHub runner labels”Install the GitHub Actions runner for this repository (not an org-wide wildcard unless you intend that). Required labels:
self-hosted(added automatically)linuxkvm
Match runs-on: [self-hosted, linux, kvm] exactly.
5. Enable the lane
Section titled “5. Enable the lane”- Confirm the runner is Idle in the repo’s Actions → Runners list.
- Set
KVM_RUNNER_ENABLED=true. - Dispatch Guest Boot once from the Actions tab (
real_guestoptional).
PR label run-guest-boot
Section titled “PR label run-guest-boot”Add the run-guest-boot label to a pull request to run REAL_GUEST on
that PR (hosted if /dev/kvm is usable, plus self-hosted when the
variable is on). Unlabelled PRs only attempt the blank-disk hosted probe.
Create the label if it is missing:
gh label create run-guest-boot --description "Run REAL_GUEST guest-boot CI on this PR" --color 0E8A16What this is not
Section titled “What this is not”- Not a required check.
- Not macOS / HVF guest boot in CI.
- Not a Windows ISO boot (the
windows-amd64guest profile is separate). - Not a multi-Device Home orchestration in CI. Cross-Device smoke stays
local and opt-in (
mise run cross-device-smoke). - Not a replacement for
mise run prepush.