mirror of
https://github.com/openclaw/openclaw.git
synced 2026-06-22 15:18:10 +00:00
fix(test): reject empty Kova summaries
This commit is contained in:
@@ -32,6 +32,11 @@ const keyMetricIds = [
|
||||
|
||||
const reportPath = path.resolve(args.report);
|
||||
const report = JSON.parse(await readFile(reportPath, "utf8"));
|
||||
const invalidReport = validateKovaSummaryReport(report);
|
||||
if (invalidReport) {
|
||||
console.error(`error: invalid Kova report: ${invalidReport}`);
|
||||
process.exit(1);
|
||||
}
|
||||
const markdown = renderSummary(report, {
|
||||
lane: args.lane || "kova",
|
||||
reportUrl: args.reportUrl || "",
|
||||
@@ -152,6 +157,29 @@ function renderSummary(reportLocal, options) {
|
||||
return `${lines.join("\n").trimEnd()}\n`;
|
||||
}
|
||||
|
||||
function validateKovaSummaryReport(reportLocal) {
|
||||
if (!reportLocal || typeof reportLocal !== "object" || Array.isArray(reportLocal)) {
|
||||
return "report must be an object";
|
||||
}
|
||||
const statuses = reportLocal.summary?.statuses;
|
||||
if (
|
||||
!statuses ||
|
||||
typeof statuses !== "object" ||
|
||||
Array.isArray(statuses) ||
|
||||
Object.keys(statuses).length === 0
|
||||
) {
|
||||
return "missing summary.statuses";
|
||||
}
|
||||
const records = Array.isArray(reportLocal.records) ? reportLocal.records : [];
|
||||
const groups = Array.isArray(reportLocal.performance?.groups)
|
||||
? reportLocal.performance.groups
|
||||
: [];
|
||||
if (records.length === 0 && groups.length === 0) {
|
||||
return "missing records or performance groups";
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
function collectViolations(records) {
|
||||
if (!Array.isArray(records)) {
|
||||
return [];
|
||||
|
||||
@@ -1,7 +1,31 @@
|
||||
// Kova Ci Summary tests cover kova ci summary script behavior.
|
||||
import { spawnSync } from "node:child_process";
|
||||
import { mkdtempSync, readFileSync, rmSync, writeFileSync } from "node:fs";
|
||||
import { tmpdir } from "node:os";
|
||||
import { join } from "node:path";
|
||||
import { describe, expect, it } from "vitest";
|
||||
|
||||
function runSummary(report: unknown) {
|
||||
const root = mkdtempSync(join(tmpdir(), "openclaw-kova-summary-"));
|
||||
const reportPath = join(root, "report.json");
|
||||
const outputPath = join(root, "summary.md");
|
||||
writeFileSync(reportPath, `${JSON.stringify(report, null, 2)}\n`, "utf8");
|
||||
const result = spawnSync(
|
||||
process.execPath,
|
||||
["scripts/kova-ci-summary.mjs", "--report", reportPath, "--output", outputPath],
|
||||
{
|
||||
cwd: process.cwd(),
|
||||
encoding: "utf8",
|
||||
},
|
||||
);
|
||||
let output = "";
|
||||
try {
|
||||
output = readFileSync(outputPath, "utf8");
|
||||
} catch {}
|
||||
rmSync(root, { force: true, recursive: true });
|
||||
return { output, result };
|
||||
}
|
||||
|
||||
describe("scripts/kova-ci-summary", () => {
|
||||
it("prints help without treating --help as a valued option", () => {
|
||||
const result = spawnSync(process.execPath, ["scripts/kova-ci-summary.mjs", "--help"], {
|
||||
@@ -13,4 +37,49 @@ describe("scripts/kova-ci-summary", () => {
|
||||
expect(result.stderr).toBe("");
|
||||
expect(result.stdout).toContain("usage: node scripts/kova-ci-summary.mjs --report");
|
||||
});
|
||||
|
||||
it("rejects empty Kova reports instead of rendering unknown summaries", () => {
|
||||
const empty = runSummary({});
|
||||
expect(empty.result.status).toBe(1);
|
||||
expect(empty.result.stderr).toContain("invalid Kova report: missing summary.statuses");
|
||||
|
||||
const noEvidence = runSummary({ summary: { statuses: { pass: 1 } } });
|
||||
expect(noEvidence.result.status).toBe(1);
|
||||
expect(noEvidence.result.stderr).toContain(
|
||||
"invalid Kova report: missing records or performance groups",
|
||||
);
|
||||
});
|
||||
|
||||
it("renders a Kova summary when status and evidence are present", () => {
|
||||
const { output, result } = runSummary({
|
||||
generatedAt: "2026-06-06T00:00:00.000Z",
|
||||
performance: {
|
||||
repeat: 1,
|
||||
groups: [
|
||||
{
|
||||
metrics: {
|
||||
timeToHealthReadyMs: {
|
||||
count: 1,
|
||||
max: 30,
|
||||
median: 20,
|
||||
p95: 30,
|
||||
title: "Health ready",
|
||||
unit: "ms",
|
||||
},
|
||||
},
|
||||
scenario: "gateway",
|
||||
state: "clean",
|
||||
},
|
||||
],
|
||||
},
|
||||
records: [{ scenario: "gateway", state: "clean", status: "pass" }],
|
||||
runId: "run-1",
|
||||
summary: { statuses: { pass: 1 } },
|
||||
target: "main",
|
||||
});
|
||||
|
||||
expect(result.status).toBe(0);
|
||||
expect(output).toContain("- Statuses: pass: 1");
|
||||
expect(output).toContain("| gateway | clean | Health ready | 20 ms | 30 ms | 30 ms |");
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user