From fbf06d32f26878236abf03594129fa20dfede0a4 Mon Sep 17 00:00:00 2001 From: Seongmin Lee Date: Mon, 26 Oct 2026 03:18:26 +0900 Subject: [PATCH] web: add 'blocked' pipeline status Signed-off-by: Seongmin Lee --- web/src/lib/api/spindle.ts | 8 ++------ .../components/repo/pipelines/PipelineStatusIcon.svelte | 3 +++ .../lib/components/repo/pipelines/PipelineSymbol.svelte | 1 + web/src/lib/components/repo/pipelines/livePipelines.ts | 6 +++++- web/src/lib/components/repo/pipelines/pipeline.ts | 6 +++++- web/src/lib/components/repo/types.ts | 3 ++- 6 files changed, 18 insertions(+), 9 deletions(-) diff --git a/web/src/lib/api/spindle.ts b/web/src/lib/api/spindle.ts index 9882e6865..89c5be268 100644 --- a/web/src/lib/api/spindle.ts +++ b/web/src/lib/api/spindle.ts @@ -5,11 +5,7 @@ import { publicOnly } from "#lib/publicFetch.ts"; import type * as GetPipeline from "#lib/api/lexicons/types/org/tangled/ci/getPipeline.ts"; import type * as Pipeline from "#lib/api/lexicons/types/org/tangled/ci/pipeline.ts"; import type * as QueryPipelines from "#lib/api/lexicons/types/org/tangled/ci/queryPipelines.ts"; -import type { - PipelineStatus, - PipelineSummary, - PipelineTrigger -} from "#lib/components/repo/types.ts"; +import type { PipelineSummary, PipelineTrigger } from "#lib/components/repo/types.ts"; const asParams = (params: object): Record => params as unknown as Record; @@ -84,7 +80,7 @@ export const toPipelineSummary = (pipeline: Pipeline.Main, repoDid?: string): Pi workflows: (pipeline.workflows ?? []).map((workflow) => ({ // id is the key logs and getPipeline go by, name is optional name: workflow.id, - status: (workflow.status === "scheduled" ? "pending" : workflow.status) as PipelineStatus, + status: workflow.status, duration: durationOf(workflow), error: workflow.error, startedAt: workflow.startedAt, diff --git a/web/src/lib/components/repo/pipelines/PipelineStatusIcon.svelte b/web/src/lib/components/repo/pipelines/PipelineStatusIcon.svelte index 8e14c8b89..635554ec4 100644 --- a/web/src/lib/components/repo/pipelines/PipelineStatusIcon.svelte +++ b/web/src/lib/components/repo/pipelines/PipelineStatusIcon.svelte @@ -4,6 +4,7 @@ import { tv, type VariantProps } from "tailwind-variants"; import Check from "$icon/check"; import CircleDashed from "$icon/circle-dashed"; + import CirclePause from "$icon/circle-pause"; import CircleSlash from "$icon/circle-slash"; import ClockAlert from "$icon/clock-alert"; import RefreshCw from "$icon/refresh-cw"; @@ -11,6 +12,7 @@ import type { PipelineStatus } from "#lib/components/repo/types.ts"; export const STATUS_ICONS: Record> = { + blocked: CirclePause, pending: CircleDashed, running: RefreshCw, success: Check, @@ -22,6 +24,7 @@ export const pipelineStatusIcon = tv({ variants: { status: { + blocked: "text-foreground-muted", pending: "text-foreground-muted", running: "animate-[spin_2s_linear_infinite] text-foreground-warning", success: "text-foreground-success", diff --git a/web/src/lib/components/repo/pipelines/PipelineSymbol.svelte b/web/src/lib/components/repo/pipelines/PipelineSymbol.svelte index 70ad69e37..a195ee806 100644 --- a/web/src/lib/components/repo/pipelines/PipelineSymbol.svelte +++ b/web/src/lib/components/repo/pipelines/PipelineSymbol.svelte @@ -3,6 +3,7 @@ import type { PipelineStatus } from "#lib/components/repo/types.ts"; export const STATUS_STROKES: Record = { + blocked: "stroke-foreground-muted", pending: "stroke-foreground-placeholder", running: "stroke-foreground-warning", success: "stroke-foreground-success", diff --git a/web/src/lib/components/repo/pipelines/livePipelines.ts b/web/src/lib/components/repo/pipelines/livePipelines.ts index b1ecb1968..4cd6dbe18 100644 --- a/web/src/lib/components/repo/pipelines/livePipelines.ts +++ b/web/src/lib/components/repo/pipelines/livePipelines.ts @@ -21,7 +21,11 @@ const pageVisibility: Visibility = { }; const hasLivePipelines = (pipelines: PipelineSummary[]): boolean => - pipelines.some((pipeline) => isLive(aggregateStatus(pipeline))); + pipelines.some((pipeline) => { + const status = aggregateStatus(pipeline); + // approval starts the run without anything else changing on the page + return status === "blocked" || isLive(status); + }); export const pollPipelineCollection = ( initial: PipelineSummary[], diff --git a/web/src/lib/components/repo/pipelines/pipeline.ts b/web/src/lib/components/repo/pipelines/pipeline.ts index 5eb0f1d2e..b91c598a5 100644 --- a/web/src/lib/components/repo/pipelines/pipeline.ts +++ b/web/src/lib/components/repo/pipelines/pipeline.ts @@ -25,10 +25,12 @@ export const STATUS_ORDER: PipelineStatus[] = [ "timeout", "cancelled", "running", - "pending" + "pending", + "blocked" ]; export const STATUS_LABELS: Record = { + blocked: "Awaiting approval", pending: "Pending", running: "Running", success: "Passed", @@ -39,6 +41,7 @@ export const STATUS_LABELS: Record = { export const statusCounts = (pipeline: PipelineSummary): Record => { const counts = { + blocked: 0, pending: 0, running: 0, success: 0, @@ -56,6 +59,7 @@ export const aggregateStatus = (pipeline: PipelineSummary): PipelineStatus => { const counts = statusCounts(pipeline); if (counts.running > 0) return "running"; if (counts.pending > 0) return "pending"; + if (counts.blocked > 0) return "blocked"; if (counts.failed > 0) return "failed"; if (counts.timeout > 0) return "timeout"; if (counts.cancelled > 0) return "cancelled"; diff --git a/web/src/lib/components/repo/types.ts b/web/src/lib/components/repo/types.ts index 655c71f03..37c79a653 100644 --- a/web/src/lib/components/repo/types.ts +++ b/web/src/lib/components/repo/types.ts @@ -80,7 +80,8 @@ export interface PullSummary { moderation?: Moderation; } -export type PipelineStatus = "pending" | "running" | "success" | "failed" | "timeout" | "cancelled"; +export type PipelineStatus = + "blocked" | "pending" | "running" | "success" | "failed" | "timeout" | "cancelled"; export interface WorkflowSummary { name: string; -- 2.54.0