Nucleic: Gitea Runner macOS VM Support
This commit is contained in:
+61
-1
@@ -35,6 +35,8 @@ gitea-macos-runner service status
|
||||
| `image build` appears to hang during install | Normal — macOS install is slow | Wait. **Do not stop the VM mid-install**; if you did, delete the image and rebuild |
|
||||
| `image build` prints its banner and then nothing, at 0% CPU | Old build: the build task was queued behind the `NSApplication` run loop and never started | Upgrade — the task is now detached. Stage lines should appear within seconds |
|
||||
| `image build` stuck at `loading restore image metadata…` | A truncated or partial `.ipsw` — the framework blocks rather than failing | Upgrade (the file is now size- and magic-checked first); re-download the IPSW |
|
||||
| `provisioning failed: … Failed to lock auxiliary storage` after install | The installer's VM had not yet released `nvram.bin` when first boot started | Upgrade — the install now drains its queue and first boot retries for 30 s. Re-run `image build`; it resumes |
|
||||
| `image build` says `image 'default' already exists` after a failed first boot | Old build: an installed-but-unprovisioned bundle was treated as a finished image | Upgrade — `image build` now resumes it instead of refusing |
|
||||
|
||||
---
|
||||
|
||||
@@ -441,7 +443,7 @@ minutes, longer on slower storage). The install phase is largely silent.
|
||||
|
||||
**Fix.** **Wait, and do not stop the VM mid-install.** Interrupting the installer leaves the disk
|
||||
image in an undefined state; the resulting image may boot and then fail in confusing ways later.
|
||||
There is no resume.
|
||||
There is no resume from a *partial* install — only from a complete one (see the next section).
|
||||
|
||||
If you did interrupt it, or the build genuinely failed:
|
||||
|
||||
@@ -453,3 +455,61 @@ gitea-macos-runner image build --ipsw <path> --name <name>
|
||||
Before rebuilding, verify the IPSW is complete and matches your host architecture (Apple Silicon)
|
||||
and version requirement (macOS 27+ for unattended provisioning), and that you have enough free disk
|
||||
for the IPSW plus the target disk size.
|
||||
|
||||
---
|
||||
|
||||
## `Failed to lock auxiliary storage` right after the install finishes
|
||||
|
||||
**Symptom.** The macOS install runs to 100%, then:
|
||||
|
||||
```
|
||||
first boot + guest provisioning…
|
||||
error: provisioning failed: could not boot image 'default': provisioning failed: Invalid
|
||||
virtual machine configuration. Failed to lock auxiliary storage.
|
||||
```
|
||||
|
||||
**Cause.** A `VZVirtualMachine` holds an exclusive lock on its bundle's `nvram.bin` for its entire
|
||||
lifetime and releases it in `dealloc`. `VZMacOSInstaller` owns a VM of its own, and older builds
|
||||
resumed the caller from inside the installer's completion handler — before the framework's frame
|
||||
had unwound and dropped the last reference. First boot then constructed a *second* VM over the same
|
||||
bundle and lost the race.
|
||||
|
||||
**Fix.** Upgrade. Two changes address it:
|
||||
|
||||
- The install now tears down its VM on its own serial queue and resumes the caller only from a
|
||||
later block on that queue, so the installer's VM is deallocated before `install()` returns.
|
||||
- First boot retries specifically on this failure for up to 30 s (2 s apart), printing
|
||||
`waiting for installer to release the VM bundle…`. Any other configuration error still fails
|
||||
immediately — an invalid configuration does not become valid by waiting.
|
||||
|
||||
Nothing is lost when it does happen: the install is complete, so re-running `image build` resumes.
|
||||
|
||||
---
|
||||
|
||||
## `image build` resumes an installed-but-unprovisioned image
|
||||
|
||||
**Symptom.** A previous `image build` finished installing macOS and then failed at first boot or
|
||||
provisioning. Re-running it prints:
|
||||
|
||||
```
|
||||
image default already installed — resuming first boot + provisioning
|
||||
```
|
||||
|
||||
**This is intended.** An `image build` that fails after the install has left an hour of work on
|
||||
disk, and throwing it away to redo an identical install is not a reasonable default. When the
|
||||
bundle exists, is complete, and is not yet marked provisioned, the install phase is skipped and the
|
||||
build goes straight to first boot.
|
||||
|
||||
It is safe because provisioning is exactly what did *not* happen: the guest has never been booted,
|
||||
so its first boot is still ahead of it and `VZMacGuestProvisioningOptions` — which macOS evaluates
|
||||
only on the first boot after a restore — still applies.
|
||||
|
||||
**The one ambiguous case.** The bundle on disk cannot say whether an earlier run got far enough to
|
||||
*boot* the guest. If it did, that single chance at automated Setup Assistant is spent. Rather than
|
||||
guess, the resume boots and waits for SSH: if the guest answers, provisioning was never applied and
|
||||
the build continues normally. Only if SSH times out does it stop, and it then tells you so
|
||||
explicitly — that state is unrecoverable, and the fix is `image delete` followed by a fresh build.
|
||||
|
||||
An image that is already `provisioned` is untouched; `image build` still refuses with
|
||||
`image '<name>' already exists`. To re-run provisioning on a finished image, use
|
||||
`gitea-macos-runner image provision <name>` instead.
|
||||
|
||||
Reference in New Issue
Block a user