#!/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); }