Release 1.4.35; build the one-file Full Setup on macOS too
- Version 1.4.35, published to the Gitea package registry and verified: the app downloads it, checks size and sha256, and lands a byte-identical installer. - tools/build-full-installer.cjs picked node_modules/7zip-bin/win/x64/7za.exe unconditionally, so the one-file Full Setup could only be built on Windows. 7za only packs the payload — the SFX stub and its config are concatenated byte-for-byte — so the host's own 7za yields the same Windows .exe. Also names the three payload files instead of passing a "*" that each 7za build expands its own way, and that would otherwise sweep the output archive into itself. - BUILD-AND-DEPLOY.md / UPDATES.md rewritten for the laptop workflow and the Gitea update source. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -127,6 +127,9 @@ never enters the repo), build the regular installer, then:
|
|||||||
node tools/build-full-installer.cjs
|
node tools/build-full-installer.cjs
|
||||||
```
|
```
|
||||||
|
|
||||||
|
This builds on the laptop too: 7-Zip only packs the payload, and the Windows SFX stub is concatenated
|
||||||
|
onto it byte-for-byte, so the host platform makes no difference to the result.
|
||||||
|
|
||||||
Machines that already have the model keep using the regular installer.
|
Machines that already have the model keep using the regular installer.
|
||||||
|
|
||||||
## 6. Git
|
## 6. Git
|
||||||
|
|||||||
+69
-65
@@ -1,58 +1,30 @@
|
|||||||
# Updating the Bible App
|
# Updating the Bible App
|
||||||
|
|
||||||
The app updates itself from **a folder you control** — a network share, a folder on this PC, a USB
|
The app updates itself from **a source you control** — the church's own Gitea server, a network
|
||||||
drive, or a small web server. No GitHub, no app store, no internet required (a network share is
|
share, a folder on this PC, or any small web server. No GitHub, no app store, nothing leaves the
|
||||||
enough).
|
building.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## One-time setup (per installed machine)
|
## One-time setup (per installed machine)
|
||||||
|
|
||||||
1. Open the app → **menu (☰) → Settings → Updates**
|
1. Open the app → **menu (☰) → Settings → Updates**
|
||||||
2. Put your update location in **Update folder or address**, for example:
|
2. Put the update source in **Update folder or address**. The church's is:
|
||||||
- `\\WATERS-SERVER\builds\bible-app` (network share — recommended)
|
|
||||||
- `D:\BibleAppBuilds` (folder on this PC)
|
```
|
||||||
- `http://server.local/bible-app` (web server)
|
http://chronicles-ab.waterschurch.org:3000/api/packages/christian/generic/bible-app/latest
|
||||||
3. Leave **“Check for updates automatically when the app starts”** ticked.
|
```
|
||||||
|
|
||||||
|
Anything else the app accepts also works: `\\WATERS-SERVER\builds\bible-app` (network share),
|
||||||
|
`D:\BibleAppBuilds` (folder on this PC), `http://server.local/bible-app` (web server).
|
||||||
|
3. Leave **"Check for updates automatically when the app starts"** ticked.
|
||||||
4. Click **Save**.
|
4. Click **Save**.
|
||||||
|
|
||||||
That's it. From now on the stage PC never needs a hand-carried .exe.
|
That's it. From now on the stage PC never needs a hand-carried .exe.
|
||||||
|
|
||||||
---
|
> **Checking is automatic; installing is not.** With that box ticked the app asks the server at
|
||||||
|
> startup and remembers the answer, which Settings → Updates then shows. It never installs on its
|
||||||
## Publishing a new version (on the dev machine)
|
> own — installing closes and reopens the app, so it stays a deliberate tap.
|
||||||
|
|
||||||
```bash
|
|
||||||
# 1. bump the version in package.json (e.g. 1.4.0 -> 1.4.1)
|
|
||||||
# 2. build + publish in one step:
|
|
||||||
npm run release
|
|
||||||
```
|
|
||||||
|
|
||||||
That produces the regular ~300 MB installer and publishes it — this is what existing machines
|
|
||||||
download. To also make the one-file installer for a **new** machine (app + AI model in a single
|
|
||||||
2.2 GB .exe), run this afterwards:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
node tools/build-full-installer.cjs
|
|
||||||
```
|
|
||||||
|
|
||||||
It lands in `dist-installer/Bible App Full Setup <version>.exe`. You only need it when setting up a
|
|
||||||
PC that has never had the app.
|
|
||||||
|
|
||||||
`npm run release` builds the installer and copies it, plus a `latest.json` manifest, into the update
|
|
||||||
folder. To publish somewhere specific, or to add release notes the operator will see:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
npm run publish-update -- "\\WATERS-SERVER\builds\bible-app" "Faster laser, new popup cards"
|
|
||||||
```
|
|
||||||
|
|
||||||
Publish destination is chosen in this order:
|
|
||||||
1. the path you pass on the command line
|
|
||||||
2. the `BIBLEAPP_UPDATE_DIR` environment variable
|
|
||||||
3. the folder configured in the app on this machine
|
|
||||||
4. `dist-installer/publish` (fallback)
|
|
||||||
|
|
||||||
The script keeps the 3 most recent installers in that folder and deletes older ones.
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -60,7 +32,7 @@ The script keeps the 3 most recent installers in that folder and deletes older o
|
|||||||
|
|
||||||
1. **Settings → Updates → Check for Updates**
|
1. **Settings → Updates → Check for Updates**
|
||||||
2. If a new version exists it shows the version number and notes → **Download & Install**
|
2. If a new version exists it shows the version number and notes → **Download & Install**
|
||||||
3. A progress bar runs while the installer copies (~1.4 GB, fast over a LAN)
|
3. A progress bar runs while the installer downloads (~750 MB, a couple of minutes over the LAN)
|
||||||
4. The app closes, the installer runs, and the app reopens
|
4. The app closes, the installer runs, and the app reopens
|
||||||
|
|
||||||
**Everything is kept:** notes, graphics, announcements, maps, annotations, service profiles,
|
**Everything is kept:** notes, graphics, announcements, maps, annotations, service profiles,
|
||||||
@@ -71,27 +43,62 @@ folder, which the installer never touches.
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
## Publishing a new version (on the laptop)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm run release -- "Faster laser, new popup cards"
|
||||||
|
git commit -am "Release <version>" && git push
|
||||||
|
```
|
||||||
|
|
||||||
|
That bumps the patch version, builds the Windows installer, uploads it and a `latest.json` manifest
|
||||||
|
to the update source, and clears out builds older than the previous one. The Windows installer builds
|
||||||
|
on the Mac — see BUILD-AND-DEPLOY.md.
|
||||||
|
|
||||||
|
To publish an existing build, or to publish somewhere other than the default:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm run publish-update # newest build -> default target
|
||||||
|
npm run publish-update -- "\\WATERS-SERVER\builds\bible-app" "Notes"
|
||||||
|
```
|
||||||
|
|
||||||
|
Publish destination is chosen in this order:
|
||||||
|
|
||||||
|
1. the path or URL you pass on the command line
|
||||||
|
2. the `BIBLEAPP_UPDATE_DIR` environment variable
|
||||||
|
3. `bibleApp.updateTarget` in `package.json` (the church's Gitea registry)
|
||||||
|
4. the source configured in the app on this machine
|
||||||
|
5. `dist-installer/publish` (fallback)
|
||||||
|
|
||||||
|
Uploading to Gitea needs a token — `GITEA_TOKEN`, or the macOS keychain item `gitea-mcp` that the
|
||||||
|
git tooling already uses. Downloading does not: the published installer is readable without a
|
||||||
|
login, which is what lets the TV fetch it. The source repository stays private.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
## What `latest.json` looks like
|
## What `latest.json` looks like
|
||||||
|
|
||||||
The publish script writes it for you; you only need this if you're placing a build by hand:
|
The publish script writes it for you; you only need this if you're placing a build by hand:
|
||||||
|
|
||||||
```json
|
```json
|
||||||
{
|
{
|
||||||
"version": "1.4.1",
|
"version": "1.4.35",
|
||||||
"file": "Bible App Setup 1.4.1.exe",
|
"file": "Bible App Setup 1.4.35.exe",
|
||||||
|
"size": 784268993,
|
||||||
|
"sha256": "7a628d27…",
|
||||||
"notes": "What changed in this version",
|
"notes": "What changed in this version",
|
||||||
"date": "2026-08-12"
|
"date": "2026-09-24"
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
Both the `.exe` and `latest.json` must sit in the same folder. Version numbers are compared
|
Both the `.exe` and `latest.json` must sit in the same place. Version numbers are compared
|
||||||
numerically, so `1.4.10` correctly beats `1.4.9`.
|
numerically, so `1.4.10` correctly beats `1.4.9` — and the app only ever offers a HIGHER version,
|
||||||
|
so re-publishing the same version number is invisible to it.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Setting up a brand-new machine — one file
|
## Setting up a brand-new machine — one file
|
||||||
|
|
||||||
Use **`Bible App Full Setup <version>.exe`** (about 2.2 GB). It is a single self-extracting file
|
Use **`Bible App Full Setup <version>.exe`** (about 2.7 GB). It is a single self-extracting file
|
||||||
containing the app *and* the offline AI model. Copy it to the new PC any way you like (USB stick,
|
containing the app *and* the offline AI model. Copy it to the new PC any way you like (USB stick,
|
||||||
network, cloud) and double-click it.
|
network, cloud) and double-click it.
|
||||||
|
|
||||||
@@ -105,15 +112,15 @@ survives every future update. Settings → Updates will show *"AI model installe
|
|||||||
this PC"*.
|
this PC"*.
|
||||||
|
|
||||||
> Why two different installers? A Windows installer cannot exceed 2 GB, and the app plus the model is
|
> Why two different installers? A Windows installer cannot exceed 2 GB, and the app plus the model is
|
||||||
> over that. The regular `Bible App Setup <version>.exe` (~300 MB) is what the in-app updater
|
> over that. The regular `Bible App Setup <version>.exe` (~750 MB) is what the in-app updater
|
||||||
> downloads, which keeps ordinary updates fast. The **Full** one exists for new machines.
|
> downloads. The **Full** one exists for new machines.
|
||||||
|
|
||||||
**Always check the file after copying it.** An interrupted copy or a cloud placeholder leaves a 0 KB
|
**Always check the file after copying it.** An interrupted copy or a cloud placeholder leaves a 0 KB
|
||||||
file, and Windows then says *"This app can't run on your PC"* — which looks like an app problem but
|
file, and Windows then says *"This app can't run on your PC"* — which looks like an app problem but
|
||||||
isn't:
|
isn't:
|
||||||
|
|
||||||
```bash
|
```powershell
|
||||||
Get-FileHash "Bible App Full Setup 1.4.1.exe" -Algorithm SHA256
|
Get-FileHash "Bible App Full Setup 1.4.35.exe" -Algorithm SHA256
|
||||||
```
|
```
|
||||||
|
|
||||||
Compare that to the `.sha256` file next to the installer. If they match, install it. If not (or the
|
Compare that to the `.sha256` file next to the installer. If they match, install it. If not (or the
|
||||||
@@ -124,21 +131,18 @@ anything, and refuses a damaged download instead of installing it.
|
|||||||
|
|
||||||
### Keeping several machines in step
|
### Keeping several machines in step
|
||||||
|
|
||||||
Point every machine at the same update location so nobody hand-carries files again:
|
Point every machine at the same update source and nobody hand-carries files again. The Gitea URL
|
||||||
|
above works from anywhere on the church network; a network share or a web address works too.
|
||||||
- **Same building:** a network share, e.g. `\\WATERS-SERVER\builds\bible-app`
|
|
||||||
- **Different site:** any web address the app can reach (`http://...`), or a synced cloud folder
|
|
||||||
that lands on that PC's disk
|
|
||||||
|
|
||||||
## If something goes wrong
|
## If something goes wrong
|
||||||
|
|
||||||
| Symptom | Fix |
|
| Symptom | Fix |
|
||||||
|---|---|
|
|---|---|
|
||||||
| “Could not read update info” | The folder path is wrong, or `latest.json` isn't in it. Check Settings → Updates. |
|
| "Could not read update info" | The address is wrong, or `latest.json` isn't there. Check Settings → Updates, and that the machine can reach the Gitea server. |
|
||||||
| “Installer not found” | `latest.json`'s `file` name doesn't match the actual .exe in the folder. |
|
| "Installer not found" | `latest.json`'s `file` name doesn't match the actual .exe. Re-run `npm run publish-update`. |
|
||||||
| Network share not reachable | Confirm the stage PC can open that share in File Explorer. |
|
| Network share not reachable | Confirm the stage PC can open that share in File Explorer. |
|
||||||
| Update seems stuck | The installer is large; watch the progress bar. It resumes fine if you retry. |
|
| Update seems stuck | The installer is large; watch the progress bar. It resumes fine if you retry. |
|
||||||
| “came across empty (0 bytes)” / “is incomplete” | The copy into the update folder didn't finish. Re-copy the installer there and try again. |
|
| "came across empty (0 bytes)" / "is incomplete" | The transfer didn't finish. Publish again and retry. |
|
||||||
| “was damaged in transfer (checksum mismatch)” | The file arrived corrupted. Publish or copy it again. |
|
| "was damaged in transfer (checksum mismatch)" | The file arrived corrupted. Publish or copy it again. |
|
||||||
| Windows: “This app can't run on your PC” | The .exe you're double-clicking is 0 KB or corrupt — check its size, verify the hash, and re-copy. |
|
| Windows: "This app can't run on your PC" | The .exe is 0 KB, corrupt, or the wrong architecture — check its size and verify the hash. |
|
||||||
| Need to roll back | Run an older installer from the update folder by hand — it installs over the top. |
|
| Need to roll back | `git checkout v<older>` and `npm run release -- --no-bump "Rolling back"`, or run the previous installer (still in the update source) by hand — it installs over the top. |
|
||||||
|
|||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "bible-app",
|
"name": "bible-app",
|
||||||
"version": "1.4.34",
|
"version": "1.4.35",
|
||||||
"description": "Minimalist Bible App for Portrait-Oriented Touchscreen TV",
|
"description": "Minimalist Bible App for Portrait-Oriented Touchscreen TV",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"main": "main.cjs",
|
"main": "main.cjs",
|
||||||
|
|||||||
@@ -31,7 +31,19 @@ const installerName = `Bible App Setup ${version}.exe`;
|
|||||||
const installerPath = path.join(DIST, installerName);
|
const installerPath = path.join(DIST, installerName);
|
||||||
const modelPath = path.join(ROOT, 'vendor', 'llama', 'model.gguf');
|
const modelPath = path.join(ROOT, 'vendor', 'llama', 'model.gguf');
|
||||||
const sfxModule = path.join(ROOT, 'tools', 'sfx', '7zSD.sfx');
|
const sfxModule = path.join(ROOT, 'tools', 'sfx', '7zSD.sfx');
|
||||||
const sevenZip = path.join(ROOT, 'node_modules', '7zip-bin', 'win', 'x64', '7za.exe');
|
/*
|
||||||
|
* 7za only packs the payload archive; the SFX stub and its config are plain byte concatenation, so
|
||||||
|
* the HOST's own 7za produces exactly the same Windows .exe. This used to be hard-coded to
|
||||||
|
* win/x64/7za.exe, which made the one-file installer buildable on Windows only — now the laptop can
|
||||||
|
* build it too.
|
||||||
|
*/
|
||||||
|
const sevenZip = (() => {
|
||||||
|
const base = path.join(ROOT, 'node_modules', '7zip-bin');
|
||||||
|
const arch = ['arm64', 'ia32', 'x64'].includes(process.arch) ? process.arch : 'x64';
|
||||||
|
if (process.platform === 'win32') return path.join(base, 'win', arch, '7za.exe');
|
||||||
|
if (process.platform === 'darwin') return path.join(base, 'mac', arch === 'arm64' ? 'arm64' : 'x64', '7za');
|
||||||
|
return path.join(base, 'linux', arch, '7za');
|
||||||
|
})();
|
||||||
const outName = `Bible App Full Setup ${version}.exe`;
|
const outName = `Bible App Full Setup ${version}.exe`;
|
||||||
const outPath = path.join(DIST, outName);
|
const outPath = path.join(DIST, outName);
|
||||||
|
|
||||||
@@ -45,7 +57,7 @@ function need(p, what) {
|
|||||||
need(installerPath, 'installer');
|
need(installerPath, 'installer');
|
||||||
need(modelPath, 'AI model (vendor/llama/model.gguf)');
|
need(modelPath, 'AI model (vendor/llama/model.gguf)');
|
||||||
need(sfxModule, 'SFX module (tools/sfx/7zSD.sfx)');
|
need(sfxModule, 'SFX module (tools/sfx/7zSD.sfx)');
|
||||||
need(sevenZip, '7za.exe');
|
need(sevenZip, `7za for ${process.platform}/${process.arch}`);
|
||||||
|
|
||||||
const mb = (n) => (n / 1048576).toFixed(1);
|
const mb = (n) => (n / 1048576).toFixed(1);
|
||||||
console.log(`Building one-file installer for ${version}`);
|
console.log(`Building one-file installer for ${version}`);
|
||||||
@@ -90,7 +102,7 @@ fs.writeFileSync(path.join(stage, 'install.cmd'), [
|
|||||||
// LZMA would burn many minutes for ~0% gain.
|
// LZMA would burn many minutes for ~0% gain.
|
||||||
const bundle = path.join(stage, 'payload.7z');
|
const bundle = path.join(stage, 'payload.7z');
|
||||||
console.log(' packing : building archive (store mode)…');
|
console.log(' packing : building archive (store mode)…');
|
||||||
execFileSync(sevenZip, ['a', '-t7z', '-mx0', '-bso0', '-bsp0', bundle, path.join(stage, '*')], { stdio: 'inherit' });
|
execFileSync(sevenZip, ['a', '-t7z', '-mx0', '-bso0', '-bsp0', bundle, installerName, 'model.gguf', 'install.cmd'], { cwd: stage, stdio: 'inherit' });
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* ExecuteFile, NOT RunProgram. RunProgram launches via CreateProcess, which cannot start a .cmd at
|
* ExecuteFile, NOT RunProgram. RunProgram launches via CreateProcess, which cannot start a .cmd at
|
||||||
|
|||||||
Reference in New Issue
Block a user