bread-ecosystem/ci/build.sh
Breadway 69c24f6d04 ci: take product name explicitly instead of deriving it from checkout dir
Every consuming product's CI checks out into a directory literally
named `src` (see e.g. breadpad's checkout step), so basename(repo_root)
resolved to "src" for every product in real CI runs — not the actual
product name, which only looked right in local testing because that
happened to run from a directory actually named after the product.

In production this meant every product sharing the runner would have
collided on the same image tag (bread-ci:src) and the same cargo-target
cache volume, silently mixing compiled artifacts across unrelated
repos. Caught before a second product (breadmon/breadclip/breadshot)
started using this and made the collision real.
2026-08-05 09:03:22 +08:00

60 lines
2.1 KiB
Bash
Executable file

#!/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 <product-name> <product-repo-root> <cargo-command...>
# e.g. ci/build.sh breadpad /path/to/breadpad cargo build --release --locked
#
# <product-name> is used verbatim as the image tag and cache-volume name —
# it must be passed explicitly rather than derived from <product-repo-root>'s
# basename, because every product's CI checks out into a directory literally
# named `src`, which would otherwise collide across every product sharing
# this runner (same image tag, same cargo-target cache volume).
#
# If <product-repo-root>/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 3 ]; then
echo "usage: build.sh <product-name> <product-repo-root> <cargo-command...>" >&2
exit 1
fi
PRODUCT="$1"
REPO_ROOT="$(cd "$2" && pwd)"
shift 2
CI_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
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 "$@"