diff --git a/ci/Containerfile b/ci/Containerfile new file mode 100644 index 0000000..3b5722f --- /dev/null +++ b/ci/Containerfile @@ -0,0 +1,30 @@ +# Shared CI build environment for bread-ecosystem GTK4/libadwaita apps. +# +# Arch base: current gtk4/libadwaita/gtk4-layer-shell/graphene are all +# available as prebuilt pacman packages, so no from-source library builds +# are needed (unlike Fedora, where breadpad's CI used to rebuild libadwaita +# from source on every single run and broke repeatedly on version drift). +# +# Base image pinned by digest, package set frozen at build time: this image +# only changes when someone deliberately rebuilds it, not on every push. +# Product repos that depend on this file should pin it to a commit sha +# (see each product's ci/bread-ecosystem.rev), not track `main` — otherwise +# an unrelated change here silently breaks every product's next release. +# +# EXTRA_PKGS lets a product layer on extra pacman packages (see that +# product's ci/deps.txt) without forking this file. +FROM archlinux@sha256:fae033b815a16f930325c2697e620362be4d2e5d739a301b10ad1fc9c8643a06 + +ARG EXTRA_PKGS="" + +RUN pacman -Syu --noconfirm --needed \ + base-devel \ + git \ + pkgconf \ + rust \ + gtk4 \ + libadwaita \ + gtk4-layer-shell \ + graphene \ + ${EXTRA_PKGS} \ + && pacman -Scc --noconfirm diff --git a/ci/build.sh b/ci/build.sh new file mode 100755 index 0000000..4e3269b --- /dev/null +++ b/ci/build.sh @@ -0,0 +1,54 @@ +#!/usr/bin/env bash +# Shared CI build script for bread-ecosystem GTK4/libadwaita apps. +# +# Builds (or reuses, via docker's own layer cache) the pinned Arch image +# from ci/Containerfile, then runs the given cargo command inside it +# against a product repo checkout. +# +# Usage: ci/build.sh +# e.g. ci/build.sh /path/to/breadpad cargo build --release --locked +# +# If /ci/deps.txt exists (one pacman package per line, +# '#' comments and blank lines ignored), those packages are installed on +# top of the shared base image. +# +# Cargo's registry/git caches are shared across all products (same crates +# regardless of which app is building); CARGO_TARGET_DIR is cached +# per-product. Both persist in named docker volumes across runs. +set -euo pipefail + +if [ $# -lt 2 ]; then + echo "usage: build.sh " >&2 + exit 1 +fi + +REPO_ROOT="$(cd "$1" && pwd)" +shift + +CI_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +PRODUCT="$(basename "$REPO_ROOT")" + +EXTRA_PKGS="" +if [ -f "${REPO_ROOT}/ci/deps.txt" ]; then + EXTRA_PKGS="$(grep -vE '^\s*(#|$)' "${REPO_ROOT}/ci/deps.txt" | tr '\n' ' ')" +fi + +docker build \ + --build-arg "EXTRA_PKGS=${EXTRA_PKGS}" \ + -t "bread-ci:${PRODUCT}" \ + -f "${CI_DIR}/Containerfile" "${CI_DIR}" + +docker run --rm \ + -v "${REPO_ROOT}:/workspace" \ + -v "bread-ci-cargo-registry:/root/.cargo/registry" \ + -v "bread-ci-cargo-git:/root/.cargo/git" \ + -v "bread-ci-${PRODUCT}-target:/cargo-target" \ + -w /workspace \ + -e CARGO_TARGET_DIR=/cargo-target \ + "bread-ci:${PRODUCT}" \ + bash -c ' + set -euo pipefail + "$@" + mkdir -p /workspace/target + cp -a /cargo-target/. /workspace/target/ + ' bash "$@"