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 515c758..eda564d 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. It carries no modules — open **Admin → Available modules**, tick the ones this machine needs and press **Install @@ -45,12 +55,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 c287a19..e97c9eb 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 43d3580..e339d73 100755 --- a/launcher/macos/build.sh +++ b/launcher/macos/build.sh @@ -13,6 +13,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 @@ -29,8 +31,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" @@ -108,7 +115,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)" @@ -127,7 +134,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 (no modules — the catalog installs them)" mkdir -p "$PAYLOAD/config" diff --git a/launcher/windows/build.sh b/launcher/windows/build.sh new file mode 100755 index 0000000..0bf4bbc --- /dev/null +++ b/launcher/windows/build.sh @@ -0,0 +1,121 @@ +#!/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. It carries no +# modules: those come from the admin page's catalog into %APPDATA%\ProdDash. +# +# ./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 (no modules — the catalog installs them)" +cp "$REPO_ROOT/server.js" "$REPO_ROOT/package.json" "$STAGE/" +cp -R "$REPO_ROOT/public" "$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. +4. The bundle ships without modules. On the admin page, tick the ones this + PC needs under Available modules and press Install selected; each one + updates on its own from then on. + +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}'))"