#!/bin/bash # # Build a versioned, checksum-verified LibrePortal release artifact. # # The stable install fetches a release tarball over plain HTTPS (no git, no auth), # so it's reproducible and version-pinned. This builds that artifact from the # COMMITTED tree via `git archive`, which honours the `export-ignore` rules in # .gitattributes — so dev-only trees (scripts/unused, site, .claude, …) never ship. # # No infrastructure needed: output lands in dist// laid out exactly like # the hosting will serve it, so you can point an install at it with: # ( cd dist && python3 -m http.server 8000 ) # LP_RELEASE_BASE_URL=http://localhost:8000 ./install.sh ... # # Usage: scripts/release/make_release.sh [channel] [git-ref] # channel stable (default) | edge # git-ref HEAD (default) | a tag/commit to build from set -euo pipefail REPO_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)" cd "$REPO_ROOT" CHANNEL="${1:-stable}" REF="${2:-HEAD}" VERSION="$(tr -d ' \t\n\r' < VERSION 2>/dev/null || true)" [[ -n "$VERSION" ]] || { echo "make_release: VERSION file is empty or missing" >&2; exit 1; } # Root-owned-footprint version (helpers/wrapper/unit/sudoers). Published in the # manifest so the updater can detect when an update needs a root re-install. FOOTPRINT_VERSION="$(grep -oE '^footprint_version=[0-9]+' init.sh | head -1 | cut -d= -f2)" [[ -n "$FOOTPRINT_VERSION" ]] || FOOTPRINT_VERSION=0 # Guard: a release must never ship stale source arrays. Regenerate them; if that # changes anything not committed, the tree was stale — abort and tell the dev to # commit, so `git archive` (committed files only) can't bake in a mismatch. Only # enforced when building HEAD (an explicit old tag/ref is taken as-is). if [[ "$REF" == "HEAD" && -x scripts/source/files/generate_arrays.sh ]]; then scripts/source/files/generate_arrays.sh run >/dev/null 2>&1 || true if ! git diff --quiet -- scripts/source/files/arrays 2>/dev/null; then echo "make_release: source arrays were stale — regenerated them now." >&2 echo " Commit the changes under scripts/source/files/arrays/ and re-run." >&2 exit 1 fi fi TARBALL="libreportal-${VERSION}.tar.gz" PREFIX="libreportal-${VERSION}/" # top-level dir inside the tarball OUT="$REPO_ROOT/dist/$CHANNEL" mkdir -p "$OUT" echo "Building $TARBALL (channel=$CHANNEL, ref=$REF) ..." git archive --format=tar.gz --prefix="$PREFIX" -o "$OUT/$TARBALL" "$REF" ( cd "$OUT" && sha256sum "$TARBALL" > "$TARBALL.sha256" ) SHA="$(cut -d' ' -f1 < "$OUT/$TARBALL.sha256")" cat > "$OUT/latest.json" <.minisig. if [[ -n "${LP_MINISIGN_SECKEY:-}" ]]; then command -v minisign >/dev/null 2>&1 || { echo "make_release: LP_MINISIGN_SECKEY set but 'minisign' isn't installed" >&2; exit 1; } minisign -Sm "$OUT/$TARBALL" -s "$LP_MINISIGN_SECKEY" -t "libreportal $VERSION ($CHANNEL)" >/dev/null SIGNED=" ✓ $OUT/$TARBALL.minisig (signed)" else SIGNED=" ℹ︎ unsigned (set LP_MINISIGN_SECKEY to sign)" fi echo "✓ $OUT/$TARBALL" echo "✓ $OUT/$TARBALL.sha256 ($SHA)" echo "✓ $OUT/latest.json" echo "$SIGNED"