furtka/scripts/build-release-tarball.sh
Daniel Maksymilian Syrnicki c080764c7e
All checks were successful
Build ISO / build-iso (push) Successful in 17m5s
CI / lint (push) Successful in 27s
CI / test (push) Successful in 40s
CI / validate-json (push) Successful in 25s
CI / markdown-links (push) Successful in 12s
fix(furtka): move assets/ to repo top level so Caddy + systemd find it
Root cause of today's 403 on a fresh install: assets/ lived inside the
Python package at furtka/assets/, so the resource-manager tarball
extracted to /opt/furtka/versions/<ver>/furtka/assets/. But Caddyfile
has `root * /opt/furtka/current/assets/www`, systemd units point at
/opt/furtka/current/assets/bin/furtka-status, and the install-time
`systemctl link /opt/furtka/current/assets/systemd/*.service` expected
the top-level layout. All three found nothing:

- Caddy → 403 Forbidden (empty/missing document root)
- systemctl link → silent no-op, nothing ever linked into
  /etc/systemd/system/
- furtka-api.service + furtka-reconcile.service → "inactive" because
  they were never registered

Nothing in the Python package ever imported furtka.assets — these are
shell scripts, HTML/CSS, systemd units, and a Caddyfile, which is
config data, not package data. Promoting assets/ to the repo root
matches how it's referenced everywhere downstream and eliminates the
path mismatch.

Changes:
- git mv furtka/assets assets
- iso/build.sh: tarball-staging step now also `cp -a "$REPO_ROOT/assets"`
  so the tarball ships ./assets at its root, and the live-ISO copy
  reads from $REPO_ROOT/assets instead of $REPO_ROOT/furtka/assets.
- scripts/build-release-tarball.sh: same for release tarballs.
- webinstaller/app.py: _resolve_assets_dir's dev fallback walks one
  level up to REPO_ROOT/assets/.
- tests/test_webinstaller_assets.py: ASSETS constant updated.

Tests still green (150/150) because both paths were fs-level — no
code imports changed. Next ISO build will land assets at the path
everything downstream expects.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-16 15:26:10 +02:00

52 lines
1.7 KiB
Bash
Executable file

#!/usr/bin/env bash
# Build a Furtka release tarball + sha256 sidecar + release.json metadata.
#
# Usage: ./scripts/build-release-tarball.sh <version>
#
# Produces (in ./dist/):
# furtka-<version>.tar.gz contents extract to /opt/furtka/versions/<version>/
# furtka-<version>.tar.gz.sha256 single-line sha256 (<hash> <name>)
# release.json {"version","sha256","size","created_at"}
#
# The tarball shape matches what iso/build.sh ships in the live ISO: a
# VERSION file at the root, plus furtka/ and apps/ trees. Self-update on a
# running box downloads this tarball, verifies the sha256, stages to
# /opt/furtka/versions/<version>/, and flips /opt/furtka/current to it.
set -euo pipefail
VERSION="${1:?usage: $0 <version>}"
REPO_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
DIST_DIR="$REPO_ROOT/dist"
STAGE="$(mktemp -d)"
trap 'rm -rf "$STAGE"' EXIT
cp -a "$REPO_ROOT/furtka" "$STAGE/"
cp -a "$REPO_ROOT/apps" "$STAGE/"
# assets/ ships at the tarball root — Caddy + systemd + updater resolve
# everything from /opt/furtka/current/assets/, never from inside the package.
cp -a "$REPO_ROOT/assets" "$STAGE/"
find "$STAGE" -type d -name __pycache__ -exec rm -rf {} +
echo "$VERSION" > "$STAGE/VERSION"
mkdir -p "$DIST_DIR"
TARBALL="$DIST_DIR/furtka-$VERSION.tar.gz"
tar -czf "$TARBALL" -C "$STAGE" .
SHA=$(sha256sum "$TARBALL" | awk '{print $1}')
SIZE=$(stat -c%s "$TARBALL")
printf '%s %s\n' "$SHA" "$(basename "$TARBALL")" > "$TARBALL.sha256"
cat > "$DIST_DIR/release.json" <<EOF
{
"version": "$VERSION",
"sha256": "$SHA",
"size": $SIZE,
"created_at": "$(date -Iseconds)"
}
EOF
echo "Built $TARBALL"
echo " sha256: $SHA"
echo " size: $SIZE bytes"