47 lines
2.5 KiB
JavaScript
47 lines
2.5 KiB
JavaScript
#!/usr/bin/env node
|
|
// Release aggregation must reject the intermediate report before the RSS seal.
|
|
import assert from 'node:assert/strict';
|
|
import fs from 'node:fs';
|
|
import os from 'node:os';
|
|
import path from 'node:path';
|
|
import { spawnSync } from 'node:child_process';
|
|
import { fileURLToPath } from 'node:url';
|
|
|
|
const repo = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..');
|
|
const root = fs.mkdtempSync(path.join(os.tmpdir(), 'mt-playable-release-'));
|
|
const write = (name, value) => fs.writeFileSync(path.join(root, name), JSON.stringify(value));
|
|
const fixture = JSON.parse(fs.readFileSync(path.join(repo, 'test/playable/report.valid.json'), 'utf8'));
|
|
const manifest = { schema_version: 1, candidate: fixture.build, required_runs: { soak: 1 },
|
|
runs: [{ run_id: fixture.run_id, suite: 'soak', path: 'run-1' }] };
|
|
const report = { ...fixture, suite: 'soak', exit_gate: { checked: true, process_code: 0, timed_out: false, errors: [] } };
|
|
const baseline = process.argv.includes('--baseline')
|
|
? spawnSync('git', ['show', 'f39a55fd:script/validate_playable_report.mjs'], { cwd: repo, encoding: 'utf8' }).stdout : null;
|
|
function check(expected, label) {
|
|
const args = baseline ? ['--input-type=module', '-'] : [path.join(repo, 'script/validate_playable_report.mjs')];
|
|
const result = spawnSync(process.execPath, [...args, '--release-dir', root], { input: baseline, encoding: 'utf8' });
|
|
assert.equal(result.status, expected, `${label}: ${result.stdout} ${result.stderr}`);
|
|
assert.equal(JSON.parse(fs.readFileSync(path.join(root, 'release-report.json'))).status, expected === 0 ? 'PASS' : 'FAIL');
|
|
console.log(`ok - ${label}`);
|
|
}
|
|
try {
|
|
fs.mkdirSync(path.join(root, 'run-1'));
|
|
write('release-manifest.json', manifest);
|
|
write('run-1/report.json', report);
|
|
check(1, 'soak PASS without external memory seal is rejected');
|
|
report.runner_cases = [{ id: 'STB-MEMORY-01', status: 'PASS' }];
|
|
write('run-1/report.json', report);
|
|
check(1, 'memory case alone cannot replace the verdict');
|
|
report.memory = { verdict: { status: 'FAIL' } };
|
|
write('run-1/report.json', report);
|
|
check(1, 'contradictory memory verdict is rejected');
|
|
report.memory.verdict.status = 'PASS';
|
|
write('run-1/report.json', report);
|
|
check(0, 'clean exit and external memory PASS can be aggregated');
|
|
write('run-1/report.json', null);
|
|
check(1, 'null run report produces a sealed release failure');
|
|
write('release-manifest.json', null);
|
|
check(1, 'null manifest produces a sealed release failure');
|
|
} finally {
|
|
fs.rmSync(root, { recursive: true, force: true });
|
|
}
|