Installable app + one-click update from forgejo

- scripts/update-app.sh: detached updater (setsid, survives app exit):
  git pull atitlan master -> gradle createDistributable -> only then
  kill app+engine and relaunch the fresh binary. Pull or build failure
  leaves the running app alone. Log: ~/.config/shonar-desktop/logs/update.log.
- Settings → About & updates: 'Install update' button appears when the
  check finds a newer remote commit; hands off to the script and tells
  the user the app will relaunch itself.
- Desktop entry (~/.local/share/applications/shonar-desktop.desktop,
  outside the repo): launches the packaged distributable via
  launch-desktop.sh; SHONAR_REPO fallback already resolves the tree,
  so the packaged app spawns the engine and sees the updater script.

Gate: :app:compileKotlin + :app:test green; desktop-file-validate clean;
launcher verified (app window from the menu path); updater fail-safe
verified (dirty-tree pull refused, app survived).
This commit is contained in:
avi 2026-09-22 12:18:24 -05:00
commit fc5502a7cd
3 changed files with 81 additions and 0 deletions

40
scripts/update-app.sh Executable file
View file

@ -0,0 +1,40 @@
#!/usr/bin/env bash
# Detached updater for SHONAR Desktop, spawned by the app's
# Settings → "Install update" button. Runs OUTSIDE the app process
# (setsid) so it survives the app quitting mid-update:
# 1. git pull the tracked branch from the forgejo remote
# 2. rebuild the distributable
# 3. kill the running app + engine
# 4. relaunch via the desktop launcher
# Log: ~/.config/shonar-desktop/logs/update.log
set -uo pipefail
repo="${SHONAR_REPO:-$HOME/Projects/Shonar Desktop}"
logdir="$HOME/.config/shonar-desktop/logs"
mkdir -p "$logdir"
log="$logdir/update.log"
exec >>"$log" 2>&1
echo "=== update started $(date -Is) ==="
cd "$repo" || { echo "no repo at $repo"; exit 1; }
if ! git pull atitlan master; then
echo "git pull FAILED — leaving the running app alone"
exit 1
fi
if ! ./gradlew :app:createDistributable -q; then
echo "build FAILED — leaving the running app alone"
exit 1
fi
# Stop the app (and its engine) only AFTER a good build exists.
pkill -f 'com.shonar.desktop.MainKt' 2>/dev/null
pkill -f 'uvicorn shonar.main:app' 2>/dev/null
sleep 2
bin="$repo/app/build/compose/binaries/main/app/shonar-desktop/bin/shonar-desktop"
[ -x "$bin" ] || { echo "distributable missing at $bin"; exit 1; }
export SHONAR_REPO="$repo"
export DISPLAY="${DISPLAY:-:0}"
setsid nohup "$bin" >/dev/null 2>&1 &
echo "=== update done, relaunched $(date -Is) ==="