Skip to content

ci: add Docker multi-platform build and Release workflows#70

Open
panos-xyz wants to merge 6 commits intomainfrom
panos/docker-release
Open

ci: add Docker multi-platform build and Release workflows#70
panos-xyz wants to merge 6 commits intomainfrom
panos/docker-release

Conversation

@panos-xyz
Copy link
Copy Markdown
Contributor

@panos-xyz panos-xyz commented Mar 27, 2026

Summary

  • Add Dockerfile with cargo-chef multi-stage build pattern (dependency caching + debian:bookworm-slim runtime)
  • Add .github/workflows/docker.yml: tag v* triggered, builds amd64+arm64 via QEMU, pushes to ghcr.io/morph-l2/morph-reth
  • Add .github/workflows/release.yml: tag v* triggered, cross-compiles Linux binaries (x86_64+aarch64), generates SHA256 checksums, auto-generates changelog, creates GitHub draft release
  • Add .dockerignore to exclude build artifacts and dev files

References: scroll-reth Docker/Release workflows, tempo Dockerfile patterns

Test plan

  • docker build -t morph-reth:test . builds successfully locally
  • Docker workflow triggers on tag push and pushes to GHCR
  • Release workflow dry-run via manual dispatch produces binaries
  • Version check validates tag matches Cargo.toml version

Summary by CodeRabbit

  • Chores
    • Added a Dockerfile to build optimized multi-architecture container images with a minimal runtime.
    • Added a workflow to build and publish multi-arch container images on version tags or manual dispatch.
    • Added a release workflow to build cross-platform binaries, produce versioned archives with checksums, and create draft releases.
    • Added a .dockerignore to exclude development artifacts from Docker build contexts.

Add production Docker and release infrastructure:

- Dockerfile: cargo-chef multi-stage build with debian:bookworm-slim
  runtime, supports release/maxperf profiles via BUILD_PROFILE arg
- .dockerignore: excludes target, .git, tests, local-test
- docker.yml: tag-triggered multi-platform (amd64+arm64) build,
  pushes to ghcr.io/morph-l2/morph-reth with semver tags
- release.yml: tag-triggered binary release with version validation,
  cross-compiled Linux binaries (x86_64+aarch64), SHA256 checksums,
  auto-generated changelog, and GitHub draft release
@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Mar 27, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 8adfa208-5058-4137-b7a1-5cbc039d9244

📥 Commits

Reviewing files that changed from the base of the PR and between c9428a3 and 300a33e.

📒 Files selected for processing (2)
  • .github/workflows/docker.yml
  • .github/workflows/release.yml
✅ Files skipped from review due to trivial changes (2)
  • .github/workflows/docker.yml
  • .github/workflows/release.yml

📝 Walkthrough

Walkthrough

Adds Docker containerization and automated release pipelines: a multi-stage Dockerfile and .dockerignore, a GitHub Actions workflow to build and push multi-arch images to GHCR, and a release workflow that validates versions, cross-compiles artifacts, packages uploads, and creates draft releases on tag or manual dispatch.

Changes

Cohort / File(s) Summary
Docker context & image
Dockerfile, .dockerignore
Adds a multi-stage Dockerfile (Cargo Chef build + minimal Debian runtime, exposes RPC/P2P ports) and .dockerignore to exclude build outputs, VCS/editor metadata, tests, and docs from Docker build context.
CI: Docker build & publish
.github/workflows/docker.yml
New "Docker" workflow: sets repo permissions, sets up QEMU and Docker Buildx, generates image metadata/tags, builds multi-arch images for linux/amd64 and linux/arm64, and logs into & pushes to GHCR with cache support.
CI: Release automation
.github/workflows/release.yml
New "Release" workflow: normalizes tag to semver, verifies crate version matches tag, cross-compiles release binaries for x86_64 and aarch64, packages .tar.gz + .sha256 artifacts, generates changelog, and creates a draft GitHub release (marks prerelease when appropriate).

Sequence Diagram(s)

sequenceDiagram
  participant GitHub as GitHub (push/tag or workflow_dispatch)
  participant Actions as GitHub Actions
  participant Runner as Runner
  participant Buildx as Docker Buildx / cross
  participant GHCR as GHCR (Registry)
  participant Releases as GitHub Releases

  GitHub->>Actions: trigger docker workflow (tag or manual)
  Actions->>Runner: checkout repo, setup QEMU & buildx
  Runner->>Buildx: build multi-arch image, run docker/metadata-action
  Buildx->>GHCR: push images & tags

  GitHub->>Actions: trigger release workflow (tag or manual)
  Actions->>Runner: extract normalized version, checkout ref
  Runner->>Runner: verify crate version matches tag
  Runner->>Buildx: cross-compile binaries for targets
  Runner->>Actions: upload artifacts
  Actions->>Releases: create draft release with changelog and artifacts
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Poem

🐰
I hopped through Dockerfiles, tidy and neat,
Cross-built my binaries, wrapped them up sweet.
Tags and drafts in a workflow ballet,
I hide stray files and send images away —
Carrots, builds, and releases — hip hip hooray! 🥕

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The PR title 'ci: add Docker multi-platform build and Release workflows' directly and concisely summarizes the main changes: adding Docker CI infrastructure (Dockerfile, multi-platform build workflow) and a Release workflow.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch panos/docker-release

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 5

🧹 Nitpick comments (1)
Dockerfile (1)

7-8: Avoid upgrading the whole distro in the builder layer.

apt-get -y upgrade makes this stage less reproducible and heavier than needed. Install only the required packages with --no-install-recommends, then clear the apt lists.

♻️ Suggested cleanup
-RUN apt-get update && apt-get -y upgrade && apt-get install -y libclang-dev pkg-config
+RUN apt-get update && \
+    apt-get install -y --no-install-recommends libclang-dev pkg-config && \
+    rm -rf /var/lib/apt/lists/*
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@Dockerfile` around lines 7 - 8, The Dockerfile's RUN line currently performs
a full distro upgrade which reduces reproducibility; change the RUN that
installs build deps (the line installing libclang-dev and pkg-config) to avoid
`apt-get -y upgrade`, use `apt-get install -y --no-install-recommends` to
install only required packages, and purge apt caches afterwards (remove apt
lists) to keep the layer small and deterministic; locate the RUN that references
libclang-dev/pkg-config in the Dockerfile and update it accordingly.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In @.github/workflows/docker.yml:
- Around line 3-6: The workflow currently triggers publishing for both tag
pushes and manual runs because "on: push: tags: ['v*']" coexists with an
unconditional "workflow_dispatch"; update the triggers and publishing guard so
manual dispatches don't publish by default: either restrict the push trigger to
tags only (keep "push: tags: ['v*']") and add a conditional on the publish job
(e.g., check github.event_name == 'push' && starts_with(github.ref,
'refs/tags/') or require a workflow_dispatch input like "publish: true" and gate
the publish steps on that input), or add an explicit if/condition in the publish
job to only run for tag pushes or when a dispatch input opt-in is true;
reference the "on", "push", "tags", and "workflow_dispatch" keys and the publish
job's if-condition to implement this.

In @.github/workflows/release.yml:
- Around line 134-139: The fallback for CHANGELOG uses "HEAD~20..HEAD" which
breaks in repos with fewer than 20 commits; update the logic that sets CHANGELOG
(the block using PREVIOUS_TAG and CHANGELOG) to use a history-length-safe git
command such as using git log --max-count=20 --pretty=format:"- %s" HEAD (or git
rev-list --max-count=20) instead of "HEAD~20..HEAD" so it always works
regardless of commit count and still limits the number of entries when
PREVIOUS_TAG is empty.
- Around line 57-59: The release guard currently uses a prefix glob check ([[
"$TAG_VERSION" != "$CARGO_VERSION"* ]]) which allows suffixed tags (e.g.
0.1.0-rc.1) to match; change the check to require exact equality by comparing
TAG_VERSION and CARGO_VERSION with [[ "$TAG_VERSION" != "$CARGO_VERSION" ]] (or
the inverse ==) so only identical versions pass; if your repo uses a leading "v"
in tags, first normalize TAG_VERSION (strip leading "v") before comparing to
CARGO_VERSION to ensure correct behavior.

In `@Dockerfile`:
- Around line 38-46: The Dockerfile currently runs the runtime image as root
(process started by ENTRYPOINT ["/usr/local/bin/morph-reth"]); add a non-root
runtime user and switch to it before ENTRYPOINT. Create a dedicated user and
group (e.g., "morph" or "appuser"), create its home or data directory, chown
that directory and the copied binary (referencing the COPY --from=builder
/app/morph-reth /usr/local/bin/ and ENTRYPOINT symbols), and add a USER
instruction so the container runs as that non-root user at runtime; ensure
permissions allow executing /usr/local/bin/morph-reth and exposing required
ports.

---

Nitpick comments:
In `@Dockerfile`:
- Around line 7-8: The Dockerfile's RUN line currently performs a full distro
upgrade which reduces reproducibility; change the RUN that installs build deps
(the line installing libclang-dev and pkg-config) to avoid `apt-get -y upgrade`,
use `apt-get install -y --no-install-recommends` to install only required
packages, and purge apt caches afterwards (remove apt lists) to keep the layer
small and deterministic; locate the RUN that references libclang-dev/pkg-config
in the Dockerfile and update it accordingly.
🪄 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: defaults

Review profile: CHILL

Plan: Pro

Run ID: f4a551e3-2842-4a9f-86c8-10c1f41422c8

📥 Commits

Reviewing files that changed from the base of the PR and between 6ea9660 and ab9060d.

📒 Files selected for processing (4)
  • .dockerignore
  • .github/workflows/docker.yml
  • .github/workflows/release.yml
  • Dockerfile

- docker.yml: only publish on tag push, not on manual workflow_dispatch
- release.yml: thread resolved tag ref through all checkout steps so
  manual dispatch builds the correct commit
- release.yml: use exact version match instead of prefix glob
- release.yml: use `git log -n 20` fallback for changelog (safe with <20 commits)
- release.yml: add --verify-tag to gh release create
- Dockerfile: remove apt-get upgrade for reproducibility, add non-root
  runtime user
Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In @.github/workflows/release.yml:
- Around line 45-49: The workflow currently skips the check-version job when
manually dispatched with inputs.dry_run true due to the if expression
(github.event_name == 'workflow_dispatch' && inputs.dry_run), which lets build
continue despite a missing version check; remove that conditional so the
check-version job always runs (delete the if: ${{ !(github.event_name ==
'workflow_dispatch' && inputs.dry_run) }} from the check-version job) and also
remove or tighten any permissive if on the build job that explicitly allows
build to proceed when check-version was skipped (update the build job's
conditional so it requires check-version to have run/succeeded rather than
allowing continuation when skipped).
- Around line 16-17: Move the repository write permission off the global
workflow level and restrict it to the release job: remove or change the
top-level "permissions: contents: write" and instead add "permissions: contents:
write" under the "draft-release" job definition so only that job gets write
access; for the "check-version" and "build" jobs locate their checkout steps
(uses: actions/checkout@...) and add "persist-credentials: false" to those
checkout steps to ensure the GITHUB_TOKEN is not persisted for non-release jobs.
🪄 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: defaults

Review profile: CHILL

Plan: Pro

Run ID: 93f5541c-abd2-45cf-a77d-c677e1e96bfb

📥 Commits

Reviewing files that changed from the base of the PR and between ab9060d and ae6438e.

📒 Files selected for processing (3)
  • .github/workflows/docker.yml
  • .github/workflows/release.yml
  • Dockerfile
✅ Files skipped from review due to trivial changes (2)
  • Dockerfile
  • .github/workflows/docker.yml

- Move OCI labels from chef stage to runtime stage so they appear on final image
- Change latest tag to always apply on tag push (is_default_branch is false for tags)
- Use sha256sum instead of shasum for Linux CI runners
…ion check

- Move contents:write to draft-release job only, default to contents:read
- Add persist-credentials:false to check-version and build checkouts
- Remove dry_run skip on check-version so version is always validated
- Require check-version success (not skipped) before build proceeds
Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In @.github/workflows/release.yml:
- Around line 33-42: When handling workflow_dispatch input, validate and
normalize the provided TAG so REF and VERSION are consistent: check the input
(inputs.tag) for a leading "v" and either strip it for VERSION or ensure REF
uses the same form; set TAG to include the "v" prefix if downstream steps (like
release creation) expect "vX.Y.Z", set VERSION="${TAG#v}" for release name, and
set REF="refs/tags/${TAG}" accordingly; update the workflow logic around the
TAG, REF, and VERSION assignments (the variables TAG, REF, VERSION and the echo
lines to GITHUB_OUTPUT) to normalize the tag format and fail fast with a clear
error if the input is not a valid semver-like tag.
🪄 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: defaults

Review profile: CHILL

Plan: Pro

Run ID: 9a58b424-be9d-46b4-b0d7-c025767eb96e

📥 Commits

Reviewing files that changed from the base of the PR and between ae6438e and c9428a3.

📒 Files selected for processing (3)
  • .github/workflows/docker.yml
  • .github/workflows/release.yml
  • Dockerfile
✅ Files skipped from review due to trivial changes (1)
  • .github/workflows/docker.yml
🚧 Files skipped from review as they are similar to previous changes (1)
  • Dockerfile

Reject non-semver inputs (e.g., `0.1.0` without `v` prefix) early
in extract-version instead of failing late during release creation.
@panos-xyz panos-xyz requested review from anylots and chengwenxi March 27, 2026 07:56
- docker.yml: only tag as `latest` when ref has no `-` (excludes
  prerelease tags like v0.1.0-rc.1, v0.1.0-alpha)
- release.yml: use prefix match for version check so tag v0.1.0-rc.1
  passes when Cargo.toml version is 0.1.0 (matches scroll-reth pattern)
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