Skip to content

v2.12.3 β€” build release images on native runners, not QEMU - #54

Merged
rancur merged 1 commit into
mainfrom
ci/native-arm-runners
Aug 9, 2026
Merged

v2.12.3 β€” build release images on native runners, not QEMU#54
rancur merged 1 commit into
mainfrom
ci/native-arm-runners

Conversation

@rancur

@rancur rancur commented Aug 9, 2026

Copy link
Copy Markdown
Owner

The problem

release-images.yml cross-built arm64 via QEMU. Measured on the v2.12.2 release:

image build time
api 6 min
worker 9 min
web (Next.js) 46+ min β€” cancelled, never finished

Emulating a Node build is pathologically slow. This would have made every release take ~50 minutes, which defeats the entire reason for publishing images: fast, low-risk updates instead of a 25-minute rebuild on the user's NAS.

The fix

Each architecture builds on a runner of that architecture β€” ubuntu-latest and ubuntu-24.04-arm (free for public repos) β€” and the results are joined into one multi-arch manifest.

Per-arch jobs push by digest only. The :<version> and :latest tags are attached by the merge job once both architectures have succeeded.

That ordering matters: the updater pulls by tag and rolls back on failure. A tag resolving to only one architecture would look like a successful pull and then fail to start on the other β€” the worst kind of failure, because it passes the step that's supposed to catch it.

πŸ€– Generated with Claude Code

https://claude.ai/code/session_01HmUiLHPmKoz215WAWV5eHe

Cross-building arm64 through docker/setup-qemu-action was pathologically slow for
the Next.js image. Measured on the 2.12.2 release: api 6 min, worker 9 min, web
46+ minutes and still going when it was cancelled. That would have made every
release ~50 minutes, defeating the reason for publishing images at all (fast,
low-risk updates instead of a 25-minute rebuild on the user's NAS).

Each architecture now builds on a runner of that architecture β€” ubuntu-latest and
ubuntu-24.04-arm, free for public repos β€” and the results are joined into one
multi-arch manifest.

Per-arch jobs push BY DIGEST only; the version and latest tags are attached by the
merge job once both architectures have succeeded. A tag therefore never points at
a half-published set, which matters because the updater pulls by tag and rolls
back on failure β€” a tag resolving to one architecture only would look like a
successful pull and then fail to start on the other.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HmUiLHPmKoz215WAWV5eHe
@rancur
rancur merged commit 8637e69 into main Aug 9, 2026
2 checks passed
@rancur
rancur deleted the ci/native-arm-runners branch August 9, 2026 22:11
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