#!/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}'))"