Skip to content

ci: build images with the production LongQT OpenCore + unified CPU recipe - #4

Merged
CMGS merged 1 commit into
masterfrom
ci/longqt-pipeline
Jul 2, 2026
Merged

ci: build images with the production LongQT OpenCore + unified CPU recipe#4
CMGS merged 1 commit into
masterfrom
ci/longqt-pipeline

Conversation

@CMGS

@CMGS CMGS commented Jul 2, 2026

Copy link
Copy Markdown
Contributor

What changed

The CI image-build pipeline now boots the exact same firmware stack production uses (doctor.sh + the Go CLI): LongQT OpenCore, apt ovmf 4M firmware, and a single Skylake-Client-v4,vendor=GenuineIntel,kvm=on CPU.

  • New scripts/lib-firmware.sh — extracts the validated ISO-download + qemu-nbd bake from doctor.sh into a self-contained bake_opencore_qcow2 OUT_QCOW2 (downloads the LongQT ISO, LONGQT_VER default v0.7, 384M qcow2, GPT+ESP via sgdisk, mkfs.fat -F32, copies EFI_RELEASE/EFI, with the blockdev-size + partition readiness waits and its own subshell-scoped temp-dir/trap cleanup). Privileged steps go through $SUDO so it works whether the caller is root (doctor) or an unprivileged CI runner with passwordless sudo.
  • scripts/doctor.sh — now sources the lib and calls bake_opencore_qcow2; observable behavior (log lines, idempotency check, exit codes, root/deps/nbd checks) is unchanged.
  • scripts/build-qemu-macos.sh
    • OpenCore is baked into the workdir via the lib; every $OSX_KVM_DIR/OpenCore/OpenCore.qcow2 reference (boot/install/setup/slim/verify + configure_opencore) now points at the baked file. The qemu-nbd config.plist patch stays, applied to the baked image.
    • OVMF now comes from apt: /usr/share/OVMF/OVMF_CODE_4M.fd (read-only pflash) + a per-build writable copy of OVMF_VARS_4M.fd. OSX-KVM OVMF copies dropped.
    • -cpu replaced with exactly Skylake-Client-v4,vendor=GenuineIntel,kvm=on.
    • kholia/OSX-KVM is now cloned only for fetch-macOS-v2.py (recovery download); header comment updated.
  • .github/workflows/build-macos-image.yml — added ovmf gdisk dosfstools parted to the apt install list (the bake now runs in CI and needs sgdisk/mkfs.fat/partprobe + the OVMF firmware).
  • README.md — the "CI image pipeline" section now describes the LongQT + unified-CPU recipe and that CI boots the exact same firmware stack production uses.

Why one stack matters

Production already runs LongQT OpenCore; the OSX-KVM OpenCore does not boot on AMD Zen5, so the old pipeline validated golden images against a loader the hosts never run. Baking the same LongQT firmware in CI means an image that passes CI boots identically on the Intel/AMD hosts the CLI targets.

Display-resolution preservation

OSX-KVM's OVMF_VARS-1920x1080.fd pre-bakes a 1920x1080 GOP mode that the OCR click-through coordinates (fixed pixel positions) depend on; stock OVMF_VARS_4M.fd boots at the default resolution. To compensate, configure_opencore's plist patch now also sets UEFI>Output>Resolution="1920x1080". Verified against the LongQT v0.7 RELEASE config.plist: its UEFI>Output already has ProvideConsoleGop=True and Resolution="", so the patch touches only Resolution (all other Output keys preserved) and will take effect. A WHY comment documents this at the patch site.

Validation

  • bash -n on all three scripts: pass.
  • shellcheck -x on lib-firmware.sh + doctor.sh: clean. build-qemu-macos.sh has only pre-existing findings (SC2054/SC2034/SC2086/SC2015, identical set to origin/master), none introduced here; the $SUDO idiom is deliberately unquoted.
  • Grep confirms no leftover OSX-KVM OpenCore/OVMF references in the build script (remaining OSX-KVM uses are the fetch-macOS-v2.py clone + the recovery/disk workdir only).
  • Go gate (no .go files changed, run as a sanity no-op): gofumpt -l . clean, go build (darwin+linux) OK, golangci-lint (darwin+linux) 0 issues, go test -race OK.
  • A real workflow_dispatch run is the follow-up validation and is still pending — no workflow was triggered as part of this PR.

🤖 Generated with Claude Code

…cipe

The CI image pipeline still booted kholia/OSX-KVM's OpenCore.qcow2 + OSX-KVM
OVMF (incl. OVMF_VARS-1920x1080.fd) + a bespoke -cpu line, while production
(doctor.sh + the Go CLI) boots LongQT OpenCore + apt ovmf 4M + a single
Skylake-Client-v4 CPU. That OSX-KVM OpenCore does not boot on AMD Zen5, so CI
validated a stack the hosts never run. Extract the doctor bake into a shared
scripts/lib-firmware.sh and point both scripts at it so CI boots the exact same
firmware everywhere. Stock OVMF_VARS_4M.fd lacks the pre-baked 1920x1080 GOP the
OCR click-through coordinates need, so the config.plist patch now also sets
UEFI>Output>Resolution to reproduce that framebuffer geometry.
@CMGS
CMGS merged commit 984bb13 into master Jul 2, 2026
3 checks passed
@CMGS
CMGS deleted the ci/longqt-pipeline branch July 2, 2026 04:56
CMGS added a commit that referenced this pull request Jul 2, 2026
The LongQT switch (PR #4) forced UEFI>Output>Resolution=1920x1080, but
qmp-input.py's absolute-pointer mapping still hardcoded 1280x800, so every
OCR-driven installer click scaled ~1.5x off-target and the click-through hung
at the Recovery chooser. Historically the OSX-KVM path actually rendered at
1280x800 (despite the OVMF_VARS-1920x1080.fd filename), coincidentally matching
the mapping — which is why it worked before and PR #4's rationale was wrong.

Make the resolution a single source (GOP_W/GOP_H in build-qemu-macos.sh):
configure_opencore forces it and QMP_W/QMP_H are exported from it, so the plist
patch and the click mapping can't drift. qmp-input.py defaults updated to match.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant