From 5530d6cfcdd8f0fb4cfd45b617639eee00a781d0 Mon Sep 17 00:00:00 2001 From: ScreenTinker Date: Wed, 10 Jun 2026 14:12:29 -0500 Subject: [PATCH] docs: tag-based upgrade flow + upgrade.sh, Tizen install paths - scripts/upgrade.sh: upgrade a self-hosted instance to a tagged release (default latest). Backs up the db (.backup), checks out the tag, npm ci --omit=dev, restarts the service (SERVICE_NAME override), reports the version. - README: replace the git-pull update flow with scripts/upgrade.sh (latest or a pinned tag); keep main as the bleeding-edge option. Add a Samsung Tizen entry to device setup (URL Launcher -> /player). - tizen/README: point path A at the server's built-in /player, and explain why the released .wgt is unsigned (Samsung distributor certs are DUID-locked). Co-Authored-By: Claude Opus 4.8 (1M context) --- README.md | 32 +++++++++++++---------- scripts/upgrade.sh | 64 ++++++++++++++++++++++++++++++++++++++++++++++ tizen/README.md | 16 +++++++++--- 3 files changed, 95 insertions(+), 17 deletions(-) create mode 100755 scripts/upgrade.sh diff --git a/README.md b/README.md index 60dc113..0ff787e 100644 --- a/README.md +++ b/README.md @@ -314,31 +314,36 @@ To update a running instance to the latest version: ```bash cd /opt/screentinker -# Back up the database first -sqlite3 server/db/remote_display.db ".backup server/db/backup-$(date +%F).db" +# Upgrade to the latest tagged release. Backs up the db (a .backup snapshot under +# ./backups), checks out the tag, runs npm ci --omit=dev, restarts the service, +# and reports the running version. +scripts/upgrade.sh -# Pull latest code -git pull origin main - -# Install any new dependencies -cd server && npm install --production - -# Restart the service -sudo systemctl restart screentinker +# ...or pin a specific release: +scripts/upgrade.sh v1.8.0 ``` -If you deployed without git, you can initialize it: +Set `SERVICE_NAME` if your systemd unit is not named `screentinker`. + +If you deployed without git, initialize it once so `upgrade.sh` can resolve tags: ```bash cd /opt/screentinker git init git remote add origin https://github.com/screentinker/screentinker.git -git fetch origin main -git checkout origin/main -- . +git fetch origin --tags +git checkout -f main cd server && npm install --production sudo systemctl restart screentinker ``` +**Track bleeding edge (`main`)** instead of tagged releases - newest code, less tested: + +```bash +cd /opt/screentinker && git checkout main && git pull origin main +cd server && npm install --production && sudo systemctl restart screentinker +``` + Your database, uploads, and configuration are preserved — only code files are updated. **Schema migrations run automatically.** No manual migration commands at any point. On detecting a database that hasn't been through Phase 1 multi-tenancy migration yet, the server takes a timestamped snapshot first (`server/db/remote_display.pre-migration-.db`) and only continues startup once migration commits cleanly. If migration fails, the server logs the snapshot's path and exits — restore it with `cp` and investigate before retrying. @@ -414,6 +419,7 @@ keytool -genkey -v -keystore android/release-key.jks -keyalg RSA -keysize 2048 - - **Android TV / tablets**: Download the APK from your instance (`/download/apk`) or build it from source (see above) - **Raspberry Pi**: `curl -sSL https://your-instance/scripts/raspberry-pi-setup.sh | bash` - **Windows**: Run the setup script from `scripts/windows-setup.bat` + - **Samsung Tizen TV / signage**: point the TV's URL Launcher (or browser) at `https://your-instance/player` - no signing needed. For an installed native app, see [tizen/README.md](tizen/README.md) - **Any browser**: Open `https://your-instance/player` in kiosk/fullscreen mode 4. Enter the pairing code shown on the device diff --git a/scripts/upgrade.sh b/scripts/upgrade.sh new file mode 100755 index 0000000..4de2961 --- /dev/null +++ b/scripts/upgrade.sh @@ -0,0 +1,64 @@ +#!/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. +TARGET="${1:-$(git tag -l 'v*' | 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:-}'" >&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:-}" +echo "==> Upgrade to $TARGET complete. (Back to bleeding edge anytime: git checkout main)" diff --git a/tizen/README.md b/tizen/README.md index 19697fb..bd0cd6d 100644 --- a/tizen/README.md +++ b/tizen/README.md @@ -35,12 +35,20 @@ build-wgt.sh package (signed if Tizen CLI present, else unsigned) ``` Without the Tizen CLI this is an **unsigned** `.wgt`. +> **Why the released `.wgt` is unsigned:** Samsung **distributor** certificates +> are locked to the **DUID** of the signer's own TVs, so a `.wgt` we signed would +> not install on your TV anyway. Releases therefore ship it unsigned (for +> inspection only). To actually run it, use **path A** (no signing) or sign it +> yourself with your own certificate (**path B**). + ## Deploy — two paths -### A) URL Launcher (easiest, no signing) — Samsung signage (SSSP) -No package needed. Host this folder on any web server (e.g. the ScreenTinker -server itself) and point the display's **URL Launcher** at `…/index.html`. -The TV runs it as a web app on boot. Best for Samsung B2B signage displays. +### A) URL Launcher / TV browser (easiest, no signing) +No package, no Tizen Studio. Point the TV's **URL Launcher** (or just its web +browser) at your server's built-in web player: `https:///player`. +The TV runs it as a web app on boot, pairs with a 6-digit code, and plays - best +for Samsung B2B signage (SSSP). (You can instead self-host this `tizen/` folder +and point the URL Launcher at `…/index.html` for the Tizen-specific build.) ### B) Signed `.wgt` (installed app) A signing profile is already set up on the build box (Tizen Studio CLI 6.1):