This repository has no description
0

Configure Feed

Select the types of activity you want to include in your feed.

core / web / src / lib / components / repo / pipelines / pipeline.ts
2.9 kB 89 lines
1// mirrors the helpers on types.Pipeline in types/pipeline.go 2 3import type { 4 PipelineStatus, 5 PipelineSummary, 6 PipelineTriggerKind 7} from "$lib/components/repo/types"; 8 9/** the trigger tabs */ 10export type PipelineFilter = "all" | PipelineTriggerKind; 11 12/** what search looks at. a real bobbin query has to cover the same fields. */ 13export const matchesQuery = (pipeline: PipelineSummary, query: string): boolean => { 14 const needle = query.trim().toLowerCase(); 15 if (!needle) return true; 16 17 const haystack = [ 18 pipeline.sha, 19 pipeline.trigger.kind === "manual" ? "manual dispatch" : pipeline.trigger.targetRef, 20 pipeline.trigger.kind === "pull_request" ? pipeline.trigger.sourceLabel : "", 21 ...pipeline.workflows.map((workflow) => workflow.name) 22 ]; 23 return haystack.some((field) => field.toLowerCase().includes(needle)); 24}; 25 26/** the order the breakdown lists statuses in */ 27export const STATUS_ORDER: PipelineStatus[] = [ 28 "success", 29 "failed", 30 "timeout", 31 "cancelled", 32 "running", 33 "pending" 34]; 35 36export const STATUS_LABELS: Record<PipelineStatus, string> = { 37 pending: "Pending", 38 running: "Running", 39 success: "Passed", 40 failed: "Failed", 41 timeout: "Timed out", 42 cancelled: "Cancelled" 43}; 44 45export const statusCounts = (pipeline: PipelineSummary): Record<PipelineStatus, number> => { 46 const counts = { 47 pending: 0, 48 running: 0, 49 success: 0, 50 failed: 0, 51 timeout: 0, 52 cancelled: 0 53 }; 54 for (const workflow of pipeline.workflows) counts[workflow.status]++; 55 return counts; 56}; 57 58/** one status for the whole run. anything still going wins, so an in-flight run says so. */ 59export const aggregateStatus = (pipeline: PipelineSummary): PipelineStatus => { 60 // no workflows yet means no spindle has picked it up 61 if (pipeline.workflows.length === 0) return "pending"; 62 63 const counts = statusCounts(pipeline); 64 if (counts.running > 0) return "running"; 65 if (counts.pending > 0) return "pending"; 66 if (counts.failed > 0) return "failed"; 67 if (counts.timeout > 0) return "timeout"; 68 if (counts.cancelled > 0) return "cancelled"; 69 return "success"; 70}; 71 72/** how many workflows are done — everything except pending and running */ 73export const finishedCount = (pipeline: PipelineSummary): number => { 74 const counts = statusCounts(pipeline); 75 return counts.success + counts.failed + counts.timeout + counts.cancelled; 76}; 77 78/** "2/3 passed, 1/3 failed" */ 79export const longSummary = (pipeline: PipelineSummary): string => { 80 const counts = statusCounts(pipeline); 81 const total = pipeline.workflows.length; 82 return STATUS_ORDER.filter((status) => counts[status] > 0) 83 .map((status) => `${counts[status]}/${total} ${STATUS_LABELS[status].toLowerCase()}`) 84 .join(", "); 85}; 86 87/** sum of the workflows, not wall time across the run */ 88export const totalDuration = (pipeline: PipelineSummary): number => 89 pipeline.workflows.reduce((sum, workflow) => sum + workflow.duration, 0);