Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 7 additions & 2 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -49,10 +49,14 @@ jobs:
# One image build per architecture, on a native runner. We push by digest;
# a final `merge` job stitches the two digests into a multi-arch manifest list.
# Native arm64 runners avoid QEMU emulation, which dominated build time.
#
# This job does NOT depend on `test`: the test job compiles for the host gnu
# target while these build for musl, so they share no artifacts and gating
# would only serialize clippy+test ahead of the build for no reuse. Tests run
# concurrently instead; the `merge` job below re-gates on `test` so a tagged
# multi-arch image is never published when linting or tests fail.
image:
name: 🐳 Build (${{ matrix.platform }})
needs:
- test
runs-on: ${{ matrix.runner }}
strategy:
fail-fast: false
Expand Down Expand Up @@ -132,6 +136,7 @@ jobs:
if: github.event_name == 'push'
needs:
- image
- test
runs-on: ubuntu-latest
outputs:
tag: ${{ steps.tag.outputs.tag }}
Expand Down
28 changes: 15 additions & 13 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
# Multi-stage build using cargo-chef for dep-only layer caching and per-arch
# cache mounts so amd64 and arm64 don't fight over the same target dir.
# Multi-stage build using cargo-chef so dependency compilation lands in a
# dedicated layer that is only invalidated when the dependency graph
# (recipe.json) changes. That layer is what CI restores from the GHA layer
# cache (see `cache-to: type=gha,mode=max`, scoped per arch in the workflow),
# so source-only changes skip recompiling dependencies.
#
# Drives the workspace into a static musl binary so the runtime image (alpine-
# based platzio/base) doesn't need a libc. Architecture is selected via Docker
Expand Down Expand Up @@ -31,9 +34,14 @@
RUN cargo chef prepare --recipe-path recipe.json

# ---------------------------------------------------------------------------
# 3. builder — cook deps from the recipe, then build the workspace. The cooked
# deps live in a buildkit cache mount keyed by TARGETARCH, so each architecture
# keeps its own warm target dir across CI runs.
# 3. builder — cook deps from the recipe, then build the workspace. The cook
# step writes compiled deps (and downloaded crates) into the layer filesystem
# — deliberately NOT a buildkit cache mount, which would be excluded from the
# image layer and dropped between CI runs on fresh builders. Keeping them in
# the layer lets Docker's layer cache capture the cook step; the workflow
# exports it via `cache-to: type=gha,mode=max` scoped per arch. recipe.json
# only changes when the dep graph changes, so source-only edits restore the
# cook layer from cache and re-run just the final `cargo build`.
# ---------------------------------------------------------------------------
FROM chef AS builder
ARG RELEASE_BUILD=1
Expand All @@ -49,10 +57,7 @@
rustup target add "${target}"

COPY --from=planner /build/recipe.json recipe.json
RUN --mount=type=cache,id=platz-cargo-target-${TARGETARCH},target=/build/target,sharing=locked \
--mount=type=cache,id=platz-cargo-git,target=/usr/local/cargo/git,sharing=locked \
--mount=type=cache,id=platz-cargo-registry,target=/usr/local/cargo/registry,sharing=locked \
set -eux; \
RUN set -eux; \
target="$(cat /target.txt)"; \
if [ "${RELEASE_BUILD}" = "1" ]; then \
cargo chef cook --release --target "${target}" --recipe-path recipe.json; \
Expand All @@ -61,10 +66,7 @@
fi

COPY . .
RUN --mount=type=cache,id=platz-cargo-target-${TARGETARCH},target=/build/target,sharing=locked \
--mount=type=cache,id=platz-cargo-git,target=/usr/local/cargo/git,sharing=locked \
--mount=type=cache,id=platz-cargo-registry,target=/usr/local/cargo/registry,sharing=locked \
set -eux; \
RUN set -eux; \
target="$(cat /target.txt)"; \
if [ "${RELEASE_BUILD}" = "1" ]; then \
cargo build --release --target "${target}"; \
Expand Down Expand Up @@ -107,6 +109,6 @@
# ---------------------------------------------------------------------------
# 4. runtime — small base image carrying just the static musl binaries.
# ---------------------------------------------------------------------------
FROM ${BASE_IMAGE}

Check warning on line 112 in Dockerfile

View workflow job for this annotation

GitHub Actions / 🐳 Build (linux/arm64)

Default value for global ARG results in an empty or invalid base image name

InvalidDefaultArgInFrom: Default value for ARG ${BASE_IMAGE} results in empty or invalid base image name More info: https://docs.docker.com/go/dockerfile/rule/invalid-default-arg-in-from/

Check warning on line 112 in Dockerfile

View workflow job for this annotation

GitHub Actions / 🐳 Build (linux/amd64)

Default value for global ARG results in an empty or invalid base image name

InvalidDefaultArgInFrom: Default value for ARG ${BASE_IMAGE} results in empty or invalid base image name More info: https://docs.docker.com/go/dockerfile/rule/invalid-default-arg-in-from/
WORKDIR /root/
COPY --from=builder /out/* /root/
Loading