Release ForgeFlow 0.5.2
This commit is contained in:
+23
-8
@@ -18,7 +18,9 @@ const required = [
|
||||
'setup-windows.ps1', 'update-windows.ps1', 'build-windows.ps1', 'UPDATE_FROM_0.3.2.md', 'scripts/apply-source-update.ps1',
|
||||
'docs/ARCHITECTURE.md', 'docs/SECURITY.md', 'docs/ROADMAP.md', 'docs/SETUP_GUIDE.md',
|
||||
'docs/UPDATING.md', 'docs/DIAGNOSTICS.md', 'docs/DEPLOYMENT_SETUP.md', 'docs/SSH_UNRAID_DEPLOYMENT.md',
|
||||
'docs/LUMAOPS_SERVER_AUDIT.md', 'docs/STATUS_ENDPOINT.md', 'docs/TEST_MATRIX.md', 'docs/RELEASE_NOTES_0.4.0.md', 'docs/RELEASE_NOTES_0.4.1.md', 'docs/RELEASE_NOTES_0.4.2.md', 'docs/RELEASE_NOTES_0.4.3.md', 'docs/RELEASE_NOTES_0.4.4.md', 'docs/RELEASE_NOTES_0.4.5.md',
|
||||
'docs/LUMAOPS_SERVER_AUDIT.md', 'docs/STATUS_ENDPOINT.md', 'docs/TEST_MATRIX.md', 'docs/RELEASE_NOTES_0.4.0.md', 'docs/RELEASE_NOTES_0.4.1.md', 'docs/RELEASE_NOTES_0.4.2.md', 'docs/RELEASE_NOTES_0.4.3.md',
|
||||
'docs/RELEASE_NOTES_0.5.0.md', 'docs/RELEASE_NOTES_0.5.1.md', 'docs/RELEASE_NOTES_0.5.2.md',
|
||||
'Publish-ForgeFlow-Release.ps1', 'docs/RELEASE_NOTES_0.4.4.md', 'docs/RELEASE_NOTES_0.4.5.md',
|
||||
'examples/gitea-actions/deploy.yml', 'examples/gitea-actions/rollback.yml',
|
||||
'examples/server/forgeflow-deploy', 'examples/server/forgeflow-targets.conf',
|
||||
'examples/server/forgeflow-runner.sudoers', 'examples/server/status-example.json',
|
||||
@@ -28,7 +30,7 @@ const required = [
|
||||
for (const file of required) await access(path.join(root, file));
|
||||
|
||||
const packageJson = JSON.parse(await readFile(path.join(root, 'package.json'), 'utf8'));
|
||||
if (packageJson.version !== '0.4.5') throw new Error(`Expected package version 0.4.5, got ${packageJson.version}.`);
|
||||
if (packageJson.version !== '0.5.2') throw new Error(`Expected package version 0.5.2, got ${packageJson.version}.`);
|
||||
for (const group of ['dependencies', 'devDependencies']) {
|
||||
for (const [name, version] of Object.entries(packageJson[group] || {})) {
|
||||
if (/^[~^*]/.test(version)) throw new Error(`${group} dependency ${name} must be pinned exactly, got ${version}.`);
|
||||
@@ -58,16 +60,29 @@ for (const file of javascriptFiles) {
|
||||
if (result.status !== 0) throw new Error(`${path.relative(root, file)} failed syntax validation:\n${result.stderr}`);
|
||||
}
|
||||
|
||||
const bashCheck = shellVerification.bashSyntaxCheckInvocation(root);
|
||||
const shell = spawnSync(bashCheck.command, bashCheck.args, bashCheck.options);
|
||||
if (shell.error) throw new Error(`Unable to start Bash for server deployment syntax validation: ${shell.error.message}`);
|
||||
if (shell.status !== 0) throw new Error(`Server deployment example failed bash syntax validation:\n${shell.stderr}`);
|
||||
const deploymentScript = await readFile(path.join(root, 'examples/server/forgeflow-deploy'), 'utf8');
|
||||
shellVerification.validateShellScriptStructure(deploymentScript);
|
||||
|
||||
// The server deployment script targets Linux/Unraid. On Windows, different tools may
|
||||
// register themselves as bash.exe (Git Bash, WSL launcher, MSYS), and several of
|
||||
// those cannot reliably accept a script over stdin from Node. Publishing and applying
|
||||
// a desktop update therefore never depend on a Windows Bash shim. Portable structural
|
||||
// validation always runs; GNU Bash syntax validation additionally runs on non-Windows.
|
||||
if (shellVerification.shouldRunExternalBash(process.platform)) {
|
||||
const bashCheck = shellVerification.bashSyntaxCheckFromTextInvocation(deploymentScript);
|
||||
const shell = spawnSync(bashCheck.command, bashCheck.args, bashCheck.options);
|
||||
if (shell.error) throw new Error(`Unable to start Bash for server deployment syntax validation: ${shell.error.message}`);
|
||||
if (shell.status !== 0) throw new Error(`Server deployment example failed bash syntax validation:
|
||||
${shell.stderr || shell.stdout || 'Bash returned a non-zero status.'}`);
|
||||
} else {
|
||||
console.log('Windows: external Bash syntax validation skipped; portable server-script validation passed.');
|
||||
}
|
||||
|
||||
JSON.parse(await readFile(path.join(root, 'examples/server/status-example.json'), 'utf8'));
|
||||
const setupGuide = await readFile(path.join(root, 'docs/SETUP_GUIDE.md'), 'utf8');
|
||||
const sshGuide = await readFile(path.join(root, 'docs/SSH_UNRAID_DEPLOYMENT.md'), 'utf8');
|
||||
const audit = await readFile(path.join(root, 'docs/LUMAOPS_SERVER_AUDIT.md'), 'utf8');
|
||||
const releaseNotes = await readFile(path.join(root, 'docs/RELEASE_NOTES_0.4.5.md'), 'utf8');
|
||||
const releaseNotes = await readFile(path.join(root, 'docs/RELEASE_NOTES_0.5.2.md'), 'utf8');
|
||||
if (!setupGuide.includes('Gitea access token') || !setupGuide.includes('diagnostic bundle')) {
|
||||
throw new Error('Setup guide is missing required connection or diagnostics instructions.');
|
||||
}
|
||||
@@ -77,7 +92,7 @@ if (!sshGuide.includes('/mnt/user/appdata') || !sshGuide.includes('host-key fing
|
||||
if (!audit.includes('d42d4a7f08240c478d07466e3fabec654dc71367') || !audit.includes('source/')) {
|
||||
throw new Error('LumaOps audit is missing the exact matching SHA or nested repository finding.');
|
||||
}
|
||||
for (const phrase of ['already staged', 'git add -A', 'silent-zebra-glow.zip']) {
|
||||
for (const phrase of ['viewport', '--pathspec-from-file', 'serialized per repository']) {
|
||||
if (!releaseNotes.includes(phrase)) throw new Error(`Release notes are missing: ${phrase}`);
|
||||
}
|
||||
const renderer = await readFile(path.join(root, 'src/renderer/app.js'), 'utf8');
|
||||
|
||||
Reference in New Issue
Block a user