Skip to content

feat(ci): publish the image for linux/arm64 as well - #25

Merged
BryanFRD merged 1 commit into
mainfrom
feat/multi-arch-image
Aug 14, 2026
Merged

feat(ci): publish the image for linux/arm64 as well#25
BryanFRD merged 1 commit into
mainfrom
feat/multi-arch-image

Conversation

@BryanFRD

Copy link
Copy Markdown
Contributor

Closes #3.

Most of that issue landed with the release wiring in #17: the image publishes on release, carries the version, the major.minor line and latest, gets a Trivy scan, a cosign signature, a provenance attestation and a CycloneDX SBOM, and has to answer /health before the push is allowed. 0.2.0, 0.3.0 and 0.4.0 are on GHCR with their signatures. What was left is the architecture.

arm64 without emulation

The naive way to get a second architecture is to hand qemu to the runner and let the whole build run emulated. For a Rust project that is brutal — the compiler itself runs under emulation, and a two-minute build becomes twenty.

So the builder stage is pinned to --platform=$BUILDPLATFORM and cross-compiles instead: it stays native, adds the target and the cross linker, and produces the aarch64 binary at full speed. The runtime stage is the only thing that varies per architecture, and it does nothing but COPY. No qemu, no binfmt on the runner, no emulated compiler.

That is also why passing two platforms to the org reusable is safe here despite its note about needing binfmt: nothing in this Dockerfile ever executes a target-architecture binary at build time.

Verified locally, not assumed

docker buildx build --platform linux/amd64,linux/arm64 produces the manifest list. The arm64 image reports arm64/linux, and running it under emulation it starts as nonroot, creates its storage root and answers /health — which also re-confirms the directory ownership fix from #17 on the other architecture.

One thing the cross build needed and did not have: libc6-dev-arm64-cross. gcc-aarch64-linux-gnu only recommends it, and the image installs with --no-install-recommends, so ring failed to compile its C sources against missing target headers. Found by building it rather than by reading the Dockerfile.

On the major tag

The issue asks for a floating major tag. Under zerover that tag would be 0, spanning every 0.x — and 0.x minor bumps are exactly where breaking changes live, so :0 would promise compatibility the versioning explicitly refuses. The floating line stays 0.4 until 1.0.0, and the major tag makes sense from that day.

What is not verified

docker.yml only fires on a published release, so this cannot run in the PR. The one interaction I could not exercise is the reusable's smoke test against a two-platform build: it runs podman run on the local manifest list, which resolves to the host architecture. If it turns out otherwise the release publishes nothing and is fixed by re-running the workflow, since the push happens after the smoke test, not before.

Copilot AI lite review requested due to automatic review settings August 14, 2026 11:55
@BryanFRD
BryanFRD enabled auto-merge (squash) August 14, 2026 11:55

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@ferrfleet ferrfleet Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cross-compile setup looks correct: --platform=$BUILDPLATFORM keeps the builder native, TARGETARCH drives the target triple/linker, and the export of CARGO_TARGET_AARCH64_UNKNOWN_LINUX_GNU_LINKER persists within the same RUN shell so it's visible to the later cargo build. Runtime stage correctly stays unpinned so it resolves per-target-platform. README numbers match the stated current release (0.4.0/0.4).

Nit: the arm64 apt-get update/install runs on every build with no version pin on gcc-aarch64-linux-gnu/libc6-dev-arm64-cross — fine for now, just a minor future reproducibility gap.

No blocking issues. The one real unknown (multi-platform smoke test behavior) is already called out in the PR description with a sane mitigation (re-run on failure).

@BryanFRD
BryanFRD merged commit 812721f into main Aug 14, 2026
12 checks passed
@BryanFRD
BryanFRD deleted the feat/multi-arch-image branch August 14, 2026 11:56
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.

Publish a container image to ghcr.io

2 participants