core/coordinators/report.coordinator.ts
core/coordinators/report.coordinator.ts is a file in GovLab Pipeline. 65 lines of code and 13 definitions.
import type { ActiveRun, ParallelStep, ReportRow, Unit } from "#types/stage.types";
import { C, FALLBACK_EXIT } from "#configuration/constants/shell.constants";
import { buildArtifact, outputOf, rowOf, rowsOf } from "#core/converters/report.converter";
import { line, printReportSummary, printStageHeading, reportLine } from "#core/reporters/stage.reporter";
import { reportWritten, violationsWritten } from "#configuration/strings/stage.strings";
import { buildViolations } from "#core/converters/violation.converter";
import process from "node:process";
import { runCaptured } from "#core/adapters/shell.adapter";
export const recordRow = function recordRow(run: ActiveRun, row: ReportRow): void {
run.store.collect(outputOf(row));
};
export const flushViolations = async function flushViolations(run: ActiveRun, stoppedAt: string | null): Promise<void> {
const { violationsPath, writeReport } = run.context.options;
if (writeReport === undefined || typeof violationsPath !== "string") {
return;
}
const artifact = buildViolations(run.store.outputs(), run.label, stoppedAt, new Date().toISOString());
await writeReport(violationsPath, artifact);
line(`${C.dim}${violationsWritten(artifact.totals.violations, artifact.totals.files, violationsPath)}${C.reset}`);
};
export const flushReports = async function flushReports(run: ActiveRun, stoppedAt: string | null): Promise<void> {
const { reportPath, writeReport } = run.context.options;
if (writeReport !== undefined && typeof reportPath === "string") {
const rows = rowsOf(run.store.outputs());
await writeReport(reportPath, buildArtifact(rows, run.label));
}
await flushViolations(run, stoppedAt);
};
const reportSub = async function reportSub(run: ActiveRun, stage: string, sub: ParallelStep): Promise<ReportRow> {
const row = rowOf(stage, sub.label, await runCaptured(run.context.shell, sub.run, sub.cwd));
recordRow(run, row);
reportLine(" ", row);
return row;
};
const reportUnit = async function reportUnit(run: ActiveRun, unit: Unit): Promise<ReportRow[]> {
printStageHeading(unit);
if (unit.step.parallel) {
return Promise.all(unit.step.parallel.map(async (sub) => reportSub(run, unit.stage.label, sub)));
}
const outcome = await runCaptured(run.context.shell, unit.step.run ?? "", unit.step.cwd);
const row = rowOf(unit.stage.label, unit.step.label ?? "", outcome);
recordRow(run, row);
reportLine("", row);
return [row];
};
export const runReport = async function runReport(
run: ActiveRun,
units: readonly Unit[],
startedAll: number,
): Promise<void> {
const rows = await units.reduce<Promise<ReportRow[]>>(async (prev, unit) => {
const acc = await prev;
return [...acc, ...(await reportUnit(run, unit))];
}, Promise.resolve([]));
printReportSummary(rows, run.label, startedAll);
const { reportPath, writeReport } = run.context.options;
if (typeof reportPath === "string" && writeReport !== undefined) {
await writeReport(reportPath, buildArtifact(rows, run.label));
line(`${C.dim}${reportWritten(reportPath)}${C.reset}`);
}
await flushViolations(run, null);
if (rows.some((row) => row.code !== 0)) {
process.exitCode = FALLBACK_EXIT;
}
};