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
+68
View File
@@ -0,0 +1,68 @@
/*
* release.cjs — one command to ship a new version from the laptop:
*
* npm run release -- "Notes the operator will see in Settings > Updates"
* npm run release -- --no-bump "Re-publish the current version"
* npm run release -- --dest "\\SERVER\share\bible-app" "Notes"
*
* It bumps the patch version, builds the Windows x64 installer, and publishes it to the update
* target. The version bump matters: the TV's updater compares versions numerically and only offers
* a HIGHER one, so re-publishing the same version is invisible to it.
*
* Default destination is package.json > bibleApp.updateTarget (the church's Gitea package
* registry). Pass --dest, or set BIBLEAPP_UPDATE_DIR, to publish somewhere else.
*/
const fs = require('fs');
const path = require('path');
const { spawnSync } = require('child_process');
const ROOT = path.join(__dirname, '..');
const PKG = path.join(ROOT, 'package.json');
const argv = process.argv.slice(2);
const noBump = argv.includes('--no-bump');
let dest = '';
const destAt = argv.indexOf('--dest');
if (destAt !== -1 && argv[destAt + 1]) dest = argv[destAt + 1];
// Whatever is left over, ignoring the flags and their values, is the release note.
const notes = argv.filter((a, i) =>
!a.startsWith('--') && !(destAt !== -1 && i === destAt + 1)
).join(' ').trim();
function run(label, cmd, args) {
console.log(`\n=== ${label} ===`);
const r = spawnSync(cmd, args, { cwd: ROOT, stdio: 'inherit' });
if (r.error) { console.error(`${label} failed to start:`, r.error.message); process.exit(1); }
if (r.status !== 0) { console.error(`${label} failed (exit ${r.status}).`); process.exit(r.status || 1); }
}
const pkg = JSON.parse(fs.readFileSync(PKG, 'utf-8'));
if (!noBump) {
const parts = String(pkg.version).split('.').map(n => parseInt(n, 10) || 0);
while (parts.length < 3) parts.push(0);
parts[2] += 1;
const next = parts.join('.');
// Rewrite only the version line, so the file keeps its own formatting and key order.
const raw = fs.readFileSync(PKG, 'utf-8');
fs.writeFileSync(PKG, raw.replace(
/^(\s*"version"\s*:\s*")[^"]+(",?)$/m,
(_m, a, b) => a + next + b
));
console.log(`Version ${pkg.version} -> ${next}`);
pkg.version = next;
} else {
console.log(`Version ${pkg.version} (not bumped)`);
}
run('Build', process.execPath, [path.join(__dirname, 'build-win.cjs')]);
const target = dest || process.env.BIBLEAPP_UPDATE_DIR || (pkg.bibleApp && pkg.bibleApp.updateTarget) || '';
const publishArgs = [path.join(__dirname, 'publish-update.cjs')];
if (target) publishArgs.push(target, notes || `Bible App ${pkg.version}`);
else if (notes) publishArgs.push('', notes);
run('Publish', process.execPath, publishArgs);
console.log(`\nReleased ${pkg.version}.`);
console.log('Commit the version bump so git matches what the TVs are running:');
console.log(` git commit -am "Release ${pkg.version}" && git push`);