Cache the expensive half of the build so iteration is cheap
Some checks failed
build image / prepare (push) Successful in 0s
build image / build (push) Failing after 29s

The dnf transaction is essentially the whole cost of a build — emulated rpm
scriptlets for 502 packages on minimal, 1929 on workstation. Everything after
it is minutes. Getting this laptop to boot will take several attempts at the
kernel command line and the dracut driver list, and paying for a reinstall each
time is not tenable.

Stage the post-dnf tree under <work>/base, keyed on a hash of the package
lists, release and variant, and copy it per build with --reflink=auto (a CoW
clone on btrfs). Config and overlay edits now reuse it; package list edits
invalidate it on their own, so --fresh is only needed to force the issue.

Keep downloaded rpms in a cachedir outside the install root, so even --fresh
re-runs the scriptlets without re-downloading. keepcache=0 was exactly the
wrong setting for a build meant to be run repeatedly.

Add --work so CI can put both outside the job workspace, which is wiped between
runs, and default the build container to the gongfoo aarch64 build base so the
assembly tooling is not installed under emulation every time. That image is a
speedup, not a dependency: fall back to stock Fedora when it is unreachable.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XWRjNJMistCy6ngXH5aJLS
This commit is contained in:
2026-07-27 11:58:12 +03:00
parent 280874f564
commit 4d1fd98683
6 changed files with 200 additions and 39 deletions

View File

@@ -36,17 +36,32 @@ before debugging a build failure.
## Disk space
The build stages a full root filesystem and three filesystem images alongside
the final disk image, under the job workspace. Budget roughly:
The build keeps persistent state in `/var/tmp/c630-build` on each runner:
- `minimal` — about 20 GiB
- `workstation` — about 45 GiB
| Path | Contents | Rough size |
|---|---|---|
| `/var/tmp/c630-build/work/<variant>/base` | Staged post-dnf root filesystem | 2 GiB minimal, 8 GiB workstation |
| `/var/tmp/c630-build/dnf` | Downloaded rpms and repo metadata | 2 GiB minimal, 6 GiB workstation |
Plus, transiently in the job workspace, the working rootfs copy, three
filesystem images and the final disk image. Budget roughly 20 GiB for
`minimal` and 45 GiB for `workstation` per runner.
The workflow prunes cached rpms untouched for 30 days. The staged base is not
pruned — it is invalidated by content hash, not age, so a stale one is
harmless. Delete `/var/tmp/c630-build` to reclaim the space.
## Runtime
Every aarch64 binary runs under qemu-user emulation, and rpm scriptlets are the
worst case. Expect roughly 4590 minutes for `minimal` and several hours for
`workstation`. The workflow's `timeout-minutes` is set to 600 accordingly.
worst case. A cold build is roughly 4590 minutes for `minimal` and several
hours for `workstation`; `timeout-minutes` is set to 600 accordingly.
A warm build — one where the package set has not changed since that runner last
built — skips the dnf transaction entirely and finishes in minutes. Because the
state is per-runner and jobs are scheduled across all nine, expect the first
build on each runner to be cold. Pinning this workflow to a single runner with
a dedicated label would make warm builds the norm at the cost of parallelism.
If this becomes tiresome, the fix is a native aarch64 runner. Register one with
an `aarch64` label and change `runs-on: metal` to `runs-on: aarch64` in