# syntax=docker/dockerfile:1
#
# The `gg` CLI, packaged for the two families the forge's own registries
# serve.
#
# docker buildx build --target packages \
# --output type=local,dest=./cli-dist --file cli/Dockerfile .
#
# The build context is the REPOSITORY ROOT, not cli/: the copyright file
# in both packages is the repo's own LICENSE.md.
#
# One source tree, two builds, because a Rust binary is linked against
# the glibc of whatever compiled it. The .deb is built on trixie, the
# oldest Debian this forge packages itself for; the .rpm on EL9, the
# oldest glibc in the rpm world worth shipping to. Building both from
# one base would produce a package that installs cleanly and then dies
# with `version GLIBC_2.41 not found`.
#
# Each stage compiles the dependency tree from Cargo.toml + Cargo.lock
# alone before the source is copied in, so that layer survives in the
# registry build cache across commits — the same staging the server
# image does with mix.exs and mix.lock. Cache mounts would be faster
# still and are deliberately not used: `setup-buildx-action` hands the
# job a fresh builder, so a mount cache starts empty on every run while
# a layer cache does not.
#
# Both stages want a C toolchain and CMake: aws-lc-sys, under rustls, is
# compiled rather than vendored as a binary.
ARG RUST_VERSION=1.98
# The version stamp, as CI computes it. The defaults are what a bare
# `docker buildx build` (or `cargo deb` by hand) produces.
ARG PKG_VERSION=
ARG RPM_RELEASE=1
ARG MAINTAINER=
ARG SUITES="trixie forky"
# ── .deb, on Debian trixie ───────────────────────────────────────────
FROM docker.io/rust:${RUST_VERSION}-trixie AS deb-builder
# dpkg-dev provides dpkg-shlibdeps, which is what cargo-deb's `$auto`
# dependency resolution shells out to. Without it the package would
# declare no libc dependency at all — quietly, which is why the build
# checks for one before it finishes.
# The rust images carry a minimal toolchain, so the two components the
# check step needs are added explicitly rather than assumed.
RUN apt-get update \
&& apt-get install -y --no-install-recommends cmake perl pkg-config dpkg-dev \
&& rm -rf /var/lib/apt/lists/* \
&& rustup component add rustfmt clippy \
&& cargo install --locked cargo-deb
WORKDIR /src/cli
# Dependencies first, against a stub binary: everything but this crate.
COPY cli/Cargo.toml cli/Cargo.lock ./
RUN mkdir -p src \
&& echo 'fn main() {}' > src/main.rs \
&& cargo build --release --locked \
&& rm -rf src target/release/gg target/release/deps/gg-*
COPY LICENSE.md /src/LICENSE.md
COPY cli ./
ARG PKG_VERSION
ARG MAINTAINER
ARG SUITES
ARG SOURCE_DATE_EPOCH
# The CLI's own checks run here rather than in a job of their own: this
# stage already has the toolchain and the compiled dependency tree, and
# a package isn't worth building from a tree that doesn't pass them.
#
# One artifact per suite. They are the same bytes with a different
# version suffix — a trixie-built binary runs on forky, and two
# filenames are what lets both sit in the pool with each `Packages`
# index naming its own. Each is copied out inside the loop, because
# cargo-deb empties target/debian on every run.
RUN set -eux; \
mkdir -p /out; \
cargo fmt --check; \
cargo clippy --all-targets --locked -- -D warnings; \
cargo test --locked; \
for suite in $SUITES; do \
set --; \
if [ -n "$PKG_VERSION" ]; then set -- --deb-version "${PKG_VERSION}+${suite}"; fi; \
if [ -n "$MAINTAINER" ]; then set -- "$@" --maintainer "$MAINTAINER"; fi; \
cargo deb "$@"; \
cp target/debian/*.deb /out/; \
done; \
for package in /out/*.deb; do \
dpkg-deb -f "$package" Depends | grep -q libc6 \
|| { echo "$package declares no library dependencies — is dpkg-dev installed?" >&2; exit 1; }; \
done; \
ls -l /out
# ── .rpm, on EL9 ─────────────────────────────────────────────────────
FROM docker.io/rockylinux/rockylinux:9 AS rpm-builder
# EL9's own rust is far older than this crate's edition, so the
# toolchain comes from rustup — the same split the server image makes
# for the NIF crates on trixie.
ARG RUST_VERSION
ENV RUSTUP_HOME=/usr/local/rustup \
CARGO_HOME=/usr/local/cargo \
PATH=/usr/local/cargo/bin:${PATH}
# `ca-certificates` and the extract, because the base image's
# /etc/pki/tls/certs/ca-bundle.crt is a symlink with nothing behind it
# until something runs update-ca-trust — curl fails with "error setting
# certificate file" and dnf, which carries its own trust, doesn't.
#
# rustup is downloaded and then run, rather than piped into sh: a
# pipeline reports the exit status of its LAST command, so a curl that
# fails hands sh an empty script, sh succeeds, and the build dies three
# commands later on `rustc: command not found`.
RUN set -eux; \
dnf -y install ca-certificates gcc gcc-c++ make cmake perl; \
update-ca-trust extract; \
dnf clean all; \
curl --proto '=https' --tlsv1.2 -fsSL https://sh.rustup.rs -o /tmp/rustup-init.sh; \
sh /tmp/rustup-init.sh -y --no-modify-path --profile minimal \
--default-toolchain "${RUST_VERSION}"; \
rm /tmp/rustup-init.sh; \
rustc --version; \
cargo --version; \
cargo install --locked cargo-generate-rpm
WORKDIR /src/cli
COPY cli/Cargo.toml cli/Cargo.lock ./
RUN mkdir -p src \
&& echo 'fn main() {}' > src/main.rs \
&& cargo build --release --locked \
&& rm -rf src target/release/gg target/release/deps/gg-*
COPY LICENSE.md /src/LICENSE.md
COPY cli ./
ARG RPM_RELEASE
# Read straight out of the environment by cargo-generate-rpm, which
# clamps every file's mtime and the package's build time to it.
ARG SOURCE_DATE_EPOCH
# RPM has no `~` convention to lean on for pre-release ordering the way
# Debian does, so the stamp goes in the release instead: `0.ci…` sorts
# before `1`, and a later tagged 0.1.0-1 upgrades over it.
RUN set -eux; \
cargo build --release --locked; \
cargo generate-rpm --set-metadata "release = \"${RPM_RELEASE}\""; \
mkdir -p /out; \
cp target/generate-rpm/*.rpm /out/; \
ls -l /out
# ── what CI collects ─────────────────────────────────────────────────
FROM scratch AS packages
COPY --from=deb-builder /out/ /
COPY --from=rpm-builder /out/ /
neiam
/gitgud
Git Gud
public · Issues · Pulls · Labels · Forks · Compare · Actions success · Badges · Packages
⭐
1
Log in to mark this repository.
6.4 KiB · text
History
e5ef8e4