@shipfox/client-workflows 14.0.1 → 16.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.storybook/preview.css +4 -0
- package/.storybook/preview.tsx +7 -2
- package/.turbo/turbo-build.log +1 -1
- package/CHANGELOG.md +42 -0
- package/dist/components/job-detail/agent-config-failure-callout.d.ts.map +1 -0
- package/dist/components/{workflow-run-view → job-detail}/agent-config-failure-callout.js +2 -2
- package/dist/components/job-detail/agent-config-failure-callout.js.map +1 -0
- package/dist/components/job-detail/job-detail-header.d.ts +15 -0
- package/dist/components/job-detail/job-detail-header.d.ts.map +1 -0
- package/dist/components/job-detail/job-detail-header.js +124 -0
- package/dist/components/job-detail/job-detail-header.js.map +1 -0
- package/dist/components/job-detail/job-detail-view.d.ts +16 -0
- package/dist/components/job-detail/job-detail-view.d.ts.map +1 -0
- package/dist/components/job-detail/job-detail-view.js +420 -0
- package/dist/components/job-detail/job-detail-view.js.map +1 -0
- package/dist/components/job-detail/job-empty-states.d.ts +10 -0
- package/dist/components/job-detail/job-empty-states.d.ts.map +1 -0
- package/dist/components/job-detail/job-empty-states.js +195 -0
- package/dist/components/job-detail/job-empty-states.js.map +1 -0
- package/dist/components/job-detail/job-execution-switcher.d.ts.map +1 -0
- package/dist/components/job-detail/job-execution-switcher.js.map +1 -0
- package/dist/components/job-detail/job-execution-time-text.d.ts.map +1 -0
- package/dist/components/job-detail/job-execution-time-text.js.map +1 -0
- package/dist/components/job-detail/job-selection.d.ts +24 -0
- package/dist/components/job-detail/job-selection.d.ts.map +1 -0
- package/dist/components/job-detail/job-selection.js +66 -0
- package/dist/components/job-detail/job-selection.js.map +1 -0
- package/dist/components/job-detail/step-attempt-log-panel.d.ts +15 -0
- package/dist/components/job-detail/step-attempt-log-panel.d.ts.map +1 -0
- package/dist/components/{workflow-run-view → job-detail}/step-attempt-log-panel.js +61 -16
- package/dist/components/job-detail/step-attempt-log-panel.js.map +1 -0
- package/dist/components/job-graph/job-graph-content.js +1 -1
- package/dist/components/job-graph/job-graph-content.js.map +1 -1
- package/dist/components/step-list/step-list-model.js +2 -2
- package/dist/components/step-list/step-list-model.js.map +1 -1
- package/dist/components/step-list/step-list.d.ts +1 -0
- package/dist/components/step-list/step-list.d.ts.map +1 -1
- package/dist/components/step-list/step-list.js +29 -4
- package/dist/components/step-list/step-list.js.map +1 -1
- package/dist/components/workflow-run-duration-label.d.ts +9 -4
- package/dist/components/workflow-run-duration-label.d.ts.map +1 -1
- package/dist/components/workflow-run-duration-label.js +27 -7
- package/dist/components/workflow-run-duration-label.js.map +1 -1
- package/dist/components/workflow-run-list/workflow-run-row.d.ts.map +1 -1
- package/dist/components/workflow-run-list/workflow-run-row.js +6 -5
- package/dist/components/workflow-run-list/workflow-run-row.js.map +1 -1
- package/dist/components/workflow-run-summary/workflow-run-summary.d.ts.map +1 -1
- package/dist/components/workflow-run-summary/workflow-run-summary.js +69 -64
- package/dist/components/workflow-run-summary/workflow-run-summary.js.map +1 -1
- package/dist/components/workflow-run-tabs/index.d.ts +3 -3
- package/dist/components/workflow-run-tabs/index.d.ts.map +1 -1
- package/dist/components/workflow-run-tabs/index.js +3 -3
- package/dist/components/workflow-run-tabs/index.js.map +1 -1
- package/dist/components/workflow-run-tabs/run-annotation-count-chip.d.ts +16 -0
- package/dist/components/workflow-run-tabs/run-annotation-count-chip.d.ts.map +1 -0
- package/dist/components/workflow-run-tabs/run-annotation-count-chip.js +50 -0
- package/dist/components/workflow-run-tabs/run-annotation-count-chip.js.map +1 -0
- package/dist/components/workflow-run-tabs/run-annotation-item.d.ts +20 -0
- package/dist/components/workflow-run-tabs/run-annotation-item.d.ts.map +1 -0
- package/dist/components/workflow-run-tabs/run-annotation-item.js +102 -0
- package/dist/components/workflow-run-tabs/run-annotation-item.js.map +1 -0
- package/dist/components/workflow-run-tabs/run-annotation-list.d.ts +32 -0
- package/dist/components/workflow-run-tabs/run-annotation-list.d.ts.map +1 -0
- package/dist/components/workflow-run-tabs/run-annotation-list.js +202 -0
- package/dist/components/workflow-run-tabs/run-annotation-list.js.map +1 -0
- package/dist/components/workflow-run-tabs/run-annotation-summary-line.d.ts +1 -1
- package/dist/components/workflow-run-tabs/run-annotation-summary-line.d.ts.map +1 -1
- package/dist/components/workflow-run-tabs/run-annotation-summary-line.js +87 -22
- package/dist/components/workflow-run-tabs/run-annotation-summary-line.js.map +1 -1
- package/dist/components/workflow-run-tabs/run-annotations-empty.d.ts +3 -1
- package/dist/components/workflow-run-tabs/run-annotations-empty.d.ts.map +1 -1
- package/dist/components/workflow-run-tabs/run-annotations-empty.js +2 -2
- package/dist/components/workflow-run-tabs/run-annotations-empty.js.map +1 -1
- package/dist/components/workflow-run-tabs/severity-visuals.d.ts +20 -0
- package/dist/components/workflow-run-tabs/severity-visuals.d.ts.map +1 -0
- package/dist/components/workflow-run-tabs/severity-visuals.js +31 -0
- package/dist/components/workflow-run-tabs/severity-visuals.js.map +1 -0
- package/dist/components/workflow-run-view/index.d.ts +0 -1
- package/dist/components/workflow-run-view/index.d.ts.map +1 -1
- package/dist/components/workflow-run-view/index.js +0 -1
- package/dist/components/workflow-run-view/index.js.map +1 -1
- package/dist/components/workflow-run-view/run-workspace-nav.d.ts +20 -0
- package/dist/components/workflow-run-view/run-workspace-nav.d.ts.map +1 -0
- package/dist/components/workflow-run-view/run-workspace-nav.js +277 -0
- package/dist/components/workflow-run-view/run-workspace-nav.js.map +1 -0
- package/dist/components/workflow-run-view/workflow-run-selection.d.ts.map +1 -1
- package/dist/components/workflow-run-view/workflow-run-selection.js +1 -14
- package/dist/components/workflow-run-view/workflow-run-selection.js.map +1 -1
- package/dist/components/workflow-run-view/workflow-run-view.d.ts +10 -10
- package/dist/components/workflow-run-view/workflow-run-view.d.ts.map +1 -1
- package/dist/components/workflow-run-view/workflow-run-view.js +351 -239
- package/dist/components/workflow-run-view/workflow-run-view.js.map +1 -1
- package/dist/components/workflow-status/status-visuals.d.ts.map +1 -1
- package/dist/components/workflow-status/status-visuals.js +10 -2
- package/dist/components/workflow-status/status-visuals.js.map +1 -1
- package/dist/components/workflow-status/workflow-status-icon.d.ts +3 -1
- package/dist/components/workflow-status/workflow-status-icon.d.ts.map +1 -1
- package/dist/components/workflow-status/workflow-status-icon.js +13 -2
- package/dist/components/workflow-status/workflow-status-icon.js.map +1 -1
- package/dist/core/entities/job-execution.d.ts +9 -0
- package/dist/core/entities/job-execution.d.ts.map +1 -1
- package/dist/core/entities/job-execution.js +13 -3
- package/dist/core/entities/job-execution.js.map +1 -1
- package/dist/core/entities/job.d.ts.map +1 -1
- package/dist/core/entities/step-attempt.d.ts.map +1 -1
- package/dist/core/entities/step.d.ts +2 -0
- package/dist/core/entities/step.d.ts.map +1 -1
- package/dist/core/entities/step.js +13 -0
- package/dist/core/entities/step.js.map +1 -1
- package/dist/core/entities/workflow-run-attempt.d.ts.map +1 -1
- package/dist/core/entities/workflow-run.d.ts +56 -1
- package/dist/core/entities/workflow-run.d.ts.map +1 -1
- package/dist/core/entities/workflow-run.js +98 -0
- package/dist/core/entities/workflow-run.js.map +1 -1
- package/dist/core/run-annotation.d.ts +73 -0
- package/dist/core/run-annotation.d.ts.map +1 -0
- package/dist/core/run-annotation.js +125 -0
- package/dist/core/run-annotation.js.map +1 -0
- package/dist/core/workflow-run.d.ts +4 -4
- package/dist/core/workflow-run.d.ts.map +1 -1
- package/dist/core/workflow-run.js +3 -3
- package/dist/core/workflow-run.js.map +1 -1
- package/dist/feature.d.ts +20 -16
- package/dist/feature.d.ts.map +1 -1
- package/dist/feature.js +5 -0
- package/dist/feature.js.map +1 -1
- package/dist/hooks/api/run-annotation-mapper.d.ts +10 -0
- package/dist/hooks/api/run-annotation-mapper.d.ts.map +1 -0
- package/dist/hooks/api/run-annotation-mapper.js +22 -0
- package/dist/hooks/api/run-annotation-mapper.js.map +1 -0
- package/dist/hooks/api/run-annotations.d.ts +25 -0
- package/dist/hooks/api/run-annotations.d.ts.map +1 -0
- package/dist/hooks/api/run-annotations.js +78 -0
- package/dist/hooks/api/run-annotations.js.map +1 -0
- package/dist/hooks/api/workflow-runs.d.ts +5 -3
- package/dist/hooks/api/workflow-runs.d.ts.map +1 -1
- package/dist/hooks/api/workflow-runs.js +5 -4
- package/dist/hooks/api/workflow-runs.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/pages/workflow-job-detail-page.d.ts +11 -0
- package/dist/pages/workflow-job-detail-page.d.ts.map +1 -0
- package/dist/pages/workflow-job-detail-page.js +66 -0
- package/dist/pages/workflow-job-detail-page.js.map +1 -0
- package/dist/pages/workflow-run-detail-page.d.ts.map +1 -1
- package/dist/pages/workflow-run-detail-page.js +4 -37
- package/dist/pages/workflow-run-detail-page.js.map +1 -1
- package/dist/routes/inputs.d.ts +52 -34
- package/dist/routes/inputs.d.ts.map +1 -1
- package/dist/routes/inputs.js +74 -43
- package/dist/routes/inputs.js.map +1 -1
- package/dist/routes/job-detail.d.ts +10 -0
- package/dist/routes/job-detail.d.ts.map +1 -0
- package/dist/routes/job-detail.js +27 -0
- package/dist/routes/job-detail.js.map +1 -0
- package/dist/routes/project-route.d.ts +1 -1
- package/dist/routes/run-detail.d.ts.map +1 -1
- package/dist/routes/runs.d.ts.map +1 -1
- package/dist/routes/workflows.d.ts.map +1 -1
- package/dist/tsconfig.test.tsbuildinfo +1 -1
- package/package.json +10 -9
- package/src/components/{workflow-run-view → job-detail}/agent-config-failure-callout.stories.tsx +1 -1
- package/src/components/{workflow-run-view → job-detail}/agent-config-failure-callout.tsx +2 -2
- package/src/components/job-detail/job-detail-header.test.tsx +34 -0
- package/src/components/job-detail/job-detail-header.tsx +136 -0
- package/src/components/job-detail/job-detail-view.stories.tsx +531 -0
- package/src/components/job-detail/job-detail-view.tsx +467 -0
- package/src/components/job-detail/job-empty-states.test.ts +27 -0
- package/src/components/job-detail/job-empty-states.tsx +248 -0
- package/src/components/job-detail/job-selection.test.ts +188 -0
- package/src/components/job-detail/job-selection.ts +96 -0
- package/src/components/{workflow-run-view → job-detail}/step-attempt-log-panel.test.tsx +32 -9
- package/src/components/{workflow-run-view → job-detail}/step-attempt-log-panel.tsx +52 -18
- package/src/components/job-graph/job-graph-content.tsx +1 -1
- package/src/components/step-list/step-list-model.test.ts +1 -1
- package/src/components/step-list/step-list-model.ts +2 -2
- package/src/components/step-list/step-list.stories.tsx +1 -1
- package/src/components/step-list/step-list.test.tsx +33 -0
- package/src/components/step-list/step-list.tsx +40 -9
- package/src/components/workflow-run-duration-label.tsx +50 -12
- package/src/components/workflow-run-list/workflow-run-row.tsx +6 -4
- package/src/components/workflow-run-summary/workflow-run-summary.stories.tsx +38 -0
- package/src/components/workflow-run-summary/workflow-run-summary.test.tsx +79 -5
- package/src/components/workflow-run-summary/workflow-run-summary.tsx +56 -60
- package/src/components/workflow-run-tabs/index.ts +3 -3
- package/src/components/workflow-run-tabs/run-annotation-count-chip.tsx +63 -0
- package/src/components/workflow-run-tabs/run-annotation-item.tsx +123 -0
- package/src/components/workflow-run-tabs/run-annotation-list.tsx +258 -0
- package/src/components/workflow-run-tabs/run-annotation-summary-line.test.tsx +77 -3
- package/src/components/workflow-run-tabs/run-annotation-summary-line.tsx +92 -17
- package/src/components/workflow-run-tabs/run-annotations-empty.tsx +6 -2
- package/src/components/workflow-run-tabs/run-annotations.stories.tsx +293 -0
- package/src/components/workflow-run-tabs/severity-visuals.ts +37 -0
- package/src/components/workflow-run-view/index.ts +0 -1
- package/src/components/workflow-run-view/run-workspace-nav.test.tsx +286 -0
- package/src/components/workflow-run-view/run-workspace-nav.tsx +314 -0
- package/src/components/workflow-run-view/workflow-run-selection.ts +1 -23
- package/src/components/workflow-run-view/workflow-run-view.test.tsx +237 -1085
- package/src/components/workflow-run-view/workflow-run-view.tsx +450 -323
- package/src/components/workflow-status/status-visuals.ts +5 -2
- package/src/components/workflow-status/workflow-status-icon.stories.tsx +1 -0
- package/src/components/workflow-status/workflow-status-icon.tsx +26 -1
- package/src/core/entities/job-execution.ts +17 -2
- package/src/core/entities/step.ts +26 -0
- package/src/core/entities/workflow-run-display.test.ts +159 -0
- package/src/core/entities/workflow-run.ts +139 -1
- package/src/core/run-annotation.test.ts +315 -0
- package/src/core/run-annotation.ts +238 -0
- package/src/core/workflow-run.ts +16 -1
- package/src/feature.ts +5 -0
- package/src/hooks/api/run-annotation-mapper.ts +30 -0
- package/src/hooks/api/run-annotations.ts +137 -0
- package/src/hooks/api/workflow-runs.ts +6 -2
- package/src/index.ts +1 -0
- package/src/page-harness-budget.test.ts +1 -0
- package/src/pages/workflow-job-detail-page.test.tsx +605 -0
- package/src/pages/workflow-job-detail-page.tsx +84 -0
- package/src/pages/workflow-run-detail-page.tsx +3 -43
- package/src/pages/workflow-run-pages.test.tsx +77 -332
- package/src/routes/inputs.test.ts +56 -6
- package/src/routes/inputs.ts +71 -19
- package/src/routes/job-detail.tsx +29 -0
- package/test/pages.tsx +25 -3
- package/test/render.tsx +6 -1
- package/tsconfig.build.tsbuildinfo +1 -1
- package/dist/components/workflow-run-tabs/run-jobs-list.d.ts +0 -18
- package/dist/components/workflow-run-tabs/run-jobs-list.d.ts.map +0 -1
- package/dist/components/workflow-run-tabs/run-jobs-list.js +0 -107
- package/dist/components/workflow-run-tabs/run-jobs-list.js.map +0 -1
- package/dist/components/workflow-run-tabs/run-tab-count.d.ts +0 -6
- package/dist/components/workflow-run-tabs/run-tab-count.d.ts.map +0 -1
- package/dist/components/workflow-run-tabs/run-tab-count.js +0 -27
- package/dist/components/workflow-run-tabs/run-tab-count.js.map +0 -1
- package/dist/components/workflow-run-tabs/run-tab-strip.d.ts +0 -8
- package/dist/components/workflow-run-tabs/run-tab-strip.d.ts.map +0 -1
- package/dist/components/workflow-run-tabs/run-tab-strip.js +0 -82
- package/dist/components/workflow-run-tabs/run-tab-strip.js.map +0 -1
- package/dist/components/workflow-run-view/agent-config-failure-callout.d.ts.map +0 -1
- package/dist/components/workflow-run-view/agent-config-failure-callout.js.map +0 -1
- package/dist/components/workflow-run-view/job-card.d.ts +0 -17
- package/dist/components/workflow-run-view/job-card.d.ts.map +0 -1
- package/dist/components/workflow-run-view/job-card.js +0 -496
- package/dist/components/workflow-run-view/job-card.js.map +0 -1
- package/dist/components/workflow-run-view/job-execution-switcher.d.ts.map +0 -1
- package/dist/components/workflow-run-view/job-execution-switcher.js.map +0 -1
- package/dist/components/workflow-run-view/job-execution-time-text.d.ts.map +0 -1
- package/dist/components/workflow-run-view/job-execution-time-text.js.map +0 -1
- package/dist/components/workflow-run-view/step-attempt-log-panel.d.ts +0 -9
- package/dist/components/workflow-run-view/step-attempt-log-panel.d.ts.map +0 -1
- package/dist/components/workflow-run-view/step-attempt-log-panel.js.map +0 -1
- package/dist/core/workflow-run-tabs.d.ts +0 -9
- package/dist/core/workflow-run-tabs.d.ts.map +0 -1
- package/dist/core/workflow-run-tabs.js +0 -3
- package/dist/core/workflow-run-tabs.js.map +0 -1
- package/src/components/workflow-run-tabs/run-jobs-list.tsx +0 -151
- package/src/components/workflow-run-tabs/run-tab-count.tsx +0 -28
- package/src/components/workflow-run-tabs/run-tab-strip.stories.tsx +0 -52
- package/src/components/workflow-run-tabs/run-tab-strip.test.tsx +0 -117
- package/src/components/workflow-run-tabs/run-tab-strip.tsx +0 -97
- package/src/components/workflow-run-view/job-card.stories.tsx +0 -789
- package/src/components/workflow-run-view/job-card.test.tsx +0 -115
- package/src/components/workflow-run-view/job-card.tsx +0 -614
- package/src/core/workflow-run-tabs.ts +0 -8
- /package/dist/components/{workflow-run-view → job-detail}/agent-config-failure-callout.d.ts +0 -0
- /package/dist/components/{workflow-run-view → job-detail}/job-execution-switcher.d.ts +0 -0
- /package/dist/components/{workflow-run-view → job-detail}/job-execution-switcher.js +0 -0
- /package/dist/components/{workflow-run-view → job-detail}/job-execution-time-text.d.ts +0 -0
- /package/dist/components/{workflow-run-view → job-detail}/job-execution-time-text.js +0 -0
- /package/src/components/{workflow-run-view → job-detail}/job-execution-switcher.tsx +0 -0
- /package/src/components/{workflow-run-view → job-detail}/job-execution-time-text.tsx +0 -0
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { WORKFLOW_JOB_STATUSES } from './job.js';
|
|
2
|
+
import { elapsedTimeFromTimestamps } from './job-execution.js';
|
|
2
3
|
export const WORKFLOW_RUN_STATUSES = [
|
|
3
4
|
'pending',
|
|
4
5
|
'running',
|
|
@@ -6,6 +7,12 @@ export const WORKFLOW_RUN_STATUSES = [
|
|
|
6
7
|
'failed',
|
|
7
8
|
'cancelled'
|
|
8
9
|
];
|
|
10
|
+
export const WORKFLOW_DISPLAY_STATUSES = [
|
|
11
|
+
...WORKFLOW_RUN_STATUSES,
|
|
12
|
+
...WORKFLOW_JOB_STATUSES,
|
|
13
|
+
'listening',
|
|
14
|
+
'queued'
|
|
15
|
+
];
|
|
9
16
|
export const TERMINAL_WORKFLOW_RUN_STATUSES = [
|
|
10
17
|
'succeeded',
|
|
11
18
|
'failed',
|
|
@@ -53,5 +60,96 @@ export function isWorkflowRunTerminal(status) {
|
|
|
53
60
|
export function isWorkflowStatus(status) {
|
|
54
61
|
return WORKFLOW_STATUSES.has(status);
|
|
55
62
|
}
|
|
63
|
+
/** When the run's earliest execution began, or null while none of them has. */ export function workflowRunFirstStartedAt(jobs) {
|
|
64
|
+
let earliest = null;
|
|
65
|
+
let earliestMs = Number.POSITIVE_INFINITY;
|
|
66
|
+
for (const job of jobs){
|
|
67
|
+
for (const { startedAt } of job.jobExecutions){
|
|
68
|
+
if (startedAt === null) continue;
|
|
69
|
+
const startedMs = new Date(startedAt).getTime();
|
|
70
|
+
if (!Number.isFinite(startedMs) || startedMs >= earliestMs) continue;
|
|
71
|
+
earliest = startedAt;
|
|
72
|
+
earliestMs = startedMs;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
return earliest;
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Whether any work has begun. A run with no jobs on hand is a run whose jobs were not fetched,
|
|
79
|
+
* which is no evidence that nothing started, so it counts as started rather than claiming a
|
|
80
|
+
* queue this surface cannot see.
|
|
81
|
+
*/ function workflowRunHasStarted({ jobStatuses, firstStartedAt }) {
|
|
82
|
+
if (firstStartedAt != null) return true;
|
|
83
|
+
if (jobStatuses.length === 0) return true;
|
|
84
|
+
return jobStatuses.some((status)=>status !== 'pending' && status !== 'skipped');
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* The single rule behind every run readout. An attempt's `startedAt` marks when the
|
|
88
|
+
* orchestrator picked the run up, not when work began, so a run whose jobs are all still
|
|
89
|
+
* waiting reads as `Queued` for queue time. Calling that "running for 2h" sends an operator to
|
|
90
|
+
* debug a build that never began.
|
|
91
|
+
*/ export function deriveWorkflowRunDisplay(progress) {
|
|
92
|
+
const { runStatus, startedAt, finishedAt, firstStartedAt } = progress;
|
|
93
|
+
const hasStarted = workflowRunHasStarted(progress);
|
|
94
|
+
const status = runStatus === 'running' && !hasStarted ? 'queued' : runStatus;
|
|
95
|
+
if (startedAt === null) return {
|
|
96
|
+
status,
|
|
97
|
+
duration: null
|
|
98
|
+
};
|
|
99
|
+
// A run cancelled before anything started keeps its queue reading rather than reporting a
|
|
100
|
+
// run that never was.
|
|
101
|
+
const time = elapsedTimeFromTimestamps({
|
|
102
|
+
from: firstStartedAt ?? startedAt,
|
|
103
|
+
to: finishedAt
|
|
104
|
+
});
|
|
105
|
+
if (time === null) return {
|
|
106
|
+
status,
|
|
107
|
+
duration: null
|
|
108
|
+
};
|
|
109
|
+
return {
|
|
110
|
+
status,
|
|
111
|
+
duration: {
|
|
112
|
+
kind: hasStarted ? 'run' : 'queue',
|
|
113
|
+
...time
|
|
114
|
+
}
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
/** The run detail's reading: whole jobs, so queue and run time split on the first execution. */ export function workflowRunDetailDisplay(run) {
|
|
118
|
+
return deriveWorkflowRunDisplay({
|
|
119
|
+
runStatus: run.runAttempt.status,
|
|
120
|
+
startedAt: run.runAttempt.startedAt,
|
|
121
|
+
finishedAt: run.runAttempt.finishedAt,
|
|
122
|
+
jobStatuses: run.jobs.map((job)=>job.status),
|
|
123
|
+
firstStartedAt: workflowRunFirstStartedAt(run.jobs)
|
|
124
|
+
});
|
|
125
|
+
}
|
|
126
|
+
/**
|
|
127
|
+
* The run list's reading: status counts cover every job, not just the drawn preview, so a row
|
|
128
|
+
* reaches the same verdict as the detail page without fetching a single timestamp more.
|
|
129
|
+
*/ export function workflowRunListItemDisplay(run) {
|
|
130
|
+
return deriveWorkflowRunDisplay({
|
|
131
|
+
runStatus: run.status,
|
|
132
|
+
startedAt: run.runAttempt.startedAt,
|
|
133
|
+
finishedAt: run.runAttempt.finishedAt,
|
|
134
|
+
jobStatuses: run.jobs.statusCounts.filter(({ count })=>count > 0).map(({ status })=>status)
|
|
135
|
+
});
|
|
136
|
+
}
|
|
137
|
+
/**
|
|
138
|
+
* The job the run is waiting on: the one queued longest without starting. Named only so a
|
|
139
|
+
* queued run says what it waits for instead of showing a number with no subject.
|
|
140
|
+
*/ export function workflowRunBlockingJob(jobs) {
|
|
141
|
+
let blocking = null;
|
|
142
|
+
let queuedMs = Number.POSITIVE_INFINITY;
|
|
143
|
+
for (const job of jobs){
|
|
144
|
+
for (const { queuedAt, startedAt, finishedAt } of job.jobExecutions){
|
|
145
|
+
if (queuedAt === null || startedAt !== null || finishedAt !== null) continue;
|
|
146
|
+
const candidateMs = new Date(queuedAt).getTime();
|
|
147
|
+
if (!Number.isFinite(candidateMs) || candidateMs >= queuedMs) continue;
|
|
148
|
+
blocking = job;
|
|
149
|
+
queuedMs = candidateMs;
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
return blocking;
|
|
153
|
+
}
|
|
56
154
|
|
|
57
155
|
//# sourceMappingURL=workflow-run.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/core/entities/workflow-run.ts"],"sourcesContent":["import {type Job, type JobStatus, WORKFLOW_JOB_STATUSES} from './job.js';\nimport type {WorkflowRunAttempt, WorkflowRunAttemptSummary} from './workflow-run-attempt.js';\n\nexport type WorkflowRunStatus = 'pending' | 'running' | 'succeeded' | 'failed' | 'cancelled';\nexport type WorkflowRunRerunMode = 'all' | 'failed';\nexport type WorkflowStatus = WorkflowRunStatus | (typeof WORKFLOW_JOB_STATUSES)[number];\nexport type WorkflowDisplayStatus = WorkflowStatus | 'listening';\n\nexport const WORKFLOW_RUN_STATUSES = [\n 'pending',\n 'running',\n 'succeeded',\n 'failed',\n 'cancelled',\n] as const satisfies readonly WorkflowRunStatus[];\n\nexport const TERMINAL_WORKFLOW_RUN_STATUSES = [\n 'succeeded',\n 'failed',\n 'cancelled',\n] as const satisfies readonly WorkflowRunStatus[];\n\nconst WORKFLOW_STATUSES = new Set<WorkflowStatus>([\n ...WORKFLOW_RUN_STATUSES,\n ...WORKFLOW_JOB_STATUSES,\n]);\nconst TERMINAL_WORKFLOW_RUN_STATUS_SET = new Set<WorkflowRunStatus>(TERMINAL_WORKFLOW_RUN_STATUSES);\n\nexport interface WorkflowSourceSnapshot {\n content: string;\n format: 'yaml';\n}\n\n/**\n * Provider-neutral trigger facts. Every field is nullable: only source-control triggers\n * resolve a reference at all, and a payload can name a ref without naming an actor.\n */\nexport interface WorkflowRunTriggerReference {\n repository: string | null;\n ref: string | null;\n commit: string | null;\n actor: string | null;\n}\n\n/** One glyph in a run row's job status strip: enough to draw and label it, nothing more. */\nexport interface WorkflowRunJobSummary {\n id: string;\n key: string;\n name: string | null;\n status: JobStatus;\n position: number;\n}\n\nexport interface WorkflowRunJobStatusCount {\n status: JobStatus;\n count: number;\n}\n\n/**\n * A run's jobs as the list receives them: a bounded slice to draw, plus totals covering all\n * of them.\n *\n * `preview` is capped by the API, so `preview.length` is not the job count and the strip\n * reads `total` and `statusCounts` for anything it says rather than anything it draws.\n */\nexport interface WorkflowRunJobs {\n preview: WorkflowRunJobSummary[];\n statusCounts: WorkflowRunJobStatusCount[];\n total: number;\n}\n\nexport interface WorkflowRun {\n id: string;\n projectId: string;\n definitionId: string;\n number: number | null;\n name: string;\n workflowName: string;\n currentAttempt: number;\n triggerProvider: string | null;\n triggerSource: string;\n triggerEvent: string;\n triggerDisplayLabel: string;\n triggerLabel: string;\n triggerPayload: Record<string, unknown>;\n triggerReference: WorkflowRunTriggerReference | null;\n inputs: Record<string, unknown> | null;\n sourceSnapshot: WorkflowSourceSnapshot | null;\n createdAt: string;\n updatedAt: string;\n isTemporary: boolean;\n}\n\n/** A run as the API returns it outside the list: no job strip, because none was fetched. */\nexport interface WorkflowRunRecord extends WorkflowRun {\n status: WorkflowRunStatus;\n latestAttempt: number;\n runAttempt: WorkflowRunAttemptSummary;\n}\n\nexport interface WorkflowRunListItem extends WorkflowRunRecord {\n jobs: WorkflowRunJobs;\n}\n\nexport interface WorkflowRunDetail extends WorkflowRun {\n latestAttempt: number;\n runAttempt: WorkflowRunAttempt;\n jobs: Job[];\n}\n\nexport interface WorkflowRunListPage {\n runs: WorkflowRunListItem[];\n nextCursor: string | null;\n filteredTotalCount: number | null;\n}\n\nexport interface ManualWorkflowLaunch {\n workflowRunId: string;\n}\n\nexport function workflowRunTriggerLabel({\n triggerSource,\n triggerEvent,\n}: {\n triggerSource: string;\n triggerEvent: string;\n}): string {\n return [triggerSource, triggerEvent].filter(Boolean).join(' · ');\n}\n\nexport function workflowRunTriggerDisplayLabel({\n triggerSource,\n triggerEvent,\n}: {\n triggerSource: string;\n triggerEvent: string;\n}): string {\n return triggerEvent || triggerSource;\n}\n\nconst SHORT_COMMIT_LENGTH = 7;\nconst PULL_REQUEST_REF_PATTERN = /^refs\\/pull\\/(\\d+)\\/head$/u;\n\n/**\n * The ref as a person names it: `main` for a branch, `#42` for a pull request, the tag for a\n * tag. An unrecognized ref is shown verbatim rather than hidden, since a ref nobody can read\n * is still better evidence than a blank cell.\n */\nexport function workflowRunBranchLabel(run: Pick<WorkflowRun, 'triggerReference'>): string | null {\n const ref = run.triggerReference?.ref;\n if (!ref) return null;\n const pullRequest = PULL_REQUEST_REF_PATTERN.exec(ref);\n if (pullRequest) return `#${pullRequest[1]}`;\n if (ref.startsWith('refs/heads/')) return ref.slice('refs/heads/'.length);\n if (ref.startsWith('refs/tags/')) return ref.slice('refs/tags/'.length);\n return ref;\n}\n\nexport function workflowRunCommitLabel(run: Pick<WorkflowRun, 'triggerReference'>): string | null {\n const commit = run.triggerReference?.commit;\n return commit ? commit.slice(0, SHORT_COMMIT_LENGTH) : null;\n}\n\nexport function workflowRunActor(run: Pick<WorkflowRun, 'triggerReference'>): string | null {\n return run.triggerReference?.actor ?? null;\n}\n\nexport function isWorkflowRunTerminal(status: WorkflowRunStatus): boolean {\n return TERMINAL_WORKFLOW_RUN_STATUS_SET.has(status);\n}\n\nexport function isWorkflowStatus(status: string): status is WorkflowStatus {\n return WORKFLOW_STATUSES.has(status as WorkflowStatus);\n}\n"],"names":["WORKFLOW_JOB_STATUSES","WORKFLOW_RUN_STATUSES","TERMINAL_WORKFLOW_RUN_STATUSES","WORKFLOW_STATUSES","Set","TERMINAL_WORKFLOW_RUN_STATUS_SET","workflowRunTriggerLabel","triggerSource","triggerEvent","filter","Boolean","join","workflowRunTriggerDisplayLabel","SHORT_COMMIT_LENGTH","PULL_REQUEST_REF_PATTERN","workflowRunBranchLabel","run","ref","triggerReference","pullRequest","exec","startsWith","slice","length","workflowRunCommitLabel","commit","workflowRunActor","actor","isWorkflowRunTerminal","status","has","isWorkflowStatus"],"mappings":"AAAA,SAAkCA,qBAAqB,QAAO,WAAW;AAQzE,OAAO,MAAMC,wBAAwB;IACnC;IACA;IACA;IACA;IACA;CACD,CAAiD;AAElD,OAAO,MAAMC,iCAAiC;IAC5C;IACA;IACA;CACD,CAAiD;AAElD,MAAMC,oBAAoB,IAAIC,IAAoB;OAC7CH;OACAD;CACJ;AACD,MAAMK,mCAAmC,IAAID,IAAuBF;AA8FpE,OAAO,SAASI,wBAAwB,EACtCC,aAAa,EACbC,YAAY,EAIb;IACC,OAAO;QAACD;QAAeC;KAAa,CAACC,MAAM,CAACC,SAASC,IAAI,CAAC;AAC5D;AAEA,OAAO,SAASC,+BAA+B,EAC7CL,aAAa,EACbC,YAAY,EAIb;IACC,OAAOA,gBAAgBD;AACzB;AAEA,MAAMM,sBAAsB;AAC5B,MAAMC,2BAA2B;AAEjC;;;;CAIC,GACD,OAAO,SAASC,uBAAuBC,GAA0C;IAC/E,MAAMC,MAAMD,IAAIE,gBAAgB,EAAED;IAClC,IAAI,CAACA,KAAK,OAAO;IACjB,MAAME,cAAcL,yBAAyBM,IAAI,CAACH;IAClD,IAAIE,aAAa,OAAO,CAAC,CAAC,EAAEA,WAAW,CAAC,EAAE,EAAE;IAC5C,IAAIF,IAAII,UAAU,CAAC,gBAAgB,OAAOJ,IAAIK,KAAK,CAAC,cAAcC,MAAM;IACxE,IAAIN,IAAII,UAAU,CAAC,eAAe,OAAOJ,IAAIK,KAAK,CAAC,aAAaC,MAAM;IACtE,OAAON;AACT;AAEA,OAAO,SAASO,uBAAuBR,GAA0C;IAC/E,MAAMS,SAAST,IAAIE,gBAAgB,EAAEO;IACrC,OAAOA,SAASA,OAAOH,KAAK,CAAC,GAAGT,uBAAuB;AACzD;AAEA,OAAO,SAASa,iBAAiBV,GAA0C;IACzE,OAAOA,IAAIE,gBAAgB,EAAES,SAAS;AACxC;AAEA,OAAO,SAASC,sBAAsBC,MAAyB;IAC7D,OAAOxB,iCAAiCyB,GAAG,CAACD;AAC9C;AAEA,OAAO,SAASE,iBAAiBF,MAAc;IAC7C,OAAO1B,kBAAkB2B,GAAG,CAACD;AAC/B"}
|
|
1
|
+
{"version":3,"sources":["../../../src/core/entities/workflow-run.ts"],"sourcesContent":["import {type Job, type JobStatus, WORKFLOW_JOB_STATUSES} from './job.js';\nimport {elapsedTimeFromTimestamps, type JobExecutionDisplayDuration} from './job-execution.js';\nimport type {WorkflowRunAttempt, WorkflowRunAttemptSummary} from './workflow-run-attempt.js';\n\nexport type WorkflowRunStatus = 'pending' | 'running' | 'succeeded' | 'failed' | 'cancelled';\nexport type WorkflowRunRerunMode = 'all' | 'failed';\nexport type WorkflowStatus = WorkflowRunStatus | (typeof WORKFLOW_JOB_STATUSES)[number];\n/**\n * `listening` and `queued` are display-only: the API never returns them, and both are derived\n * from the jobs a run already carries.\n */\nexport type WorkflowDisplayStatus = WorkflowStatus | 'listening' | 'queued';\n\nexport const WORKFLOW_RUN_STATUSES = [\n 'pending',\n 'running',\n 'succeeded',\n 'failed',\n 'cancelled',\n] as const satisfies readonly WorkflowRunStatus[];\n\nexport const WORKFLOW_DISPLAY_STATUSES = [\n ...WORKFLOW_RUN_STATUSES,\n ...WORKFLOW_JOB_STATUSES,\n 'listening',\n 'queued',\n] as const satisfies readonly WorkflowDisplayStatus[];\n\nexport const TERMINAL_WORKFLOW_RUN_STATUSES = [\n 'succeeded',\n 'failed',\n 'cancelled',\n] as const satisfies readonly WorkflowRunStatus[];\n\nconst WORKFLOW_STATUSES = new Set<WorkflowStatus>([\n ...WORKFLOW_RUN_STATUSES,\n ...WORKFLOW_JOB_STATUSES,\n]);\nconst TERMINAL_WORKFLOW_RUN_STATUS_SET = new Set<WorkflowRunStatus>(TERMINAL_WORKFLOW_RUN_STATUSES);\n\nexport interface WorkflowSourceSnapshot {\n content: string;\n format: 'yaml';\n}\n\n/**\n * Provider-neutral trigger facts. Every field is nullable: only source-control triggers\n * resolve a reference at all, and a payload can name a ref without naming an actor.\n */\nexport interface WorkflowRunTriggerReference {\n repository: string | null;\n ref: string | null;\n commit: string | null;\n actor: string | null;\n}\n\n/** One glyph in a run row's job status strip: enough to draw and label it, nothing more. */\nexport interface WorkflowRunJobSummary {\n id: string;\n key: string;\n name: string | null;\n status: JobStatus;\n position: number;\n}\n\nexport interface WorkflowRunJobStatusCount {\n status: JobStatus;\n count: number;\n}\n\n/**\n * A run's jobs as the list receives them: a bounded slice to draw, plus totals covering all\n * of them.\n *\n * `preview` is capped by the API, so `preview.length` is not the job count and the strip\n * reads `total` and `statusCounts` for anything it says rather than anything it draws.\n */\nexport interface WorkflowRunJobs {\n preview: WorkflowRunJobSummary[];\n statusCounts: WorkflowRunJobStatusCount[];\n total: number;\n}\n\nexport interface WorkflowRun {\n id: string;\n projectId: string;\n definitionId: string;\n number: number | null;\n name: string;\n workflowName: string;\n currentAttempt: number;\n triggerProvider: string | null;\n triggerSource: string;\n triggerEvent: string;\n triggerDisplayLabel: string;\n triggerLabel: string;\n triggerPayload: Record<string, unknown>;\n triggerReference: WorkflowRunTriggerReference | null;\n inputs: Record<string, unknown> | null;\n sourceSnapshot: WorkflowSourceSnapshot | null;\n createdAt: string;\n updatedAt: string;\n isTemporary: boolean;\n}\n\n/** A run as the API returns it outside the list: no job strip, because none was fetched. */\nexport interface WorkflowRunRecord extends WorkflowRun {\n status: WorkflowRunStatus;\n latestAttempt: number;\n runAttempt: WorkflowRunAttemptSummary;\n}\n\nexport interface WorkflowRunListItem extends WorkflowRunRecord {\n jobs: WorkflowRunJobs;\n}\n\nexport interface WorkflowRunDetail extends WorkflowRun {\n latestAttempt: number;\n runAttempt: WorkflowRunAttempt;\n jobs: Job[];\n}\n\nexport interface WorkflowRunListPage {\n runs: WorkflowRunListItem[];\n nextCursor: string | null;\n filteredTotalCount: number | null;\n}\n\nexport interface ManualWorkflowLaunch {\n workflowRunId: string;\n}\n\nexport function workflowRunTriggerLabel({\n triggerSource,\n triggerEvent,\n}: {\n triggerSource: string;\n triggerEvent: string;\n}): string {\n return [triggerSource, triggerEvent].filter(Boolean).join(' · ');\n}\n\nexport function workflowRunTriggerDisplayLabel({\n triggerSource,\n triggerEvent,\n}: {\n triggerSource: string;\n triggerEvent: string;\n}): string {\n return triggerEvent || triggerSource;\n}\n\nconst SHORT_COMMIT_LENGTH = 7;\nconst PULL_REQUEST_REF_PATTERN = /^refs\\/pull\\/(\\d+)\\/head$/u;\n\n/**\n * The ref as a person names it: `main` for a branch, `#42` for a pull request, the tag for a\n * tag. An unrecognized ref is shown verbatim rather than hidden, since a ref nobody can read\n * is still better evidence than a blank cell.\n */\nexport function workflowRunBranchLabel(run: Pick<WorkflowRun, 'triggerReference'>): string | null {\n const ref = run.triggerReference?.ref;\n if (!ref) return null;\n const pullRequest = PULL_REQUEST_REF_PATTERN.exec(ref);\n if (pullRequest) return `#${pullRequest[1]}`;\n if (ref.startsWith('refs/heads/')) return ref.slice('refs/heads/'.length);\n if (ref.startsWith('refs/tags/')) return ref.slice('refs/tags/'.length);\n return ref;\n}\n\nexport function workflowRunCommitLabel(run: Pick<WorkflowRun, 'triggerReference'>): string | null {\n const commit = run.triggerReference?.commit;\n return commit ? commit.slice(0, SHORT_COMMIT_LENGTH) : null;\n}\n\nexport function workflowRunActor(run: Pick<WorkflowRun, 'triggerReference'>): string | null {\n return run.triggerReference?.actor ?? null;\n}\n\nexport function isWorkflowRunTerminal(status: WorkflowRunStatus): boolean {\n return TERMINAL_WORKFLOW_RUN_STATUS_SET.has(status);\n}\n\nexport function isWorkflowStatus(status: string): status is WorkflowStatus {\n return WORKFLOW_STATUSES.has(status as WorkflowStatus);\n}\n\n/**\n * A run's headline duration, split the way a job's already is. An attempt's `startedAt` marks\n * when the orchestrator picked the run up, not when work began, so a run whose jobs are all\n * still waiting for a runner reads as queue time rather than as run time.\n */\nexport type WorkflowRunDisplayDuration = JobExecutionDisplayDuration;\n\n/** What every surface shows for a run, derived together so status and duration cannot disagree. */\nexport interface WorkflowRunDisplay {\n status: WorkflowDisplayStatus;\n duration: WorkflowRunDisplayDuration | null;\n}\n\n/**\n * The evidence a surface can offer about a run's progress.\n *\n * `jobStatuses` is what every surface has: the list carries status counts, the detail carries\n * whole jobs. `firstStartedAt` is the detail's extra precision, and where it is absent the\n * attempt's own mark stands in.\n */\nexport interface WorkflowRunProgress {\n runStatus: WorkflowRunStatus;\n startedAt: string | null;\n finishedAt: string | null;\n jobStatuses: JobStatus[];\n firstStartedAt?: string | null | undefined;\n}\n\n/** When the run's earliest execution began, or null while none of them has. */\nexport function workflowRunFirstStartedAt(jobs: Job[]): string | null {\n let earliest: string | null = null;\n let earliestMs = Number.POSITIVE_INFINITY;\n\n for (const job of jobs) {\n for (const {startedAt} of job.jobExecutions) {\n if (startedAt === null) continue;\n const startedMs = new Date(startedAt).getTime();\n if (!Number.isFinite(startedMs) || startedMs >= earliestMs) continue;\n earliest = startedAt;\n earliestMs = startedMs;\n }\n }\n\n return earliest;\n}\n\n/**\n * Whether any work has begun. A run with no jobs on hand is a run whose jobs were not fetched,\n * which is no evidence that nothing started, so it counts as started rather than claiming a\n * queue this surface cannot see.\n */\nfunction workflowRunHasStarted({jobStatuses, firstStartedAt}: WorkflowRunProgress): boolean {\n if (firstStartedAt != null) return true;\n if (jobStatuses.length === 0) return true;\n return jobStatuses.some((status) => status !== 'pending' && status !== 'skipped');\n}\n\n/**\n * The single rule behind every run readout. An attempt's `startedAt` marks when the\n * orchestrator picked the run up, not when work began, so a run whose jobs are all still\n * waiting reads as `Queued` for queue time. Calling that \"running for 2h\" sends an operator to\n * debug a build that never began.\n */\nexport function deriveWorkflowRunDisplay(progress: WorkflowRunProgress): WorkflowRunDisplay {\n const {runStatus, startedAt, finishedAt, firstStartedAt} = progress;\n const hasStarted = workflowRunHasStarted(progress);\n const status = runStatus === 'running' && !hasStarted ? 'queued' : runStatus;\n\n if (startedAt === null) return {status, duration: null};\n\n // A run cancelled before anything started keeps its queue reading rather than reporting a\n // run that never was.\n const time = elapsedTimeFromTimestamps({from: firstStartedAt ?? startedAt, to: finishedAt});\n if (time === null) return {status, duration: null};\n\n return {status, duration: {kind: hasStarted ? 'run' : 'queue', ...time}};\n}\n\n/** The run detail's reading: whole jobs, so queue and run time split on the first execution. */\nexport function workflowRunDetailDisplay(run: {\n runAttempt: Pick<WorkflowRunAttemptSummary, 'status' | 'startedAt' | 'finishedAt'>;\n jobs: Job[];\n}): WorkflowRunDisplay {\n return deriveWorkflowRunDisplay({\n runStatus: run.runAttempt.status,\n startedAt: run.runAttempt.startedAt,\n finishedAt: run.runAttempt.finishedAt,\n jobStatuses: run.jobs.map((job) => job.status),\n firstStartedAt: workflowRunFirstStartedAt(run.jobs),\n });\n}\n\n/**\n * The run list's reading: status counts cover every job, not just the drawn preview, so a row\n * reaches the same verdict as the detail page without fetching a single timestamp more.\n */\nexport function workflowRunListItemDisplay(run: WorkflowRunListItem): WorkflowRunDisplay {\n return deriveWorkflowRunDisplay({\n runStatus: run.status,\n startedAt: run.runAttempt.startedAt,\n finishedAt: run.runAttempt.finishedAt,\n jobStatuses: run.jobs.statusCounts.filter(({count}) => count > 0).map(({status}) => status),\n });\n}\n\n/**\n * The job the run is waiting on: the one queued longest without starting. Named only so a\n * queued run says what it waits for instead of showing a number with no subject.\n */\nexport function workflowRunBlockingJob(jobs: Job[]): Job | null {\n let blocking: Job | null = null;\n let queuedMs = Number.POSITIVE_INFINITY;\n\n for (const job of jobs) {\n for (const {queuedAt, startedAt, finishedAt} of job.jobExecutions) {\n if (queuedAt === null || startedAt !== null || finishedAt !== null) continue;\n const candidateMs = new Date(queuedAt).getTime();\n if (!Number.isFinite(candidateMs) || candidateMs >= queuedMs) continue;\n blocking = job;\n queuedMs = candidateMs;\n }\n }\n\n return blocking;\n}\n"],"names":["WORKFLOW_JOB_STATUSES","elapsedTimeFromTimestamps","WORKFLOW_RUN_STATUSES","WORKFLOW_DISPLAY_STATUSES","TERMINAL_WORKFLOW_RUN_STATUSES","WORKFLOW_STATUSES","Set","TERMINAL_WORKFLOW_RUN_STATUS_SET","workflowRunTriggerLabel","triggerSource","triggerEvent","filter","Boolean","join","workflowRunTriggerDisplayLabel","SHORT_COMMIT_LENGTH","PULL_REQUEST_REF_PATTERN","workflowRunBranchLabel","run","ref","triggerReference","pullRequest","exec","startsWith","slice","length","workflowRunCommitLabel","commit","workflowRunActor","actor","isWorkflowRunTerminal","status","has","isWorkflowStatus","workflowRunFirstStartedAt","jobs","earliest","earliestMs","Number","POSITIVE_INFINITY","job","startedAt","jobExecutions","startedMs","Date","getTime","isFinite","workflowRunHasStarted","jobStatuses","firstStartedAt","some","deriveWorkflowRunDisplay","progress","runStatus","finishedAt","hasStarted","duration","time","from","to","kind","workflowRunDetailDisplay","runAttempt","map","workflowRunListItemDisplay","statusCounts","count","workflowRunBlockingJob","blocking","queuedMs","queuedAt","candidateMs"],"mappings":"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"}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import type { Job } from './workflow-run.js';
|
|
2
|
+
export type RunAnnotationStyle = 'default' | 'info' | 'success' | 'warning' | 'error';
|
|
3
|
+
/**
|
|
4
|
+
* The severities the run surfaces rank and filter by. The `default` style carries no severity:
|
|
5
|
+
* it counts toward the total and sorts last, but no severity filter selects it.
|
|
6
|
+
*/
|
|
7
|
+
export declare const RUN_ANNOTATION_SEVERITIES: readonly ['error', 'warning', 'info', 'success'];
|
|
8
|
+
export type RunAnnotationSeverity = (typeof RUN_ANNOTATION_SEVERITIES)[number];
|
|
9
|
+
export interface RunAnnotation {
|
|
10
|
+
id: string;
|
|
11
|
+
jobId: string;
|
|
12
|
+
jobExecutionId: string;
|
|
13
|
+
originStepId: string;
|
|
14
|
+
originStepAttempt: number;
|
|
15
|
+
context: string;
|
|
16
|
+
style: RunAnnotationStyle;
|
|
17
|
+
sequence: number;
|
|
18
|
+
}
|
|
19
|
+
export interface RunAnnotationRecord extends RunAnnotation {
|
|
20
|
+
body: string;
|
|
21
|
+
}
|
|
22
|
+
/** Counts shown by the run rail and the severity summary line. */
|
|
23
|
+
export interface RunAnnotationSummary {
|
|
24
|
+
total: number;
|
|
25
|
+
error: number;
|
|
26
|
+
warning: number;
|
|
27
|
+
info: number;
|
|
28
|
+
success: number;
|
|
29
|
+
/** True when the read hit its page budget, so every count is a lower bound. */
|
|
30
|
+
truncated: boolean;
|
|
31
|
+
}
|
|
32
|
+
/** Everything the annotations list needs to route back to the step that emitted an annotation. */
|
|
33
|
+
export interface RunAnnotationOrigin {
|
|
34
|
+
jobId: string;
|
|
35
|
+
jobExecutionId: string;
|
|
36
|
+
stepId: string;
|
|
37
|
+
stepAttemptId: string;
|
|
38
|
+
}
|
|
39
|
+
export interface RunAnnotationEntry {
|
|
40
|
+
annotation: RunAnnotationRecord;
|
|
41
|
+
jobName: string | null;
|
|
42
|
+
/** Only set when the job ran more than once, so a single-execution job stays uncluttered. */
|
|
43
|
+
executionLabel: string | null;
|
|
44
|
+
stepLabel: string | null;
|
|
45
|
+
attemptLabel: string;
|
|
46
|
+
/** `null` when the run attempt no longer contains the emitting step, so no link is offered. */
|
|
47
|
+
origin: RunAnnotationOrigin | null;
|
|
48
|
+
}
|
|
49
|
+
export declare function annotationSeverity(style: RunAnnotationStyle): RunAnnotationSeverity | null;
|
|
50
|
+
export declare function summarizeRunAnnotations(annotations: readonly RunAnnotation[], { truncated }?: {
|
|
51
|
+
truncated?: boolean | undefined;
|
|
52
|
+
}): RunAnnotationSummary;
|
|
53
|
+
export interface BuildRunAnnotationListInput {
|
|
54
|
+
annotations: readonly RunAnnotationRecord[];
|
|
55
|
+
jobs: readonly Job[];
|
|
56
|
+
severity?: RunAnnotationSeverity | undefined;
|
|
57
|
+
jobId?: string | undefined;
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Ranks annotations for display.
|
|
61
|
+
*
|
|
62
|
+
* Severity leads: emission order is a log affordance, not a summary affordance. `sequence` is
|
|
63
|
+
* only stable within one job execution, so the tie-break walks down job position and execution
|
|
64
|
+
* sequence before using it, and ends on the id so the order never depends on input order.
|
|
65
|
+
*/
|
|
66
|
+
export declare function buildRunAnnotationList({ annotations, jobs, severity, jobId, }: BuildRunAnnotationListInput): RunAnnotationEntry[];
|
|
67
|
+
/** Counts annotations owned by one job, for the job page's bounded reference chip. */
|
|
68
|
+
export declare function summarizeJobAnnotations(annotations: readonly RunAnnotation[], jobId: string, options?: {
|
|
69
|
+
truncated?: boolean | undefined;
|
|
70
|
+
}): RunAnnotationSummary;
|
|
71
|
+
/** The loudest severity present, which tints a count chip. */
|
|
72
|
+
export declare function highestRunAnnotationSeverity(summary: RunAnnotationSummary): RunAnnotationSeverity | null;
|
|
73
|
+
//# sourceMappingURL=run-annotation.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"run-annotation.d.ts","sourceRoot":"","sources":["../../src/core/run-annotation.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,GAAG,EAAC,MAAM,mBAAmB,CAAC;AAE3C,MAAM,MAAM,kBAAkB,GAAG,SAAS,GAAG,MAAM,GAAG,SAAS,GAAG,SAAS,GAAG,OAAO,CAAC;AAEtF;;;GAGG;AACH,eAAO,MAAM,yBAAyB,YAAI,OAAO,EAAE,SAAS,EAAE,MAAM,EAAE,SAAS,CAAU,CAAC;AAE1F,MAAM,MAAM,qBAAqB,GAAG,CAAC,OAAO,yBAAyB,CAAC,CAAC,MAAM,CAAC,CAAC;AAY/E,MAAM,WAAW,aAAa;IAC5B,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,cAAc,EAAE,MAAM,CAAC;IACvB,YAAY,EAAE,MAAM,CAAC;IACrB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,kBAAkB,CAAC;IAC1B,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,mBAAoB,SAAQ,aAAa;IACxD,IAAI,EAAE,MAAM,CAAC;CACd;AAED,kEAAkE;AAClE,MAAM,WAAW,oBAAoB;IACnC,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,+EAA+E;IAC/E,SAAS,EAAE,OAAO,CAAC;CACpB;AAED,kGAAkG;AAClG,MAAM,WAAW,mBAAmB;IAClC,KAAK,EAAE,MAAM,CAAC;IACd,cAAc,EAAE,MAAM,CAAC;IACvB,MAAM,EAAE,MAAM,CAAC;IACf,aAAa,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,kBAAkB;IACjC,UAAU,EAAE,mBAAmB,CAAC;IAChC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,6FAA6F;IAC7F,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,YAAY,EAAE,MAAM,CAAC;IACrB,+FAA+F;IAC/F,MAAM,EAAE,mBAAmB,GAAG,IAAI,CAAC;CACpC;AAED,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,kBAAkB,GAAG,qBAAqB,GAAG,IAAI,CAE1F;AAED,wBAAgB,uBAAuB,CACrC,WAAW,EAAE,SAAS,aAAa,EAAE,EACrC,EAAC,SAAiB,EAAC,GAAE;IAAC,SAAS,CAAC,EAAE,OAAO,GAAG,SAAS,CAAA;CAAM,GAC1D,oBAAoB,CAgBtB;AAED,MAAM,WAAW,2BAA2B;IAC1C,WAAW,EAAE,SAAS,mBAAmB,EAAE,CAAC;IAC5C,IAAI,EAAE,SAAS,GAAG,EAAE,CAAC;IACrB,QAAQ,CAAC,EAAE,qBAAqB,GAAG,SAAS,CAAC;IAC7C,KAAK,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CAC5B;AAED;;;;;;GAMG;AACH,wBAAgB,sBAAsB,CAAC,EACrC,WAAW,EACX,IAAI,EACJ,QAAQ,EACR,KAAK,GACN,EAAE,2BAA2B,GAAG,kBAAkB,EAAE,CAYpD;AAED,sFAAsF;AACtF,wBAAgB,uBAAuB,CACrC,WAAW,EAAE,SAAS,aAAa,EAAE,EACrC,KAAK,EAAE,MAAM,EACb,OAAO,GAAE;IAAC,SAAS,CAAC,EAAE,OAAO,GAAG,SAAS,CAAA;CAAM,GAC9C,oBAAoB,CAKtB;AAED,8DAA8D;AAC9D,wBAAgB,4BAA4B,CAC1C,OAAO,EAAE,oBAAoB,GAC5B,qBAAqB,GAAG,IAAI,CAE9B"}
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The severities the run surfaces rank and filter by. The `default` style carries no severity:
|
|
3
|
+
* it counts toward the total and sorts last, but no severity filter selects it.
|
|
4
|
+
*/ export const RUN_ANNOTATION_SEVERITIES = [
|
|
5
|
+
'error',
|
|
6
|
+
'warning',
|
|
7
|
+
'info',
|
|
8
|
+
'success'
|
|
9
|
+
];
|
|
10
|
+
const SEVERITY_RANK = {
|
|
11
|
+
error: 0,
|
|
12
|
+
warning: 1,
|
|
13
|
+
info: 2,
|
|
14
|
+
success: 3,
|
|
15
|
+
default: 4
|
|
16
|
+
};
|
|
17
|
+
const SEVERITY_SET = new Set(RUN_ANNOTATION_SEVERITIES);
|
|
18
|
+
export function annotationSeverity(style) {
|
|
19
|
+
return SEVERITY_SET.has(style) ? style : null;
|
|
20
|
+
}
|
|
21
|
+
export function summarizeRunAnnotations(annotations, { truncated = false } = {}) {
|
|
22
|
+
const summary = {
|
|
23
|
+
total: annotations.length,
|
|
24
|
+
error: 0,
|
|
25
|
+
warning: 0,
|
|
26
|
+
info: 0,
|
|
27
|
+
success: 0,
|
|
28
|
+
truncated
|
|
29
|
+
};
|
|
30
|
+
for (const annotation of annotations){
|
|
31
|
+
const severity = annotationSeverity(annotation.style);
|
|
32
|
+
if (severity) summary[severity] += 1;
|
|
33
|
+
}
|
|
34
|
+
return summary;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Ranks annotations for display.
|
|
38
|
+
*
|
|
39
|
+
* Severity leads: emission order is a log affordance, not a summary affordance. `sequence` is
|
|
40
|
+
* only stable within one job execution, so the tie-break walks down job position and execution
|
|
41
|
+
* sequence before using it, and ends on the id so the order never depends on input order.
|
|
42
|
+
*/ export function buildRunAnnotationList({ annotations, jobs, severity, jobId }) {
|
|
43
|
+
const index = indexJobs(jobs);
|
|
44
|
+
const entries = [];
|
|
45
|
+
for (const annotation of annotations){
|
|
46
|
+
if (jobId && annotation.jobId !== jobId) continue;
|
|
47
|
+
const annotationSeverityValue = annotationSeverity(annotation.style);
|
|
48
|
+
if (severity && annotationSeverityValue !== severity) continue;
|
|
49
|
+
entries.push(toEntry(annotation, index));
|
|
50
|
+
}
|
|
51
|
+
return entries.sort((left, right)=>compareEntries(left, right, index));
|
|
52
|
+
}
|
|
53
|
+
/** Counts annotations owned by one job, for the job page's bounded reference chip. */ export function summarizeJobAnnotations(annotations, jobId, options = {}) {
|
|
54
|
+
return summarizeRunAnnotations(annotations.filter((annotation)=>annotation.jobId === jobId), options);
|
|
55
|
+
}
|
|
56
|
+
/** The loudest severity present, which tints a count chip. */ export function highestRunAnnotationSeverity(summary) {
|
|
57
|
+
return RUN_ANNOTATION_SEVERITIES.find((severity)=>summary[severity] > 0) ?? null;
|
|
58
|
+
}
|
|
59
|
+
function indexJobs(jobs) {
|
|
60
|
+
const index = new Map();
|
|
61
|
+
for (const job of jobs){
|
|
62
|
+
const executions = new Map();
|
|
63
|
+
for (const execution of job.jobExecutions){
|
|
64
|
+
const steps = new Map();
|
|
65
|
+
for (const step of execution.steps){
|
|
66
|
+
const attemptIds = new Map();
|
|
67
|
+
for (const attempt of step.attempts)attemptIds.set(attempt.attempt, attempt.id);
|
|
68
|
+
steps.set(step.id, {
|
|
69
|
+
label: step.name || step.key || step.id,
|
|
70
|
+
attemptIds
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
executions.set(execution.id, {
|
|
74
|
+
sequence: execution.sequence,
|
|
75
|
+
steps
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
index.set(job.id, {
|
|
79
|
+
position: job.position,
|
|
80
|
+
name: job.displayName,
|
|
81
|
+
executionCount: job.jobExecutions.length,
|
|
82
|
+
executions
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
return index;
|
|
86
|
+
}
|
|
87
|
+
function toEntry(annotation, index) {
|
|
88
|
+
const job = index.get(annotation.jobId);
|
|
89
|
+
const execution = job?.executions.get(annotation.jobExecutionId);
|
|
90
|
+
const step = execution?.steps.get(annotation.originStepId);
|
|
91
|
+
const stepAttemptId = step?.attemptIds.get(annotation.originStepAttempt);
|
|
92
|
+
return {
|
|
93
|
+
annotation,
|
|
94
|
+
jobName: job?.name ?? null,
|
|
95
|
+
executionLabel: execution && job && job.executionCount > 1 ? `execution #${execution.sequence}` : null,
|
|
96
|
+
stepLabel: step?.label ?? null,
|
|
97
|
+
attemptLabel: `attempt ${annotation.originStepAttempt}`,
|
|
98
|
+
origin: stepAttemptId ? {
|
|
99
|
+
jobId: annotation.jobId,
|
|
100
|
+
jobExecutionId: annotation.jobExecutionId,
|
|
101
|
+
stepId: annotation.originStepId,
|
|
102
|
+
stepAttemptId
|
|
103
|
+
} : null
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
function compareEntries(left, right, index) {
|
|
107
|
+
const bySeverity = SEVERITY_RANK[left.annotation.style] - SEVERITY_RANK[right.annotation.style];
|
|
108
|
+
if (bySeverity !== 0) return bySeverity;
|
|
109
|
+
const byJob = jobPosition(left, index) - jobPosition(right, index);
|
|
110
|
+
if (byJob !== 0) return byJob;
|
|
111
|
+
const byExecution = executionSequence(left, index) - executionSequence(right, index);
|
|
112
|
+
if (byExecution !== 0) return byExecution;
|
|
113
|
+
const bySequence = left.annotation.sequence - right.annotation.sequence;
|
|
114
|
+
if (bySequence !== 0) return bySequence;
|
|
115
|
+
return left.annotation.id.localeCompare(right.annotation.id);
|
|
116
|
+
}
|
|
117
|
+
/** An unmatched job sorts last rather than first, so known provenance leads the list. */ function jobPosition(entry, index) {
|
|
118
|
+
return index.get(entry.annotation.jobId)?.position ?? Number.MAX_SAFE_INTEGER;
|
|
119
|
+
}
|
|
120
|
+
function executionSequence(entry, index) {
|
|
121
|
+
const job = index.get(entry.annotation.jobId);
|
|
122
|
+
return job?.executions.get(entry.annotation.jobExecutionId)?.sequence ?? Number.MAX_SAFE_INTEGER;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
//# sourceMappingURL=run-annotation.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/core/run-annotation.ts"],"sourcesContent":["import type {Job} from './workflow-run.js';\n\nexport type RunAnnotationStyle = 'default' | 'info' | 'success' | 'warning' | 'error';\n\n/**\n * The severities the run surfaces rank and filter by. The `default` style carries no severity:\n * it counts toward the total and sorts last, but no severity filter selects it.\n */\nexport const RUN_ANNOTATION_SEVERITIES = ['error', 'warning', 'info', 'success'] as const;\n\nexport type RunAnnotationSeverity = (typeof RUN_ANNOTATION_SEVERITIES)[number];\n\nconst SEVERITY_RANK: Record<RunAnnotationStyle, number> = {\n error: 0,\n warning: 1,\n info: 2,\n success: 3,\n default: 4,\n};\n\nconst SEVERITY_SET = new Set<string>(RUN_ANNOTATION_SEVERITIES);\n\nexport interface RunAnnotation {\n id: string;\n jobId: string;\n jobExecutionId: string;\n originStepId: string;\n originStepAttempt: number;\n context: string;\n style: RunAnnotationStyle;\n sequence: number;\n}\n\nexport interface RunAnnotationRecord extends RunAnnotation {\n body: string;\n}\n\n/** Counts shown by the run rail and the severity summary line. */\nexport interface RunAnnotationSummary {\n total: number;\n error: number;\n warning: number;\n info: number;\n success: number;\n /** True when the read hit its page budget, so every count is a lower bound. */\n truncated: boolean;\n}\n\n/** Everything the annotations list needs to route back to the step that emitted an annotation. */\nexport interface RunAnnotationOrigin {\n jobId: string;\n jobExecutionId: string;\n stepId: string;\n stepAttemptId: string;\n}\n\nexport interface RunAnnotationEntry {\n annotation: RunAnnotationRecord;\n jobName: string | null;\n /** Only set when the job ran more than once, so a single-execution job stays uncluttered. */\n executionLabel: string | null;\n stepLabel: string | null;\n attemptLabel: string;\n /** `null` when the run attempt no longer contains the emitting step, so no link is offered. */\n origin: RunAnnotationOrigin | null;\n}\n\nexport function annotationSeverity(style: RunAnnotationStyle): RunAnnotationSeverity | null {\n return SEVERITY_SET.has(style) ? (style as RunAnnotationSeverity) : null;\n}\n\nexport function summarizeRunAnnotations(\n annotations: readonly RunAnnotation[],\n {truncated = false}: {truncated?: boolean | undefined} = {},\n): RunAnnotationSummary {\n const summary: RunAnnotationSummary = {\n total: annotations.length,\n error: 0,\n warning: 0,\n info: 0,\n success: 0,\n truncated,\n };\n\n for (const annotation of annotations) {\n const severity = annotationSeverity(annotation.style);\n if (severity) summary[severity] += 1;\n }\n\n return summary;\n}\n\nexport interface BuildRunAnnotationListInput {\n annotations: readonly RunAnnotationRecord[];\n jobs: readonly Job[];\n severity?: RunAnnotationSeverity | undefined;\n jobId?: string | undefined;\n}\n\n/**\n * Ranks annotations for display.\n *\n * Severity leads: emission order is a log affordance, not a summary affordance. `sequence` is\n * only stable within one job execution, so the tie-break walks down job position and execution\n * sequence before using it, and ends on the id so the order never depends on input order.\n */\nexport function buildRunAnnotationList({\n annotations,\n jobs,\n severity,\n jobId,\n}: BuildRunAnnotationListInput): RunAnnotationEntry[] {\n const index = indexJobs(jobs);\n const entries: RunAnnotationEntry[] = [];\n\n for (const annotation of annotations) {\n if (jobId && annotation.jobId !== jobId) continue;\n const annotationSeverityValue = annotationSeverity(annotation.style);\n if (severity && annotationSeverityValue !== severity) continue;\n entries.push(toEntry(annotation, index));\n }\n\n return entries.sort((left, right) => compareEntries(left, right, index));\n}\n\n/** Counts annotations owned by one job, for the job page's bounded reference chip. */\nexport function summarizeJobAnnotations(\n annotations: readonly RunAnnotation[],\n jobId: string,\n options: {truncated?: boolean | undefined} = {},\n): RunAnnotationSummary {\n return summarizeRunAnnotations(\n annotations.filter((annotation) => annotation.jobId === jobId),\n options,\n );\n}\n\n/** The loudest severity present, which tints a count chip. */\nexport function highestRunAnnotationSeverity(\n summary: RunAnnotationSummary,\n): RunAnnotationSeverity | null {\n return RUN_ANNOTATION_SEVERITIES.find((severity) => summary[severity] > 0) ?? null;\n}\n\ninterface JobIndexEntry {\n position: number;\n name: string;\n executionCount: number;\n executions: Map<string, JobExecutionIndexEntry>;\n}\n\ninterface JobExecutionIndexEntry {\n sequence: number;\n steps: Map<string, {label: string; attemptIds: Map<number, string>}>;\n}\n\nfunction indexJobs(jobs: readonly Job[]): Map<string, JobIndexEntry> {\n const index = new Map<string, JobIndexEntry>();\n\n for (const job of jobs) {\n const executions = new Map<string, JobExecutionIndexEntry>();\n for (const execution of job.jobExecutions) {\n const steps = new Map<string, {label: string; attemptIds: Map<number, string>}>();\n for (const step of execution.steps) {\n const attemptIds = new Map<number, string>();\n for (const attempt of step.attempts) attemptIds.set(attempt.attempt, attempt.id);\n steps.set(step.id, {label: step.name || step.key || step.id, attemptIds});\n }\n executions.set(execution.id, {sequence: execution.sequence, steps});\n }\n\n index.set(job.id, {\n position: job.position,\n name: job.displayName,\n executionCount: job.jobExecutions.length,\n executions,\n });\n }\n\n return index;\n}\n\nfunction toEntry(\n annotation: RunAnnotationRecord,\n index: Map<string, JobIndexEntry>,\n): RunAnnotationEntry {\n const job = index.get(annotation.jobId);\n const execution = job?.executions.get(annotation.jobExecutionId);\n const step = execution?.steps.get(annotation.originStepId);\n const stepAttemptId = step?.attemptIds.get(annotation.originStepAttempt);\n\n return {\n annotation,\n jobName: job?.name ?? null,\n executionLabel:\n execution && job && job.executionCount > 1 ? `execution #${execution.sequence}` : null,\n stepLabel: step?.label ?? null,\n attemptLabel: `attempt ${annotation.originStepAttempt}`,\n origin: stepAttemptId\n ? {\n jobId: annotation.jobId,\n jobExecutionId: annotation.jobExecutionId,\n stepId: annotation.originStepId,\n stepAttemptId,\n }\n : null,\n };\n}\n\nfunction compareEntries(\n left: RunAnnotationEntry,\n right: RunAnnotationEntry,\n index: Map<string, JobIndexEntry>,\n): number {\n const bySeverity = SEVERITY_RANK[left.annotation.style] - SEVERITY_RANK[right.annotation.style];\n if (bySeverity !== 0) return bySeverity;\n\n const byJob = jobPosition(left, index) - jobPosition(right, index);\n if (byJob !== 0) return byJob;\n\n const byExecution = executionSequence(left, index) - executionSequence(right, index);\n if (byExecution !== 0) return byExecution;\n\n const bySequence = left.annotation.sequence - right.annotation.sequence;\n if (bySequence !== 0) return bySequence;\n\n return left.annotation.id.localeCompare(right.annotation.id);\n}\n\n/** An unmatched job sorts last rather than first, so known provenance leads the list. */\nfunction jobPosition(entry: RunAnnotationEntry, index: Map<string, JobIndexEntry>): number {\n return index.get(entry.annotation.jobId)?.position ?? Number.MAX_SAFE_INTEGER;\n}\n\nfunction executionSequence(entry: RunAnnotationEntry, index: Map<string, JobIndexEntry>): number {\n const job = index.get(entry.annotation.jobId);\n return job?.executions.get(entry.annotation.jobExecutionId)?.sequence ?? Number.MAX_SAFE_INTEGER;\n}\n"],"names":["RUN_ANNOTATION_SEVERITIES","SEVERITY_RANK","error","warning","info","success","default","SEVERITY_SET","Set","annotationSeverity","style","has","summarizeRunAnnotations","annotations","truncated","summary","total","length","annotation","severity","buildRunAnnotationList","jobs","jobId","index","indexJobs","entries","annotationSeverityValue","push","toEntry","sort","left","right","compareEntries","summarizeJobAnnotations","options","filter","highestRunAnnotationSeverity","find","Map","job","executions","execution","jobExecutions","steps","step","attemptIds","attempt","attempts","set","id","label","name","key","sequence","position","displayName","executionCount","get","jobExecutionId","originStepId","stepAttemptId","originStepAttempt","jobName","executionLabel","stepLabel","attemptLabel","origin","stepId","bySeverity","byJob","jobPosition","byExecution","executionSequence","bySequence","localeCompare","entry","Number","MAX_SAFE_INTEGER"],"mappings":"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"}
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
export type { JobDisplayDuration, JobDisplayStatus, JobListening, JobMode, JobStatus, JobStatusReason, ListenerStatus, ResolutionReason, } from './entities/job.js';
|
|
2
2
|
export { defaultJobExecution, deriveJobDisplayStatus, isTerminalJobStatus, Job, resolveJobExecution, TERMINAL_WORKFLOW_JOB_STATUSES, WORKFLOW_JOB_STATUSES, } from './entities/job.js';
|
|
3
3
|
export type { JobExecutionDisplayDuration, JobExecutionDisplayStatus, JobExecutionStatus, JobExecutionTime, WorkflowExecutionEvent, } from './entities/job-execution.js';
|
|
4
|
-
export { deriveJobExecutionDisplayStatus, isTerminalJobExecutionStatus, JobExecution, } from './entities/job-execution.js';
|
|
4
|
+
export { deriveJobExecutionDisplayStatus, elapsedTimeFromTimestamps, isTerminalJobExecutionStatus, JobExecution, } from './entities/job-execution.js';
|
|
5
5
|
export type { AgentConfigIssue, AgentStepConfig, Step, StepError, StepErrorCategory, StepErrorReason, StepSourceLocation, } from './entities/step.js';
|
|
6
|
-
export { AGENT_CONFIG_ISSUES, STEP_ERROR_REASONS } from './entities/step.js';
|
|
6
|
+
export { AGENT_CONFIG_ISSUES, compareStepAttempts, resolveStepAttempt, STEP_ERROR_REASONS, } from './entities/step.js';
|
|
7
7
|
export type { StepAttemptDisplayDuration, StepGateResult, } from './entities/step-attempt.js';
|
|
8
8
|
export { StepAttempt } from './entities/step-attempt.js';
|
|
9
|
-
export type { ManualWorkflowLaunch, WorkflowDisplayStatus, WorkflowRun, WorkflowRunDetail, WorkflowRunJobStatusCount, WorkflowRunJobSummary, WorkflowRunJobs, WorkflowRunListItem, WorkflowRunListPage, WorkflowRunRecord, WorkflowRunRerunMode, WorkflowRunStatus, WorkflowRunTriggerReference, WorkflowSourceSnapshot, WorkflowStatus, } from './entities/workflow-run.js';
|
|
10
|
-
export { isWorkflowRunTerminal, isWorkflowStatus, TERMINAL_WORKFLOW_RUN_STATUSES, WORKFLOW_RUN_STATUSES, workflowRunActor, workflowRunBranchLabel, workflowRunCommitLabel, workflowRunTriggerDisplayLabel, workflowRunTriggerLabel, } from './entities/workflow-run.js';
|
|
9
|
+
export type { ManualWorkflowLaunch, WorkflowDisplayStatus, WorkflowRun, WorkflowRunDetail, WorkflowRunDisplay, WorkflowRunDisplayDuration, WorkflowRunJobStatusCount, WorkflowRunJobSummary, WorkflowRunJobs, WorkflowRunListItem, WorkflowRunListPage, WorkflowRunProgress, WorkflowRunRecord, WorkflowRunRerunMode, WorkflowRunStatus, WorkflowRunTriggerReference, WorkflowSourceSnapshot, WorkflowStatus, } from './entities/workflow-run.js';
|
|
10
|
+
export { deriveWorkflowRunDisplay, isWorkflowRunTerminal, isWorkflowStatus, TERMINAL_WORKFLOW_RUN_STATUSES, WORKFLOW_DISPLAY_STATUSES, WORKFLOW_RUN_STATUSES, workflowRunActor, workflowRunBlockingJob, workflowRunBranchLabel, workflowRunCommitLabel, workflowRunDetailDisplay, workflowRunFirstStartedAt, workflowRunListItemDisplay, workflowRunTriggerDisplayLabel, workflowRunTriggerLabel, } from './entities/workflow-run.js';
|
|
11
11
|
export type { WorkflowRunAttemptDisplayDuration } from './entities/workflow-run-attempt.js';
|
|
12
12
|
export { WorkflowRunAttempt, WorkflowRunAttemptSummary } from './entities/workflow-run-attempt.js';
|
|
13
13
|
//# sourceMappingURL=workflow-run.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"workflow-run.d.ts","sourceRoot":"","sources":["../../src/core/workflow-run.ts"],"names":[],"mappings":"AAAA,YAAY,EACV,kBAAkB,EAClB,gBAAgB,EAChB,YAAY,EACZ,OAAO,EACP,SAAS,EACT,eAAe,EACf,cAAc,EACd,gBAAgB,GACjB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EACL,mBAAmB,EACnB,sBAAsB,EACtB,mBAAmB,EACnB,GAAG,EACH,mBAAmB,EACnB,8BAA8B,EAC9B,qBAAqB,GACtB,MAAM,mBAAmB,CAAC;AAC3B,YAAY,EACV,2BAA2B,EAC3B,yBAAyB,EACzB,kBAAkB,EAClB,gBAAgB,EAChB,sBAAsB,GACvB,MAAM,6BAA6B,CAAC;AACrC,OAAO,EACL,+BAA+B,EAC/B,4BAA4B,EAC5B,YAAY,GACb,MAAM,6BAA6B,CAAC;AACrC,YAAY,EACV,gBAAgB,EAChB,eAAe,EACf,IAAI,EACJ,SAAS,EACT,iBAAiB,EACjB,eAAe,EACf,kBAAkB,GACnB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,
|
|
1
|
+
{"version":3,"file":"workflow-run.d.ts","sourceRoot":"","sources":["../../src/core/workflow-run.ts"],"names":[],"mappings":"AAAA,YAAY,EACV,kBAAkB,EAClB,gBAAgB,EAChB,YAAY,EACZ,OAAO,EACP,SAAS,EACT,eAAe,EACf,cAAc,EACd,gBAAgB,GACjB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EACL,mBAAmB,EACnB,sBAAsB,EACtB,mBAAmB,EACnB,GAAG,EACH,mBAAmB,EACnB,8BAA8B,EAC9B,qBAAqB,GACtB,MAAM,mBAAmB,CAAC;AAC3B,YAAY,EACV,2BAA2B,EAC3B,yBAAyB,EACzB,kBAAkB,EAClB,gBAAgB,EAChB,sBAAsB,GACvB,MAAM,6BAA6B,CAAC;AACrC,OAAO,EACL,+BAA+B,EAC/B,yBAAyB,EACzB,4BAA4B,EAC5B,YAAY,GACb,MAAM,6BAA6B,CAAC;AACrC,YAAY,EACV,gBAAgB,EAChB,eAAe,EACf,IAAI,EACJ,SAAS,EACT,iBAAiB,EACjB,eAAe,EACf,kBAAkB,GACnB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EACL,mBAAmB,EACnB,mBAAmB,EACnB,kBAAkB,EAClB,kBAAkB,GACnB,MAAM,oBAAoB,CAAC;AAC5B,YAAY,EACV,0BAA0B,EAC1B,cAAc,GACf,MAAM,4BAA4B,CAAC;AACpC,OAAO,EAAC,WAAW,EAAC,MAAM,4BAA4B,CAAC;AACvD,YAAY,EACV,oBAAoB,EACpB,qBAAqB,EACrB,WAAW,EACX,iBAAiB,EACjB,kBAAkB,EAClB,0BAA0B,EAC1B,yBAAyB,EACzB,qBAAqB,EACrB,eAAe,EACf,mBAAmB,EACnB,mBAAmB,EACnB,mBAAmB,EACnB,iBAAiB,EACjB,oBAAoB,EACpB,iBAAiB,EACjB,2BAA2B,EAC3B,sBAAsB,EACtB,cAAc,GACf,MAAM,4BAA4B,CAAC;AACpC,OAAO,EACL,wBAAwB,EACxB,qBAAqB,EACrB,gBAAgB,EAChB,8BAA8B,EAC9B,yBAAyB,EACzB,qBAAqB,EACrB,gBAAgB,EAChB,sBAAsB,EACtB,sBAAsB,EACtB,sBAAsB,EACtB,wBAAwB,EACxB,yBAAyB,EACzB,0BAA0B,EAC1B,8BAA8B,EAC9B,uBAAuB,GACxB,MAAM,4BAA4B,CAAC;AACpC,YAAY,EAAC,iCAAiC,EAAC,MAAM,oCAAoC,CAAC;AAC1F,OAAO,EAAC,kBAAkB,EAAE,yBAAyB,EAAC,MAAM,oCAAoC,CAAC"}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
export { defaultJobExecution, deriveJobDisplayStatus, isTerminalJobStatus, Job, resolveJobExecution, TERMINAL_WORKFLOW_JOB_STATUSES, WORKFLOW_JOB_STATUSES } from './entities/job.js';
|
|
2
|
-
export { deriveJobExecutionDisplayStatus, isTerminalJobExecutionStatus, JobExecution } from './entities/job-execution.js';
|
|
3
|
-
export { AGENT_CONFIG_ISSUES, STEP_ERROR_REASONS } from './entities/step.js';
|
|
2
|
+
export { deriveJobExecutionDisplayStatus, elapsedTimeFromTimestamps, isTerminalJobExecutionStatus, JobExecution } from './entities/job-execution.js';
|
|
3
|
+
export { AGENT_CONFIG_ISSUES, compareStepAttempts, resolveStepAttempt, STEP_ERROR_REASONS } from './entities/step.js';
|
|
4
4
|
export { StepAttempt } from './entities/step-attempt.js';
|
|
5
|
-
export { isWorkflowRunTerminal, isWorkflowStatus, TERMINAL_WORKFLOW_RUN_STATUSES, WORKFLOW_RUN_STATUSES, workflowRunActor, workflowRunBranchLabel, workflowRunCommitLabel, workflowRunTriggerDisplayLabel, workflowRunTriggerLabel } from './entities/workflow-run.js';
|
|
5
|
+
export { deriveWorkflowRunDisplay, isWorkflowRunTerminal, isWorkflowStatus, TERMINAL_WORKFLOW_RUN_STATUSES, WORKFLOW_DISPLAY_STATUSES, WORKFLOW_RUN_STATUSES, workflowRunActor, workflowRunBlockingJob, workflowRunBranchLabel, workflowRunCommitLabel, workflowRunDetailDisplay, workflowRunFirstStartedAt, workflowRunListItemDisplay, workflowRunTriggerDisplayLabel, workflowRunTriggerLabel } from './entities/workflow-run.js';
|
|
6
6
|
export { WorkflowRunAttempt, WorkflowRunAttemptSummary } from './entities/workflow-run-attempt.js';
|
|
7
7
|
|
|
8
8
|
//# sourceMappingURL=workflow-run.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/core/workflow-run.ts"],"sourcesContent":["export type {\n JobDisplayDuration,\n JobDisplayStatus,\n JobListening,\n JobMode,\n JobStatus,\n JobStatusReason,\n ListenerStatus,\n ResolutionReason,\n} from './entities/job.js';\nexport {\n defaultJobExecution,\n deriveJobDisplayStatus,\n isTerminalJobStatus,\n Job,\n resolveJobExecution,\n TERMINAL_WORKFLOW_JOB_STATUSES,\n WORKFLOW_JOB_STATUSES,\n} from './entities/job.js';\nexport type {\n JobExecutionDisplayDuration,\n JobExecutionDisplayStatus,\n JobExecutionStatus,\n JobExecutionTime,\n WorkflowExecutionEvent,\n} from './entities/job-execution.js';\nexport {\n deriveJobExecutionDisplayStatus,\n isTerminalJobExecutionStatus,\n JobExecution,\n} from './entities/job-execution.js';\nexport type {\n AgentConfigIssue,\n AgentStepConfig,\n Step,\n StepError,\n StepErrorCategory,\n StepErrorReason,\n StepSourceLocation,\n} from './entities/step.js';\nexport {AGENT_CONFIG_ISSUES
|
|
1
|
+
{"version":3,"sources":["../../src/core/workflow-run.ts"],"sourcesContent":["export type {\n JobDisplayDuration,\n JobDisplayStatus,\n JobListening,\n JobMode,\n JobStatus,\n JobStatusReason,\n ListenerStatus,\n ResolutionReason,\n} from './entities/job.js';\nexport {\n defaultJobExecution,\n deriveJobDisplayStatus,\n isTerminalJobStatus,\n Job,\n resolveJobExecution,\n TERMINAL_WORKFLOW_JOB_STATUSES,\n WORKFLOW_JOB_STATUSES,\n} from './entities/job.js';\nexport type {\n JobExecutionDisplayDuration,\n JobExecutionDisplayStatus,\n JobExecutionStatus,\n JobExecutionTime,\n WorkflowExecutionEvent,\n} from './entities/job-execution.js';\nexport {\n deriveJobExecutionDisplayStatus,\n elapsedTimeFromTimestamps,\n isTerminalJobExecutionStatus,\n JobExecution,\n} from './entities/job-execution.js';\nexport type {\n AgentConfigIssue,\n AgentStepConfig,\n Step,\n StepError,\n StepErrorCategory,\n StepErrorReason,\n StepSourceLocation,\n} from './entities/step.js';\nexport {\n AGENT_CONFIG_ISSUES,\n compareStepAttempts,\n resolveStepAttempt,\n STEP_ERROR_REASONS,\n} from './entities/step.js';\nexport type {\n StepAttemptDisplayDuration,\n StepGateResult,\n} from './entities/step-attempt.js';\nexport {StepAttempt} from './entities/step-attempt.js';\nexport type {\n ManualWorkflowLaunch,\n WorkflowDisplayStatus,\n WorkflowRun,\n WorkflowRunDetail,\n WorkflowRunDisplay,\n WorkflowRunDisplayDuration,\n WorkflowRunJobStatusCount,\n WorkflowRunJobSummary,\n WorkflowRunJobs,\n WorkflowRunListItem,\n WorkflowRunListPage,\n WorkflowRunProgress,\n WorkflowRunRecord,\n WorkflowRunRerunMode,\n WorkflowRunStatus,\n WorkflowRunTriggerReference,\n WorkflowSourceSnapshot,\n WorkflowStatus,\n} from './entities/workflow-run.js';\nexport {\n deriveWorkflowRunDisplay,\n isWorkflowRunTerminal,\n isWorkflowStatus,\n TERMINAL_WORKFLOW_RUN_STATUSES,\n WORKFLOW_DISPLAY_STATUSES,\n WORKFLOW_RUN_STATUSES,\n workflowRunActor,\n workflowRunBlockingJob,\n workflowRunBranchLabel,\n workflowRunCommitLabel,\n workflowRunDetailDisplay,\n workflowRunFirstStartedAt,\n workflowRunListItemDisplay,\n workflowRunTriggerDisplayLabel,\n workflowRunTriggerLabel,\n} from './entities/workflow-run.js';\nexport type {WorkflowRunAttemptDisplayDuration} from './entities/workflow-run-attempt.js';\nexport {WorkflowRunAttempt, WorkflowRunAttemptSummary} from './entities/workflow-run-attempt.js';\n"],"names":["defaultJobExecution","deriveJobDisplayStatus","isTerminalJobStatus","Job","resolveJobExecution","TERMINAL_WORKFLOW_JOB_STATUSES","WORKFLOW_JOB_STATUSES","deriveJobExecutionDisplayStatus","elapsedTimeFromTimestamps","isTerminalJobExecutionStatus","JobExecution","AGENT_CONFIG_ISSUES","compareStepAttempts","resolveStepAttempt","STEP_ERROR_REASONS","StepAttempt","deriveWorkflowRunDisplay","isWorkflowRunTerminal","isWorkflowStatus","TERMINAL_WORKFLOW_RUN_STATUSES","WORKFLOW_DISPLAY_STATUSES","WORKFLOW_RUN_STATUSES","workflowRunActor","workflowRunBlockingJob","workflowRunBranchLabel","workflowRunCommitLabel","workflowRunDetailDisplay","workflowRunFirstStartedAt","workflowRunListItemDisplay","workflowRunTriggerDisplayLabel","workflowRunTriggerLabel","WorkflowRunAttempt","WorkflowRunAttemptSummary"],"mappings":"AAUA,SACEA,mBAAmB,EACnBC,sBAAsB,EACtBC,mBAAmB,EACnBC,GAAG,EACHC,mBAAmB,EACnBC,8BAA8B,EAC9BC,qBAAqB,QAChB,oBAAoB;AAQ3B,SACEC,+BAA+B,EAC/BC,yBAAyB,EACzBC,4BAA4B,EAC5BC,YAAY,QACP,8BAA8B;AAUrC,SACEC,mBAAmB,EACnBC,mBAAmB,EACnBC,kBAAkB,EAClBC,kBAAkB,QACb,qBAAqB;AAK5B,SAAQC,WAAW,QAAO,6BAA6B;AAqBvD,SACEC,wBAAwB,EACxBC,qBAAqB,EACrBC,gBAAgB,EAChBC,8BAA8B,EAC9BC,yBAAyB,EACzBC,qBAAqB,EACrBC,gBAAgB,EAChBC,sBAAsB,EACtBC,sBAAsB,EACtBC,sBAAsB,EACtBC,wBAAwB,EACxBC,yBAAyB,EACzBC,0BAA0B,EAC1BC,8BAA8B,EAC9BC,uBAAuB,QAClB,6BAA6B;AAEpC,SAAQC,kBAAkB,EAAEC,yBAAyB,QAAO,qCAAqC"}
|
package/dist/feature.d.ts
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
export declare const workflowsNavigation: readonly [{
|
|
2
|
-
readonly id:
|
|
3
|
-
readonly scope:
|
|
4
|
-
readonly label:
|
|
5
|
-
readonly to:
|
|
2
|
+
readonly id: 'nav.runs';
|
|
3
|
+
readonly scope: 'project';
|
|
4
|
+
readonly label: 'Runs';
|
|
5
|
+
readonly to: '/w/$workspaceSlug/p/$projectSlug/runs';
|
|
6
6
|
readonly order: 100;
|
|
7
7
|
}, {
|
|
8
|
-
readonly id:
|
|
9
|
-
readonly scope:
|
|
10
|
-
readonly label:
|
|
11
|
-
readonly to:
|
|
8
|
+
readonly id: 'nav.workflows';
|
|
9
|
+
readonly scope: 'project';
|
|
10
|
+
readonly label: 'Workflows';
|
|
11
|
+
readonly to: '/w/$workspaceSlug/p/$projectSlug/workflows';
|
|
12
12
|
readonly order: 200;
|
|
13
13
|
}];
|
|
14
14
|
export declare const workflowsFeature: {
|
|
@@ -25,18 +25,22 @@ export declare const workflowsFeature: {
|
|
|
25
25
|
readonly path: "/w/$workspaceSlug/p/$projectSlug/runs/$workflowRunId";
|
|
26
26
|
readonly parent: "projectLayout";
|
|
27
27
|
readonly impl: "@shipfox/client-workflows/routes/run-detail";
|
|
28
|
+
}, {
|
|
29
|
+
readonly path: "/w/$workspaceSlug/p/$projectSlug/runs/$workflowRunId/jobs/$jobId";
|
|
30
|
+
readonly parent: "projectLayout";
|
|
31
|
+
readonly impl: "@shipfox/client-workflows/routes/job-detail";
|
|
28
32
|
}];
|
|
29
33
|
readonly navigation: readonly [{
|
|
30
|
-
readonly id:
|
|
31
|
-
readonly scope:
|
|
32
|
-
readonly label:
|
|
33
|
-
readonly to:
|
|
34
|
+
readonly id: 'nav.runs';
|
|
35
|
+
readonly scope: 'project';
|
|
36
|
+
readonly label: 'Runs';
|
|
37
|
+
readonly to: '/w/$workspaceSlug/p/$projectSlug/runs';
|
|
34
38
|
readonly order: 100;
|
|
35
39
|
}, {
|
|
36
|
-
readonly id:
|
|
37
|
-
readonly scope:
|
|
38
|
-
readonly label:
|
|
39
|
-
readonly to:
|
|
40
|
+
readonly id: 'nav.workflows';
|
|
41
|
+
readonly scope: 'project';
|
|
42
|
+
readonly label: 'Workflows';
|
|
43
|
+
readonly to: '/w/$workspaceSlug/p/$projectSlug/workflows';
|
|
40
44
|
readonly order: 200;
|
|
41
45
|
}];
|
|
42
46
|
};
|
package/dist/feature.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"feature.d.ts","sourceRoot":"","sources":["../src/feature.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,mBAAmB
|
|
1
|
+
{"version":3,"file":"feature.d.ts","sourceRoot":"","sources":["../src/feature.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,mBAAmB;iBAExB,UAAU;oBACP,SAAS;oBACT,MAAM;iBACT,uCAAuC;oBACpC,GAAG;;iBAGN,eAAe;oBACZ,SAAS;oBACT,WAAW;iBACd,4CAA4C;oBACzC,GAAG;EAE6B,CAAC;AAE5C,eAAO,MAAM,gBAAgB;;;;;;;;;;;;;;;;;;;;qBAfrB,UAAU;wBACP,SAAS;wBACT,MAAM;qBACT,uCAAuC;wBACpC,GAAG;;qBAGN,eAAe;wBACZ,SAAS;wBACT,WAAW;qBACd,4CAA4C;wBACzC,GAAG;;CA6BZ,CAAC"}
|
package/dist/feature.js
CHANGED
|
@@ -32,6 +32,11 @@ export const workflowsFeature = defineClientFeature({
|
|
|
32
32
|
path: '/w/$workspaceSlug/p/$projectSlug/runs/$workflowRunId',
|
|
33
33
|
parent: 'projectLayout',
|
|
34
34
|
impl: '@shipfox/client-workflows/routes/run-detail'
|
|
35
|
+
},
|
|
36
|
+
{
|
|
37
|
+
path: '/w/$workspaceSlug/p/$projectSlug/runs/$workflowRunId/jobs/$jobId',
|
|
38
|
+
parent: 'projectLayout',
|
|
39
|
+
impl: '@shipfox/client-workflows/routes/job-detail'
|
|
35
40
|
}
|
|
36
41
|
],
|
|
37
42
|
navigation: workflowsNavigation
|
package/dist/feature.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/feature.ts"],"sourcesContent":["import {defineClientFeature, type NavTabEntry} from '@shipfox/client-shell';\n\nexport const workflowsNavigation = [\n {\n id: 'nav.runs',\n scope: 'project',\n label: 'Runs',\n to: '/w/$workspaceSlug/p/$projectSlug/runs',\n order: 100,\n },\n {\n id: 'nav.workflows',\n scope: 'project',\n label: 'Workflows',\n to: '/w/$workspaceSlug/p/$projectSlug/workflows',\n order: 200,\n },\n] as const satisfies readonly NavTabEntry[];\n\nexport const workflowsFeature = defineClientFeature({\n id: 'shipfox.workflows',\n routes: [\n {\n path: '/w/$workspaceSlug/p/$projectSlug/workflows',\n parent: 'projectLayout',\n impl: '@shipfox/client-workflows/routes/workflows',\n },\n {\n path: '/w/$workspaceSlug/p/$projectSlug/runs',\n parent: 'projectLayout',\n impl: '@shipfox/client-workflows/routes/runs',\n },\n {\n path: '/w/$workspaceSlug/p/$projectSlug/runs/$workflowRunId',\n parent: 'projectLayout',\n impl: '@shipfox/client-workflows/routes/run-detail',\n },\n ],\n navigation: workflowsNavigation,\n});\n"],"names":["defineClientFeature","workflowsNavigation","id","scope","label","to","order","workflowsFeature","routes","path","parent","impl","navigation"],"mappings":"AAAA,SAAQA,mBAAmB,QAAyB,wBAAwB;AAE5E,OAAO,MAAMC,sBAAsB;IACjC;QACEC,IAAI;QACJC,OAAO;QACPC,OAAO;QACPC,IAAI;QACJC,OAAO;IACT;IACA;QACEJ,IAAI;QACJC,OAAO;QACPC,OAAO;QACPC,IAAI;QACJC,OAAO;IACT;CACD,CAA2C;AAE5C,OAAO,MAAMC,mBAAmBP,oBAAoB;IAClDE,IAAI;IACJM,QAAQ;QACN;YACEC,MAAM;YACNC,QAAQ;YACRC,MAAM;QACR;QACA;YACEF,MAAM;YACNC,QAAQ;YACRC,MAAM;QACR;QACA;YACEF,MAAM;YACNC,QAAQ;YACRC,MAAM;QACR;KACD;IACDC,YAAYX;AACd,GAAG"}
|
|
1
|
+
{"version":3,"sources":["../src/feature.ts"],"sourcesContent":["import {defineClientFeature, type NavTabEntry} from '@shipfox/client-shell';\n\nexport const workflowsNavigation = [\n {\n id: 'nav.runs',\n scope: 'project',\n label: 'Runs',\n to: '/w/$workspaceSlug/p/$projectSlug/runs',\n order: 100,\n },\n {\n id: 'nav.workflows',\n scope: 'project',\n label: 'Workflows',\n to: '/w/$workspaceSlug/p/$projectSlug/workflows',\n order: 200,\n },\n] as const satisfies readonly NavTabEntry[];\n\nexport const workflowsFeature = defineClientFeature({\n id: 'shipfox.workflows',\n routes: [\n {\n path: '/w/$workspaceSlug/p/$projectSlug/workflows',\n parent: 'projectLayout',\n impl: '@shipfox/client-workflows/routes/workflows',\n },\n {\n path: '/w/$workspaceSlug/p/$projectSlug/runs',\n parent: 'projectLayout',\n impl: '@shipfox/client-workflows/routes/runs',\n },\n {\n path: '/w/$workspaceSlug/p/$projectSlug/runs/$workflowRunId',\n parent: 'projectLayout',\n impl: '@shipfox/client-workflows/routes/run-detail',\n },\n {\n path: '/w/$workspaceSlug/p/$projectSlug/runs/$workflowRunId/jobs/$jobId',\n parent: 'projectLayout',\n impl: '@shipfox/client-workflows/routes/job-detail',\n },\n ],\n navigation: workflowsNavigation,\n});\n"],"names":["defineClientFeature","workflowsNavigation","id","scope","label","to","order","workflowsFeature","routes","path","parent","impl","navigation"],"mappings":"AAAA,SAAQA,mBAAmB,QAAyB,wBAAwB;AAE5E,OAAO,MAAMC,sBAAsB;IACjC;QACEC,IAAI;QACJC,OAAO;QACPC,OAAO;QACPC,IAAI;QACJC,OAAO;IACT;IACA;QACEJ,IAAI;QACJC,OAAO;QACPC,OAAO;QACPC,IAAI;QACJC,OAAO;IACT;CACD,CAA2C;AAE5C,OAAO,MAAMC,mBAAmBP,oBAAoB;IAClDE,IAAI;IACJM,QAAQ;QACN;YACEC,MAAM;YACNC,QAAQ;YACRC,MAAM;QACR;QACA;YACEF,MAAM;YACNC,QAAQ;YACRC,MAAM;QACR;QACA;YACEF,MAAM;YACNC,QAAQ;YACRC,MAAM;QACR;QACA;YACEF,MAAM;YACNC,QAAQ;YACRC,MAAM;QACR;KACD;IACDC,YAAYX;AACd,GAAG"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { AnnotationDto, ReadAnnotationsResponseDto } from '@shipfox/annotations-dto';
|
|
2
|
+
import type { RunAnnotationRecord } from '#core/run-annotation.js';
|
|
3
|
+
export interface RunAnnotationPage {
|
|
4
|
+
annotations: RunAnnotationRecord[];
|
|
5
|
+
hasMore: boolean;
|
|
6
|
+
nextCursor: string | null;
|
|
7
|
+
}
|
|
8
|
+
export declare function toRunAnnotation(dto: AnnotationDto): RunAnnotationRecord;
|
|
9
|
+
export declare function toRunAnnotationPage(response: ReadAnnotationsResponseDto): RunAnnotationPage;
|
|
10
|
+
//# sourceMappingURL=run-annotation-mapper.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"run-annotation-mapper.d.ts","sourceRoot":"","sources":["../../../src/hooks/api/run-annotation-mapper.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,aAAa,EAAE,0BAA0B,EAAC,MAAM,0BAA0B,CAAC;AACxF,OAAO,KAAK,EAAC,mBAAmB,EAAC,MAAM,yBAAyB,CAAC;AAEjE,MAAM,WAAW,iBAAiB;IAChC,WAAW,EAAE,mBAAmB,EAAE,CAAC;IACnC,OAAO,EAAE,OAAO,CAAC;IACjB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;CAC3B;AAED,wBAAgB,eAAe,CAAC,GAAG,EAAE,aAAa,GAAG,mBAAmB,CAYvE;AAED,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,0BAA0B,GAAG,iBAAiB,CAM3F"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
export function toRunAnnotation(dto) {
|
|
2
|
+
return {
|
|
3
|
+
id: dto.id,
|
|
4
|
+
jobId: dto.job_id,
|
|
5
|
+
jobExecutionId: dto.job_execution_id,
|
|
6
|
+
originStepId: dto.origin_step_id,
|
|
7
|
+
originStepAttempt: dto.origin_step_attempt,
|
|
8
|
+
context: dto.context,
|
|
9
|
+
style: dto.style,
|
|
10
|
+
sequence: dto.sequence,
|
|
11
|
+
body: dto.body
|
|
12
|
+
};
|
|
13
|
+
}
|
|
14
|
+
export function toRunAnnotationPage(response) {
|
|
15
|
+
return {
|
|
16
|
+
annotations: response.annotations.map(toRunAnnotation),
|
|
17
|
+
hasMore: response.has_more,
|
|
18
|
+
nextCursor: response.next_cursor
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
//# sourceMappingURL=run-annotation-mapper.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/hooks/api/run-annotation-mapper.ts"],"sourcesContent":["import type {AnnotationDto, ReadAnnotationsResponseDto} from '@shipfox/annotations-dto';\nimport type {RunAnnotationRecord} from '#core/run-annotation.js';\n\nexport interface RunAnnotationPage {\n annotations: RunAnnotationRecord[];\n hasMore: boolean;\n nextCursor: string | null;\n}\n\nexport function toRunAnnotation(dto: AnnotationDto): RunAnnotationRecord {\n return {\n id: dto.id,\n jobId: dto.job_id,\n jobExecutionId: dto.job_execution_id,\n originStepId: dto.origin_step_id,\n originStepAttempt: dto.origin_step_attempt,\n context: dto.context,\n style: dto.style,\n sequence: dto.sequence,\n body: dto.body,\n };\n}\n\nexport function toRunAnnotationPage(response: ReadAnnotationsResponseDto): RunAnnotationPage {\n return {\n annotations: response.annotations.map(toRunAnnotation),\n hasMore: response.has_more,\n nextCursor: response.next_cursor,\n };\n}\n"],"names":["toRunAnnotation","dto","id","jobId","job_id","jobExecutionId","job_execution_id","originStepId","origin_step_id","originStepAttempt","origin_step_attempt","context","style","sequence","body","toRunAnnotationPage","response","annotations","map","hasMore","has_more","nextCursor","next_cursor"],"mappings":"AASA,OAAO,SAASA,gBAAgBC,GAAkB;IAChD,OAAO;QACLC,IAAID,IAAIC,EAAE;QACVC,OAAOF,IAAIG,MAAM;QACjBC,gBAAgBJ,IAAIK,gBAAgB;QACpCC,cAAcN,IAAIO,cAAc;QAChCC,mBAAmBR,IAAIS,mBAAmB;QAC1CC,SAASV,IAAIU,OAAO;QACpBC,OAAOX,IAAIW,KAAK;QAChBC,UAAUZ,IAAIY,QAAQ;QACtBC,MAAMb,IAAIa,IAAI;IAChB;AACF;AAEA,OAAO,SAASC,oBAAoBC,QAAoC;IACtE,OAAO;QACLC,aAAaD,SAASC,WAAW,CAACC,GAAG,CAAClB;QACtCmB,SAASH,SAASI,QAAQ;QAC1BC,YAAYL,SAASM,WAAW;IAClC;AACF"}
|