新增 release gate execution summary API
This commit is contained in:
@@ -3,6 +3,7 @@ export { createLinuxCncInterpSdk } from "./linuxcnc-interp.js";
|
||||
export {
|
||||
createProjectReleaseGateActionPlan,
|
||||
createProjectReleaseGateExecutionManifest,
|
||||
createProjectReleaseGateExecutionSummaryViewModel,
|
||||
createProjectReleaseGateManifest,
|
||||
createProjectReleaseGateResultMatrix,
|
||||
createProjectReleaseReadinessArtifactJsonWorkflow,
|
||||
|
||||
@@ -176,6 +176,81 @@ export function createProjectReleaseGateExecutionManifest({
|
||||
};
|
||||
}
|
||||
|
||||
export function createProjectReleaseGateExecutionSummaryViewModel(
|
||||
executionManifest = createProjectReleaseGateExecutionManifest(),
|
||||
) {
|
||||
const rows = arrayOrEmpty(executionManifest?.rows);
|
||||
const ready = executionManifest?.ready === true;
|
||||
const missingGateIds = arrayOrEmpty(executionManifest?.missingGateIds);
|
||||
const statusText = ready ? "Ready" : "Waiting";
|
||||
const detailText = ready
|
||||
? "All release gate evidence present"
|
||||
: (missingGateIds.length > 0 ? missingGateIds.join(", ") : "release gate evidence missing");
|
||||
const evidenceCounts = rows.reduce((counts, row) => ({
|
||||
...counts,
|
||||
[row.evidence ?? "missing"]: (counts[row.evidence ?? "missing"] ?? 0) + 1,
|
||||
}), {});
|
||||
|
||||
return {
|
||||
apiName: "project-release-gate-execution-summary-view-model",
|
||||
viewModelVersion: 1,
|
||||
phase: ready ? "ready" : "waiting",
|
||||
ready,
|
||||
title: "Project release gate execution",
|
||||
statusText,
|
||||
detailText,
|
||||
statusLine: `${statusText}: ${detailText}`,
|
||||
gateCount: executionManifest?.gateCount ?? rows.length,
|
||||
passedCount: executionManifest?.passedCount ?? rows.filter(({ passed }) => passed === true).length,
|
||||
unknownCount: executionManifest?.unknownCount ?? rows.filter(({ passed }) => passed !== true).length,
|
||||
missingGateIds,
|
||||
nextGateId: missingGateIds[0] ?? null,
|
||||
evidenceCounts,
|
||||
rows: [
|
||||
{
|
||||
id: "gate-results",
|
||||
label: "Release gate evidence",
|
||||
value: `${executionManifest?.passedCount ?? 0}/${executionManifest?.gateCount ?? rows.length} passed`,
|
||||
},
|
||||
{
|
||||
id: "unknown-gates",
|
||||
label: "Unknown gates",
|
||||
value: `${executionManifest?.unknownCount ?? 0}`,
|
||||
},
|
||||
{
|
||||
id: "next-gate",
|
||||
label: "Next gate",
|
||||
value: missingGateIds[0] ?? "none",
|
||||
},
|
||||
{
|
||||
id: "expected-output-evidence",
|
||||
label: "Expected-output evidence",
|
||||
value: `${evidenceCounts["expected-output"] ?? 0}`,
|
||||
},
|
||||
{
|
||||
id: "explicit-result-evidence",
|
||||
label: "Explicit-result evidence",
|
||||
value: `${evidenceCounts["explicit-result"] ?? 0}`,
|
||||
},
|
||||
{
|
||||
id: "missing",
|
||||
label: "Missing gate evidence",
|
||||
value: missingGateIds.length > 0 ? missingGateIds.join(", ") : "none",
|
||||
},
|
||||
],
|
||||
gateRows: rows.map((row) => ({
|
||||
id: row.id,
|
||||
label: row.label,
|
||||
command: row.command,
|
||||
expectedOutput: row.expectedOutput ?? null,
|
||||
observedOutput: row.observedOutput ?? null,
|
||||
evidence: row.evidence ?? "missing",
|
||||
status: row.status ?? (row.passed === true ? "passed" : "unknown"),
|
||||
passed: row.passed === true,
|
||||
})),
|
||||
};
|
||||
}
|
||||
|
||||
export function createProjectReleaseGateResultMatrix({
|
||||
gateResults = {},
|
||||
observedOutputs = [],
|
||||
@@ -274,6 +349,9 @@ export function createProjectReleaseReadinessReport({
|
||||
observedOutputs,
|
||||
manifest: gateManifest,
|
||||
});
|
||||
const gateExecutionSummaryViewModel = createProjectReleaseGateExecutionSummaryViewModel(
|
||||
gateExecutionManifest,
|
||||
);
|
||||
const gateResultMatrix = createProjectReleaseGateResultMatrix({
|
||||
gateResults,
|
||||
observedOutputs,
|
||||
@@ -318,6 +396,7 @@ export function createProjectReleaseReadinessReport({
|
||||
promotedBlockedFamilies,
|
||||
gateManifest,
|
||||
gateExecutionManifest,
|
||||
gateExecutionSummaryViewModel,
|
||||
gateResultMatrix,
|
||||
gateActionPlan,
|
||||
gates: gateRows,
|
||||
@@ -432,6 +511,11 @@ export function createProjectReleaseReadinessArtifactValidationSummaryViewModel(
|
||||
label: "Gate execution manifest",
|
||||
value: validation?.gateExecutionManifestReady === true ? "ready" : "missing",
|
||||
},
|
||||
{
|
||||
id: "gate-execution-summary",
|
||||
label: "Gate execution summary",
|
||||
value: validation?.gateExecutionSummaryReady === true ? "ready" : "missing",
|
||||
},
|
||||
{
|
||||
id: "gate-result-matrix",
|
||||
label: "Gate result matrix",
|
||||
@@ -889,6 +973,7 @@ export function createProjectReleaseReadinessArtifactValidation(artifact = {}) {
|
||||
const simConfigInventory = objectOrEmpty(artifactObject.simConfigInventory);
|
||||
const gateManifest = objectOrEmpty(artifactObject.gateManifest);
|
||||
const gateExecutionManifest = objectOrEmpty(artifactObject.gateExecutionManifest);
|
||||
const gateExecutionSummaryViewModel = objectOrEmpty(artifactObject.gateExecutionSummaryViewModel);
|
||||
const gateResultMatrix = objectOrEmpty(artifactObject.gateResultMatrix);
|
||||
const gateActionPlan = objectOrEmpty(artifactObject.gateActionPlan);
|
||||
const gates = arrayOrEmpty(artifactObject.gates);
|
||||
@@ -917,6 +1002,13 @@ export function createProjectReleaseReadinessArtifactValidation(artifact = {}) {
|
||||
&& gateExecutionManifest.unknownCount === 0
|
||||
&& executionRows.length === REQUIRED_RELEASE_GATES.length
|
||||
&& executionRows.every(({ command, status }) => typeof command === "string" && status === "passed");
|
||||
const executionSummaryReady = gateExecutionSummaryViewModel.apiName === "project-release-gate-execution-summary-view-model"
|
||||
&& gateExecutionSummaryViewModel.viewModelVersion === 1
|
||||
&& gateExecutionSummaryViewModel.ready === true
|
||||
&& gateExecutionSummaryViewModel.passedCount === REQUIRED_RELEASE_GATES.length
|
||||
&& gateExecutionSummaryViewModel.unknownCount === 0
|
||||
&& gateExecutionSummaryViewModel.nextGateId === null
|
||||
&& arrayOrEmpty(gateExecutionSummaryViewModel.gateRows).length === REQUIRED_RELEASE_GATES.length;
|
||||
const actionPlanReady = gateActionPlan.apiName === "project-release-gate-action-plan"
|
||||
&& gateActionPlan.planVersion === 1
|
||||
&& gateActionPlan.ready === true
|
||||
@@ -942,6 +1034,7 @@ export function createProjectReleaseReadinessArtifactValidation(artifact = {}) {
|
||||
...(arrayOrEmpty(artifactObject.promotedBlockedFamilies).length === 0 ? [] : ["promotedBlockedFamilies"]),
|
||||
...(manifestReady ? [] : ["gateManifest"]),
|
||||
...(executionManifestReady ? [] : ["gateExecutionManifest"]),
|
||||
...(executionSummaryReady ? [] : ["gateExecutionSummaryViewModel"]),
|
||||
...(matrixReady ? [] : ["gateResultMatrix"]),
|
||||
...(actionPlanReady ? [] : ["gateActionPlan"]),
|
||||
...(gateCountReady ? [] : ["gates.length"]),
|
||||
@@ -964,6 +1057,7 @@ export function createProjectReleaseReadinessArtifactValidation(artifact = {}) {
|
||||
expectedGateIds,
|
||||
gateManifestReady: manifestReady,
|
||||
gateExecutionManifestReady: executionManifestReady,
|
||||
gateExecutionSummaryReady: executionSummaryReady,
|
||||
gateResultMatrixReady: matrixReady,
|
||||
gateActionPlanReady: actionPlanReady,
|
||||
blockedRuntimeFamilies: arrayOrEmpty(artifactObject.blockedRuntimeFamilies),
|
||||
@@ -988,6 +1082,11 @@ export function createProjectReleaseReadinessArtifactValidation(artifact = {}) {
|
||||
label: "Gate execution manifest",
|
||||
value: executionManifestReady ? "ready" : "missing",
|
||||
},
|
||||
{
|
||||
id: "gate-execution-summary",
|
||||
label: "Gate execution summary",
|
||||
value: executionSummaryReady ? "ready" : "missing",
|
||||
},
|
||||
{
|
||||
id: "gate-result-matrix",
|
||||
label: "Gate result matrix",
|
||||
|
||||
Reference in New Issue
Block a user