Skip to content

fix(ci): build arm64 images on native arm64 runner#357

Open
juandelperal wants to merge 1 commit into
peaberry-studio:mainfrom
juandelperal:fix/ci-arm64-native-runner
Open

fix(ci): build arm64 images on native arm64 runner#357
juandelperal wants to merge 1 commit into
peaberry-studio:mainfrom
juandelperal:fix/ci-arm64-native-runner

Conversation

@juandelperal

Copy link
Copy Markdown

Summary

Multi-arch image builds were introduced in #270 (April 2026), but no *-arm64 tag has ever been published to GHCR. Every release since then has shipped without arm64, and the docs/.env.example files that tell users to pull :latest-arm64 are silently broken:

$ docker pull ghcr.io/peaberry-studio/arche/web:latest-arm64
Error response from daemon: manifest unknown
$ docker pull ghcr.io/peaberry-studio/arche/workspace:latest-arm64
Error response from daemon: manifest unknown

Direct registry probe confirms zero *-arm64 tags exist on either peaberry-studio/arche/web or peaberry-studio/arche/workspace:

latest-arm64 -> HTTP 404
v3.0.0-arm64 -> HTTP 404
v2.4.0-arm64 -> HTTP 404

Root cause: .github/workflows/build-push.yml and build-push-workspace.yml build the arm64 leg under QEMU on ubuntu-latest. The Next.js + Prisma build is OOM-ing / timing out under emulation, but fail-fast: false keeps the amd64 leg green, so release tags get cut and the failure is invisible unless you open the Actions UI.

Changes

  1. Switch arm64 to a native runner. Replace the QEMU-on-ubuntu-latest arm64 leg with GitHub's free public-repo ubuntu-24.04-arm runner. Drop the now-redundant docker/setup-qemu-action@v3 step. Tag scheme is unchanged — :latest/:vX.Y.Z stay amd64-default and -amd64/-arm64 suffix tags remain published, so no consumer pins need to change.
  2. Move the PR-image comment to its own job. The existing comment step ran on the amd64 matrix leg unconditionally, so it always advertised an -arm64 tag regardless of whether arm64 actually built. Moved it to a comment-pr job that needs: the full matrix, so the comment only appears when every arch published successfully. Rewrote the body from "Optional arm64" to plain "arm64" now that both arches are reliably built.

No code, docs, or .env.example changes were needed — the docs were already accurate in intent; the CI just wasn't delivering on them.

Why native runner instead of a multi-arch manifest

Considered (option 1a from the issue): single buildx step pushing --platform linux/amd64,linux/arm64 into one manifest list, dropping the arch suffixes. Rejected because:

  • It would break every pinned :vX.Y.Z-amd64 consumer that exists on GHCR today.
  • Native arm64 builds are roughly 4-10x faster than QEMU emulation for the Next.js + Prisma image, which keeps release latency low.
  • It's a strictly smaller diff.

Why no change to build-and-deploy.yml

Re-checked the deploy flow. deploy: needs: [build-web, build-workspace] already correctly blocks deploy when any matrix entry fails — fail-fast: false only controls cancellation of sibling matrix entries, not the overall job result. The "silent release" described in the original issue happens on tag pushes (v*.*.*), which trigger build-push.yml directly and never involve build-and-deploy.yml. The git tag is created manually by a maintainer regardless of CI outcome, so the missing safeguard is really "don't let arm64 fail in the first place" — which this PR achieves.

Test plan

  • Re-run Build & Push Web Image and Build & Push Workspace Image workflows on this branch via workflow_dispatch and confirm both amd64 and arm64 matrix legs succeed.
  • Confirm actionlint is clean (verified locally).
  • After merge, cut a dry-run tag (or wait for the next release) and confirm:
    • ghcr.io/peaberry-studio/arche/web:<tag>-arm64 exists.
    • ghcr.io/peaberry-studio/arche/workspace:<tag>-arm64 exists.
    • docker pull --platform linux/arm64 ghcr.io/peaberry-studio/arche/web:<tag>-arm64 works on an arm64 host.
  • Trigger a PR-image build and confirm the comment now posts from the standalone comment-pr job with the updated wording, and that it only fires when both arches actually built.

The per-arch build matrix was running the arm64 leg under QEMU on
ubuntu-latest. Since multi-arch was introduced in peaberry-studio#270, no `*-arm64`
tag has ever surfaced on GHCR despite `infra/deploy/README.md`,
`apps/web/README.md`, and both `.env.example` files instructing users
to pull them. arm64 hosts that follow the docs get `manifest unknown`.

Switch the arm64 leg to GitHub's free native `ubuntu-24.04-arm`
runner (public-repo GA since early 2026) so the build actually
completes, and drop the now-redundant QEMU setup step. Move the
PR-image comment into a separate `comment-pr` job that `needs:` the
full build matrix so we only advertise tags when every arch actually
published. Update the wording from "Optional arm64" to plain "arm64"
since both arches are now reliably built.
@Inakitajes

Copy link
Copy Markdown
Contributor

Thanks for the contribution Juan! @albertoperdomo2 could you please check this out?

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.

2 participants