Files
OmniRoute/tests/unit/release-acceptance-cli.test.ts
Bob.Hou e7214c72fc ci(acceptance): emit a shadow release-acceptance report next to release-green (#13701)
Adds a shadow release-acceptance report alongside release-green: an inventory/reduce/oracle pipeline under `scripts/quality/release-acceptance/` with a JSON schema, fixtures and a workflow that uploads the report as an artifact.

Contained by design, which is why it merges as-is: it runs only on push to `release/v*` and on manual dispatch (never on pull requests), the step is `continue-on-error`, `permissions: contents: read`, `persist-credentials: false`, and it consumes no secrets. Nothing in the product changes; the report is advisory until we decide to promote it.

Validated as a combined board first (this PR merged with the 11 siblings of the same batch on the release tip): eslint on every changed file with the suppressions file, typecheck:core, check:open-sse-typecheck, complexity, cognitive-complexity, changelog-integrity, i18n new-key coverage, docs-sync, migration-numbering, provider-consistency and a duplicate-identifier audit all green, plus 275 passing / 0 failing focused node:test cases across the 28 test files the batch touches. Then re-validated alone on the fresh tip before this merge: conflicts re-resolved, file sizes rebaselined for this PR's own growth, eslint and this PR's focused tests re-run.

Thanks @HouMinXi!
2026-09-16 03:17:52 -03:00

175 lines
4.9 KiB
TypeScript

import test from "node:test";
import assert from "node:assert/strict";
import { mkdtempSync, mkdirSync, writeFileSync, readFileSync } from "node:fs";
import { tmpdir } from "node:os";
import { join } from "node:path";
import {
exitFor,
reduceManifests,
main,
} from "../../scripts/quality/validate-release-acceptance.mjs";
const SHA = "30b5bf18fbe827a0283ce17e91bda22cc8b4c13e";
function key(id) {
return { gate_id: id, suite_id: null, shard_index: null, shard_total: null };
}
function gate(id, status) {
return {
gate_id: id,
suite_id: null,
shard_index: null,
shard_total: null,
tested_sha: SHA,
run_id: "1",
run_attempt: 1,
command_id: id,
gate_type: "static",
status,
cause: null,
exit_code: status === "PASS" ? 0 : 1,
duration_ms: 1,
evidence: [
{
artifact_id: "logs",
member: "lint.log",
algorithm: "sha256",
digest: "7f227db1653b6b723b07c8f2f6eb488f1f09e2f083ca7a3f5e02bbb274f5ff2e",
},
],
};
}
test("exit mapping", () => {
assert.equal(exitFor("VERIFIED"), 0);
assert.equal(exitFor("FAILED"), 1);
assert.equal(exitFor("UNVERIFIED"), 2);
});
test("three PASS manifests yield VERIFIED", () => {
const plan = {
required_gates: [key("a"), key("b"), key("c")],
identity: { tested_sha: SHA, run_id: "1", run_attempt: 1 },
};
const out = reduceManifests(plan, [
{ gates: [gate("a", "PASS")] },
{ gates: [gate("b", "PASS")] },
{ gates: [gate("c", "PASS")] },
]);
assert.equal(out.verdict, "VERIFIED");
assert.equal(exitFor(out.verdict), 0);
});
test("one FAIL yields FAILED", () => {
const plan = {
required_gates: [key("a")],
identity: { tested_sha: SHA, run_id: "1", run_attempt: 1 },
};
const out = reduceManifests(plan, [{ gates: [gate("a", "FAIL")] }]);
assert.equal(out.verdict, "FAILED");
assert.equal(exitFor(out.verdict), 1);
});
test("required missing yields UNVERIFIED", () => {
const plan = {
required_gates: [key("a"), key("b")],
identity: { tested_sha: SHA, run_id: "1", run_attempt: 1 },
};
const out = reduceManifests(plan, [{ gates: [gate("a", "PASS")] }]);
assert.equal(out.verdict, "UNVERIFIED");
assert.equal(exitFor(out.verdict), 2);
});
test("workflow source-guard", () => {
const text = readFileSync(".github/workflows/release-acceptance.yml", "utf8");
assert.match(text, /name: Release acceptance/);
assert.match(text, /cancel-in-progress: false/);
assert.equal(text.includes("gh issue close"), false);
assert.match(text, /if: github.event_name != 'pull_request'/);
});
test("schema_invalid does not throw when required_gates is missing", async () => {
const dir = mkdtempSync(join(tmpdir(), "acc-"));
writeFileSync(
join(dir, "plan.json"),
JSON.stringify({
identity: {
repository: "diegosouzapw/OmniRoute",
run_id: "1",
run_attempt: 1,
workflow: "release-acceptance.yml",
trigger: "push",
scope: "release",
requested_ref: "refs/heads/release/v3.8.51",
base_sha: SHA,
candidate_sha: SHA,
tested_sha: SHA,
},
artifact: null,
})
);
const man = join(dir, "m");
mkdirSync(man);
writeFileSync(join(man, "a.json"), JSON.stringify({ gates: [gate("a", "PASS")] }));
const out = join(dir, "report.json");
const code = await main([
"node",
"cli",
"--plan",
join(dir, "plan.json"),
"--manifests",
man,
"--out",
out,
]);
assert.equal(code, 2);
const report = JSON.parse(readFileSync(out, "utf8"));
assert.equal(report.verdict, "UNVERIFIED");
assert.ok(Array.isArray(report.required_gates));
assert.ok(report.evidence_errors.some((e) => e.code === "empty_required_set"));
assert.equal(
report.evidence_errors.some((e) => e.code === "schema_invalid"),
false
);
});
test("schema_invalid keeps FAILED when reduce already failed", async () => {
const dir = mkdtempSync(join(tmpdir(), "acc-fail-"));
const plan = {
required_gates: [key("a")],
identity: {
repository: "diegosouzapw/OmniRoute",
run_id: "1",
run_attempt: 1,
workflow: "release-acceptance.yml",
trigger: "push",
scope: "release",
requested_ref: "refs/heads/release/v3.8.51",
base_sha: SHA,
candidate_sha: SHA,
tested_sha: SHA,
},
artifact: null,
};
writeFileSync(join(dir, "plan.json"), JSON.stringify(plan));
const man = join(dir, "m");
mkdirSync(man);
const g = gate("a", "FAIL");
g.unexpected = true;
writeFileSync(join(man, "a.json"), JSON.stringify({ gates: [g] }));
const out = join(dir, "report.json");
const code = await main([
"node",
"cli",
"--plan",
join(dir, "plan.json"),
"--manifests",
man,
"--out",
out,
]);
assert.equal(code, 1);
const report = JSON.parse(readFileSync(out, "utf8"));
assert.equal(report.verdict, "FAILED");
assert.ok(report.evidence_errors.some((e) => e.code === "schema_invalid"));
});