feat(docker): multi-arch image (amd64 + arm64) — native on Apple Silicon Macs - #947
Conversation
… macOS
The Docker image was single-arch linux/amd64 (built from the amd64-only
release .deb), so on Apple Silicon Macs it only ran under slow QEMU
emulation. Ship a native linux/arm64 variant so `docker run` works natively
on both Intel and Apple Silicon Macs.
Build the arm64 .deb:
- build-linux + its assimp/ogre cache-builder jobs are now a strategy.matrix
over {amd64: ubuntu-latest, arm64: ubuntu-24.04-arm} — arm64 builds on
GitHub's NATIVE arm64 runner (no QEMU). Qt arm64 = arch linux_gcc_arm64
(path gcc_arm64); lib triplet aarch64-linux-gnu; the .deb control
Architecture field is sed'd to match. Produces qtmesheditor_{amd64,arm64}.deb.
- Cache keys embed matrix.arch (runner.os is "Linux" for both runners, so
without it the two arches would clobber each other's assimp/ogre caches).
- Per-arch release artifacts linux-binaries-{amd64,arm64} (upload-artifact@v4
rejects duplicate names). amd64-pinned consumers updated: unit-tests-linux
restores the -amd64- caches; snap-publish pulls linux-binaries-amd64.
Multi-arch image:
- Dockerfile uses ARG TARGETARCH → COPY qtmesheditor_${TARGETARCH}.deb, so
each platform installs its own .deb. (Verified locally with buildx that
linux/amd64 and linux/arm64 each select the right file.)
- Release docker-publish (deploy.yml) downloads both artifacts + buildx
--platform linux/amd64,linux/arm64, pushes one manifest, and asserts both
arches are in it. Manual docker-publish.yml downloads both release .debs
and falls back to amd64-only for old releases lacking an arm64 .deb.
Docs (README/CLAUDE.md) note the image now runs natively on Apple Silicon.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
Warning Review limit reached
Next review available in: 38 minutes You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository. How can I continue?After more reviews become available, a review can be triggered using the To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews. How do review limits work?CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability. For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window. Please refer docs for additional details. Review details⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (1)
📝 WalkthroughWalkthroughThe release pipeline now builds amd64 and arm64 Linux packages, publishes multi-architecture Docker images, verifies both image platforms, and selects architecture-specific packages during image builds. Documentation describes the new package, runner, cache, and native ARM behavior. ChangesMulti-architecture release pipeline
Estimated code review effort: 4 (Complex) | ~60 minutes Mergeability Score: 🟠 High · up to The release workflow can publish a broken arm64 image and an unverifiable arm64 package because smoke-test failures are suppressed and the new package is not included in signing. Merge should wait until both release checks are corrected or explicitly accepted by the owner. Sequence Diagram(s)sequenceDiagram
participant LinuxPackageBuild
participant DockerPublishing
participant DockerBuildx
participant DockerRegistry
participant DockerVerification
LinuxPackageBuild->>DockerPublishing: provide amd64 and arm64 Debian packages
DockerPublishing->>DockerBuildx: select platforms and enable arm64 emulation
DockerBuildx->>DockerRegistry: publish linux/amd64 and linux/arm64 manifest
DockerVerification->>DockerRegistry: inspect manifest platforms
DockerVerification->>DockerRegistry: run amd64 and arm64 smoke tests
Possibly related PRs
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches 💡 1🛠️ Fix failing CI checks 💡
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
- scan-assets-qtmesh builds the Dockerfile from a single downloaded .deb; the
new Dockerfile COPYs qtmesheditor_${TARGETARCH}.deb, so download to that
exact name (amd64) and pin --platform linux/amd64. (Broke on this PR:
"/qtmesheditor_amd64.deb: not found" during docker build.)
- Add qtmesheditor_arm64.deb to the release required-asset verification lists
now that build-linux produces it for both arches.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 4561cc0022
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| ARG TARGETARCH | ||
| COPY qtmesheditor_${TARGETARCH}.deb /tmp/qtmesheditor.deb |
There was a problem hiding this comment.
Keep the asset-scan package name compatible
In the scan-assets-qtmesh job's “Build qtmesh Docker image for asset scan” step, the package is still downloaded as qtmesheditor.deb before this Dockerfile is built. This new COPY instead requests qtmesheditor_amd64.deb on the amd64 runner, so the Docker build cannot find its source file and the prerequisite scan job blocks every downstream build on pushes, pull requests, and releases. Save the scan package under the architecture-qualified name or retain a compatible single-architecture input path.
Useful? React with 👍 / 👎.
|
|
||
| dpkg-deb --build --root-owner-group pack-deb | ||
| mv pack-deb.deb qtmesheditor_amd64.deb | ||
| mv pack-deb.deb qtmesheditor_${{ matrix.arch }}.deb |
There was a problem hiding this comment.
Sign the new arm64 release package
When the release matrix creates and publishes qtmesheditor_arm64.deb, the sign-release-artifacts job's wait, download, and signing REQUIRED arrays still contain only qtmesheditor_amd64.deb. The arm64 package is therefore omitted from both its expected .minisig sidecar and the signed SHA256SUMS manifest, leaving the newly advertised ARM download without the integrity metadata supplied for the other release artifacts.
Useful? React with 👍 / 👎.
The arm64 Assimp build failed on Common/Assimp.cpp with 'all warnings being treated as errors' — Assimp defaults ASSIMP_WARNINGS_AS_ERRORS=ON and arm64 GCC emits a warning amd64 GCC doesn't. Pass -DASSIMP_WARNINGS_AS_ERRORS=OFF (the Windows Assimp build already does this). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
Actionable comments posted: 2
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
.github/workflows/deploy.yml (1)
625-646: 🩺 Stability & Availability | 🔴 Critical | ⚡ Quick winReplace
actions/cache@v3withactions/cache@v4.
actions/cache@v3declares the retired Node 16 runtime. Update all 17 references in.github/workflows/deploy.ymlat lines 176, 229, 239, 330, 341, 630, 712, 728, 824, 843, 1119, 1139, 1802, 1892, 1911, 2010, and 2027.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In @.github/workflows/deploy.yml around lines 625 - 646, Replace every actions/cache@v3 reference with actions/cache@v4 in .github/workflows/deploy.yml, including the sites at lines 176, 229, 239, 330, 341, 630, 712, 728, 824, 843, 1119, 1139, 1802, 1892, 1911, 2010, and 2027; no other workflow behavior needs to change.Source: Linters/SAST tools
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In @.github/workflows/deploy.yml:
- Around line 2995-3001: Update the arm64 variant smoke test in the deployment
workflow to propagate failure from docker run instead of suppressing it with the
warning-and-true fallback. The release must stop when the linux/arm64 --version
check fails; alternatively, execute the equivalent mandatory check on a native
arm64 runner before publishing the image manifest.
- Around line 1041-1049: Update the sign-release-artifacts job to include
qtmesheditor_arm64.deb in each of its three REQUIRED arrays, covering artifact
readiness, download/signing, and hash generation alongside
qtmesheditor_amd64.deb.
---
Outside diff comments:
In @.github/workflows/deploy.yml:
- Around line 625-646: Replace every actions/cache@v3 reference with
actions/cache@v4 in .github/workflows/deploy.yml, including the sites at lines
176, 229, 239, 330, 341, 630, 712, 728, 824, 843, 1119, 1139, 1802, 1892, 1911,
2010, and 2027; no other workflow behavior needs to change.
🪄 Autofix
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro Plus
Run ID: 0f2e9cfe-494b-4271-9ecd-80d2185c83b2
📒 Files selected for processing (5)
.github/workflows/deploy.yml.github/workflows/docker-publish.ymlCLAUDE.mdDockerfileREADME.md
| # Smoke-test the arm64 variant under QEMU (the layer only installs a | ||
| # .deb; this confirms the arm64 binary loads + CLI dispatches). | ||
| echo "=== arm64 variant smoke test (QEMU) ===" | ||
| docker run --rm --platform linux/arm64 "$IMAGE" --version || { | ||
| echo "::warning::arm64 --version under QEMU failed (emulation-only check)" | ||
| true | ||
| } |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟠 Major | ⚡ Quick win
Fail the release when the arm64 smoke test fails.
Lines 2998-3001 suppress every arm64 --version failure. A missing library or invalid arm64 package can therefore publish a broken linux/arm64 image manifest.
Require this smoke test to pass. If QEMU is not reliable enough to gate releases, run the equivalent check on a native arm64 runner before publishing the manifest.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In @.github/workflows/deploy.yml around lines 2995 - 3001, Update the arm64
variant smoke test in the deployment workflow to propagate failure from docker
run instead of suppressing it with the warning-and-true fallback. The release
must stop when the linux/arm64 --version check fails; alternatively, execute the
equivalent mandatory check on a native arm64 runner before publishing the image
manifest.
build-linux (arm64) failed at Install Qt: aqt errored 'qt_base/qtmultimedia not found' because host was hardcoded to 'linux', which has no arm64 packages. Qt 6.9.3 arm64 lives under aqt host 'linux_arm64' (arch linux_gcc_arm64). Make host a matrix var (linux for amd64, linux_arm64 for arm64). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
install-qt-action@v3 rejects host 'linux_arm64' with 'not one of windows|mac|linux'. v4 adds linux_arm64 (and windows_arm64) hosts and is backward-compatible with the amd64 host: linux inputs. Required for the build-linux arm64 matrix leg. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
✅ The native arm64 build lane is green on real CI — validated end-to-end on this PR (the matrix jobs run on
Three arm64-specific issues surfaced and were fixed by iterating on CI:
The arm64 app build also confirmed the remaining unknowns resolve on arm64: Qt 6.9.3 arm64 installs, and ONNX Runtime's aarch64 archive downloads/links. The multi-arch Remaining CI (build-linux amd64 / build-macos / build-windows / unit-tests-linux) are unchanged code paths, still running. |
|
Cut a release so the multi-arch Docker work (#947) actually ships: the arm64 .deb build + the linux/amd64+arm64 docker-publish manifest only run on 'release: published'. 3.28.0 predates that merge (amd64-only image), so a new release is required to publish the native Apple Silicon image. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>



Problem
The Docker image (
ghcr.io/fernandotonon/qtmesh,fernandotr1/qtmesh) was single-archlinux/amd64, built from the amd64-only release.deb. On Apple Silicon Macs it only ran under QEMU emulation — slow, and fragile with software GL + Xvfb + Ogre. There was no nativelinux/arm64variant.Fix — ship a native multi-arch image
1. Build an arm64
.debbuild-linuxand itsbuild-n-cache-assimp-linux/build-n-cache-ogre-linuxdependencies are now astrategy.matrixover both arches:ubuntu-latestlinux_gcc_64x86_64-linux-gnuubuntu-24.04-arm(native, no QEMU)linux_gcc_arm64aarch64-linux-gnuProduces
qtmesheditor_amd64.deb+qtmesheditor_arm64.deb(controlArchitecture:field set per arch). Packaging logic is shared verbatim — only Qt path + lib triplet are matrix vars.matrix.arch—runner.osisLinuxfor both runners, so without it the two arches would clobber each other's assimp/ogre caches.linux-binaries-{amd64,arm64}(upload-artifact@v4rejects duplicate names).unit-tests-linuxrestores the-amd64-caches;snap-publishpullslinux-binaries-amd64(Snap stays amd64-only).2. Multi-arch image
ARG TARGETARCH→COPY qtmesheditor_${TARGETARCH}.deb, so each platform in the buildx manifest installs its own.deb.docker-publish(deploy.yml): downloads both artifacts (pattern: linux-binaries-*,merge-multiple),buildx --platform linux/amd64,linux/arm64, pushes one manifest, and asserts both arches are present.docker-publish.yml: downloads both release.debs; falls back to amd64-only for old releases without an arm64.deb.Verification
COPYend-to-end withdocker buildx --platform linux/amd64,linux/arm64: the amd64 stage picksqtmesheditor_amd64.deb, the arm64 stage picksqtmesheditor_arm64.deb(confirmed viaTARGETARCH+ payload echo).arch: linux_gcc_arm64).Result on Apple Silicon:
Notes / risks to watch on first release run
ubuntu-24.04-arm) is GA on GitHub-hosted.cmake/OnnxRuntime.cmake) — the arm64 build must resolve the aarch64 ORT; will confirm on the first arm64 CI run.install-qt-action@v3on the arm64 host — will confirm it resolveslinux_gcc_arm64on the native runner.The heavy CI (arm64 assimp/ogre/draco builds) only runs on
release: published, so it validates on the next release; happy to iterate on that run like we did for the Draco PR.🤖 Generated with Claude Code
Summary by CodeRabbit
New Features
Documentation