@vitest-evals/github-reporter 0.14.0 → 0.16.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +22 -1
- package/dist/cli.js +232 -17
- package/dist/cli.js.map +1 -1
- package/dist/cli.mjs +232 -17
- package/dist/cli.mjs.map +1 -1
- package/dist/index.d.mts +94 -1
- package/dist/index.d.ts +94 -1
- package/dist/index.js +360 -12
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +358 -12
- package/dist/index.mjs.map +1 -1
- package/package.json +2 -2
package/dist/index.mjs
CHANGED
|
@@ -269,9 +269,10 @@ var DEFAULT_MAX_CHECK_ANNOTATIONS = 50;
|
|
|
269
269
|
var MAX_CHECK_FIELD_LENGTH = 64e3;
|
|
270
270
|
function renderWorkflowCommands(report, options = {}) {
|
|
271
271
|
const maxAnnotations = options.maxAnnotations ?? DEFAULT_MAX_WORKFLOW_ANNOTATIONS;
|
|
272
|
+
const command = caseAnnotationCommand(options.gate);
|
|
272
273
|
return report.failures.filter(hasAnnotationLocation).slice(0, maxAnnotations).map(
|
|
273
274
|
(testCase) => formatWorkflowCommand({
|
|
274
|
-
command
|
|
275
|
+
command,
|
|
275
276
|
properties: {
|
|
276
277
|
file: testCase.displayFile,
|
|
277
278
|
line: String(testCase.location.line),
|
|
@@ -287,11 +288,12 @@ function buildCheckAnnotations(report, options = {}) {
|
|
|
287
288
|
options.maxAnnotations ?? DEFAULT_MAX_CHECK_ANNOTATIONS,
|
|
288
289
|
DEFAULT_MAX_CHECK_ANNOTATIONS
|
|
289
290
|
);
|
|
291
|
+
const annotationLevel = caseAnnotationLevel(options.gate);
|
|
290
292
|
return report.failures.filter(hasAnnotationLocation).slice(0, maxAnnotations).map((testCase) => ({
|
|
291
293
|
path: testCase.displayFile,
|
|
292
294
|
start_line: testCase.location.line,
|
|
293
295
|
end_line: testCase.location.line,
|
|
294
|
-
annotation_level:
|
|
296
|
+
annotation_level: annotationLevel,
|
|
295
297
|
title: truncate(
|
|
296
298
|
`${testCase.primaryFailure?.judgeName ?? "vitest-evals"} - ${testCase.displayName}`,
|
|
297
299
|
255
|
|
@@ -303,6 +305,12 @@ function buildCheckAnnotations(report, options = {}) {
|
|
|
303
305
|
raw_details: truncate(formatRawDetails(testCase), MAX_CHECK_FIELD_LENGTH)
|
|
304
306
|
}));
|
|
305
307
|
}
|
|
308
|
+
function caseAnnotationCommand(gate) {
|
|
309
|
+
return gate?.ok ? "warning" : "error";
|
|
310
|
+
}
|
|
311
|
+
function caseAnnotationLevel(gate) {
|
|
312
|
+
return gate?.ok ? "warning" : "failure";
|
|
313
|
+
}
|
|
306
314
|
function hasAnnotationLocation(testCase) {
|
|
307
315
|
return Boolean(testCase.location);
|
|
308
316
|
}
|
|
@@ -362,6 +370,164 @@ function formatWorkflowCommand({
|
|
|
362
370
|
return `::${command} ${renderedProperties}::${escapeCommandData(message)}`;
|
|
363
371
|
}
|
|
364
372
|
|
|
373
|
+
// src/gate.ts
|
|
374
|
+
function evaluateEvalGate(report, policy = {}) {
|
|
375
|
+
const minPassRate = resolveMinPassRate(policy);
|
|
376
|
+
const minScoreAverage = policy.minScoreAverage;
|
|
377
|
+
const enforced = minPassRate !== void 0 || minScoreAverage !== void 0 || policy.failOnFailures === true;
|
|
378
|
+
const passRate = computePassRate(report);
|
|
379
|
+
const counts = formatEvalCounts(report, passRate);
|
|
380
|
+
if (!enforced) {
|
|
381
|
+
const ok = report.status === "passed";
|
|
382
|
+
return {
|
|
383
|
+
ok,
|
|
384
|
+
status: ok ? "passed" : "failed",
|
|
385
|
+
enforced: false,
|
|
386
|
+
passRate,
|
|
387
|
+
title: defaultCheckTitle(report),
|
|
388
|
+
message: ok ? `eval report passed: ${counts}` : `eval report failed: ${counts}`
|
|
389
|
+
};
|
|
390
|
+
}
|
|
391
|
+
const nonEvalFailures = Math.max(
|
|
392
|
+
0,
|
|
393
|
+
report.totals.failed - report.totals.evalFailed
|
|
394
|
+
);
|
|
395
|
+
if (nonEvalFailures > 0) {
|
|
396
|
+
return {
|
|
397
|
+
ok: false,
|
|
398
|
+
status: "failed",
|
|
399
|
+
enforced: true,
|
|
400
|
+
passRate,
|
|
401
|
+
title: "Eval report hard failure",
|
|
402
|
+
message: `${formatNumber(nonEvalFailures)} non-eval test failure${nonEvalFailures === 1 ? "" : "s"}; ${counts}`
|
|
403
|
+
};
|
|
404
|
+
}
|
|
405
|
+
if (report.totals.evalTotal === 0) {
|
|
406
|
+
return {
|
|
407
|
+
ok: false,
|
|
408
|
+
status: "failed",
|
|
409
|
+
enforced: true,
|
|
410
|
+
passRate: null,
|
|
411
|
+
title: "Eval report hard failure",
|
|
412
|
+
message: "no eval cases were reported"
|
|
413
|
+
};
|
|
414
|
+
}
|
|
415
|
+
if (report.status === "failed" && report.totals.failed === 0 && report.failures.length === 0) {
|
|
416
|
+
return {
|
|
417
|
+
ok: false,
|
|
418
|
+
status: "failed",
|
|
419
|
+
enforced: true,
|
|
420
|
+
passRate,
|
|
421
|
+
title: "Eval report hard failure",
|
|
422
|
+
message: `vitest run failed without counted test failures; ${counts}`
|
|
423
|
+
};
|
|
424
|
+
}
|
|
425
|
+
if (minPassRate !== void 0 && (passRate === null || passRate + Number.EPSILON < minPassRate)) {
|
|
426
|
+
return {
|
|
427
|
+
ok: false,
|
|
428
|
+
status: "failed",
|
|
429
|
+
enforced: true,
|
|
430
|
+
passRate,
|
|
431
|
+
title: `Eval pass rate ${formatPercent(passRate)} \u2014 required ${formatPercent(minPassRate)}`,
|
|
432
|
+
message: `eval pass rate below floor: ${counts}; required >= ${formatPercent(minPassRate)}`
|
|
433
|
+
};
|
|
434
|
+
}
|
|
435
|
+
if (minScoreAverage !== void 0) {
|
|
436
|
+
const average = report.score?.average;
|
|
437
|
+
if (average === void 0 || !Number.isFinite(average)) {
|
|
438
|
+
return {
|
|
439
|
+
ok: false,
|
|
440
|
+
status: "failed",
|
|
441
|
+
enforced: true,
|
|
442
|
+
passRate,
|
|
443
|
+
title: "Eval score gate failed",
|
|
444
|
+
message: `no score average available; required avg score >= ${formatScore(minScoreAverage)}`
|
|
445
|
+
};
|
|
446
|
+
}
|
|
447
|
+
if (average + Number.EPSILON < minScoreAverage) {
|
|
448
|
+
return {
|
|
449
|
+
ok: false,
|
|
450
|
+
status: "failed",
|
|
451
|
+
enforced: true,
|
|
452
|
+
passRate,
|
|
453
|
+
title: `Avg score ${formatScore(average)} \u2014 required ${formatScore(minScoreAverage)}`,
|
|
454
|
+
message: `avg score below floor: ${counts}; required avg score >= ${formatScore(minScoreAverage)}`
|
|
455
|
+
};
|
|
456
|
+
}
|
|
457
|
+
}
|
|
458
|
+
return {
|
|
459
|
+
ok: true,
|
|
460
|
+
status: "passed",
|
|
461
|
+
enforced: true,
|
|
462
|
+
passRate,
|
|
463
|
+
title: enforcedPassTitle(report, passRate, minPassRate, minScoreAverage),
|
|
464
|
+
message: `eval gate passed: ${counts}${formatFloorSuffix(minPassRate, minScoreAverage)}`
|
|
465
|
+
};
|
|
466
|
+
}
|
|
467
|
+
function computePassRate(report) {
|
|
468
|
+
if (report.totals.evalTotal <= 0) {
|
|
469
|
+
return null;
|
|
470
|
+
}
|
|
471
|
+
return report.totals.evalPassed / report.totals.evalTotal;
|
|
472
|
+
}
|
|
473
|
+
function formatPercent(value) {
|
|
474
|
+
if (value == null || !Number.isFinite(value)) {
|
|
475
|
+
return "n/a";
|
|
476
|
+
}
|
|
477
|
+
return `${(value * 100).toFixed(1)}%`;
|
|
478
|
+
}
|
|
479
|
+
function renderGateWorkflowCommand(gate) {
|
|
480
|
+
if (gate.ok || !gate.enforced) {
|
|
481
|
+
return void 0;
|
|
482
|
+
}
|
|
483
|
+
return `::error title=${escapeCommandProperty(gate.title)}::${escapeCommandData(gate.message)}`;
|
|
484
|
+
}
|
|
485
|
+
function resolveMinPassRate(policy) {
|
|
486
|
+
const configured = policy.minPassRate;
|
|
487
|
+
if (policy.failOnFailures) {
|
|
488
|
+
if (configured === void 0) {
|
|
489
|
+
return 1;
|
|
490
|
+
}
|
|
491
|
+
return Math.max(configured, 1);
|
|
492
|
+
}
|
|
493
|
+
return configured;
|
|
494
|
+
}
|
|
495
|
+
function defaultCheckTitle(report) {
|
|
496
|
+
if (report.failures.length === 0 && report.status === "passed") {
|
|
497
|
+
return "No eval failures";
|
|
498
|
+
}
|
|
499
|
+
if (report.failures.length === 0) {
|
|
500
|
+
return "Vitest run failed";
|
|
501
|
+
}
|
|
502
|
+
return `${report.failures.length} eval failure${report.failures.length === 1 ? "" : "s"}`;
|
|
503
|
+
}
|
|
504
|
+
function enforcedPassTitle(report, passRate, minPassRate, minScoreAverage) {
|
|
505
|
+
if (minPassRate !== void 0) {
|
|
506
|
+
return `Eval pass rate ${formatPercent(passRate)} \u2014 floor ${formatPercent(minPassRate)}`;
|
|
507
|
+
}
|
|
508
|
+
if (minScoreAverage !== void 0) {
|
|
509
|
+
return `Avg score ${formatScore(report.score?.average)} \u2014 floor ${formatScore(minScoreAverage)}`;
|
|
510
|
+
}
|
|
511
|
+
return defaultCheckTitle(report);
|
|
512
|
+
}
|
|
513
|
+
function formatEvalCounts(report, passRate) {
|
|
514
|
+
const scoreText = report.score?.average === void 0 ? "n/a" : formatScore(report.score.average);
|
|
515
|
+
const passRateText = passRate === null ? "n/a" : formatPercent(passRate);
|
|
516
|
+
return `${formatNumber(report.totals.evalPassed)}/${formatNumber(
|
|
517
|
+
report.totals.evalTotal
|
|
518
|
+
)} passed (${passRateText}), avg score ${scoreText}`;
|
|
519
|
+
}
|
|
520
|
+
function formatFloorSuffix(minPassRate, minScoreAverage) {
|
|
521
|
+
const parts = [];
|
|
522
|
+
if (minPassRate !== void 0) {
|
|
523
|
+
parts.push(`pass rate floor ${formatPercent(minPassRate)}`);
|
|
524
|
+
}
|
|
525
|
+
if (minScoreAverage !== void 0) {
|
|
526
|
+
parts.push(`avg score floor ${formatScore(minScoreAverage)}`);
|
|
527
|
+
}
|
|
528
|
+
return parts.length === 0 ? "" : `; ${parts.join(", ")}`;
|
|
529
|
+
}
|
|
530
|
+
|
|
365
531
|
// src/summary.ts
|
|
366
532
|
var DEFAULT_MAX_FAILURES = 20;
|
|
367
533
|
var DEFAULT_MAX_REASON_CHARS = 8e3;
|
|
@@ -382,20 +548,22 @@ function renderJobSummary(report, options = {}) {
|
|
|
382
548
|
const lines = [
|
|
383
549
|
"# vitest-evals",
|
|
384
550
|
"",
|
|
385
|
-
...renderSummaryTable(report, nonEvalFailures),
|
|
551
|
+
...renderSummaryTable(report, nonEvalFailures, options.gate),
|
|
386
552
|
"",
|
|
387
553
|
...renderScoreDistribution(report),
|
|
388
554
|
"## Results",
|
|
389
555
|
""
|
|
390
556
|
];
|
|
391
557
|
if (report.failures.length > 0) {
|
|
392
|
-
|
|
558
|
+
const failureHeading = options.gate?.ok === true ? "### Quality Misses" : "### Failures";
|
|
559
|
+
lines.push(failureHeading, "");
|
|
393
560
|
failures.forEach((testCase, index) => {
|
|
394
561
|
lines.push(...renderFailureDetails(testCase, index + 1, options), "");
|
|
395
562
|
});
|
|
396
563
|
if (report.failures.length > failures.length) {
|
|
564
|
+
const omittedLabel = options.gate?.ok === true ? "quality misses" : "failures";
|
|
397
565
|
lines.push(
|
|
398
|
-
`${report.failures.length - failures.length} more
|
|
566
|
+
`${report.failures.length - failures.length} more ${omittedLabel} omitted from this summary.`,
|
|
399
567
|
""
|
|
400
568
|
);
|
|
401
569
|
}
|
|
@@ -411,9 +579,9 @@ function renderJobSummary(report, options = {}) {
|
|
|
411
579
|
function formatCountLine(passed, failed, total) {
|
|
412
580
|
return `${formatNumber(passed)} passed, ${formatNumber(failed)} failed, ${formatNumber(total)} total`;
|
|
413
581
|
}
|
|
414
|
-
function renderSummaryTable(report, nonEvalFailures) {
|
|
582
|
+
function renderSummaryTable(report, nonEvalFailures, gate) {
|
|
415
583
|
const rows = [
|
|
416
|
-
["Status", report.status],
|
|
584
|
+
["Status", gate?.status ?? report.status],
|
|
417
585
|
[
|
|
418
586
|
"Evals",
|
|
419
587
|
formatCountLine(
|
|
@@ -423,9 +591,20 @@ function renderSummaryTable(report, nonEvalFailures) {
|
|
|
423
591
|
)
|
|
424
592
|
]
|
|
425
593
|
];
|
|
594
|
+
if (gate?.passRate !== void 0 && gate.passRate !== null) {
|
|
595
|
+
rows.push(["Pass Rate", formatPercent(gate.passRate)]);
|
|
596
|
+
} else if (report.totals.evalTotal > 0) {
|
|
597
|
+
rows.push([
|
|
598
|
+
"Pass Rate",
|
|
599
|
+
formatPercent(report.totals.evalPassed / report.totals.evalTotal)
|
|
600
|
+
]);
|
|
601
|
+
}
|
|
426
602
|
if (report.score) {
|
|
427
603
|
rows.push(["Score", formatScoreSummary(report.score)]);
|
|
428
604
|
}
|
|
605
|
+
if (gate?.enforced) {
|
|
606
|
+
rows.push(["Gate", gate.message]);
|
|
607
|
+
}
|
|
429
608
|
if (nonEvalFailures > 0) {
|
|
430
609
|
rows.push([
|
|
431
610
|
"Other Failures",
|
|
@@ -702,23 +881,25 @@ async function publishCheckRun(report, options = {}) {
|
|
|
702
881
|
};
|
|
703
882
|
}
|
|
704
883
|
function buildCheckRunPayload(report, options) {
|
|
884
|
+
const gate = options.gate ?? evaluateEvalGate(report);
|
|
705
885
|
const annotations = buildCheckAnnotations(report, {
|
|
706
|
-
maxAnnotations: options.maxAnnotations
|
|
886
|
+
maxAnnotations: options.maxAnnotations,
|
|
887
|
+
gate
|
|
707
888
|
});
|
|
708
|
-
const title = report.failures.length === 0 && report.status === "passed" ? "No eval failures" : report.failures.length === 0 ? "Vitest run failed" : `${report.failures.length} eval failure${report.failures.length === 1 ? "" : "s"}`;
|
|
709
889
|
return {
|
|
710
890
|
status: "completed",
|
|
711
|
-
conclusion:
|
|
891
|
+
conclusion: gate.ok ? "success" : "failure",
|
|
712
892
|
completed_at: (/* @__PURE__ */ new Date()).toISOString(),
|
|
713
893
|
output: {
|
|
714
|
-
title,
|
|
894
|
+
title: gate.title,
|
|
715
895
|
summary: truncateCheckSummary(
|
|
716
896
|
renderJobSummary(report, {
|
|
717
897
|
...options,
|
|
718
898
|
maxFailures: options.maxFailures ?? 5,
|
|
719
899
|
maxReasonChars: options.maxReasonChars ?? 4e3,
|
|
720
900
|
maxOutputChars: options.maxOutputChars ?? 2e3,
|
|
721
|
-
maxToolCalls: options.maxToolCalls ?? 10
|
|
901
|
+
maxToolCalls: options.maxToolCalls ?? 10,
|
|
902
|
+
gate
|
|
722
903
|
})
|
|
723
904
|
),
|
|
724
905
|
annotations
|
|
@@ -731,10 +912,175 @@ function truncateCheckSummary(summary) {
|
|
|
731
912
|
}
|
|
732
913
|
return `${summary.slice(0, MAX_CHECK_SUMMARY_LENGTH - CHECK_SUMMARY_TRUNCATION_SUFFIX.length).trimEnd()}${CHECK_SUMMARY_TRUNCATION_SUFFIX}`;
|
|
733
914
|
}
|
|
915
|
+
|
|
916
|
+
// src/report.ts
|
|
917
|
+
import { appendFile } from "fs/promises";
|
|
918
|
+
import {
|
|
919
|
+
readVitestJsonReportFile,
|
|
920
|
+
resolveResultFiles
|
|
921
|
+
} from "@vitest-evals/core/node";
|
|
922
|
+
|
|
923
|
+
// src/merge.ts
|
|
924
|
+
function mergeEvalReports(reports) {
|
|
925
|
+
const cases = reports.flatMap((report) => report.cases);
|
|
926
|
+
const failures = reports.flatMap((report) => report.failures);
|
|
927
|
+
const scoredCases = cases.map((testCase) => testCase.eval?.avgScore).filter(
|
|
928
|
+
(score) => typeof score === "number" && Number.isFinite(score)
|
|
929
|
+
);
|
|
930
|
+
const startedAtValues = reports.map((report) => report.startedAt).filter(
|
|
931
|
+
(startedAt2) => typeof startedAt2 === "number" && Number.isFinite(startedAt2)
|
|
932
|
+
);
|
|
933
|
+
const startedAt = startedAtValues.length > 0 ? Math.min(...startedAtValues) : void 0;
|
|
934
|
+
return {
|
|
935
|
+
status: reports.some((report) => report.status === "failed") ? "failed" : "passed",
|
|
936
|
+
startedAt,
|
|
937
|
+
durationMs: mergeDuration(reports),
|
|
938
|
+
totals: {
|
|
939
|
+
total: sum(reports, (report) => report.totals.total),
|
|
940
|
+
passed: sum(reports, (report) => report.totals.passed),
|
|
941
|
+
failed: sum(reports, (report) => report.totals.failed),
|
|
942
|
+
skipped: sum(reports, (report) => report.totals.skipped),
|
|
943
|
+
evalTotal: sum(reports, (report) => report.totals.evalTotal),
|
|
944
|
+
evalPassed: sum(reports, (report) => report.totals.evalPassed),
|
|
945
|
+
evalFailed: sum(reports, (report) => report.totals.evalFailed)
|
|
946
|
+
},
|
|
947
|
+
score: scoredCases.length > 0 ? {
|
|
948
|
+
average: scoredCases.reduce((total, score) => total + score, 0) / scoredCases.length,
|
|
949
|
+
minimum: Math.min(...scoredCases)
|
|
950
|
+
} : void 0,
|
|
951
|
+
usage: mergeUsage(reports.map((report) => report.usage)),
|
|
952
|
+
cases,
|
|
953
|
+
failures
|
|
954
|
+
};
|
|
955
|
+
}
|
|
956
|
+
function mergeUsage(usages) {
|
|
957
|
+
return {
|
|
958
|
+
inputTokens: sum(usages, (usage) => usage.inputTokens),
|
|
959
|
+
outputTokens: sum(usages, (usage) => usage.outputTokens),
|
|
960
|
+
reasoningTokens: sum(usages, (usage) => usage.reasoningTokens),
|
|
961
|
+
totalTokens: sum(usages, (usage) => usage.totalTokens),
|
|
962
|
+
toolCalls: sum(usages, (usage) => usage.toolCalls)
|
|
963
|
+
};
|
|
964
|
+
}
|
|
965
|
+
function mergeDuration(reports) {
|
|
966
|
+
const durations = reports.map((report) => report.durationMs).filter(
|
|
967
|
+
(durationMs) => typeof durationMs === "number" && Number.isFinite(durationMs)
|
|
968
|
+
);
|
|
969
|
+
const intervals = reports.map((report) => {
|
|
970
|
+
if (typeof report.startedAt !== "number" || !Number.isFinite(report.startedAt) || typeof report.durationMs !== "number" || !Number.isFinite(report.durationMs)) {
|
|
971
|
+
return void 0;
|
|
972
|
+
}
|
|
973
|
+
return {
|
|
974
|
+
start: report.startedAt,
|
|
975
|
+
end: report.startedAt + report.durationMs
|
|
976
|
+
};
|
|
977
|
+
}).filter(
|
|
978
|
+
(interval) => Boolean(interval)
|
|
979
|
+
);
|
|
980
|
+
if (intervals.length > 0 && intervals.length === durations.length) {
|
|
981
|
+
return Math.max(...intervals.map((interval) => interval.end)) - Math.min(...intervals.map((interval) => interval.start));
|
|
982
|
+
}
|
|
983
|
+
return durations.length > 0 ? durations.reduce((total, durationMs) => total + durationMs, 0) : void 0;
|
|
984
|
+
}
|
|
985
|
+
function sum(items, select) {
|
|
986
|
+
return items.reduce((total, item) => total + select(item), 0);
|
|
987
|
+
}
|
|
988
|
+
|
|
989
|
+
// src/report.ts
|
|
990
|
+
async function publishEvalReport(options) {
|
|
991
|
+
const resultFiles = await resolveResultFiles(options.resultPatterns, {
|
|
992
|
+
cwd: options.cwd
|
|
993
|
+
});
|
|
994
|
+
if (resultFiles.length === 0) {
|
|
995
|
+
throw new Error(
|
|
996
|
+
`No eval result files matched: ${options.resultPatterns.join(", ")}`
|
|
997
|
+
);
|
|
998
|
+
}
|
|
999
|
+
const reports = await Promise.all(
|
|
1000
|
+
resultFiles.map(async (resultFile) => {
|
|
1001
|
+
const json = await readVitestJsonReportFile(resultFile);
|
|
1002
|
+
return collectEvalReport(json, {
|
|
1003
|
+
workspace: options.workspace
|
|
1004
|
+
});
|
|
1005
|
+
})
|
|
1006
|
+
);
|
|
1007
|
+
const report = mergeEvalReports(reports);
|
|
1008
|
+
const gate = evaluateEvalGate(report, {
|
|
1009
|
+
failOnFailures: options.failOnFailures,
|
|
1010
|
+
minPassRate: options.minPassRate,
|
|
1011
|
+
minScoreAverage: options.minScoreAverage
|
|
1012
|
+
});
|
|
1013
|
+
const summary = renderJobSummary(report, {
|
|
1014
|
+
maxFailures: options.maxFailures,
|
|
1015
|
+
maxOutputChars: options.maxOutputChars,
|
|
1016
|
+
maxReasonChars: options.maxReasonChars,
|
|
1017
|
+
maxToolCalls: options.maxToolCalls,
|
|
1018
|
+
gate
|
|
1019
|
+
});
|
|
1020
|
+
if (options.summaryEnabled !== false) {
|
|
1021
|
+
if (options.summaryPath) {
|
|
1022
|
+
await appendFile(options.summaryPath, `${summary}
|
|
1023
|
+
`);
|
|
1024
|
+
} else {
|
|
1025
|
+
console.log(summary);
|
|
1026
|
+
}
|
|
1027
|
+
}
|
|
1028
|
+
if (options.annotations) {
|
|
1029
|
+
const gateCommand = renderGateWorkflowCommand(gate);
|
|
1030
|
+
if (gateCommand) {
|
|
1031
|
+
console.log(gateCommand);
|
|
1032
|
+
}
|
|
1033
|
+
for (const command of renderWorkflowCommands(report, {
|
|
1034
|
+
maxAnnotations: options.maxAnnotations,
|
|
1035
|
+
gate
|
|
1036
|
+
})) {
|
|
1037
|
+
console.log(command);
|
|
1038
|
+
}
|
|
1039
|
+
}
|
|
1040
|
+
let checkRun;
|
|
1041
|
+
if (options.checkRun) {
|
|
1042
|
+
try {
|
|
1043
|
+
checkRun = await publishCheckRun(report, {
|
|
1044
|
+
checkRunId: options.checkRunId,
|
|
1045
|
+
maxAnnotations: options.maxAnnotations,
|
|
1046
|
+
maxFailures: options.maxFailures,
|
|
1047
|
+
maxOutputChars: options.maxOutputChars,
|
|
1048
|
+
maxReasonChars: options.maxReasonChars,
|
|
1049
|
+
maxToolCalls: options.maxToolCalls,
|
|
1050
|
+
name: options.checkName,
|
|
1051
|
+
repository: options.repository,
|
|
1052
|
+
sha: options.sha,
|
|
1053
|
+
token: options.token,
|
|
1054
|
+
gate
|
|
1055
|
+
});
|
|
1056
|
+
if (checkRun.status === "skipped") {
|
|
1057
|
+
options.warn?.(`GitHub Check Run skipped: ${checkRun.reason}`);
|
|
1058
|
+
}
|
|
1059
|
+
} catch (error) {
|
|
1060
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
1061
|
+
if (options.failOnCheckError) {
|
|
1062
|
+
throw error;
|
|
1063
|
+
}
|
|
1064
|
+
options.warn?.(message);
|
|
1065
|
+
}
|
|
1066
|
+
}
|
|
1067
|
+
return {
|
|
1068
|
+
report,
|
|
1069
|
+
resultFiles,
|
|
1070
|
+
gate,
|
|
1071
|
+
shouldFail: gate.enforced && !gate.ok,
|
|
1072
|
+
checkRun
|
|
1073
|
+
};
|
|
1074
|
+
}
|
|
734
1075
|
export {
|
|
735
1076
|
buildCheckAnnotations,
|
|
736
1077
|
collectEvalReport,
|
|
1078
|
+
computePassRate,
|
|
1079
|
+
evaluateEvalGate,
|
|
1080
|
+
formatPercent,
|
|
737
1081
|
publishCheckRun,
|
|
1082
|
+
publishEvalReport,
|
|
1083
|
+
renderGateWorkflowCommand,
|
|
738
1084
|
renderJobSummary,
|
|
739
1085
|
renderWorkflowCommands
|
|
740
1086
|
};
|