core/reporters/stage.reporter.ts
core/reporters/stage.reporter.ts is a file in GovLab Pipeline. 94 lines of code and 13 definitions.
import type { AbortInfo, HeaderInfo, ReportRow, Unit } from "#types/stage.types";
import {
FAIL_MARK,
PASS_MARK,
REPORT_TABLE_DIVIDER,
REPORT_TABLE_HEAD,
allPassed,
bypassNote,
bypassedStage,
commandLine,
countNote,
exitMark,
exitNote,
failedOutputDivider,
failedTitle,
headerLine,
notRunLine,
reportTitle,
scopeNote,
someFailed,
stageHeading,
tableRow,
totalsLine,
} from "#configuration/strings/stage.strings";
import { C } from "#configuration/constants/shell.constants";
import { NUMBER_LOCALE } from "#configuration/constants/stage.constants";
import process from "node:process";
import { seconds } from "#core/formatters/stage.formatter";
import { tallyByStage } from "#core/converters/report.converter";
export const line = function line(text = ""): void {
process.stdout.write(`${text}\n`);
};
export const printOutput = function printOutput(out: string): void {
process.stdout.write(out.endsWith("\n") ? out : `${out}\n`);
};
export const printStageHeading = function printStageHeading(unit: Unit): void {
if (unit.firstInStage) {
line(`${C.bold}${C.cyan}${stageHeading(unit.stage.label, unit.stage.slug)}${C.reset}`);
}
};
export const abort = function abort(info: AbortInfo): never {
line(
`\n${C.bold}${C.red}${FAIL_MARK} ${failedTitle(info.label)}${C.reset} ${info.tag} ${info.stepLabel} ${C.dim}${exitNote(info.elapsed, info.status)}${C.reset}`,
);
line(`${C.dim}${commandLine(info.command)}${C.reset}`);
line(`${C.dim}${notRunLine(info.notRun)}${C.reset}\n`);
process.exit(info.status);
};
const scopeNoteOf = function scopeNoteOf(scope: readonly string[]): string {
return scope.length > 0 ? `${C.yellow}${scopeNote(scope)}${C.reset}` : "";
};
export const printHeader = function printHeader(info: HeaderInfo): void {
line(
`${C.bold}${C.cyan}${headerLine(info.label, info.total, info.activeCount)}${C.reset}${bypassNote(info.bypassed.length)}${scopeNoteOf(info.scope)}\n`,
);
for (const stage of info.bypassed) {
line(`${C.dim}${bypassedStage(stage.label, stage.slug)}${C.reset}`);
}
if (info.bypassed.length > 0) {
line();
}
};
const countTag = function countTag(row: ReportRow): string {
return row.count === null ? "" : ` ${C.dim}${countNote(row.count)}${C.reset}`;
};
export const reportLine = function reportLine(prefix: string, row: ReportRow): void {
const mark = row.code === 0 ? `${C.green}${PASS_MARK}${C.reset}` : `${C.red}${exitMark(row.code)}${C.reset}`;
line(`${prefix}${mark} ${row.label}${countTag(row)}`);
};
export const printReportSummary = function printReportSummary(
rows: readonly ReportRow[],
label: string,
startedAll: number,
): void {
line(`\n${C.bold}${C.cyan}${reportTitle(label)}${C.reset}\n`);
line(REPORT_TABLE_HEAD);
line(REPORT_TABLE_DIVIDER);
for (const [stage, entry] of tallyByStage(rows)) {
line(tableRow(stage, entry.passed, entry.failed, entry.violations.toLocaleString(NUMBER_LOCALE)));
}
const totalViolations = rows.reduce((sum, row) => sum + (row.count ?? 0), 0);
const failed = rows.filter((row) => row.code !== 0);
const verdict =
failed.length === 0
? `${C.green}${allPassed(rows.length)}`
: `${C.red}${someFailed(failed.length, rows.length)}`;
line(
`\n${C.bold}${verdict}${C.reset}: ${totalsLine(totalViolations.toLocaleString(NUMBER_LOCALE), seconds(startedAll))}`,
);
for (const row of failed) {
line(`\n${C.dim}${failedOutputDivider(row.stage, row.label, row.code)}${C.reset}`);
printOutput(row.out);
}
};