#!/usr/bin/env bash # Assembles Signage into the Ekklesia platform it is tested against: the platform at the commit pinned # in ci/platform.env, this checkout at modules/signage, and ci/pnpm-lock.yaml as the workspace # lockfile. Signage cannot build or run outside an Ekklesia workspace, so every CI job starts here. # # bash ci/assemble.sh [--allow-missing-lock] [output directory] # # The output directory (default build/workspace) is deleted and recreated. The platform is fetched # by its `main` branch and the pinned commit must be on it, so CI only ever runs reviewed platform # code; the checkout is then by commit, so nothing after it depends on a ref the network can move. # Every .git directory is removed afterwards. # # --allow-missing-lock keeps the platform's own lockfile. Only ci/update-lock.sh uses it. set -Eeuo pipefail root="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")/.." && pwd)" allow_missing_lock=0 if [[ "${1:-}" == "--allow-missing-lock" ]]; then allow_missing_lock=1 shift fi out="${1:-$root/build/workspace}" fail() { echo "assemble: $*" >&2 exit 1 } for command in git tar; do command -v "$command" >/dev/null || fail "$command is required." done # Read the two pins without sourcing the file: it is data, not a script. pin() { local value value="$(sed -n "s/^$1=//p" "$root/ci/platform.env")" [[ -n "$value" ]] || fail "ci/platform.env has no $1." printf '%s' "$value" } repository="$(pin EKKLESIA_PLATFORM_REPOSITORY)" commit="$(pin EKKLESIA_PLATFORM_COMMIT)" [[ "$commit" =~ ^[0-9a-f]{40}$ ]] || fail "EKKLESIA_PLATFORM_COMMIT must be a full commit SHA." rm -rf "$out" mkdir -p "$(dirname -- "$out")" git init --quiet "$out" git -C "$out" remote add origin "$repository" git -C "$out" fetch --quiet --no-tags origin "+refs/heads/main:refs/remotes/origin/main" || fail "cannot fetch the platform's main from ${repository}." git -C "$out" cat-file -e "${commit}^{commit}" 2>/dev/null || fail "the pinned platform commit ${commit} is not on the platform's main." git -C "$out" merge-base --is-ancestor "$commit" refs/remotes/origin/main || fail "the pinned platform commit ${commit} is not on the platform's main." git -C "$out" -c advice.detachedHead=false checkout --quiet --detach "$commit" [[ "$(git -C "$out" rev-parse HEAD)" == "$commit" ]] || fail "the platform did not check out at ${commit}." rm -rf "$out/.git" echo "assemble: platform ${commit}" [[ ! -e "$out/modules/signage" ]] || fail "the platform checkout already has modules/signage." mkdir -p "$out/modules/signage" # Exactly the files this checkout tracks, as committed or as changed in the working tree. Nothing # installed, built, or ignored, and not the CI scaffolding, which is not part of the module. git -C "$root" ls-files -z --cached --others --exclude-standard -- . ':!ci' ':!.gitea' | tar -C "$root" --null --files-from=- --create --file=- | tar -C "$out/modules/signage" --extract --file=- echo "assemble: signage $(git -C "$root" rev-parse HEAD 2>/dev/null || echo "(working tree)")" if [[ -f "$root/ci/pnpm-lock.yaml" ]]; then cp "$root/ci/pnpm-lock.yaml" "$out/pnpm-lock.yaml" elif ((allow_missing_lock == 0)); then fail "ci/pnpm-lock.yaml is missing; run bash ci/update-lock.sh." fi