fix: prioritize follower taskrun visibility
This commit is contained in:
@@ -0,0 +1,74 @@
|
||||
// SPEC: PJ2026-01060703 CI/CD TaskRun summaries.
|
||||
// Responsibility: shared bounded TaskRun prioritization for branch-follower status/debug visibility.
|
||||
|
||||
export type TaskRunMode = "failed" | "active" | "slow";
|
||||
|
||||
export function taskRunItems(taskRuns: Record<string, unknown>, mode: TaskRunMode, limit = 5): Record<string, unknown>[] {
|
||||
const explicit = mode === "failed" ? taskRuns.failedItems : mode === "active" ? taskRuns.activeItems : taskRuns.slowItems;
|
||||
const explicitItems = arrayRecords(explicit);
|
||||
if (explicitItems.length > 0) return explicitItems.slice(0, limit).map(compactTaskRunItem);
|
||||
const items = arrayRecords(taskRuns.items);
|
||||
if (mode === "failed") return items.filter((item) => item.status === "False").slice(0, limit).map(compactTaskRunItem);
|
||||
if (mode === "active") return items.filter((item) => item.status !== "True" && item.status !== "False").slice(0, limit).map(compactTaskRunItem);
|
||||
const slowItems = arrayRecords(asOptionalRecord(taskRuns.performance)?.slowTaskRuns);
|
||||
if (slowItems.length > 0) return slowItems.slice(0, limit).map(compactTaskRunItem);
|
||||
return items.filter((item) => {
|
||||
const seconds = numberOrNull(item.durationSeconds);
|
||||
return seconds !== null && seconds > 60;
|
||||
}).slice(0, limit).map(compactTaskRunItem);
|
||||
}
|
||||
|
||||
export function prioritizedTaskRunItems(taskRuns: Record<string, unknown>, limit = 16): Record<string, unknown>[] {
|
||||
const prioritized = [
|
||||
...taskRunItems(taskRuns, "failed", limit),
|
||||
...taskRunItems(taskRuns, "active", limit),
|
||||
...taskRunItems(taskRuns, "slow", limit),
|
||||
...arrayRecords(taskRuns.items).map(compactTaskRunItem),
|
||||
];
|
||||
const seen = new Set<string>();
|
||||
const out: Record<string, unknown>[] = [];
|
||||
for (const item of prioritized) {
|
||||
const key = taskRunKey(item);
|
||||
if (seen.has(key)) continue;
|
||||
seen.add(key);
|
||||
out.push(item);
|
||||
if (out.length >= limit) break;
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
export function compactTaskRunItem(item: Record<string, unknown>): Record<string, unknown> {
|
||||
return {
|
||||
name: stringOrNull(item.name),
|
||||
pipelineTask: stringOrNull(item.pipelineTask),
|
||||
status: stringOrNull(item.status),
|
||||
reason: stringOrNull(item.reason),
|
||||
durationSeconds: numberOrNull(item.durationSeconds),
|
||||
};
|
||||
}
|
||||
|
||||
function taskRunKey(item: Record<string, unknown>): string {
|
||||
const key = [
|
||||
stringOrNull(item.name),
|
||||
stringOrNull(item.pipelineTask),
|
||||
stringOrNull(item.status),
|
||||
stringOrNull(item.reason),
|
||||
].filter((value) => value !== null).join("|");
|
||||
return key.length > 0 ? key : JSON.stringify(item);
|
||||
}
|
||||
|
||||
function asOptionalRecord(value: unknown): Record<string, unknown> | null {
|
||||
return typeof value === "object" && value !== null && !Array.isArray(value) ? value as Record<string, unknown> : null;
|
||||
}
|
||||
|
||||
function arrayRecords(value: unknown): Record<string, unknown>[] {
|
||||
return Array.isArray(value) ? value.filter((item): item is Record<string, unknown> => typeof item === "object" && item !== null && !Array.isArray(item)) : [];
|
||||
}
|
||||
|
||||
function stringOrNull(value: unknown): string | null {
|
||||
return typeof value === "string" && value.length > 0 ? value : null;
|
||||
}
|
||||
|
||||
function numberOrNull(value: unknown): number | null {
|
||||
return typeof value === "number" && Number.isFinite(value) ? value : null;
|
||||
}
|
||||
Reference in New Issue
Block a user