Files
memind/scripts/verify-release-gate-report.mjs
T
john b1577a16e9
Memind CI / Test, build, and release guards (push) Failing after 12m3s
fix: harden release gate and page delivery
2026-07-26 14:32:01 +08:00

71 lines
2.5 KiB
JavaScript

#!/usr/bin/env node
import fs from 'node:fs/promises';
import path from 'node:path';
import { assertPortalRuntimePath, hashArtifact } from '../release-gate/artifact.mjs';
import { validateGateReport } from '../release-gate/report.mjs';
import { runCommand } from '../release-gate/runner.mjs';
const ROOT = path.resolve(new URL('..', import.meta.url).pathname);
function parseArgs(argv) {
const options = {
artifact: path.join(ROOT, '.runtime', 'portal'),
report: null,
};
for (let index = 2; index < argv.length; index += 1) {
const arg = argv[index];
if (arg === '--artifact') options.artifact = path.resolve(argv[++index] ?? '');
else if (arg === '--report') options.report = path.resolve(argv[++index] ?? '');
else throw new Error(`Unknown argument: ${arg}`);
}
return options;
}
async function git(...args) {
const result = await runCommand('git', args, { cwd: ROOT, timeoutMs: 30_000 });
if (result.code !== 0) throw new Error(`git ${args.join(' ')} failed`);
return result.stdout.trim();
}
try {
const options = parseArgs(process.argv);
options.artifact = assertPortalRuntimePath(options.artifact, { repoRoot: ROOT });
const commitSha = await git('rev-parse', 'HEAD');
const reportPath = options.report ?? path.join(ROOT, '.release-gate', commitSha, 'report.json');
const [raw, artifact] = await Promise.all([
fs.readFile(reportPath, 'utf8'),
hashArtifact(options.artifact),
]);
const report = JSON.parse(raw);
const validation = validateGateReport(report, {
expectedCommit: commitSha,
expectedArtifactSha256: artifact.sha256,
expectedBranch: 'main',
});
if (!validation.valid) {
const blocking = report.scenarios.filter(
(scenario) => !['passed', 'not_applicable'].includes(scenario.status),
);
const preview = blocking
.slice(0, 20)
.map((scenario) => `${scenario.id}:${scenario.status}`)
.join(', ');
const structural = validation.errors.filter(
(message) => !/^[A-Z]+-\d{2} is (failed|skipped|blocked|unknown)$/.test(message),
);
throw new Error([
'Gate report rejected.',
`blocking_scenarios=${blocking.length}`,
`preview=${preview}${blocking.length > 20 ? ', ...' : ''}`,
...structural.map((message) => `- ${message}`),
].join('\n'));
}
console.log(`Gate report verified: ${reportPath}`);
console.log(`commit=${commitSha}`);
console.log(`artifact_sha256=${artifact.sha256}`);
} catch (error) {
console.error(error.message);
process.exit(1);
}