@shipfox/client-workflows 12.0.2 → 13.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.tsx +3 -3
- package/.turbo/turbo-build.log +1 -1
- package/CHANGELOG.md +56 -0
- package/dist/components/job-graph/job-duration-format.d.ts +2 -2
- package/dist/components/job-graph/job-duration-format.d.ts.map +1 -1
- package/dist/components/job-graph/job-duration-format.js +4 -2
- package/dist/components/job-graph/job-duration-format.js.map +1 -1
- package/dist/components/job-graph/job-node.d.ts +1 -1
- package/dist/components/job-graph/job-node.d.ts.map +1 -1
- package/dist/components/job-graph/job-node.js +5 -4
- package/dist/components/job-graph/job-node.js.map +1 -1
- package/dist/components/step-list/step-list.d.ts +2 -2
- package/dist/components/step-list/step-list.d.ts.map +1 -1
- package/dist/components/step-list/step-list.js.map +1 -1
- package/dist/components/workflow-run-list/job-status-strip.d.ts +21 -0
- package/dist/components/workflow-run-list/job-status-strip.d.ts.map +1 -0
- package/dist/components/workflow-run-list/job-status-strip.js +185 -0
- package/dist/components/workflow-run-list/job-status-strip.js.map +1 -0
- package/dist/components/workflow-run-list/run-display.d.ts +27 -3
- package/dist/components/workflow-run-list/run-display.d.ts.map +1 -1
- package/dist/components/workflow-run-list/run-display.js +78 -7
- package/dist/components/workflow-run-list/run-display.js.map +1 -1
- package/dist/components/workflow-run-list/types.d.ts +23 -24
- package/dist/components/workflow-run-list/types.d.ts.map +1 -1
- package/dist/components/workflow-run-list/types.js.map +1 -1
- package/dist/components/workflow-run-list/workflow-run-filter-menu.d.ts +22 -0
- package/dist/components/workflow-run-list/workflow-run-filter-menu.d.ts.map +1 -0
- package/dist/components/workflow-run-list/workflow-run-filter-menu.js +68 -0
- package/dist/components/workflow-run-list/workflow-run-filter-menu.js.map +1 -0
- package/dist/components/workflow-run-list/workflow-run-filters.d.ts +18 -0
- package/dist/components/workflow-run-list/workflow-run-filters.d.ts.map +1 -0
- package/dist/components/workflow-run-list/workflow-run-filters.js +236 -0
- package/dist/components/workflow-run-list/workflow-run-filters.js.map +1 -0
- package/dist/components/workflow-run-list/workflow-run-list-content.d.ts +8 -4
- package/dist/components/workflow-run-list/workflow-run-list-content.d.ts.map +1 -1
- package/dist/components/workflow-run-list/workflow-run-list-content.js +40 -12
- package/dist/components/workflow-run-list/workflow-run-list-content.js.map +1 -1
- package/dist/components/workflow-run-list/workflow-run-list-states.d.ts +29 -2
- package/dist/components/workflow-run-list/workflow-run-list-states.d.ts.map +1 -1
- package/dist/components/workflow-run-list/workflow-run-list-states.js +103 -44
- package/dist/components/workflow-run-list/workflow-run-list-states.js.map +1 -1
- package/dist/components/workflow-run-list/workflow-run-list-view.d.ts +1 -1
- package/dist/components/workflow-run-list/workflow-run-list-view.d.ts.map +1 -1
- package/dist/components/workflow-run-list/workflow-run-list-view.js +60 -43
- package/dist/components/workflow-run-list/workflow-run-list-view.js.map +1 -1
- package/dist/components/workflow-run-list/workflow-run-list.d.ts +1 -1
- package/dist/components/workflow-run-list/workflow-run-list.d.ts.map +1 -1
- package/dist/components/workflow-run-list/workflow-run-list.js +20 -8
- package/dist/components/workflow-run-list/workflow-run-list.js.map +1 -1
- package/dist/components/workflow-run-list/workflow-run-row.d.ts +19 -9
- package/dist/components/workflow-run-list/workflow-run-row.d.ts.map +1 -1
- package/dist/components/workflow-run-list/workflow-run-row.js +179 -112
- package/dist/components/workflow-run-list/workflow-run-row.js.map +1 -1
- package/dist/components/workflow-run-number-label.d.ts +15 -0
- package/dist/components/workflow-run-number-label.d.ts.map +1 -0
- package/dist/components/workflow-run-number-label.js +41 -0
- package/dist/components/workflow-run-number-label.js.map +1 -0
- package/dist/components/workflow-run-summary/workflow-run-attempt-switcher.d.ts +3 -3
- package/dist/components/workflow-run-summary/workflow-run-attempt-switcher.d.ts.map +1 -1
- package/dist/components/workflow-run-summary/workflow-run-attempt-switcher.js +8 -7
- package/dist/components/workflow-run-summary/workflow-run-attempt-switcher.js.map +1 -1
- package/dist/components/workflow-run-summary/workflow-run-summary.d.ts +3 -3
- package/dist/components/workflow-run-summary/workflow-run-summary.d.ts.map +1 -1
- package/dist/components/workflow-run-summary/workflow-run-summary.js +16 -7
- package/dist/components/workflow-run-summary/workflow-run-summary.js.map +1 -1
- package/dist/components/workflow-run-view/agent-config-failure-callout.d.ts +2 -2
- package/dist/components/workflow-run-view/agent-config-failure-callout.d.ts.map +1 -1
- package/dist/components/workflow-run-view/agent-config-failure-callout.js +4 -4
- package/dist/components/workflow-run-view/agent-config-failure-callout.js.map +1 -1
- package/dist/components/workflow-run-view/job-card.d.ts +2 -2
- package/dist/components/workflow-run-view/job-card.d.ts.map +1 -1
- package/dist/components/workflow-run-view/job-card.js +51 -32
- package/dist/components/workflow-run-view/job-card.js.map +1 -1
- package/dist/components/workflow-run-view/job-execution-switcher.d.ts +1 -1
- package/dist/components/workflow-run-view/job-execution-switcher.d.ts.map +1 -1
- package/dist/components/workflow-run-view/job-execution-switcher.js +20 -8
- package/dist/components/workflow-run-view/job-execution-switcher.js.map +1 -1
- package/dist/components/workflow-run-view/workflow-run-view.d.ts +3 -2
- package/dist/components/workflow-run-view/workflow-run-view.d.ts.map +1 -1
- package/dist/components/workflow-run-view/workflow-run-view.js +15 -11
- package/dist/components/workflow-run-view/workflow-run-view.js.map +1 -1
- package/dist/components/workflow-status/status-visuals.d.ts +4 -4
- package/dist/components/workflow-status/status-visuals.d.ts.map +1 -1
- package/dist/components/workflow-status/status-visuals.js +7 -0
- package/dist/components/workflow-status/status-visuals.js.map +1 -1
- package/dist/components/workflow-status/workflow-status-icon.d.ts +3 -4
- package/dist/components/workflow-status/workflow-status-icon.d.ts.map +1 -1
- package/dist/components/workflow-status/workflow-status-icon.js +6 -4
- package/dist/components/workflow-status/workflow-status-icon.js.map +1 -1
- package/dist/core/entities/job-execution.d.ts +10 -0
- package/dist/core/entities/job-execution.d.ts.map +1 -1
- package/dist/core/entities/job-execution.js +11 -0
- package/dist/core/entities/job-execution.js.map +1 -1
- package/dist/core/entities/job.d.ts +4 -2
- package/dist/core/entities/job.d.ts.map +1 -1
- package/dist/core/entities/job.js +8 -1
- package/dist/core/entities/job.js.map +1 -1
- package/dist/core/entities/workflow-run.d.ts +52 -4
- package/dist/core/entities/workflow-run.d.ts.map +1 -1
- package/dist/core/entities/workflow-run.js +22 -3
- package/dist/core/entities/workflow-run.js.map +1 -1
- package/dist/core/workflow-run.d.ts +6 -6
- 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 +7 -7
- package/dist/feature.js +5 -5
- package/dist/feature.js.map +1 -1
- package/dist/hooks/api/workflow-run-mapper.d.ts +4 -3
- package/dist/hooks/api/workflow-run-mapper.d.ts.map +1 -1
- package/dist/hooks/api/workflow-run-mapper.js +31 -3
- package/dist/hooks/api/workflow-run-mapper.js.map +1 -1
- package/dist/hooks/api/workflow-runs.d.ts +4 -4
- package/dist/hooks/api/workflow-runs.d.ts.map +1 -1
- package/dist/hooks/api/workflow-runs.js +12 -4
- package/dist/hooks/api/workflow-runs.js.map +1 -1
- package/dist/index.d.ts +4 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -2
- package/dist/index.js.map +1 -1
- package/dist/pages/project-workflows-page.js +46 -1
- package/dist/pages/project-workflows-page.js.map +1 -1
- package/dist/pages/workflow-run-detail-page.d.ts +11 -0
- package/dist/pages/workflow-run-detail-page.d.ts.map +1 -0
- package/dist/pages/workflow-run-detail-page.js +30 -0
- package/dist/pages/workflow-run-detail-page.js.map +1 -0
- package/dist/pages/workflow-run-list-page.d.ts +10 -0
- package/dist/pages/workflow-run-list-page.d.ts.map +1 -0
- package/dist/pages/workflow-run-list-page.js +43 -0
- package/dist/pages/workflow-run-list-page.js.map +1 -0
- package/dist/routes/inputs.d.ts +61 -5
- package/dist/routes/inputs.d.ts.map +1 -1
- package/dist/routes/inputs.js +150 -13
- package/dist/routes/inputs.js.map +1 -1
- package/dist/routes/project-route.d.ts +6 -0
- package/dist/routes/project-route.d.ts.map +1 -0
- package/dist/routes/project-route.js +25 -0
- package/dist/routes/project-route.js.map +1 -0
- package/dist/routes/run-detail.d.ts.map +1 -1
- package/dist/routes/run-detail.js +12 -7
- package/dist/routes/run-detail.js.map +1 -1
- package/dist/routes/runs.d.ts.map +1 -1
- package/dist/routes/runs.js +11 -6
- package/dist/routes/runs.js.map +1 -1
- package/dist/routes/workflows.d.ts.map +1 -1
- package/dist/routes/workflows.js +6 -5
- package/dist/routes/workflows.js.map +1 -1
- package/dist/tsconfig.test.tsbuildinfo +1 -1
- package/package.json +9 -9
- package/src/components/job-graph/job-duration-format.ts +11 -2
- package/src/components/job-graph/job-graph-view.test.tsx +19 -8
- package/src/components/job-graph/job-graph.stories.tsx +23 -19
- package/src/components/job-graph/job-node.stories.tsx +10 -5
- package/src/components/job-graph/job-node.test.tsx +55 -10
- package/src/components/job-graph/job-node.tsx +16 -9
- package/src/components/step-list/step-list.stories.tsx +2 -3
- package/src/components/step-list/step-list.tsx +3 -2
- package/src/components/workflow-run-list/job-status-strip.tsx +189 -0
- package/src/components/workflow-run-list/run-display.test.ts +169 -30
- package/src/components/workflow-run-list/run-display.ts +116 -9
- package/src/components/workflow-run-list/types.ts +21 -17
- package/src/components/workflow-run-list/workflow-run-filter-menu.tsx +100 -0
- package/src/components/workflow-run-list/workflow-run-filters.tsx +243 -0
- package/src/components/workflow-run-list/workflow-run-list-content.tsx +44 -16
- package/src/components/workflow-run-list/workflow-run-list-states.tsx +128 -27
- package/src/components/workflow-run-list/workflow-run-list-view.test.tsx +441 -104
- package/src/components/workflow-run-list/workflow-run-list-view.tsx +73 -43
- package/src/components/workflow-run-list/workflow-run-list.stories.tsx +140 -20
- package/src/components/workflow-run-list/workflow-run-list.tsx +20 -10
- package/src/components/workflow-run-list/workflow-run-row.tsx +173 -106
- package/src/components/workflow-run-number-label.test.tsx +45 -0
- package/src/components/workflow-run-number-label.tsx +47 -0
- package/src/components/workflow-run-summary/workflow-run-attempt-switcher.test.tsx +7 -8
- package/src/components/workflow-run-summary/workflow-run-attempt-switcher.tsx +13 -12
- package/src/components/workflow-run-summary/workflow-run-summary.stories.tsx +6 -8
- package/src/components/workflow-run-summary/workflow-run-summary.test.tsx +27 -2
- package/src/components/workflow-run-summary/workflow-run-summary.tsx +19 -9
- package/src/components/workflow-run-view/agent-config-failure-callout.stories.tsx +2 -3
- package/src/components/workflow-run-view/agent-config-failure-callout.tsx +4 -4
- package/src/components/workflow-run-view/job-card.stories.tsx +11 -10
- package/src/components/workflow-run-view/job-card.test.tsx +115 -0
- package/src/components/workflow-run-view/job-card.tsx +74 -35
- package/src/components/workflow-run-view/job-execution-switcher.tsx +31 -9
- package/src/components/workflow-run-view/workflow-run-view.test.tsx +88 -30
- package/src/components/workflow-run-view/workflow-run-view.tsx +24 -14
- package/src/components/workflow-status/status-visuals.test.ts +9 -0
- package/src/components/workflow-status/status-visuals.ts +6 -4
- package/src/components/workflow-status/workflow-status-icon.stories.tsx +10 -2
- package/src/components/workflow-status/workflow-status-icon.test.tsx +18 -0
- package/src/components/workflow-status/workflow-status-icon.tsx +17 -24
- package/src/core/entities/job-execution.ts +22 -0
- package/src/core/entities/job-status.test.ts +104 -0
- package/src/core/entities/job.ts +18 -3
- package/src/core/entities/workflow-run.ts +76 -7
- package/src/core/workflow-run.test.ts +24 -9
- package/src/core/workflow-run.ts +17 -2
- package/src/feature.ts +5 -5
- package/src/hooks/api/workflow-run-mapper.ts +30 -3
- package/src/hooks/api/workflow-runs.test.tsx +2 -0
- package/src/hooks/api/workflow-runs.ts +12 -7
- package/src/index.ts +7 -2
- package/src/page-harness-budget.test.ts +1 -1
- package/src/pages/project-workflows-page.test.tsx +59 -5
- package/src/pages/project-workflows-page.tsx +34 -1
- package/src/pages/workflow-run-detail-page.tsx +45 -0
- package/src/pages/workflow-run-list-page.tsx +65 -0
- package/src/pages/{workflow-run-page.test.tsx → workflow-run-pages.test.tsx} +211 -47
- package/src/routes/inputs.test.ts +193 -12
- package/src/routes/inputs.ts +170 -11
- package/src/routes/project-route.tsx +25 -0
- package/src/routes/run-detail.tsx +15 -8
- package/src/routes/runs.tsx +14 -7
- package/src/routes/workflows.tsx +5 -4
- package/test/fixtures/workflow-run.ts +76 -7
- package/test/pages.tsx +18 -8
- package/test/render.tsx +8 -2
- package/tsconfig.build.tsbuildinfo +1 -1
- package/dist/components/workflow-run-list/workflow-run-list-header.d.ts +0 -10
- package/dist/components/workflow-run-list/workflow-run-list-header.d.ts.map +0 -1
- package/dist/components/workflow-run-list/workflow-run-list-header.js +0 -55
- package/dist/components/workflow-run-list/workflow-run-list-header.js.map +0 -1
- package/dist/pages/workflow-run-first-time-use.d.ts +0 -6
- package/dist/pages/workflow-run-first-time-use.d.ts.map +0 -1
- package/dist/pages/workflow-run-first-time-use.js +0 -17
- package/dist/pages/workflow-run-first-time-use.js.map +0 -1
- package/dist/pages/workflow-run-page.d.ts +0 -10
- package/dist/pages/workflow-run-page.d.ts.map +0 -1
- package/dist/pages/workflow-run-page.js +0 -90
- package/dist/pages/workflow-run-page.js.map +0 -1
- package/src/components/workflow-run-list/workflow-run-list-header.tsx +0 -53
- package/src/pages/workflow-run-first-time-use.tsx +0 -17
- package/src/pages/workflow-run-page.tsx +0 -94
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
import {deriveJobDisplayStatus, type JobDisplayStatus} from './job.js';
|
|
2
|
+
import {deriveJobExecutionDisplayStatus, type JobExecutionStatus} from './job-execution.js';
|
|
3
|
+
|
|
4
|
+
type DisplayStep = Parameters<typeof deriveJobExecutionDisplayStatus>[0]['steps'][number];
|
|
5
|
+
|
|
6
|
+
function displayStep(status: string): DisplayStep {
|
|
7
|
+
return {status} as DisplayStep;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
const EXECUTION_STATUSES = ['pending', 'running', 'succeeded', 'failed', 'cancelled'] as const;
|
|
11
|
+
const TERMINAL_EXECUTION_STATUSES = ['succeeded', 'failed', 'cancelled'] as const;
|
|
12
|
+
|
|
13
|
+
describe('deriveJobExecutionDisplayStatus', () => {
|
|
14
|
+
test.each(
|
|
15
|
+
EXECUTION_STATUSES,
|
|
16
|
+
)('%s without a running step displays Pending unless terminal', (status) => {
|
|
17
|
+
const displayStatus = deriveJobExecutionDisplayStatus({status, steps: []});
|
|
18
|
+
|
|
19
|
+
expect(displayStatus).toBe(
|
|
20
|
+
TERMINAL_EXECUTION_STATUSES.includes(status as (typeof TERMINAL_EXECUTION_STATUSES)[number])
|
|
21
|
+
? status
|
|
22
|
+
: 'pending',
|
|
23
|
+
);
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
test.each([
|
|
27
|
+
'pending',
|
|
28
|
+
'running',
|
|
29
|
+
] as const)('%s with a running step displays Running', (status) => {
|
|
30
|
+
expect(deriveJobExecutionDisplayStatus({status, steps: [displayStep('running')]})).toBe(
|
|
31
|
+
'running',
|
|
32
|
+
);
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
test.each(TERMINAL_EXECUTION_STATUSES)('%s wins over a running child step', (status) => {
|
|
36
|
+
expect(deriveJobExecutionDisplayStatus({status, steps: [displayStep('running')]})).toBe(status);
|
|
37
|
+
});
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
describe('deriveJobDisplayStatus', () => {
|
|
41
|
+
test('uses the execution activity for a one-shot job', () => {
|
|
42
|
+
const statuses: Array<[JobExecutionStatus, string[], JobDisplayStatus]> = [
|
|
43
|
+
['pending', [], 'pending'],
|
|
44
|
+
['pending', ['running'], 'running'],
|
|
45
|
+
['running', [], 'pending'],
|
|
46
|
+
['running', ['running'], 'running'],
|
|
47
|
+
];
|
|
48
|
+
|
|
49
|
+
for (const [status, stepStatuses, expected] of statuses) {
|
|
50
|
+
expect(
|
|
51
|
+
deriveJobDisplayStatus({
|
|
52
|
+
mode: 'one_shot',
|
|
53
|
+
status: 'running',
|
|
54
|
+
listenerStatus: 'inactive',
|
|
55
|
+
jobExecutions: [
|
|
56
|
+
{
|
|
57
|
+
status,
|
|
58
|
+
steps: stepStatuses.map(displayStep),
|
|
59
|
+
sequence: 1,
|
|
60
|
+
},
|
|
61
|
+
] as never,
|
|
62
|
+
}),
|
|
63
|
+
).toBe(expected);
|
|
64
|
+
}
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
test.each([
|
|
68
|
+
'succeeded',
|
|
69
|
+
'failed',
|
|
70
|
+
'cancelled',
|
|
71
|
+
'skipped',
|
|
72
|
+
] as const)('terminal job status %s wins over child activity', (status) => {
|
|
73
|
+
expect(
|
|
74
|
+
deriveJobDisplayStatus({
|
|
75
|
+
mode: 'one_shot',
|
|
76
|
+
status,
|
|
77
|
+
listenerStatus: 'inactive',
|
|
78
|
+
jobExecutions: [{status: 'running', steps: [{status: 'running'}], sequence: 1}] as never,
|
|
79
|
+
}),
|
|
80
|
+
).toBe(status);
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
test('keeps an active listener as Listening without executions', () => {
|
|
84
|
+
expect(
|
|
85
|
+
deriveJobDisplayStatus({
|
|
86
|
+
mode: 'listening',
|
|
87
|
+
status: 'running',
|
|
88
|
+
listenerStatus: 'listening',
|
|
89
|
+
jobExecutions: [],
|
|
90
|
+
}),
|
|
91
|
+
).toBe('listening');
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
test('uses the terminal job status when an active listener has resolved', () => {
|
|
95
|
+
expect(
|
|
96
|
+
deriveJobDisplayStatus({
|
|
97
|
+
mode: 'listening',
|
|
98
|
+
status: 'succeeded',
|
|
99
|
+
listenerStatus: 'listening',
|
|
100
|
+
jobExecutions: [],
|
|
101
|
+
}),
|
|
102
|
+
).toBe('succeeded');
|
|
103
|
+
});
|
|
104
|
+
});
|
package/src/core/entities/job.ts
CHANGED
|
@@ -1,6 +1,11 @@
|
|
|
1
|
-
import
|
|
1
|
+
import {
|
|
2
|
+
deriveJobExecutionDisplayStatus,
|
|
3
|
+
type JobExecution,
|
|
4
|
+
type JobExecutionDisplayDuration,
|
|
5
|
+
} from './job-execution.js';
|
|
2
6
|
|
|
3
7
|
export type JobStatus = 'pending' | 'running' | 'succeeded' | 'failed' | 'cancelled' | 'skipped';
|
|
8
|
+
export type JobDisplayStatus = JobStatus | 'listening';
|
|
4
9
|
export type JobMode = 'one_shot' | 'listening';
|
|
5
10
|
export type ListenerStatus = 'inactive' | 'listening' | 'resolved';
|
|
6
11
|
export type ResolutionReason = 'until' | 'timeout' | 'max_executions' | 'cancelled';
|
|
@@ -103,7 +108,7 @@ export class Job {
|
|
|
103
108
|
}
|
|
104
109
|
|
|
105
110
|
get displayName(): string {
|
|
106
|
-
return this.name
|
|
111
|
+
return this.name ?? this.key;
|
|
107
112
|
}
|
|
108
113
|
|
|
109
114
|
get displayDuration(): JobDisplayDuration | null {
|
|
@@ -123,6 +128,16 @@ export function isTerminalJobStatus(status: JobStatus): boolean {
|
|
|
123
128
|
return TERMINAL_JOB_STATUS_SET.has(status);
|
|
124
129
|
}
|
|
125
130
|
|
|
131
|
+
export function deriveJobDisplayStatus(
|
|
132
|
+
job: Pick<Job, 'mode' | 'status' | 'listenerStatus' | 'jobExecutions'>,
|
|
133
|
+
): JobDisplayStatus {
|
|
134
|
+
if (isTerminalJobStatus(job.status)) return job.status;
|
|
135
|
+
if (job.mode === 'listening' && job.listenerStatus === 'listening') return 'listening';
|
|
136
|
+
|
|
137
|
+
const execution = defaultJobExecution(job);
|
|
138
|
+
return execution ? deriveJobExecutionDisplayStatus(execution) : 'pending';
|
|
139
|
+
}
|
|
140
|
+
|
|
126
141
|
export function resolveJobExecution(
|
|
127
142
|
job: Job,
|
|
128
143
|
jobExecutionId: string | undefined,
|
|
@@ -135,7 +150,7 @@ export function resolveJobExecution(
|
|
|
135
150
|
return defaultJobExecution(job);
|
|
136
151
|
}
|
|
137
152
|
|
|
138
|
-
export function defaultJobExecution(job: Job): JobExecution | undefined {
|
|
153
|
+
export function defaultJobExecution(job: Pick<Job, 'jobExecutions'>): JobExecution | undefined {
|
|
139
154
|
const runningExecution = job.jobExecutions.find(
|
|
140
155
|
(jobExecution) => jobExecution.status === 'running',
|
|
141
156
|
);
|
|
@@ -1,9 +1,10 @@
|
|
|
1
|
-
import {type Job, WORKFLOW_JOB_STATUSES} from './job.js';
|
|
1
|
+
import {type Job, type JobStatus, WORKFLOW_JOB_STATUSES} from './job.js';
|
|
2
2
|
import type {WorkflowRunAttempt, WorkflowRunAttemptSummary} from './workflow-run-attempt.js';
|
|
3
3
|
|
|
4
4
|
export type WorkflowRunStatus = 'pending' | 'running' | 'succeeded' | 'failed' | 'cancelled';
|
|
5
5
|
export type WorkflowRunRerunMode = 'all' | 'failed';
|
|
6
6
|
export type WorkflowStatus = WorkflowRunStatus | (typeof WORKFLOW_JOB_STATUSES)[number];
|
|
7
|
+
export type WorkflowDisplayStatus = WorkflowStatus | 'listening';
|
|
7
8
|
|
|
8
9
|
export const WORKFLOW_RUN_STATUSES = [
|
|
9
10
|
'pending',
|
|
@@ -30,11 +31,51 @@ export interface WorkflowSourceSnapshot {
|
|
|
30
31
|
format: 'yaml';
|
|
31
32
|
}
|
|
32
33
|
|
|
34
|
+
/**
|
|
35
|
+
* Provider-neutral trigger facts. Every field is nullable: only source-control triggers
|
|
36
|
+
* resolve a reference at all, and a payload can name a ref without naming an actor.
|
|
37
|
+
*/
|
|
38
|
+
export interface WorkflowRunTriggerReference {
|
|
39
|
+
repository: string | null;
|
|
40
|
+
ref: string | null;
|
|
41
|
+
commit: string | null;
|
|
42
|
+
actor: string | null;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/** One glyph in a run row's job status strip: enough to draw and label it, nothing more. */
|
|
46
|
+
export interface WorkflowRunJobSummary {
|
|
47
|
+
id: string;
|
|
48
|
+
key: string;
|
|
49
|
+
name: string | null;
|
|
50
|
+
status: JobStatus;
|
|
51
|
+
position: number;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
export interface WorkflowRunJobStatusCount {
|
|
55
|
+
status: JobStatus;
|
|
56
|
+
count: number;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* A run's jobs as the list receives them: a bounded slice to draw, plus totals covering all
|
|
61
|
+
* of them.
|
|
62
|
+
*
|
|
63
|
+
* `preview` is capped by the API, so `preview.length` is not the job count and the strip
|
|
64
|
+
* reads `total` and `statusCounts` for anything it says rather than anything it draws.
|
|
65
|
+
*/
|
|
66
|
+
export interface WorkflowRunJobs {
|
|
67
|
+
preview: WorkflowRunJobSummary[];
|
|
68
|
+
statusCounts: WorkflowRunJobStatusCount[];
|
|
69
|
+
total: number;
|
|
70
|
+
}
|
|
71
|
+
|
|
33
72
|
export interface WorkflowRun {
|
|
34
73
|
id: string;
|
|
35
74
|
projectId: string;
|
|
36
75
|
definitionId: string;
|
|
76
|
+
number: number | null;
|
|
37
77
|
name: string;
|
|
78
|
+
workflowName: string;
|
|
38
79
|
currentAttempt: number;
|
|
39
80
|
triggerProvider: string | null;
|
|
40
81
|
triggerSource: string;
|
|
@@ -42,20 +83,25 @@ export interface WorkflowRun {
|
|
|
42
83
|
triggerDisplayLabel: string;
|
|
43
84
|
triggerLabel: string;
|
|
44
85
|
triggerPayload: Record<string, unknown>;
|
|
86
|
+
triggerReference: WorkflowRunTriggerReference | null;
|
|
45
87
|
inputs: Record<string, unknown> | null;
|
|
46
88
|
sourceSnapshot: WorkflowSourceSnapshot | null;
|
|
47
89
|
createdAt: string;
|
|
48
90
|
updatedAt: string;
|
|
49
|
-
shortId: string;
|
|
50
91
|
isTemporary: boolean;
|
|
51
92
|
}
|
|
52
93
|
|
|
53
|
-
|
|
94
|
+
/** A run as the API returns it outside the list: no job strip, because none was fetched. */
|
|
95
|
+
export interface WorkflowRunRecord extends WorkflowRun {
|
|
54
96
|
status: WorkflowRunStatus;
|
|
55
97
|
latestAttempt: number;
|
|
56
98
|
runAttempt: WorkflowRunAttemptSummary;
|
|
57
99
|
}
|
|
58
100
|
|
|
101
|
+
export interface WorkflowRunListItem extends WorkflowRunRecord {
|
|
102
|
+
jobs: WorkflowRunJobs;
|
|
103
|
+
}
|
|
104
|
+
|
|
59
105
|
export interface WorkflowRunDetail extends WorkflowRun {
|
|
60
106
|
latestAttempt: number;
|
|
61
107
|
runAttempt: WorkflowRunAttempt;
|
|
@@ -72,10 +118,6 @@ export interface ManualWorkflowLaunch {
|
|
|
72
118
|
workflowRunId: string;
|
|
73
119
|
}
|
|
74
120
|
|
|
75
|
-
export function workflowRunShortId(id: string): string {
|
|
76
|
-
return id.length <= 8 ? id : id.slice(0, 8);
|
|
77
|
-
}
|
|
78
|
-
|
|
79
121
|
export function workflowRunTriggerLabel({
|
|
80
122
|
triggerSource,
|
|
81
123
|
triggerEvent,
|
|
@@ -96,6 +138,33 @@ export function workflowRunTriggerDisplayLabel({
|
|
|
96
138
|
return triggerEvent || triggerSource;
|
|
97
139
|
}
|
|
98
140
|
|
|
141
|
+
const SHORT_COMMIT_LENGTH = 7;
|
|
142
|
+
const PULL_REQUEST_REF_PATTERN = /^refs\/pull\/(\d+)\/head$/u;
|
|
143
|
+
|
|
144
|
+
/**
|
|
145
|
+
* The ref as a person names it: `main` for a branch, `#42` for a pull request, the tag for a
|
|
146
|
+
* tag. An unrecognized ref is shown verbatim rather than hidden, since a ref nobody can read
|
|
147
|
+
* is still better evidence than a blank cell.
|
|
148
|
+
*/
|
|
149
|
+
export function workflowRunBranchLabel(run: Pick<WorkflowRun, 'triggerReference'>): string | null {
|
|
150
|
+
const ref = run.triggerReference?.ref;
|
|
151
|
+
if (!ref) return null;
|
|
152
|
+
const pullRequest = PULL_REQUEST_REF_PATTERN.exec(ref);
|
|
153
|
+
if (pullRequest) return `#${pullRequest[1]}`;
|
|
154
|
+
if (ref.startsWith('refs/heads/')) return ref.slice('refs/heads/'.length);
|
|
155
|
+
if (ref.startsWith('refs/tags/')) return ref.slice('refs/tags/'.length);
|
|
156
|
+
return ref;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
export function workflowRunCommitLabel(run: Pick<WorkflowRun, 'triggerReference'>): string | null {
|
|
160
|
+
const commit = run.triggerReference?.commit;
|
|
161
|
+
return commit ? commit.slice(0, SHORT_COMMIT_LENGTH) : null;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
export function workflowRunActor(run: Pick<WorkflowRun, 'triggerReference'>): string | null {
|
|
165
|
+
return run.triggerReference?.actor ?? null;
|
|
166
|
+
}
|
|
167
|
+
|
|
99
168
|
export function isWorkflowRunTerminal(status: WorkflowRunStatus): boolean {
|
|
100
169
|
return TERMINAL_WORKFLOW_RUN_STATUS_SET.has(status);
|
|
101
170
|
}
|
|
@@ -6,6 +6,7 @@ import {
|
|
|
6
6
|
toWorkflowRunListPage,
|
|
7
7
|
} from '#hooks/api/workflow-run-mapper.js';
|
|
8
8
|
import {
|
|
9
|
+
workflowJob,
|
|
9
10
|
workflowJobDto,
|
|
10
11
|
workflowJobExecutionDto,
|
|
11
12
|
workflowRunAttemptDto,
|
|
@@ -18,7 +19,6 @@ import {
|
|
|
18
19
|
import {
|
|
19
20
|
isWorkflowRunTerminal,
|
|
20
21
|
isWorkflowStatus,
|
|
21
|
-
workflowRunShortId,
|
|
22
22
|
workflowRunTriggerDisplayLabel,
|
|
23
23
|
workflowRunTriggerLabel,
|
|
24
24
|
} from './workflow-run.js';
|
|
@@ -51,7 +51,9 @@ describe('workflow run model mapping', () => {
|
|
|
51
51
|
id: '66666666-6666-4666-8666-666666666666',
|
|
52
52
|
projectId: '44444444-4444-4444-8444-444444444444',
|
|
53
53
|
definitionId: '55555555-5555-4555-8555-555555555555',
|
|
54
|
+
number: 1,
|
|
54
55
|
name: 'deploy-web',
|
|
56
|
+
workflowName: 'deploy-web',
|
|
55
57
|
currentAttempt: 3,
|
|
56
58
|
triggerProvider: 'github',
|
|
57
59
|
triggerSource: 'github_acme',
|
|
@@ -63,7 +65,6 @@ describe('workflow run model mapping', () => {
|
|
|
63
65
|
sourceSnapshot: {format: 'yaml', content: 'jobs: {}'},
|
|
64
66
|
createdAt: '2026-05-07T01:01:00.000Z',
|
|
65
67
|
updatedAt: '2026-05-07T01:02:00.000Z',
|
|
66
|
-
shortId: '66666666',
|
|
67
68
|
isTemporary: false,
|
|
68
69
|
});
|
|
69
70
|
expect(run).not.toHaveProperty('status');
|
|
@@ -91,7 +92,6 @@ describe('workflow run model mapping', () => {
|
|
|
91
92
|
triggerLabel: '',
|
|
92
93
|
inputs: null,
|
|
93
94
|
sourceSnapshot: null,
|
|
94
|
-
shortId: 'temp-123',
|
|
95
95
|
isTemporary: true,
|
|
96
96
|
});
|
|
97
97
|
});
|
|
@@ -299,6 +299,10 @@ describe('workflow run model mapping', () => {
|
|
|
299
299
|
event: 'deployment_status',
|
|
300
300
|
delivery_id: 'delivery-1',
|
|
301
301
|
received_at: '2026-05-07T01:00:00.000Z',
|
|
302
|
+
project: {id: '44444444-4444-4444-8444-444444444444'},
|
|
303
|
+
repository: 'acme/api',
|
|
304
|
+
ref: 'refs/heads/main',
|
|
305
|
+
commit: 'a'.repeat(40),
|
|
302
306
|
data: {state: 'success'},
|
|
303
307
|
},
|
|
304
308
|
],
|
|
@@ -332,6 +336,10 @@ describe('workflow run model mapping', () => {
|
|
|
332
336
|
event: 'deployment_status',
|
|
333
337
|
deliveryId: 'delivery-1',
|
|
334
338
|
receivedAt: '2026-05-07T01:00:00.000Z',
|
|
339
|
+
project: {id: '44444444-4444-4444-8444-444444444444'},
|
|
340
|
+
repository: 'acme/api',
|
|
341
|
+
ref: 'refs/heads/main',
|
|
342
|
+
commit: 'a'.repeat(40),
|
|
335
343
|
data: {state: 'success'},
|
|
336
344
|
},
|
|
337
345
|
],
|
|
@@ -376,6 +384,18 @@ describe('workflow run model mapping', () => {
|
|
|
376
384
|
});
|
|
377
385
|
});
|
|
378
386
|
|
|
387
|
+
test('exposes display names for jobs and job executions', () => {
|
|
388
|
+
const job = workflowJob({
|
|
389
|
+
name: 'Deploy',
|
|
390
|
+
key: 'deploy',
|
|
391
|
+
job_executions: [workflowJobExecutionDto({name: 'Deploy production'})],
|
|
392
|
+
});
|
|
393
|
+
|
|
394
|
+
expect(job.displayName).toBe('Deploy');
|
|
395
|
+
expect(job.jobExecutions[0]?.displayName).toBe('Deploy production');
|
|
396
|
+
expect(workflowJob({name: null, key: 'deploy-prod'}).displayName).toBe('deploy-prod');
|
|
397
|
+
});
|
|
398
|
+
|
|
379
399
|
test('returns no job display duration when a job has multiple executions', () => {
|
|
380
400
|
const job = workflowJobDto({
|
|
381
401
|
job_executions: [
|
|
@@ -628,12 +648,7 @@ describe('workflow run helpers', () => {
|
|
|
628
648
|
expect(neither).toBe('');
|
|
629
649
|
});
|
|
630
650
|
|
|
631
|
-
test('
|
|
632
|
-
const short = workflowRunShortId('abc123');
|
|
633
|
-
const long = workflowRunShortId('66666666-6666-4666-8666-666666666666');
|
|
634
|
-
|
|
635
|
-
expect(short).toBe('abc123');
|
|
636
|
-
expect(long).toBe('66666666');
|
|
651
|
+
test('classifies workflow statuses', () => {
|
|
637
652
|
expect(isWorkflowRunTerminal('succeeded')).toBe(true);
|
|
638
653
|
expect(isWorkflowRunTerminal('running')).toBe(false);
|
|
639
654
|
expect(isWorkflowStatus('pending')).toBe(true);
|
package/src/core/workflow-run.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
export type {
|
|
2
2
|
JobDisplayDuration,
|
|
3
|
+
JobDisplayStatus,
|
|
3
4
|
JobListening,
|
|
4
5
|
JobMode,
|
|
5
6
|
JobStatus,
|
|
@@ -9,6 +10,7 @@ export type {
|
|
|
9
10
|
} from './entities/job.js';
|
|
10
11
|
export {
|
|
11
12
|
defaultJobExecution,
|
|
13
|
+
deriveJobDisplayStatus,
|
|
12
14
|
isTerminalJobStatus,
|
|
13
15
|
Job,
|
|
14
16
|
resolveJobExecution,
|
|
@@ -17,11 +19,16 @@ export {
|
|
|
17
19
|
} from './entities/job.js';
|
|
18
20
|
export type {
|
|
19
21
|
JobExecutionDisplayDuration,
|
|
22
|
+
JobExecutionDisplayStatus,
|
|
20
23
|
JobExecutionStatus,
|
|
21
24
|
JobExecutionTime,
|
|
22
25
|
WorkflowExecutionEvent,
|
|
23
26
|
} from './entities/job-execution.js';
|
|
24
|
-
export {
|
|
27
|
+
export {
|
|
28
|
+
deriveJobExecutionDisplayStatus,
|
|
29
|
+
isTerminalJobExecutionStatus,
|
|
30
|
+
JobExecution,
|
|
31
|
+
} from './entities/job-execution.js';
|
|
25
32
|
export type {
|
|
26
33
|
AgentConfigIssue,
|
|
27
34
|
AgentStepConfig,
|
|
@@ -39,12 +46,18 @@ export type {
|
|
|
39
46
|
export {StepAttempt} from './entities/step-attempt.js';
|
|
40
47
|
export type {
|
|
41
48
|
ManualWorkflowLaunch,
|
|
49
|
+
WorkflowDisplayStatus,
|
|
42
50
|
WorkflowRun,
|
|
43
51
|
WorkflowRunDetail,
|
|
52
|
+
WorkflowRunJobStatusCount,
|
|
53
|
+
WorkflowRunJobSummary,
|
|
54
|
+
WorkflowRunJobs,
|
|
44
55
|
WorkflowRunListItem,
|
|
45
56
|
WorkflowRunListPage,
|
|
57
|
+
WorkflowRunRecord,
|
|
46
58
|
WorkflowRunRerunMode,
|
|
47
59
|
WorkflowRunStatus,
|
|
60
|
+
WorkflowRunTriggerReference,
|
|
48
61
|
WorkflowSourceSnapshot,
|
|
49
62
|
WorkflowStatus,
|
|
50
63
|
} from './entities/workflow-run.js';
|
|
@@ -53,7 +66,9 @@ export {
|
|
|
53
66
|
isWorkflowStatus,
|
|
54
67
|
TERMINAL_WORKFLOW_RUN_STATUSES,
|
|
55
68
|
WORKFLOW_RUN_STATUSES,
|
|
56
|
-
|
|
69
|
+
workflowRunActor,
|
|
70
|
+
workflowRunBranchLabel,
|
|
71
|
+
workflowRunCommitLabel,
|
|
57
72
|
workflowRunTriggerDisplayLabel,
|
|
58
73
|
workflowRunTriggerLabel,
|
|
59
74
|
} from './entities/workflow-run.js';
|
package/src/feature.ts
CHANGED
|
@@ -5,14 +5,14 @@ export const workflowsNavigation = [
|
|
|
5
5
|
id: 'nav.runs',
|
|
6
6
|
scope: 'project',
|
|
7
7
|
label: 'Runs',
|
|
8
|
-
to: '/
|
|
8
|
+
to: '/w/$workspaceSlug/p/$projectSlug/runs',
|
|
9
9
|
order: 100,
|
|
10
10
|
},
|
|
11
11
|
{
|
|
12
12
|
id: 'nav.workflows',
|
|
13
13
|
scope: 'project',
|
|
14
14
|
label: 'Workflows',
|
|
15
|
-
to: '/
|
|
15
|
+
to: '/w/$workspaceSlug/p/$projectSlug/workflows',
|
|
16
16
|
order: 200,
|
|
17
17
|
},
|
|
18
18
|
] as const satisfies readonly NavTabEntry[];
|
|
@@ -21,17 +21,17 @@ export const workflowsFeature = defineClientFeature({
|
|
|
21
21
|
id: 'shipfox.workflows',
|
|
22
22
|
routes: [
|
|
23
23
|
{
|
|
24
|
-
path: '/
|
|
24
|
+
path: '/w/$workspaceSlug/p/$projectSlug/workflows',
|
|
25
25
|
parent: 'projectLayout',
|
|
26
26
|
impl: '@shipfox/client-workflows/routes/workflows',
|
|
27
27
|
},
|
|
28
28
|
{
|
|
29
|
-
path: '/
|
|
29
|
+
path: '/w/$workspaceSlug/p/$projectSlug/runs',
|
|
30
30
|
parent: 'projectLayout',
|
|
31
31
|
impl: '@shipfox/client-workflows/routes/runs',
|
|
32
32
|
},
|
|
33
33
|
{
|
|
34
|
-
path: '/
|
|
34
|
+
path: '/w/$workspaceSlug/p/$projectSlug/runs/$workflowRunId',
|
|
35
35
|
parent: 'projectLayout',
|
|
36
36
|
impl: '@shipfox/client-workflows/routes/run-detail',
|
|
37
37
|
},
|
|
@@ -7,6 +7,7 @@ import type {
|
|
|
7
7
|
WorkflowRunDetailResponseDto,
|
|
8
8
|
WorkflowRunJobDetailDto,
|
|
9
9
|
WorkflowRunJobExecutionDetailDto,
|
|
10
|
+
WorkflowRunListItemDto,
|
|
10
11
|
WorkflowRunListResponseDto,
|
|
11
12
|
WorkflowRunResponseDto,
|
|
12
13
|
WorkflowRunStepDetailDto,
|
|
@@ -25,7 +26,7 @@ import {
|
|
|
25
26
|
type WorkflowRunDetail,
|
|
26
27
|
type WorkflowRunListItem,
|
|
27
28
|
type WorkflowRunListPage,
|
|
28
|
-
|
|
29
|
+
type WorkflowRunRecord,
|
|
29
30
|
workflowRunTriggerDisplayLabel,
|
|
30
31
|
workflowRunTriggerLabel,
|
|
31
32
|
} from '#core/workflow-run.js';
|
|
@@ -35,7 +36,9 @@ export function toWorkflowRun(dto: WorkflowRunResponseDto): WorkflowRun {
|
|
|
35
36
|
id: dto.id,
|
|
36
37
|
projectId: dto.project_id,
|
|
37
38
|
definitionId: dto.definition_id,
|
|
39
|
+
number: dto.number,
|
|
38
40
|
name: dto.name,
|
|
41
|
+
workflowName: dto.workflow_name,
|
|
39
42
|
currentAttempt: dto.current_attempt,
|
|
40
43
|
triggerProvider: dto.trigger_provider,
|
|
41
44
|
triggerSource: dto.trigger_source,
|
|
@@ -49,13 +52,13 @@ export function toWorkflowRun(dto: WorkflowRunResponseDto): WorkflowRun {
|
|
|
49
52
|
triggerEvent: dto.trigger_event,
|
|
50
53
|
}),
|
|
51
54
|
triggerPayload: dto.trigger_payload,
|
|
55
|
+
triggerReference: dto.trigger_reference,
|
|
52
56
|
inputs: dto.inputs ?? null,
|
|
53
57
|
sourceSnapshot: dto.source_snapshot
|
|
54
58
|
? {content: dto.source_snapshot.content, format: dto.source_snapshot.format}
|
|
55
59
|
: null,
|
|
56
60
|
createdAt: dto.created_at,
|
|
57
61
|
updatedAt: dto.updated_at,
|
|
58
|
-
shortId: workflowRunShortId(dto.id),
|
|
59
62
|
isTemporary: dto.id.startsWith('temp-'),
|
|
60
63
|
};
|
|
61
64
|
}
|
|
@@ -73,7 +76,7 @@ export function toWorkflowRunAttempt(dto: WorkflowRunAttemptDto): WorkflowRunAtt
|
|
|
73
76
|
});
|
|
74
77
|
}
|
|
75
78
|
|
|
76
|
-
export function
|
|
79
|
+
export function toWorkflowRunRecord(dto: WorkflowRunResponseDto): WorkflowRunRecord {
|
|
77
80
|
return {
|
|
78
81
|
...toWorkflowRun(dto),
|
|
79
82
|
status: dto.status,
|
|
@@ -89,6 +92,26 @@ export function toWorkflowRunListItem(dto: WorkflowRunResponseDto): WorkflowRunL
|
|
|
89
92
|
};
|
|
90
93
|
}
|
|
91
94
|
|
|
95
|
+
export function toWorkflowRunListItem(dto: WorkflowRunListItemDto): WorkflowRunListItem {
|
|
96
|
+
const statusCounts = dto.job_status_counts.map(({status, count}) => ({status, count}));
|
|
97
|
+
return {
|
|
98
|
+
...toWorkflowRunRecord(dto),
|
|
99
|
+
jobs: {
|
|
100
|
+
preview: dto.jobs.map((job) => ({
|
|
101
|
+
id: job.id,
|
|
102
|
+
key: job.key,
|
|
103
|
+
name: job.name,
|
|
104
|
+
status: job.status,
|
|
105
|
+
position: job.position,
|
|
106
|
+
})),
|
|
107
|
+
statusCounts,
|
|
108
|
+
// Derived rather than sent: the counts already cover every job, and a separate total
|
|
109
|
+
// would be a second source of truth that could disagree with them.
|
|
110
|
+
total: statusCounts.reduce((sum, entry) => sum + entry.count, 0),
|
|
111
|
+
},
|
|
112
|
+
};
|
|
113
|
+
}
|
|
114
|
+
|
|
92
115
|
export function toWorkflowRunListPage(dto: WorkflowRunListResponseDto): WorkflowRunListPage {
|
|
93
116
|
return {
|
|
94
117
|
runs: dto.runs.map(toWorkflowRunListItem),
|
|
@@ -220,6 +243,10 @@ function toWorkflowExecutionEvent(dto: WorkflowExecutionEventDto): WorkflowExecu
|
|
|
220
243
|
event: dto.event,
|
|
221
244
|
deliveryId: dto.delivery_id,
|
|
222
245
|
receivedAt: dto.received_at,
|
|
246
|
+
project: dto.project,
|
|
247
|
+
repository: dto.repository,
|
|
248
|
+
ref: dto.ref,
|
|
249
|
+
commit: dto.commit,
|
|
223
250
|
data: dto.data,
|
|
224
251
|
};
|
|
225
252
|
}
|
|
@@ -240,6 +240,8 @@ describe('workflow run API hooks', () => {
|
|
|
240
240
|
expect(cached?.pages[0]?.runs[0]).toMatchObject({
|
|
241
241
|
projectId: PROJECT_ID,
|
|
242
242
|
definitionId: DEFINITION_ID,
|
|
243
|
+
number: null,
|
|
244
|
+
workflowName: 'New run',
|
|
243
245
|
status: 'pending',
|
|
244
246
|
triggerSource: 'manual',
|
|
245
247
|
triggerProvider: null,
|
|
@@ -29,13 +29,14 @@ import {
|
|
|
29
29
|
type WorkflowRunDetail,
|
|
30
30
|
type WorkflowRunListItem,
|
|
31
31
|
type WorkflowRunListPage,
|
|
32
|
+
type WorkflowRunRecord,
|
|
32
33
|
type WorkflowRunStatus,
|
|
33
34
|
} from '#core/workflow-run.js';
|
|
34
35
|
import {
|
|
35
36
|
toWorkflowRunAttempt,
|
|
36
37
|
toWorkflowRunDetail,
|
|
37
|
-
toWorkflowRunListItem,
|
|
38
38
|
toWorkflowRunListPage,
|
|
39
|
+
toWorkflowRunRecord,
|
|
39
40
|
} from './workflow-run-mapper.js';
|
|
40
41
|
|
|
41
42
|
export interface WorkflowRunFilters {
|
|
@@ -250,8 +251,8 @@ async function cancelWorkflowRun({
|
|
|
250
251
|
workflowRunId,
|
|
251
252
|
}: {
|
|
252
253
|
workflowRunId: string;
|
|
253
|
-
}): Promise<
|
|
254
|
-
return
|
|
254
|
+
}): Promise<WorkflowRunRecord> {
|
|
255
|
+
return toWorkflowRunRecord(
|
|
255
256
|
await checkedApiRequest(workflowRunDtoSchema, `/workflows/runs/${workflowRunId}/cancel`, {
|
|
256
257
|
method: 'POST',
|
|
257
258
|
}),
|
|
@@ -264,8 +265,8 @@ export async function rerunWorkflowRun({
|
|
|
264
265
|
}: {
|
|
265
266
|
workflowRunId: string;
|
|
266
267
|
mode: WorkflowRunRerunModeDto;
|
|
267
|
-
}): Promise<
|
|
268
|
-
return
|
|
268
|
+
}): Promise<WorkflowRunRecord> {
|
|
269
|
+
return toWorkflowRunRecord(
|
|
269
270
|
await checkedApiRequest(workflowRunResponseSchema, `/workflows/runs/${workflowRunId}/rerun`, {
|
|
270
271
|
method: 'POST',
|
|
271
272
|
body: {mode} satisfies RerunWorkflowRunBodyDto,
|
|
@@ -338,7 +339,9 @@ function buildTempRun({
|
|
|
338
339
|
id,
|
|
339
340
|
projectId,
|
|
340
341
|
definitionId,
|
|
342
|
+
number: null,
|
|
341
343
|
name,
|
|
344
|
+
workflowName: name,
|
|
342
345
|
status: 'pending',
|
|
343
346
|
currentAttempt: 1,
|
|
344
347
|
latestAttempt: 1,
|
|
@@ -348,12 +351,14 @@ function buildTempRun({
|
|
|
348
351
|
triggerPayload: {source: 'manual', event: 'fire'},
|
|
349
352
|
triggerDisplayLabel: 'fire',
|
|
350
353
|
triggerLabel: 'manual · fire',
|
|
354
|
+
triggerReference: null,
|
|
351
355
|
inputs: null,
|
|
352
356
|
sourceSnapshot: null,
|
|
353
357
|
createdAt,
|
|
354
358
|
updatedAt: createdAt,
|
|
355
|
-
shortId: id.slice(0, 8),
|
|
356
359
|
isTemporary: true,
|
|
360
|
+
// The optimistic row genuinely has no jobs yet: the server has not planned the graph.
|
|
361
|
+
jobs: {preview: [], statusCounts: [], total: 0},
|
|
357
362
|
runAttempt: new WorkflowRunAttemptSummary({
|
|
358
363
|
workflowRunId: id,
|
|
359
364
|
attempt: 1,
|
|
@@ -568,7 +573,7 @@ export function workflowRunAttemptsQueryOptions({
|
|
|
568
573
|
export function useCancelWorkflowRunMutation(run: WorkflowRun | undefined) {
|
|
569
574
|
const queryClient = useQueryClient();
|
|
570
575
|
return useMutation({
|
|
571
|
-
mutationFn: async (): Promise<
|
|
576
|
+
mutationFn: async (): Promise<WorkflowRunRecord> => {
|
|
572
577
|
if (!run) throw new Error('Workflow run is not loaded');
|
|
573
578
|
return await cancelWorkflowRun({workflowRunId: run.id});
|
|
574
579
|
},
|
package/src/index.ts
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
export type {
|
|
2
2
|
AgentConfigIssue,
|
|
3
3
|
JobDisplayDuration,
|
|
4
|
+
JobDisplayStatus,
|
|
4
5
|
JobExecutionDisplayDuration,
|
|
6
|
+
JobExecutionDisplayStatus,
|
|
5
7
|
JobExecutionStatus,
|
|
6
8
|
JobExecutionTime,
|
|
7
9
|
JobStatus,
|
|
@@ -14,6 +16,7 @@ export type {
|
|
|
14
16
|
StepErrorReason,
|
|
15
17
|
StepGateResult,
|
|
16
18
|
StepSourceLocation,
|
|
19
|
+
WorkflowDisplayStatus,
|
|
17
20
|
WorkflowRun,
|
|
18
21
|
WorkflowRunAttempt,
|
|
19
22
|
WorkflowRunDetail,
|
|
@@ -23,13 +26,14 @@ export type {
|
|
|
23
26
|
WorkflowStatus,
|
|
24
27
|
} from '#core/workflow-run.js';
|
|
25
28
|
export {
|
|
29
|
+
deriveJobDisplayStatus,
|
|
30
|
+
deriveJobExecutionDisplayStatus,
|
|
26
31
|
isWorkflowRunTerminal,
|
|
27
32
|
isWorkflowStatus,
|
|
28
33
|
Job,
|
|
29
34
|
JobExecution,
|
|
30
35
|
TERMINAL_WORKFLOW_RUN_STATUSES,
|
|
31
36
|
WORKFLOW_RUN_STATUSES,
|
|
32
|
-
workflowRunShortId,
|
|
33
37
|
workflowRunTriggerLabel,
|
|
34
38
|
} from '#core/workflow-run.js';
|
|
35
39
|
export {
|
|
@@ -47,4 +51,5 @@ export {
|
|
|
47
51
|
workflowRunsQueryKeys,
|
|
48
52
|
} from './hooks/api/workflow-runs.js';
|
|
49
53
|
export {ProjectWorkflowsPage} from './pages/project-workflows-page.js';
|
|
50
|
-
export {
|
|
54
|
+
export {WorkflowRunDetailPage} from './pages/workflow-run-detail-page.js';
|
|
55
|
+
export {WorkflowRunsPage} from './pages/workflow-run-list-page.js';
|