Publish updates to the Gitea package registry, and build the installer on macOS

The dev machine is now a laptop, so the release path had to stop assuming Windows
and a reachable network share.

- tools/build-win.cjs: build the Windows x64 installer from macOS or Windows.
  electron-builder fetches its own mac wine build, so the only real trap is
  architecture: a plain `electron-builder --win` on Apple Silicon silently
  produces an arm64 installer the stage PC cannot run. This pins --x64 and
  strips the CSC_* signing vars (an EMPTY WIN_CSC_LINK aborts the build).
- tools/publish-update.cjs: an http(s) destination now uploads to a Gitea
  generic package registry. Not a Gitea release: this server caps release
  attachments at 100 MB and disallows .exe, while the package registry takes the
  750 MB installer and serves it anonymously — which the updater requires, since
  it sends no credentials. Installer first, manifest last, so a TV checking
  mid-publish never sees a manifest naming a file that is not there yet.
- tools/release.cjs: bump, build and publish in one command.
- server.js: honour "check for updates automatically when the app starts". The
  setting was stored but never acted on. It checks only — installing restarts
  the app, which must stay a deliberate tap.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
2026-09-24 13:17:55 -04:00
co-authored by Claude Opus 5
parent 0db5e9b07d
commit 838a87dbf3
6 changed files with 422 additions and 100 deletions
+99 -64
View File
@@ -3,6 +3,16 @@
This folder is the complete source tree of the Bible App as it runs on the stage TV (version in
`package.json`). Everything the installer build needs is here. Nothing the build produces is.
The short version, once set up:
```bash
npm run release -- "What changed in this version"
git commit -am "Release <version>" && git push
```
That bumps the version, builds the Windows installer, uploads it to the church Gitea server, and the
TV picks it up from **Settings › Updates**. No .exe to hand-carry.
## 1. What is (and is not) in this folder
Included — everything the build and the app need:
@@ -13,115 +23,140 @@ Included — everything the build and the app need:
`dict/`, `fonts/`, `Notes/`, `Announcements/`, `Graphics/` (the defaults that ship inside the installer).
- Vendored runtimes that ship inside the installer: `vendor/whisper`, `vendor/upscale`, `vendor/redist`,
`vendor/llama` (the llama-server binaries — NOT the models), `vendor/fontawesome`.
- Build inputs: `package.json`, `package-lock.json`, `build/installer.nsh`, `tools/` (`build-full-installer.cjs`,
`publish-update.cjs`, the SFX stub in `tools/sfx`, `mock-propresenter.cjs`), `build-installer.bat`.
- Build inputs: `package.json`, `package-lock.json`, `build/installer.nsh`, `tools/` (`build-win.cjs`,
`release.cjs`, `publish-update.cjs`, `build-full-installer.cjs`, the SFX stub in `tools/sfx`,
`mock-propresenter.cjs`), `build-installer.bat`.
- The `*.md` notes at the root (small; project history worth keeping).
Left out on purpose (would only take space):
| Left out | Why |
|---|---|
| `dist-installer/` (57 GB), `dist/` | every old installer ever built; the build recreates them |
| `.git/` (32 GB) | the old history had installers and models committed into it — start a fresh repo (below) |
| `dist-installer/`, `dist/` | every installer ever built; the build recreates them |
| `node_modules/` (640 MB) | `npm ci` recreates it exactly from `package-lock.json` |
| `vendor/llama/*.gguf` (8 GB) | AI models; the regular installer never carries them (see §5) |
| `.ebcache/`, `archive/`, `*.log`, `server-port.txt` | build cache, retired scratch files, runtime files |
| `Dictionary/**/*.zip`, the Strong's XML folder | source archives; the app reads the converted JSON beside them |
Size of this folder: about 1.3 GB, of which ~700 MB is the vendored runtimes and ~400 MB is Bible data.
Size of this folder: about 1.2 GB, of which ~700 MB is the vendored runtimes and ~400 MB is Bible data.
## 2. Build machine prerequisites (the laptop)
## 2. Build machine prerequisites
- Windows 10/11 x64.
- Node.js 22 LTS (this tree was built with Node 22.18 / npm 10.9). Install from nodejs.org.
- Internet the first time: `npm ci` downloads Electron and electron-builder pulls NSIS and its
winCodeSign helper into `%LOCALAPPDATA%\electron-builder\Cache` (a few hundred MB, once).
- No code-signing certificate is used. The build must be told so (step 3).
**The Windows installer builds on macOS as well as on Windows.** electron-builder downloads its own
mac build of wine for the few Windows-only steps, so the laptop produces the exact same installer the
stage PC installs. Nothing has to be done on the Windows machine any more.
## 3. Build the regular installer
- macOS (Apple Silicon or Intel), or Windows 10/11 x64.
- Node.js 22 LTS. On macOS: `brew install node@22`. On Windows: nodejs.org.
- Internet the first time: `npm ci` downloads Electron, and electron-builder pulls NSIS, winCodeSign
and (on macOS) wine into its cache — a few hundred MB, once.
- No code-signing certificate is used, and `tools/build-win.cjs` sets the environment up accordingly.
```bat
cd bible-app-source
npm ci
set CSC_IDENTITY_AUTO_DISCOVERY=false
npx electron-builder --win
## 3. Build the installer
```bash
npm ci # first time only
npm run build:win
```
Output: `dist-installer\Bible App Setup <version>.exe` (about 750 MB).
Output: `dist-installer/Bible App Setup <version>.exe` (about 750 MB).
Notes:
- Bump `"version"` in `package.json` before every build you intend to ship. The TV's updater compares
versions numerically and only offers a HIGHER version.
- `build-installer.bat` does the same as the commands above and also bumps the patch version and clears
the electron-builder cache first. Either way works.
- If `WIN_CSC_LINK` / `CSC_LINK` / `CSC_KEY_PASSWORD` / `CSC_KEYCHAIN` exist in your environment they must be
REMOVED, not set to empty — electron-builder aborts on an empty `WIN_CSC_LINK`
("Env WIN_CSC_LINK is not correct"). In PowerShell: `Remove-Item Env:WIN_CSC_LINK`.
- If the build fails while extracting `winCodeSign` (symlink / permission errors), run the terminal as
administrator or turn on Windows Developer Mode, delete `%LOCALAPPDATA%\electron-builder\Cache\winCodeSign`,
and build again.
- `npm run build:win` always builds **x64**. Do not call `npx electron-builder --win` directly on an
Apple Silicon Mac: electron-builder defaults to the host architecture and will quietly hand you an
arm64 build that the stage PC cannot run.
- Bump `"version"` in `package.json` before every build you intend to ship — `npm run release` does it
for you. The TV's updater compares versions numerically and only offers a HIGHER version.
- If `WIN_CSC_LINK` / `CSC_LINK` / `CSC_KEY_PASSWORD` / `CSC_KEYCHAIN` exist in your environment,
`build-win.cjs` removes them for the build (electron-builder aborts on an EMPTY `WIN_CSC_LINK`).
- On Windows, if the build fails while extracting `winCodeSign` (symlink / permission errors), run the
terminal as administrator or turn on Developer Mode, delete
`%LOCALAPPDATA%\electron-builder\Cache\winCodeSign`, and build again.
## 4. Update the TVs remotely (no cable, no remote desktop)
Each TV has **Settings › Updates › "Update folder or address"** — a network share (`\\SERVER\share\bible-app`),
a folder, or an `http://` address — plus "Check for updates automatically when the app starts". The TV reads
`<source>/latest.json` there, compares versions, then downloads and runs the installer. The app closes,
installs, reopens; notes, graphics, annotations and settings are kept.
Each TV has **Settings › Updates › "Update folder or address"** plus "Check for updates automatically
when the app starts". The TV reads `<source>/latest.json`, compares versions, then downloads and runs
the installer. The app closes, installs, reopens; notes, graphics, annotations and settings are kept.
From the laptop, after a build:
The church's update source is the Gitea **package registry**:
```bat
npm run publish-update -- "\\SERVER\share\bible-app" "what changed in this version"
```
http://chronicles-ab.waterschurch.org:3000/api/packages/christian/generic/bible-app/latest
```
That copies the newest installer into the folder and writes `latest.json` (version, file name, size,
sha256, notes). For an `http://` source, upload the `.exe` and `latest.json` to the web server yourself.
`npm run release` builds and publishes in one go.
Paste that into Settings › Updates on every machine, once. It is also `bibleApp.updateTarget` in
`package.json`, which is where the publish script gets it from.
The TV picks the update up at its next start (auto-check on) or when someone taps **Check for Updates**
in Settings. It never installs without that check, so time the publish for after the service.
> Why the package registry and not a Gitea *release*? This server caps release attachments at 100 MB
> and does not allow `.exe`. The package registry takes the 750 MB installer and — importantly —
> serves it to **anonymous** readers, which is what the updater needs: it sends no credentials. The
> code repository stays private; only the published installer is readable without a login.
Ship a version:
```bash
npm run release -- "Faster laser, new popup cards"
```
That bumps the patch version, builds, uploads the installer and `latest.json`, and removes builds
older than the previous one. To publish somewhere else instead (a network share, a folder, a web
server), pass a destination — the same string you would put in Settings › Updates:
```bash
npm run release -- --dest "\\SERVER\share\bible-app" "Notes"
npm run publish-update -- "\\SERVER\share\bible-app" "Notes" # publish an existing build
```
Publishing needs a Gitea token: `GITEA_TOKEN`, or the macOS keychain item `gitea-mcp` that the git
tooling already uses. It is never written to disk.
The TV picks the update up at its next start (auto-check on) or when someone taps **Check for
Updates** in Settings. It never installs without that check, so time the publish for after the service.
## 5. Full Setup (only for a brand-new machine)
A machine that has never had the app needs the AI model once (about 1.9 GB). That is the one-file
"Bible App Full Setup", which drops the model into `%ProgramData%\Bible App\llama-cache` where updates never
touch it. To build it, put the model at `vendor/llama/model.gguf` (exactly 2,019,377,696 bytes — copy it from
the stage PC: `C:\Users\media\Downloads\bible-app\vendor\llama\model.gguf` or
`C:\ProgramData\Bible App\llama-cache\model.gguf`; it is gitignored, so it never enters the repo), build the
regular installer, then:
"Bible App Full Setup", which drops the model into `%ProgramData%\Bible App\llama-cache` where updates
never touch it. To build it, put the model at `vendor/llama/model.gguf` (exactly 2,019,377,696 bytes —
copy it from the stage PC: `C:\ProgramData\Bible App\llama-cache\model.gguf`; it is gitignored, so it
never enters the repo), build the regular installer, then:
```bat
```bash
node tools/build-full-installer.cjs
```
Machines that already have the model keep using the regular installer.
## 6. Put it in git
## 6. Git
```bat
cd bible-app-source
git init
git add -A
git commit -m "Bible App <version> — full source"
git remote add origin <your local git server URL>
git push -u origin main
The tree lives on the church Gitea server:
```
http://chronicles-ab.waterschurch.org:3000/christian/bible-app
```
`.gitignore` keeps the build outputs, `node_modules`, models and logs out; `.gitattributes` stores every
file byte-for-byte (the sources are CRLF, and several maintenance scripts match CRLF exactly).
`git push` and `git pull` work as usual; the credential is in the macOS keychain. `.gitignore` keeps
build outputs, `node_modules`, models and logs out; `.gitattributes` stores every file byte-for-byte
(several maintenance scripts match CRLF exactly).
The first push is about 1.3 GB, mostly the vendored runtimes and Bible JSON. A local Gitea / GitLab
handles that fine; if your server has Git LFS enabled, the commented lines in `.gitattributes` move the
`vendor/` binaries into LFS (only do that with LFS actually on, or clones get pointer files).
Tag what you ship, so a rollback is a checkout rather than an archaeology exercise:
```bash
git tag v<version> && git push --tags
```
If your server has Git LFS enabled, the commented lines in `.gitattributes` move the `vendor/`
binaries into LFS (only do that with LFS actually on, or clones get pointer files).
## 7. Dev-run without building
```bat
```bash
npm ci
node server.js
npm start
```
then open `http://localhost:8080/`. To run a test copy beside a live app, set `BIBLE_APP_PORT=8095` and
`BIBLE_APP_DATA_DIR=<some scratch folder>` so it never touches the church's real content in
`%APPDATA%\Bible App`.
then open `http://localhost:8080/`. This runs the server on macOS and Windows alike. To run a test copy
beside a live app, set `BIBLE_APP_PORT=8095` and `BIBLE_APP_DATA_DIR=<some scratch folder>` so it never
touches the church's real content.