Skip to content

Commit d1cbe29

Browse files
committed
fix(qa): require sampled Kova metric counts
1 parent 9dbc21d commit d1cbe29

2 files changed

Lines changed: 92 additions & 2 deletions

File tree

scripts/kova-ci-summary.mjs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ function renderSummary(reportLocal, options) {
8686
for (const group of groups) {
8787
for (const metricId of keyMetricIds) {
8888
const metric = group.metrics?.[metricId];
89-
if (!metric || metric.count === 0) {
89+
if (!hasPositiveSampleCount(metric)) {
9090
continue;
9191
}
9292
lines.push(
@@ -198,10 +198,14 @@ function hasExplicitResourceCollectionSkip(reportLocal) {
198198
function hasSampledMetric(group, metricIds) {
199199
return metricIds.some((metricId) => {
200200
const metric = group?.metrics?.[metricId];
201-
return metric && Number(metric.count) > 0;
201+
return hasPositiveSampleCount(metric);
202202
});
203203
}
204204

205+
function hasPositiveSampleCount(metric) {
206+
return Number.isSafeInteger(metric?.count) && metric.count > 0;
207+
}
208+
205209
function collectViolations(records) {
206210
if (!Array.isArray(records)) {
207211
return [];

test/scripts/kova-ci-summary.test.ts

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -183,4 +183,90 @@ describe("scripts/kova-ci-summary", () => {
183183
"invalid Kova report: missing sampled CPU metric in performance groups",
184184
);
185185
});
186+
187+
it("rejects malformed resource metric counts instead of treating them as sampled", () => {
188+
const { result } = runSummary({
189+
performance: {
190+
repeat: 1,
191+
groups: [
192+
{
193+
metrics: {
194+
cpuPercentMax: {
195+
count: "Infinity",
196+
max: 12,
197+
median: 12,
198+
p95: 12,
199+
title: "CPU max",
200+
unit: "%",
201+
},
202+
resourcePeakGatewayRssMb: {
203+
count: true,
204+
max: 256,
205+
median: 256,
206+
p95: 256,
207+
title: "Gateway RSS",
208+
unit: "MB",
209+
},
210+
},
211+
scenario: "gateway",
212+
state: "clean",
213+
},
214+
],
215+
},
216+
records: [{ scenario: "gateway", state: "clean", status: "pass" }],
217+
summary: { statuses: { pass: 1 } },
218+
});
219+
220+
expect(result.status).toBe(1);
221+
expect(result.stderr).toContain(
222+
"invalid Kova report: missing sampled RSS metric in performance groups",
223+
);
224+
});
225+
226+
it("omits key metric rows with invalid sample counts", () => {
227+
const { output, result } = runSummary({
228+
performance: {
229+
repeat: 1,
230+
groups: [
231+
{
232+
metrics: {
233+
cpuPercentMax: {
234+
count: 1,
235+
max: 12,
236+
median: 12,
237+
p95: 12,
238+
title: "CPU max",
239+
unit: "%",
240+
},
241+
resourcePeakGatewayRssMb: {
242+
count: 1,
243+
max: 256,
244+
median: 256,
245+
p95: 256,
246+
title: "Gateway RSS",
247+
unit: "MB",
248+
},
249+
timeToHealthReadyMs: {
250+
count: "0",
251+
max: 30,
252+
median: 20,
253+
p95: 30,
254+
title: "Health ready",
255+
unit: "ms",
256+
},
257+
},
258+
scenario: "gateway",
259+
state: "clean",
260+
},
261+
],
262+
},
263+
records: [{ scenario: "gateway", state: "clean", status: "pass" }],
264+
summary: { statuses: { pass: 1 } },
265+
});
266+
267+
expect(result.status).toBe(0);
268+
expect(output).not.toContain("Health ready");
269+
expect(output).toContain("| gateway | clean | Gateway RSS | 256 MB | 256 MB | 256 MB |");
270+
expect(output).toContain("| gateway | clean | CPU max | 12 % | 12 % | 12 % |");
271+
});
186272
});

0 commit comments

Comments
 (0)