A manager-run 'update apply' refreshes code/apps/WebUI but CANNOT rewrite the root-owned footprint (helpers/wrapper/uninstall/unit/sudoers) — that immutability is the de-sudo boundary. Previously a release that changed those would silently leave them stale. Make it explicit: - init.sh: footprint_version=1 constant, baked at install into /usr/local/lib/libreportal/.footprint_version (root:root 0644) by initRootHelpers. Bump it whenever a root component changes. - make_release.sh: publishes footprint_version in latest.json. - fetch.sh: lpInstalledFootprintVersion (marker) + lpReleaseLatestFootprint (manifest). - check_update.sh: 'update apply' REFUSES when the release's footprint_version exceeds the installed one, directing to a root re-install (which fetches + re-bakes everything atomically). No half-applied updates. - webui_system_update.sh: badge sets footprint_update_needed + clears can_update so the WebUI won't offer a one-click apply for a footprint-bumping release. - docs/DEVELOPMENT.md: the bump rule + the footprint exception explained. Verified: manifest carries footprint_version; drift decision correct both ways (no marker/older -> needs re-install; equal -> no drift). Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> Signed-off-by: librelad <librelad@digitalangels.vip>
59 lines
2.1 KiB
Bash
59 lines
2.1 KiB
Bash
#!/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/<channel>/ 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
|
|
|
|
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" <<EOF
|
|
{
|
|
"version": "$VERSION",
|
|
"channel": "$CHANNEL",
|
|
"url": "$TARBALL",
|
|
"sha256": "$SHA",
|
|
"footprint_version": $FOOTPRINT_VERSION,
|
|
"notes": ""
|
|
}
|
|
EOF
|
|
|
|
echo "✓ $OUT/$TARBALL"
|
|
echo "✓ $OUT/$TARBALL.sha256 ($SHA)"
|
|
echo "✓ $OUT/latest.json"
|