Fix Windows installer and build versioning

This commit is contained in:
2026-06-26 22:37:13 -05:00
parent 999f4a13b8
commit 7c006a7bb7
12 changed files with 39 additions and 19 deletions
+2
View File
@@ -21,6 +21,7 @@ const { readLock } = require('../core/locks');
const CaptureService = require('./capture');
const { TextIntelService } = require('./text-intel');
const { keepProcessesResponsive } = require('./win-power');
const PACKAGE_JSON = require(path.join(__dirname, '..', 'package.json'));
const APP_ID = 'com.stepforge.app';
@@ -762,6 +763,7 @@ function setupIpc() {
h('shell:showItemInFolder', ({ target }) => shell.showItemInFolder(target));
h('app:info', () => ({
version: app.getVersion(),
buildVersion: PACKAGE_JSON.buildVersion || app.getVersion(),
dataDir: store.root,
platform: process.platform,
}));
+1 -1
View File
@@ -401,7 +401,7 @@ class StepForgeApp {
el('div', { style: { fontWeight: 650 } }, folderLabel),
q ? el('div.muted', {}, `Search: ${q}`) : el('div.muted', {}, `${this.state.library.guides.length} guides`),
),
el('div.muted', {}, this.state.info ? `StepForge ${this.state.info.version}` : ''),
el('div.muted', {}, this.state.info ? `StepForge ${this.state.info.buildVersion || this.state.info.version}` : ''),
),
this.domBulkBar = el('div', {}),
this.domLibraryResults = el('div', {}),
+3 -3
View File
@@ -1,10 +1,10 @@
!include LogicLib.nsh
!include nsDialogs.nsh
Var StepForgeDesktopShortcutCheckbox
Var StepForgeDesktopShortcutState
!ifndef BUILD_UNINSTALLER
Var StepForgeDesktopShortcutCheckbox
Var StepForgeDesktopShortcutState
; Assisted installer page for the desktop shortcut choice.
!macro customInit
StrCpy $StepForgeDesktopShortcutState "true"
+2 -2
View File
@@ -1,12 +1,12 @@
{
"name": "stepforge",
"version": "0.3.2.1",
"version": "0.3.2",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "stepforge",
"version": "0.3.2.1",
"version": "0.3.2",
"license": "MPL-2.0",
"dependencies": {
"@tesseract.js-data/eng": "^1.0.0",
+2 -1
View File
@@ -1,6 +1,7 @@
{
"name": "stepforge",
"version": "0.3.2.1",
"version": "0.3.2",
"buildVersion": "0.3.2.1",
"description": "Fully offline desktop tool for capturing, annotating, and exporting step-by-step guides.",
"main": "app/main.js",
"author": "StepForge [email protected]",
+1 -1
View File
@@ -20,5 +20,5 @@ fi
node - <<'NODE'
const pkg = require('./package.json');
console.log(`StepForge ${pkg.version} bootstrap OK`);
console.log(`StepForge ${pkg.buildVersion || pkg.version} bootstrap OK`);
NODE
+4 -1
View File
@@ -70,6 +70,7 @@ for (const rel of walk(examplesRoot, examplesRoot)) {
}
const pkg = require(path.join(rootDir, 'package.json'));
const buildVersion = pkg.buildVersion || pkg.version;
const { execSync } = require('node:child_process');
function toolAvailable(cmd) {
@@ -88,7 +89,8 @@ const toolRows = Object.entries(tools)
const report = `# StepForge Build Report
Version: ${pkg.version}
Build version: ${buildVersion}
Package version: ${pkg.version}
Generated: ${new Date().toISOString()}
Host: ${process.platform} ${process.arch} (node ${process.version})
@@ -133,6 +135,7 @@ fs.writeFileSync(manifestFile, JSON.stringify({
version: 1,
generatedAt: new Date().toISOString(),
packageVersion: pkg.version,
buildVersion,
files,
}, null, 2) + '\n');
NODE
+1 -1
View File
@@ -3,7 +3,7 @@
set -euo pipefail
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
VERSION="$(node -p "require('${ROOT_DIR}/package.json').version" 2>/dev/null || echo 0.0.0)"
VERSION="$(node -p "const pkg=require('${ROOT_DIR}/package.json'); pkg.buildVersion || pkg.version" 2>/dev/null || echo 0.0.0)"
OUT_DIR="${STEPFORGE_PACKAGE_DIR:-$ROOT_DIR/build/artifacts}"
mkdir -p "$OUT_DIR"
WORK_DIR="$(mktemp -d "${OUT_DIR%/}/.pkg.XXXXXX")"
+4 -1
View File
@@ -10,6 +10,7 @@ const { build, Platform } = require('electron-builder');
const ROOT_DIR = path.resolve(__dirname, '..');
const PACKAGE_JSON = require(path.join(ROOT_DIR, 'package.json'));
const APP_ID = 'com.stepforge.app';
const BUILD_VERSION = PACKAGE_JSON.buildVersion || PACKAGE_JSON.version;
function findInstallerExe(dir) {
if (!fs.existsSync(dir)) return null;
@@ -32,6 +33,7 @@ function createWindowsInstallerConfig(outputDir) {
return {
appId: APP_ID,
productName: 'StepForge',
buildVersion: BUILD_VERSION,
directories: {
output: outputDir,
},
@@ -52,6 +54,7 @@ function createWindowsInstallerConfig(outputDir) {
createDesktopShortcut: true,
createStartMenuShortcut: true,
shortcutName: 'StepForge',
artifactName: '${productName} Setup ${buildVersion}.${ext}',
include: 'build/installer.nsh',
},
};
@@ -87,7 +90,7 @@ async function buildWindowsInstaller() {
const releaseInstaller = path.join(releaseDir, path.basename(builtInstaller));
fs.copyFileSync(builtInstaller, releaseInstaller);
console.log(`StepForge ${PACKAGE_JSON.version} Windows installer written to ${releaseInstaller}`);
console.log(`StepForge ${BUILD_VERSION} Windows installer written to ${releaseInstaller}`);
}
if (require.main === module) {
+10 -3
View File
@@ -16,18 +16,25 @@ function stampVersion(rootDir, version) {
throw new Error('version is required');
}
const normalized = version.replace(/^v/i, '');
const parts = normalized.split('.');
const isFourPartBuild = parts.length === 4 && parts.every((part) => /^\d+$/.test(part));
const packageVersion = isFourPartBuild ? parts.slice(0, 3).join('.') : normalized;
const buildVersion = normalized;
const pkgPath = path.join(rootDir, 'package.json');
const pkg = readJson(pkgPath);
pkg.version = version;
pkg.version = packageVersion;
pkg.buildVersion = buildVersion;
writeJson(pkgPath, pkg);
const lockPath = path.join(rootDir, 'package-lock.json');
if (!fs.existsSync(lockPath)) return;
const lock = readJson(lockPath);
lock.version = version;
lock.version = packageVersion;
if (lock.packages && lock.packages['']) {
lock.packages[''].version = version;
lock.packages[''].version = packageVersion;
}
writeJson(lockPath, lock);
}
+3 -1
View File
@@ -21,6 +21,8 @@ test('Windows packaging uses an assisted NSIS installer', (t) => {
assert.equal(config.nsis.createDesktopShortcut, true);
assert.equal(config.nsis.createStartMenuShortcut, true);
assert.equal(config.nsis.shortcutName, 'StepForge');
assert.equal(config.buildVersion, '0.3.2.1');
assert.equal(config.nsis.artifactName, '${productName} Setup ${buildVersion}.${ext}');
assert.equal(config.nsis.include, 'build/installer.nsh');
assert.equal(config.asar, true);
assert.ok(config.files.includes('app/**/*'));
@@ -35,7 +37,7 @@ test('Windows packaging uses an assisted NSIS installer', (t) => {
const tmp = makeTmpDir('windows-installer');
t.after(() => rmrf(tmp));
fs.mkdirSync(path.join(tmp, 'nested', 'deeper'), { recursive: true });
const installer = path.join(tmp, 'nested', 'deeper', 'StepForge Setup 0.2.0.exe');
const installer = path.join(tmp, 'nested', 'deeper', 'StepForge Setup 0.3.2.1.exe');
fs.writeFileSync(installer, Buffer.from('fake installer'));
assert.equal(findInstallerExe(tmp), installer);
});
+6 -4
View File
@@ -8,13 +8,14 @@ const assert = require('node:assert/strict');
const { makeTmpDir, rmrf } = require('./helpers');
const { stampVersion } = require('../../scripts/stamp-version');
test('stampVersion updates package metadata without semver validation', () => {
test('stampVersion splits build labels into package and build versions', () => {
const root = makeTmpDir('stamp-version');
try {
fs.writeFileSync(path.join(root, 'package.json'), JSON.stringify({
name: 'stepforge',
version: '0.1.0',
private: true,
buildVersion: '0.1.0',
}, null, 2));
fs.writeFileSync(path.join(root, 'package-lock.json'), JSON.stringify({
@@ -35,9 +36,10 @@ test('stampVersion updates package metadata without semver validation', () => {
const pkg = JSON.parse(fs.readFileSync(path.join(root, 'package.json'), 'utf8'));
const lock = JSON.parse(fs.readFileSync(path.join(root, 'package-lock.json'), 'utf8'));
assert.equal(pkg.version, '0.3.2.1');
assert.equal(lock.version, '0.3.2.1');
assert.equal(lock.packages[''].version, '0.3.2.1');
assert.equal(pkg.version, '0.3.2');
assert.equal(pkg.buildVersion, '0.3.2.1');
assert.equal(lock.version, '0.3.2');
assert.equal(lock.packages[''].version, '0.3.2');
} finally {
rmrf(root);
}