From b5c539ba05d6f5fb2da47d694a17202928376a3d Mon Sep 17 00:00:00 2001 From: Waters Church Date: Thu, 24 Sep 2026 17:53:19 -0400 Subject: [PATCH] Release builds: Intel disk images, a Windows bundle, and where to download them MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit launcher/macos/build.sh takes ARCH=x86_64 for Intel Macs — the Swift target and the embedded Node follow (nodejs.org calls that one darwin-x64). The default stays arm64. launcher/windows/build.sh is new: the same payload plus Node for Windows, checksum-verified against nodejs.org, and ProdDash.bat, which keeps the server running and starts it again on exit code 75 — the admin page's update restart — the way the macOS launcher does. No Windows launcher app yet. The README's Run it section now points at the Releases page and the ProdDash-releases repo that holds the files, one line each for Apple silicon, Intel and Windows. Co-Authored-By: Claude Fable 5.1 --- .gitignore | 2 + README.md | 28 ++++++++- launcher/macos/README.md | 1 + launcher/macos/build.sh | 13 ++++- launcher/windows/build.sh | 117 ++++++++++++++++++++++++++++++++++++++ 5 files changed, 156 insertions(+), 5 deletions(-) create mode 100644 launcher/windows/build.sh diff --git a/.gitignore b/.gitignore index e3910f3..b553dd6 100644 --- a/.gitignore +++ b/.gitignore @@ -14,6 +14,8 @@ modules/propresenter-timers/ltc-capture # the launcher's build output, and its cache of the Node runtime it embeds launcher/macos/build/ launcher/macos/.cache/ +launcher/windows/build/ +launcher/windows/.cache/ # Compiled per-machine, source sits next to it (see spl-capture.swift). modules/spl-meter/spl-capture diff --git a/README.md b/README.md index 70b747b..b36d66f 100644 --- a/README.md +++ b/README.md @@ -30,9 +30,19 @@ and a clear degraded state, then recover on their own. ## Run it +Ready-made builds are on the +[Releases page](http://chronicles-ab.waterschurch.org:3000/michael/ProdDash/releases); +the files themselves live in +[ProdDash-releases](http://chronicles-ab.waterschurch.org:3000/michael/ProdDash-releases). +There is a disk image for Apple silicon Macs, one for Intel Macs, and a +bundle for 64-bit Windows. Every build updates itself afterwards from the +admin page, so the download only has to be recent, not current. + ### macOS — the app -Open the disk image and drag **ProdDash** to Applications. That's the whole +Download the disk image for your Mac — `ProdDash--arm64.dmg` for +Apple silicon, `ProdDash--x86_64.dmg` for Intel — open it and drag +**ProdDash** to Applications. That's the whole installation: the app carries the dashboard and its own Node runtime, so nothing else has to be installed and nothing can be missing. It lives in the menu bar, starts and stops the server, can open at login, and holds the @@ -43,12 +53,26 @@ a launchd job) simply doesn't have them, and an LTC input goes silently to zeroes. Build the disk image from a checkout with -[launcher/macos](launcher/macos)/`build.sh`: +[launcher/macos](launcher/macos)/`build.sh` (`ARCH=x86_64` in front of it +for Intel): ```bash cd launcher/macos && ./build.sh --dmg ``` +### Windows — the bundle + +Download `ProdDash--win-x64.zip`, unzip it somewhere you can write +to — `C:\ProdDash`, say, not Program Files, because updates write into the +folder — and double-click **ProdDash.bat**. The window it opens is the +dashboard running: it stays open, and it starts the server again when the +admin page applies an update. Allow `node.exe` on private networks when the +firewall asks, so other screens can reach it. Settings and layouts live in +`%APPDATA%\ProdDash`, so a new bundle never loses them. To start with +Windows, put a shortcut to `ProdDash.bat` in `shell:startup`. There is no +menu-bar-style launcher for Windows yet; the bundle is built with +[launcher/windows](launcher/windows)/`build.sh`. + ### Anywhere else, or from a checkout Requires [Node.js](https://nodejs.org) 18 or newer. diff --git a/launcher/macos/README.md b/launcher/macos/README.md index 9ea0e6d..d8a0f16 100644 --- a/launcher/macos/README.md +++ b/launcher/macos/README.md @@ -51,6 +51,7 @@ the cycle rather than spinning forever. ```bash ./build.sh # build/ProdDash.app — the whole application ./build.sh --dmg # …and build/ProdDash--arm64.dmg +ARCH=x86_64 ./build.sh --dmg # the same for Intel Macs (…-x86_64.dmg) ./build.sh --install # …and copy it to /Applications ./build.sh --run # …and open it ./build.sh --notarize # with --dmg: notarise and staple (Developer ID) diff --git a/launcher/macos/build.sh b/launcher/macos/build.sh index 5bb9b0b..8b0b219 100755 --- a/launcher/macos/build.sh +++ b/launcher/macos/build.sh @@ -11,6 +11,8 @@ # ./build.sh --dev launcher only — no Node, no server payload, so # it runs against the checkout. Seconds, not # minutes, while working on the launcher itself. +# ARCH=x86_64 ./build.sh the same for Intel Macs (default: arm64, Apple +# silicon); the Node it embeds follows. # # Signing: a "Developer ID Application" certificate is used when one is # installed (override with CODESIGN_IDENTITY). Without one the app is signed @@ -27,8 +29,13 @@ LAUNCHER_VERSION="1.0.0" # The Node the app ships. Bump it here; the download is checksum-verified # against nodejs.org's own SHASUMS256.txt and cached in .cache/. NODE_VERSION="v24.21.0" -ARCH="arm64" +ARCH="${ARCH:-arm64}" # arm64 (Apple silicon) or x86_64 (Intel) DEPLOYMENT_TARGET="13.0" +case "$ARCH" in + arm64) NODE_ARCH="arm64" ;; + x86_64) NODE_ARCH="x64" ;; # nodejs.org's name for it + *) echo "build.sh: ARCH must be arm64 or x86_64, not $ARCH" >&2; exit 2 ;; +esac REPO_ROOT="../.." OUT_DIR="build" @@ -106,7 +113,7 @@ fi # ── the server, and the Node that runs it ──────────────────────────────── if [[ $DEV -eq 0 ]]; then - TARBALL="node-$NODE_VERSION-darwin-$ARCH.tar.gz" + TARBALL="node-$NODE_VERSION-darwin-$NODE_ARCH.tar.gz" mkdir -p "$CACHE_DIR" if [[ ! -f "$CACHE_DIR/$TARBALL" ]]; then echo " fetching Node $NODE_VERSION (~50 MB, cached for next time)" @@ -125,7 +132,7 @@ if [[ $DEV -eq 0 ]]; then echo " embedding Node $NODE_VERSION" mkdir -p "$CONTENTS/Resources/node/bin" tar -xzf "$CACHE_DIR/$TARBALL" -C "$CONTENTS/Resources/node/bin" --strip-components 2 \ - "node-$NODE_VERSION-darwin-$ARCH/bin/node" + "node-$NODE_VERSION-darwin-$NODE_ARCH/bin/node" echo " embedding ProdDash $VERSION" mkdir -p "$PAYLOAD/config" diff --git a/launcher/windows/build.sh b/launcher/windows/build.sh new file mode 100644 index 0000000..aa150e0 --- /dev/null +++ b/launcher/windows/build.sh @@ -0,0 +1,117 @@ +#!/bin/zsh +# Build the Windows bundle — ProdDash--win-x64.zip: the dashboard, +# its own Node runtime and a start script, so nothing has to be installed on +# the Windows machine. Unzip, double-click ProdDash.bat, done. +# +# ./build.sh build/ProdDash--win-x64.zip +# +# Builds on macOS or Linux (zsh, curl, shasum, unzip, zip). Node for Windows +# comes from nodejs.org, checksum-verified against its SHASUMS256.txt and +# cached in .cache/. There is no Windows launcher app yet: ProdDash.bat keeps +# the server running and starts it again when the admin page applies an +# update (the server exits with code 75 to ask for that). +set -e -u +cd "$(dirname "$0")" + +APP_NAME="ProdDash" +# The Node the bundle ships — keep in step with launcher/macos/build.sh. +NODE_VERSION="v24.21.0" +NODE_DIST="node-$NODE_VERSION-win-x64" + +REPO_ROOT="../.." +OUT_DIR="build" +CACHE_DIR=".cache" + +for tool in curl shasum unzip zip; do + command -v "$tool" >/dev/null || { echo "build.sh: $tool not found" >&2; exit 1; } +done + +VERSION=$(sed -n 's/.*"version" *: *"\([^"]*\)".*/\1/p' "$REPO_ROOT/package.json" | head -1) +[[ -n "$VERSION" ]] || { echo "build.sh: can't read the version from package.json" >&2; exit 1; } +NAME="$APP_NAME-$VERSION-win-x64" +STAGE="$OUT_DIR/$NAME" + +echo "ProdDash $VERSION — building the Windows bundle" +rm -rf "$OUT_DIR" +mkdir -p "$STAGE/node" "$STAGE/config" "$CACHE_DIR" + +# ── Node for Windows ───────────────────────────────────────────────────── +ZIPFILE="$NODE_DIST.zip" +if [[ ! -f "$CACHE_DIR/$ZIPFILE" ]]; then + echo " fetching Node $NODE_VERSION for Windows (~30 MB, cached for next time)" + curl -fsSL --retry 3 -o "$CACHE_DIR/$ZIPFILE.part" "https://nodejs.org/dist/$NODE_VERSION/$ZIPFILE" + mv "$CACHE_DIR/$ZIPFILE.part" "$CACHE_DIR/$ZIPFILE" +fi +SUMS="$CACHE_DIR/SHASUMS256-$NODE_VERSION.txt" +[[ -f "$SUMS" ]] || curl -fsSL --retry 3 -o "$SUMS" "https://nodejs.org/dist/$NODE_VERSION/SHASUMS256.txt" +# This binary ships under ProdDash's name — check it every build. +WANT=$(awk -v f="$ZIPFILE" '$2 == f {print $1}' "$SUMS") +GOT=$(shasum -a 256 "$CACHE_DIR/$ZIPFILE" | awk '{print $1}') +if [[ -z "$WANT" || "$WANT" != "$GOT" ]]; then + echo "build.sh: $ZIPFILE does not match nodejs.org's checksum — refusing to ship it" >&2 + exit 1 +fi +echo " embedding Node $NODE_VERSION (node.exe and its licence)" +unzip -q -j "$CACHE_DIR/$ZIPFILE" "$NODE_DIST/node.exe" "$NODE_DIST/LICENSE" -d "$STAGE/node" + +# ── ProdDash ───────────────────────────────────────────────────────────── +echo " embedding ProdDash $VERSION" +cp "$REPO_ROOT/server.js" "$REPO_ROOT/package.json" "$STAGE/" +cp -R "$REPO_ROOT/public" "$REPO_ROOT/modules" "$STAGE/" +# Only the checked-in defaults: config/ also holds this machine's own +# modules.json and layouts when ProdDash has ever run from the checkout. +cp "$REPO_ROOT/config/proddash.json" "$STAGE/config/" +find "$STAGE" -name '.DS_Store' -delete + +# ── the start script and the read-me, with Windows line endings ────────── +crlf() { awk '{ printf "%s\r\n", $0 }' > "$1"; } + +crlf "$STAGE/ProdDash.bat" <<'BAT' +@echo off +rem ProdDash - double-click to start. Keep this window open: closing it stops the dashboard. +title ProdDash +cd /d "%~dp0" +rem The server exits with code 75 after applying an update from the admin page; start it again. +set PRODDASH_LAUNCHER=1 +:run +"%~dp0node\node.exe" server.js +set CODE=%ERRORLEVEL% +if %CODE% EQU 75 goto run +echo. +echo ProdDash stopped (exit code %CODE%). Press any key to close this window. +pause >nul +BAT + +crlf "$STAGE/README.txt" <:24500. Settings are on the admin page, + http://localhost:24500/admin. + +Your settings and layouts live in %APPDATA%\ProdDash, not in this folder, +so unzipping a new version or updating never loses them. + +Start with Windows: press Win+R, type shell:startup, press Enter, and put a +shortcut to ProdDash.bat in the folder that opens. + +Updates: the admin page's Update now fetches the new version into this +folder and restarts the dashboard; the window stays open. A copy of the +version it replaced is kept for a short while in case the new one will not +start. +README + +# ── zip ────────────────────────────────────────────────────────────────── +echo " zipping" +(cd "$OUT_DIR" && zip -q -r -X "$NAME.zip" "$NAME") +echo "built $OUT_DIR/$NAME.zip ($(du -sh "$OUT_DIR/$NAME.zip" | awk '{print $1}'))"