tv-anarchy/tools/release.sh
Natalie 7ff780fe56 feat(apps/tv-anarchy): add restart command support
Co-Authored-By: Lilith Autocommit <noreply@atlilith.com>
2026-06-09 21:17:10 -07:00

84 lines
4.2 KiB
Bash
Executable file

#!/usr/bin/env bash
# Cut a RELEASE of TVAnarchy and publish it to forge.black (Forgejo).
#
# Two-tier distribution: day-to-day `./build-install.sh` builds are ephemeral
# (tmp, install-to-/Applications, gone). A release is the durable, shareable
# artifact — built once here, tagged, and uploaded to the Forgejo repo so any
# node on the mesh can install/update from it WITHOUT the Xcode toolchain or
# source. Nodes pull with `tools/update.sh` (or the documented curl one-liner).
#
# Usage: tools/release.sh [vX.Y.Z] # tag defaults to v<MARKETING_VERSION>
# Auth: FORGEJO_TOKEN env, or ~/.config/tv-anarchy/forgejo-token (mode 600).
# Mint one at the Forgejo web UI → Settings → Applications → Tokens
# (scopes: write:repository). Required — the script will not guess.
set -euo pipefail
cd "$(dirname "$0")/.."
[ "$(uname -s)" = "Darwin" ] || { echo "✗ releases are cut on the macOS build box (xcodebuild); this is $(uname -s)." >&2; exit 1; }
API="${FORGEJO_API:-http://10.9.0.4:3000}" # overlay IP: mesh-stable (LAN addr flaps)
# --- auth (fail loud; never publish anonymously) ---------------------------
TOKEN="${FORGEJO_TOKEN:-}"
TOKEN_FILE="$HOME/.config/tv-anarchy/forgejo-token"
[ -z "$TOKEN" ] && [ -f "$TOKEN_FILE" ] && TOKEN="$(tr -d '[:space:]' < "$TOKEN_FILE")"
if [ -z "$TOKEN" ]; then
echo "✗ no Forgejo token. Set FORGEJO_TOKEN, or write one to $TOKEN_FILE (chmod 600)." >&2
echo " Mint: Forgejo → Settings → Applications → Generate Token (scope: write:repository)." >&2
exit 1
fi
# --- repo owner/name from the git remote ------------------------------------
remote="$(git remote get-url origin)" # forge-wg:lilith/tv-anarchy.git
path="${remote##*:}"; path="${path%.git}" # lilith/tv-anarchy
OWNER="${path%%/*}"; REPO="${path##*/}"
# --- build (ephemeral tmp) + install, reusing build-install.sh --------------
DD="$(mktemp -d "${TMPDIR:-/tmp}/tvanarchy-release.XXXXXX")"
trap 'rm -rf "$DD"' EXIT
echo "→ building release into $DD"
TVANARCHY_DD="$DD" ./build-install.sh
# Same destination resolution as build-install.sh (which we just ran) — both
# read tools/platform.sh, the single source of truth — so we zip the app it
# actually installed.
. tools/platform.sh
APP="$(tva_resolve_dest mac)"
[ -d "$APP" ] || { echo "✗ build-install did not produce $APP" >&2; exit 1; }
VER="$(/usr/libexec/PlistBuddy -c 'Print :CFBundleShortVersionString' "$APP/Contents/Info.plist")"
BUILD="$(/usr/libexec/PlistBuddy -c 'Print :CFBundleVersion' "$APP/Contents/Info.plist" 2>/dev/null || echo 0)"
SHA="$(sed -n 's/.*sha = "\(.*\)"/\1/p' Sources/TVAnarchyCore/BuildStamp.swift)"
TAG="${1:-v$VER}"
# --- refuse to ship a dirty tree (a release must be reproducible) -----------
if [ -n "$(git status --porcelain)" ]; then
echo "✗ working tree is dirty — commit before cutting release $TAG (a release must be reproducible)." >&2
exit 1
fi
# --- zip the .app (ditto preserves bundle symlinks/resources) ---------------
ZIP="$DD/TVAnarchy-$TAG.zip"
echo "→ packaging $ZIP"
ditto -c -k --sequesterRsrc --keepParent "$APP" "$ZIP"
# --- tag + push (over forge-wg ssh) -----------------------------------------
if git rev-parse -q --verify "refs/tags/$TAG" >/dev/null; then
echo "✗ tag $TAG already exists — bump MARKETING_VERSION or pass a new tag." >&2
exit 1
fi
echo "→ tagging $TAG @ $SHA and pushing"
git tag -a "$TAG" -m "TVAnarchy $TAG (build $BUILD · $SHA)"
git push origin "$TAG"
# --- create the Forgejo release + upload the zip ----------------------------
api() { curl -fsSL -H "Authorization: token $TOKEN" "$@"; }
echo "→ creating Forgejo release $TAG on $OWNER/$REPO"
rel="$(api -X POST "$API/api/v1/repos/$OWNER/$REPO/releases" \
-H 'Content-Type: application/json' \
-d "{\"tag_name\":\"$TAG\",\"name\":\"TVAnarchy $TAG\",\"body\":\"Build $BUILD · $SHA\"}")"
rid="$(printf '%s' "$rel" | python3 -c 'import sys,json; print(json.load(sys.stdin)["id"])')"
echo "→ uploading asset (release id $rid)"
api -X POST "$API/api/v1/repos/$OWNER/$REPO/releases/$rid/assets?name=TVAnarchy-$TAG.zip" \
-F "attachment=@$ZIP;type=application/zip" >/dev/null
echo "✓ released $TAG$API/$OWNER/$REPO/releases/tag/$TAG"
echo " nodes update with: tools/update.sh"