Files
heros_web/scripts/ship-release.mjs

85 lines
2.9 KiB
JavaScript

import { spawnSync } from 'node:child_process';
import { mkdirSync, writeFileSync } from 'node:fs';
import { join } from 'node:path';
const qaVersion = process.env.PUBLIC_QA_VERSION ?? makeQaVersion();
const releaseCommit = gitValue(['rev-parse', 'HEAD'], 'unknown');
const releaseShortCommit = gitValue(['rev-parse', '--short', 'HEAD'], 'unknown');
const qaReportFile = 'qa-early-report.json';
assertNoTrackedChanges();
runPnpmScript('verify:local-release');
runPnpmScript('qa:early', { QA_REPORT_PATH: join('dist', qaReportFile) });
writeReleaseManifest(qaVersion, releaseCommit, releaseShortCommit, qaReportFile);
runPnpmScript('deploy:nas:dist');
runPnpmScript('verify:public-deploy', { PUBLIC_QA_VERSION: qaVersion, PUBLIC_QA_COMMIT: releaseCommit });
console.log(`Shipped and verified public deploy with PUBLIC_QA_VERSION=${qaVersion} at ${releaseShortCommit}`);
function makeQaVersion() {
const stamp = new Date().toISOString().replace(/[-:.TZ]/g, '').slice(0, 14);
return `ship-${stamp}`;
}
function assertNoTrackedChanges() {
const result = spawnSync('git', ['status', '--porcelain', '--untracked-files=no'], {
cwd: process.cwd(),
encoding: 'utf8'
});
if (result.status !== 0) {
throw new Error(`Could not inspect tracked git status before shipping:\n${result.stderr.trim()}`);
}
const dirty = result.stdout.trim();
if (dirty) {
throw new Error(`Refusing to ship release with uncommitted tracked changes:\n${dirty}`);
}
}
function writeReleaseManifest(qaVersion, commit, shortCommit, qaReport) {
const manifest = {
app: 'heros_web',
qaVersion,
commit,
shortCommit,
branch: gitValue(['branch', '--show-current'], 'unknown'),
generatedAt: new Date().toISOString(),
qaReport,
verification: ['verify:local-release', 'qa:early', 'verify:public-deploy']
};
mkdirSync('dist', { recursive: true });
writeFileSync(join('dist', 'release-manifest.json'), `${JSON.stringify(manifest, null, 2)}\n`, 'utf8');
console.log(`Wrote dist/release-manifest.json for ${manifest.shortCommit} (${qaVersion})`);
}
function gitValue(args, fallback) {
const result = spawnSync('git', args, { cwd: process.cwd(), encoding: 'utf8' });
if (result.status !== 0) {
return fallback;
}
return result.stdout.trim() || fallback;
}
function runPnpmScript(scriptName, extraEnv = {}) {
const label = `pnpm run ${scriptName}`;
console.log(`\n$ ${label}`);
const result =
process.platform === 'win32'
? spawnSync(process.env.ComSpec ?? 'cmd.exe', ['/d', '/s', '/c', `pnpm.cmd run ${scriptName}`], {
cwd: process.cwd(),
env: { ...process.env, ...extraEnv },
stdio: 'inherit'
})
: spawnSync('pnpm', ['run', scriptName], {
cwd: process.cwd(),
env: { ...process.env, ...extraEnv },
stdio: 'inherit'
});
if (result.status !== 0) {
throw new Error(`Command failed: ${label}`);
}
}