screentinker/scripts/upgrade.sh
ScreenTinker 11e339dd89
Some checks are pending
CI / Unit tests (node --test) (push) Waiting to run
CI / Android unit tests (Kotlin schedule evaluator vectors) (push) Waiting to run
CI / Boot smoke + version check (push) Waiting to run
ci(release): make the pipeline prerelease-aware (#80)
Tagging a pre-release (e.g. v1.9.0-rc1) was unsafe. Four fixes:

1. bump-version.sh writes a numeric-only x.y.z to tizen/config.xml (strips a
   -rc1/-beta.N suffix) so the .wgt still signs/installs; the full VERSION
   (with the suffix) still drives server/Android/package.json.
2. release.yml flags the GitHub Release --prerelease for a -suffix version
   (keeps it off "Latest" and out of the /releases/latest API).
3. release.yml moves docker :latest only for final releases - a pre-release no
   longer repoints :latest onto untested code.
4. upgrade.sh excludes pre-release tags from its default selection - GNU
   `sort -V` ranks 1.9.0-rc1 above the final 1.9.0, so the unfiltered default
   would silently pick an RC (which then auto-OTAs to field kiosks). An explicit
   `upgrade.sh v1.9.0-rc1` still works.

Verified the strip, tag selection, prerelease/tags logic, and YAML validity in
isolation.

Closes #80

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-12 08:53:39 -05:00

68 lines
2.6 KiB
Bash
Executable file

#!/bin/bash
# Upgrade a self-hosted ScreenTinker to a tagged release (default: the latest).
#
# scripts/upgrade.sh # upgrade to the highest vX.Y.Z tag
# scripts/upgrade.sh v1.8.0 # upgrade to a specific tag
#
# Backs up the database first, checks out the tag (detached HEAD - you are now
# running a specific release, not a moving branch), installs production deps,
# restarts the service, and reports the running version. Schema migrations run
# automatically on the next boot.
#
# Env overrides: SERVICE_NAME (systemd unit, default screentinker), DB,
# BACKUP_DIR, STATUS_URL.
set -euo pipefail
cd "$(dirname "$0")/.."
APP_DIR="$(pwd)"
SERVICE_NAME="${SERVICE_NAME:-screentinker}"
DB="${DB:-$APP_DIR/server/db/remote_display.db}"
BACKUP_DIR="${BACKUP_DIR:-$APP_DIR/backups}"
echo "==> Fetching tags"
git fetch --tags origin
# Target tag: explicit arg, or the highest semver v* tag. #80: exclude pre-release
# tags (-rc/-beta/-alpha) from the default - GNU `sort -V` ranks 1.9.0-rc1 ABOVE the
# final 1.9.0, so an unfiltered default would silently pick an RC. An explicit arg
# still lets you target a pre-release deliberately (scripts/upgrade.sh v1.9.0-rc1).
TARGET="${1:-$(git tag -l 'v*' | grep -vE -- '-(rc|beta|alpha|pre)' | sort -V | tail -1)}"
if [ -z "$TARGET" ] || ! git rev-parse -q --verify "refs/tags/$TARGET^{commit}" >/dev/null; then
echo "ERROR: no such release tag: '${TARGET:-<none found>}'" >&2
exit 1
fi
echo "==> Target release: $TARGET"
# Back up the db first (reuses backup.sh's .backup - a consistent online copy).
if [ -f "$DB" ]; then
mkdir -p "$BACKUP_DIR"
BK="$BACKUP_DIR/remote_display-pre-${TARGET}-$(date +%Y%m%d-%H%M%S).db"
echo "==> Backing up db -> $BK"
sqlite3 "$DB" ".backup '$BK'"
else
echo "==> No db at $DB yet (fresh install) - skipping backup"
fi
echo "==> Checking out $TARGET"
git checkout -q "$TARGET"
echo "==> Installing server deps (npm ci --omit=dev)"
( cd server && npm ci --omit=dev )
echo "==> Restarting $SERVICE_NAME"
sudo systemctl restart "$SERVICE_NAME"
# Best-effort: report the running version. Tries HTTP :3001 then HTTPS :3443.
echo "==> Waiting for the service to answer..."
OUT=""
for i in $(seq 1 30); do
for URL in "${STATUS_URL:-}" http://localhost:3001/api/status https://localhost:3443/api/status; do
[ -z "$URL" ] && continue
OUT="$(curl -skf "$URL" 2>/dev/null || true)"
[ -n "$OUT" ] && break
done
[ -n "$OUT" ] && break
sleep 1
done
echo "==> /api/status: ${OUT:-<no response - check: journalctl -u $SERVICE_NAME>}"
echo "==> Upgrade to $TARGET complete. (Back to bleeding edge anytime: git checkout main)"