Wire desktop updates through a generic feed

electron-builder now publishes latest-linux.yml / latest.yml and embeds
app-update.yml plus package-type, so electron-updater runs pacman -U or
dpkg -i through pkexec for packages and updates the per-user NSIS install
without elevation. The app checks only when asked (menu item), asks before
downloading and before installing, and J621_UPDATE_URL overrides the feed
for tests or forks.

deploy/push_desktop.sh builds and publishes the artifacts to
deploy/data/desktop, which the frontend nginx mounts read-only at
/desktop/. Verified detection and up-to-date handling against a local feed
with the packaged Arch build.
This commit is contained in:
2026-09-20 17:32:41 -05:00
parent 84ec431441
commit 7c39383655
11 changed files with 312 additions and 14 deletions
+12
View File
@@ -136,6 +136,18 @@ Push multi-arch images to the Gitea registry:
They tag `:latest` and `:<commit-sha>` and expect `docker login
gitea.rainbow-herring.ts.net` to succeed.
Push the desktop builds and their update metadata to the frontend's feed:
```bash
./push_desktop.sh # Linux packages (deb + pacman)
./push_desktop.sh --win # also cross-build the NSIS installer (wine)
```
Artifacts land in `deploy/data/desktop/`, which the frontend nginx mounts
read-only and serves at `/desktop/`. The desktop app's "Check for updates…"
menu item reads `latest-linux.yml` / `latest.yml` from there (see
`desktop/README.md`). Backend-only composes have no frontend, so no feed.
## Scheduled jobs
Compose files with a backend also run a **`scheduler`** service — the same
+3
View File
@@ -20,6 +20,9 @@ services:
context: ..
dockerfile: deploy/J621-Frontend
restart: unless-stopped
volumes:
# Desktop update feed (deploy/push_desktop.sh): latest*.yml + installers.
- ./data/desktop:/usr/share/nginx/html/desktop:ro
nginx:
image: nginx:1.29-alpine
+3
View File
@@ -21,6 +21,9 @@ services:
context: ..
dockerfile: deploy/J621-Frontend
restart: unless-stopped
volumes:
# Desktop update feed (deploy/push_desktop.sh): latest*.yml + installers.
- ./data/desktop:/usr/share/nginx/html/desktop:ro
nginx:
image: nginx:1.29-alpine
+3
View File
@@ -100,6 +100,9 @@ services:
context: ..
dockerfile: deploy/J621-Frontend
restart: unless-stopped
volumes:
# Desktop update feed (deploy/push_desktop.sh): latest*.yml + installers.
- ./data/desktop:/usr/share/nginx/html/desktop:ro
nginx:
image: nginx:1.29-alpine
+3
View File
@@ -99,6 +99,9 @@ services:
context: ..
dockerfile: deploy/J621-Frontend
restart: unless-stopped
volumes:
# Desktop update feed (deploy/push_desktop.sh): latest*.yml + installers.
- ./data/desktop:/usr/share/nginx/html/desktop:ro
nginx:
image: nginx:1.29-alpine
+62
View File
@@ -0,0 +1,62 @@
#!/bin/bash
# Build the J621 desktop packages and publish them to the frontend's update
# feed (deploy/data/desktop, mounted read-only into the frontend nginx and
# served at /desktop/). electron-updater reads latest-linux.yml / latest.yml
# from there; the app's feed URL comes from desktop/electron-builder.yml.
#
# Usage: ./push_desktop.sh [--win] [--no-build]
# --win also cross-build the Windows NSIS installer (needs wine)
# --no-build publish what is already in desktop/release/
set -euo pipefail
cd "$(dirname "$0")/.."
BUILD=1
WIN=0
for arg in "$@"; do
case "$arg" in
--win) WIN=1 ;;
--no-build) BUILD=0 ;;
*)
echo "usage: $0 [--win] [--no-build]" >&2
exit 2
;;
esac
done
if [ "$BUILD" = 1 ]; then
echo "==> Building Linux packages (deb + pacman) ..."
npm --prefix desktop run dist:linux
if [ "$WIN" = 1 ]; then
echo "==> Cross-building the Windows installer (wine) ..."
npm --prefix desktop run dist:win
fi
fi
FEED=deploy/data/desktop
mkdir -p "$FEED"
shopt -s nullglob
deb=(desktop/release/*.deb)
zst=(desktop/release/*.pkg.tar.zst)
linux_meta=(desktop/release/latest-linux.yml)
win_exe=("desktop/release/J621 Setup "*.exe)
win_meta=(desktop/release/latest.yml)
blockmaps=(desktop/release/*.blockmap)
if [ "${#deb[@]}" -eq 0 ] && [ "${#zst[@]}" -eq 0 ]; then
echo "No artifacts in desktop/release/ — run without --no-build first." >&2
exit 1
fi
# Replace the previous release's metadata before copying the new artifacts.
rm -f "$FEED"/latest-linux.yml "$FEED"/latest.yml
cp -f "${deb[@]}" "${zst[@]}" "${linux_meta[@]}" "$FEED"/ 2>/dev/null || true
if [ "${#win_exe[@]}" -gt 0 ]; then
cp -f "${win_exe[@]}" "${win_meta[@]}" "${blockmaps[@]}" "$FEED"/ 2>/dev/null || true
fi
echo "==> Published to $FEED:"
ls -1sh "$FEED" | sed 's/^/ /'
echo
echo "Served read-only by the frontend nginx at /desktop/ (no restart needed):"
echo " https://<frontend-host>/desktop/latest-linux.yml"