librelad 63b53c7751 feat(hosting): getlibreportal as a first-class LibrePortal app (phase E)
Redo the download/website host as a normal app under containers/ (dogfooded — the
project hosts its own downloads on LibrePortal), instead of the bespoke repo-root
thing. Modeled on speedtest: standard getlibreportal.{config,sh,svg} +
docker-compose.yml (tagged template) so it plugs into the app scan + install
dispatch (installGetlibreportal) like every other app. nginx serves ./data (the
app data dir) — no special /web.

- getlibreportal.config: features category, public (login=false — it's a download
  host), no backup (regenerable), healthcheck on.
- docker-compose.yml: nginx:alpine, ./data:ro docroot + ./nginx.conf, traefik tags.
- nginx.conf: install.sh + latest.json no-cache; tarball/.sha256/.minisig immutable.
- publish.sh: assembles the docroot (built site + install.sh + dist/<channel>) into
  a target data dir; run on a full repo checkout (site/ + dist/ are host-side).
- exec bits set on the run-directly scripts (make_release.sh, install.sh, publish.sh).
- .gitattributes: dropped the stray 'getlibreportal export-ignore' (the no-slash
  pattern would also have excluded containers/getlibreportal — the app must ship);
  data/ gitignored.

Verified: app discovered by the site catalog (32 apps), installGetlibreportal matches
the dispatch name, and the full release->publish flow yields a docroot with the
website + install.sh + the signed/checksummed stable channel. The actual app-install
run + DNS/TLS for get.libreportal.org are operational steps (need a real host).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Signed-off-by: librelad <librelad@digitalangels.vip>
2026-05-25 20:02:47 +01:00

52 lines
2.1 KiB
Bash

#!/usr/bin/env bash
#
# Assemble the getlibreportal docroot — the website + install.sh + release
# channels — into the served data dir. Run on a FULL repo checkout (build/release
# machine), since it needs ../../site and ../../dist (both export-ignored, i.e.
# not in release tarballs).
#
# Usage: publish.sh [TARGET_DIR]
# TARGET_DIR defaults to ./data (next to this script). On a host where the app
# is installed, pass its live data dir, e.g.:
# containers/getlibreportal/publish.sh /libreportal-containers/getlibreportal/data
#
# Layout produced:
# <target>/ ← built website (repo: site/)
# <target>/install.sh ← bootstrap installer (repo: install.sh)
# <target>/<channel>/… ← release manifests + tarballs (repo: dist/<channel>/)
set -euo pipefail
HERE="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
ROOT="$(cd "$HERE/../.." && pwd)" # repo root (containers/getlibreportal -> ../../)
TARGET="${1:-$HERE/data}"
echo "Assembling getlibreportal docroot -> $TARGET"
mkdir -p "$TARGET"
# Clean only the things we manage (keep the dir itself / its mount).
rm -rf "${TARGET:?}"/* "${TARGET:?}"/.??* 2>/dev/null || true
# 1. Website (optional — skip cleanly without the toolchain).
if [[ -d "$ROOT/site" ]] && command -v npm >/dev/null 2>&1; then
( cd "$ROOT/site" && npm install --silent && npm run build )
cp -a "$ROOT/site/dist/." "$TARGET/" 2>/dev/null || true
echo " ✓ website"
else
echo " ! site build skipped (no site/ or no npm) — install.sh + releases still published"
fi
# 2. Bootstrap installer.
if [[ -f "$ROOT/install.sh" ]]; then cp -f "$ROOT/install.sh" "$TARGET/install.sh"; echo " ✓ install.sh"; fi
# 3. Release channels (from scripts/release/make_release.sh).
if [[ -d "$ROOT/dist" ]]; then
for ch in "$ROOT/dist"/*/; do
[[ -d "$ch" ]] || continue
n="$(basename "$ch")"; mkdir -p "$TARGET/$n"; cp -f "$ch"/* "$TARGET/$n/" 2>/dev/null || true
echo " ✓ channel $n"
done
else
echo " ! no dist/ — run scripts/release/make_release.sh first"
fi
echo "Done. Restart the container to serve it."