ci(docker): portable multi-arch image, unprivileged runtime, GHCR publish - #927
Conversation
…lish - Drop `-C target-cpu=native`: a published image must run on any host of its arch, so keep the portable musl baseline. native risked SIGILL on older/different CPUs and is meaningless under emulated cross-arch builds. - Cook the dependency layer with `--example demo` so the example's dev-deps (env_logger, …) land in the cached layer instead of recompiling after COPY. - Run as unprivileged uid 65532 with writable /data (named-volume ownership) and /tmp for SQLite temp files, staged via COPY --chown. - Add docker.yml: build linux/amd64 + linux/arm64 on native runners, push by digest, merge into one manifest, publish to GHCR. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0161LFHLPTdCNyianZFH8dor
|
Warning Review limit reached
Next review available in: 26 minutes Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available. 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: Repository UI (base), Organization UI (inherited) Review profile: ASSERTIVE Plan: Pro Plus Run ID: 📒 Files selected for processing (2)
📝 WalkthroughWalkthroughAdds a Docker workflow that builds amd64 and arm64 images, merges them into a multi-arch manifest on ChangesDocker build and publish flow
Estimated code review effort🎯 4 (Complex) | ⏱️ ~40 minutes Possibly related PRs
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches🧪 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 |
📦 Binary size report
.text per crate
Top movers (cargo-bloat attribution)
Baseline: |
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 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 `@Dockerfile`:
- Line 58: Preserve the failure from rustc when writing the target in the
Dockerfile build step: the current RUN command in the rustc -vV / sed / test
sequence hides rustc status behind the pipe, so rewrite the logic in the same
Docker layer without piping and make the failure path explicit. Use the existing
rustc -vV target extraction step to store the host target directly, then
validate the output separately so Hadolint no longer flags the instruction.
🪄 Autofix (Beta)
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: Repository UI (base), Organization UI (inherited)
Review profile: ASSERTIVE
Plan: Pro Plus
Run ID: 49d6c878-9b22-42a0-afb6-d5f51d4f3529
📒 Files selected for processing (2)
.github/workflows/docker.ymlDockerfile
Piping rustc -vV into sed let sed's exit status drive the layer, masking a rustc failure. Write the version to a temp file first so the failure path is explicit. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0161LFHLPTdCNyianZFH8dor
There was a problem hiding this comment.
1 issue found and verified against the latest diff
Prompt for AI agents (unresolved issues)
Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.
<file name=".github/workflows/docker.yml">
<violation number="1" location=".github/workflows/docker.yml:1">
P2: Net-new workflow pins Docker and artifact actions to stale major versions. Start with current releases (setup-buildx@v4, login@v4, metadata@v6, build-push@v7, upload-artifact@v7, download-artifact@v8) for Node.js 24 compatibility and latest fixes.</violation>
</file>
Reply with feedback, questions, or to request a fix.
Re-trigger cubic
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: a81fca4bd1
ℹ️ 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".
cargo-chef 0.1.77's `cook` CLI defines `--examples` (plural bool) but not `--example <name>`, so `--example demo` aborted the dependency layer with a clap unexpected-argument error. Under default features `--examples` builds only demo (the other examples gate on extra features), and dev-deps are per-package, so the demo's dev-deps still land in the cached layer. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0161LFHLPTdCNyianZFH8dor
setup-buildx@v4, login@v4, metadata@v6, build-push@v7, upload-artifact@v7, download-artifact@v8 — current releases (verified), for Node 24 runtime and latest fixes. Only stable, still-supported inputs are used. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0161LFHLPTdCNyianZFH8dor
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 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 `@Dockerfile`:
- Around line 63-65: The Dockerfile’s cargo-chef cache step is using an invalid
specific example argument with cargo chef cook, so update the `RUN cargo chef
cook` invocation to use the supported `--examples` flag instead of `--example
demo`. Keep the existing `cargo chef cook`, `--release`, `--recipe-path`, and
target handling intact, and adjust this layer so it matches the
example-dependency caching behavior needed before the final build.
🪄 Autofix (Beta)
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: Repository UI (base), Organization UI (inherited)
Review profile: ASSERTIVE
Plan: Pro Plus
Run ID: 2a6edf9e-92d8-4ada-b51d-25f560bdc9b6
📒 Files selected for processing (1)
Dockerfile
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 33dfdfac57
ℹ️ 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".
A v* tag pushed by release.yml with GITHUB_TOKEN can't trigger docker.yml's tag event (GitHub suppresses workflow runs from token-pushed refs), so semver image tags were never produced by automated releases. Make docker.yml callable via workflow_call with a version input and invoke it from release.yml after the GitHub release, tagging the image :<version>. Push-to-main keeps publishing :latest/:sha on its own. Concurrency now keys on event_name so a main push can't cancel a release's build. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0161LFHLPTdCNyianZFH8dor
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 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/release.yml:
- Around line 108-110: The reusable workflow call needs an explicit note
explaining why it requests packages: write. Update the permissions block in the
release workflow near the reusable workflow invocation to document that the
called workflow logs into GHCR and pushes the manifest, so reviewers and
security tooling can see the purpose of the package-write grant. Keep the
permission values unchanged and add the explanation close to the permissions
declaration for easy discovery.
🪄 Autofix (Beta)
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: Repository UI (base), Organization UI (inherited)
Review profile: ASSERTIVE
Plan: Pro Plus
Run ID: 3a35d332-0e88-4335-840e-3db2fdb76f59
📒 Files selected for processing (2)
.github/workflows/docker.yml.github/workflows/release.yml
There was a problem hiding this comment.
1 issue found across 2 files (changes from recent commits).
Tip: Review your code locally with the cubic CLI to iterate faster.
Re-trigger cubic
…mor) zizmor's undocumented-permissions flags permission grants without a rationale; note that the called docker.yml logs into GHCR and pushes the manifest. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0161LFHLPTdCNyianZFH8dor
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 53d311e31d
ℹ️ 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".
…umes Dropping to uid 65532 can't write a whatsapp-data volume that an older root-running image populated; Docker won't re-chown an existing named volume. Auto-migration isn't possible on scratch (no shell/su-exec), so document the one-time chown via a throwaway image. Fresh volumes inherit 65532 and are unaffected. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0161LFHLPTdCNyianZFH8dor
Summary
Fixes correctness/security issues in the
Dockerfileand adds a workflow that builds and publishes a single multi-arch image to GHCR.Dockerfile
-C target-cpu=native. A published image must run on any host of its arch;nativetuned the binary to the build machine's CPU, riskingSIGILLon older/different hosts and meaning nothing under emulated cross-arch builds — it directly contradicted the musl-portability rationale in the header.RUSTFLAGSis now just-Zshare-generics=y.--example demo, matching the final build. Thedemoexample pullsenv_logger(a dev-dependency), so without matching flags those deps recompiled after the sourceCOPYinstead of landing in the cached layer.USER 65532:65532./dataand/tmpare staged as empty dirs and copied withCOPY --chown=65532:65532(numeric uid → reliable, works on buildkit and the legacy builder). A fresh named volume inherits/data's ownership, so the SQLite DB stays writable./tmp.scratchships no/tmp; added one plusENV TMPDIR=/tmpfor any SQLite temp files.CI —
.github/workflows/docker.ymlmain,v*tags, and manualworkflow_dispatch.linux/amd64andlinux/arm64on native runners (ubuntu-latest+ubuntu-24.04-arm) — not QEMU, which would be far too slow for thisbuild-std+ fat-LTO build.mergejob assembles a single multi-arch manifest and publishes toghcr.io/oxidezap/whatsapp-rustwith branch/tag/semver/sha tags pluslateston the default branch. Per-archghacache scopes.One manifest, one URL
The image is published as a single manifest list, so consumers pull one reference and Docker resolves the right arch automatically:
Notes / to verify
ubuntu-24.04-armrunners are free for public repos but must be enabled in the org's Actions settings.docker buildwas run in the dev environment (no daemon); first real validation happens when the workflow runs — it can be triggered manually via the Actions tab after merge.🤖 Generated with Claude Code
Generated by Claude Code