Adds an "advisory" `gateMode` option for workflow steps: steps in advisory mode log findings but no longer block merge completion, while steps that must block can still be configured as blocking. The change covers the workflow step types and schema, executor gating logic, dashboard UI in WorkflowSte Fusion-Task-Id: FN-4468
89 lines
2.5 KiB
TypeScript
89 lines
2.5 KiB
TypeScript
import type { Task, WorkflowStepResult, WorkflowStepPhase, StepStatus } from "@fusion/core";
|
|
|
|
export type UnifiedTaskProgressStatus = StepStatus | "failed";
|
|
|
|
export interface UnifiedTaskProgressItem {
|
|
id: string;
|
|
name: string;
|
|
status: UnifiedTaskProgressStatus;
|
|
source: "step" | "workflow";
|
|
phase: WorkflowStepPhase;
|
|
}
|
|
|
|
export interface UnifiedTaskProgress {
|
|
total: number;
|
|
completed: number;
|
|
items: UnifiedTaskProgressItem[];
|
|
}
|
|
|
|
function mapWorkflowStatus(status: WorkflowStepResult["status"]): UnifiedTaskProgressStatus {
|
|
switch (status) {
|
|
case "passed":
|
|
return "done";
|
|
case "failed":
|
|
case "advisory_failure":
|
|
return "failed";
|
|
case "skipped":
|
|
return "skipped";
|
|
case "pending":
|
|
default:
|
|
return "pending";
|
|
}
|
|
}
|
|
|
|
function isCompleted(status: UnifiedTaskProgressStatus): boolean {
|
|
return status === "done" || status === "skipped";
|
|
}
|
|
|
|
function resolveWorkflowStepName(
|
|
workflowStepId: string,
|
|
result: WorkflowStepResult | undefined,
|
|
workflowStepNameLookup?: ReadonlyMap<string, string>,
|
|
): string {
|
|
const lookupName = workflowStepNameLookup?.get(workflowStepId)?.trim();
|
|
if (lookupName) {
|
|
return lookupName;
|
|
}
|
|
|
|
const resultName = result?.workflowStepName?.trim();
|
|
if (resultName) {
|
|
return resultName;
|
|
}
|
|
|
|
return workflowStepId;
|
|
}
|
|
|
|
export function getUnifiedTaskProgress(
|
|
task: Pick<Task, "steps" | "enabledWorkflowSteps" | "workflowStepResults">,
|
|
workflowStepNameLookup?: ReadonlyMap<string, string>,
|
|
): UnifiedTaskProgress {
|
|
const stepItems: UnifiedTaskProgressItem[] = (task.steps ?? []).map((step, index) => ({
|
|
id: `step-${index}`,
|
|
name: step.name,
|
|
status: step.status,
|
|
source: "step",
|
|
phase: "pre-merge",
|
|
}));
|
|
|
|
const workflowResultsById = new Map(
|
|
(task.workflowStepResults ?? []).map((result) => [result.workflowStepId, result] as const),
|
|
);
|
|
|
|
const workflowItems: UnifiedTaskProgressItem[] = (task.enabledWorkflowSteps ?? []).map((workflowStepId) => {
|
|
const result = workflowResultsById.get(workflowStepId);
|
|
return {
|
|
id: `workflow-${workflowStepId}`,
|
|
name: resolveWorkflowStepName(workflowStepId, result, workflowStepNameLookup),
|
|
status: result ? mapWorkflowStatus(result.status) : "pending",
|
|
source: "workflow",
|
|
phase: result?.phase ?? "pre-merge",
|
|
};
|
|
});
|
|
|
|
const items = [...stepItems, ...workflowItems];
|
|
const total = items.length;
|
|
const completed = items.filter((item) => isCompleted(item.status)).length;
|
|
|
|
return { total, completed, items };
|
|
}
|