test: add PI release proof harness
This commit is contained in:
97
scripts/verify-pi-product-artifact.mjs
Normal file
97
scripts/verify-pi-product-artifact.mjs
Normal file
@@ -0,0 +1,97 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
import { mkdir, writeFile } from 'node:fs/promises';
|
||||
import { dirname, resolve } from 'node:path';
|
||||
import { pathToFileURL } from 'node:url';
|
||||
|
||||
import {
|
||||
defaultProductExecutable,
|
||||
verifyPiProductArtifact,
|
||||
} from './lib/pi-product-artifact.mjs';
|
||||
import { runProbe } from './probe-pi-runtime.mjs';
|
||||
|
||||
export function parsePiArtifactVerifierArgs(argv, projectRoot = process.cwd()) {
|
||||
const options = {
|
||||
projectRoot: resolve(projectRoot),
|
||||
executable: undefined,
|
||||
reportPath: undefined,
|
||||
samples: 1,
|
||||
timeoutMs: 10_000,
|
||||
};
|
||||
for (let index = 0; index < argv.length; index += 1) {
|
||||
const argument = argv[index];
|
||||
const next = () => {
|
||||
const value = argv[index + 1];
|
||||
if (!value || value.startsWith('--')) throw new Error(`${argument} requires a value`);
|
||||
index += 1;
|
||||
return value;
|
||||
};
|
||||
if (argument === '--app-exe') options.executable = resolve(next());
|
||||
else if (argument === '--report') options.reportPath = resolve(next());
|
||||
else if (argument === '--samples') options.samples = Number.parseInt(next(), 10);
|
||||
else if (argument === '--timeout-ms') options.timeoutMs = Number.parseInt(next(), 10);
|
||||
else if (argument === '--help') options.help = true;
|
||||
else throw new Error(`Unknown argument: ${argument}`);
|
||||
}
|
||||
for (const [name, value] of [['--samples', options.samples], ['--timeout-ms', options.timeoutMs]]) {
|
||||
if (!Number.isSafeInteger(value) || value <= 0) throw new Error(`${name} must be a positive integer`);
|
||||
}
|
||||
options.executable ??= defaultProductExecutable(options.projectRoot);
|
||||
return options;
|
||||
}
|
||||
|
||||
function printHelp() {
|
||||
process.stdout.write('Usage: node scripts/verify-pi-product-artifact.mjs [options]\n\n');
|
||||
process.stdout.write(' --app-exe <path> Final unpacked Makelore executable\n');
|
||||
process.stdout.write(' --samples <count> Packaged get_state/runtime samples (default: 1)\n');
|
||||
process.stdout.write(' --timeout-ms <ms> Runtime probe timeout (default: 10000)\n');
|
||||
process.stdout.write(' --report <path> Write structured JSON evidence\n');
|
||||
}
|
||||
|
||||
export async function runPiArtifactVerifier(options) {
|
||||
const artifact = await verifyPiProductArtifact(options);
|
||||
const runtime = await runProbe({
|
||||
samples: options.samples,
|
||||
timeoutMs: options.timeoutMs,
|
||||
stage: false,
|
||||
keepStage: false,
|
||||
reportPath: undefined,
|
||||
providerFixturePath: undefined,
|
||||
imagePath: undefined,
|
||||
electronExecutablePath: artifact.artifact.executable,
|
||||
cliPath: artifact.artifact.cliPath,
|
||||
artifactLabel: 'final-makelore-product-artifact',
|
||||
}, options.projectRoot);
|
||||
if (runtime.result === 'fail') throw new Error('Final product Pi get_state/runtime probe failed');
|
||||
const report = {
|
||||
schemaVersion: 1,
|
||||
generatedAt: new Date().toISOString(),
|
||||
artifact,
|
||||
runtime,
|
||||
result: 'pass',
|
||||
};
|
||||
if (options.reportPath) {
|
||||
await mkdir(dirname(options.reportPath), { recursive: true });
|
||||
await writeFile(options.reportPath, `${JSON.stringify(report, null, 2)}\n`);
|
||||
}
|
||||
return report;
|
||||
}
|
||||
|
||||
async function main() {
|
||||
const options = parsePiArtifactVerifierArgs(process.argv.slice(2));
|
||||
if (options.help) {
|
||||
printHelp();
|
||||
return;
|
||||
}
|
||||
const report = await runPiArtifactVerifier(options);
|
||||
process.stdout.write(`${JSON.stringify(report, null, 2)}\n`);
|
||||
}
|
||||
|
||||
const isMain = process.argv[1]
|
||||
&& pathToFileURL(resolve(process.argv[1])).href === import.meta.url;
|
||||
if (isMain) {
|
||||
main().catch((error) => {
|
||||
process.stderr.write(`${error.stack ?? error.message}\n`);
|
||||
process.exitCode = 1;
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user