@shipfox/client-workflows 18.0.0 → 20.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/.turbo/turbo-build.log +1 -1
- package/CHANGELOG.md +25 -0
- package/dist/components/workflow-run-duration-label.d.ts +8 -7
- package/dist/components/workflow-run-duration-label.d.ts.map +1 -1
- package/dist/components/workflow-run-duration-label.js +15 -31
- package/dist/components/workflow-run-duration-label.js.map +1 -1
- package/dist/components/workflow-run-list/job-status-strip.d.ts.map +1 -1
- package/dist/components/workflow-run-list/job-status-strip.js +20 -7
- package/dist/components/workflow-run-list/job-status-strip.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 +9 -6
- 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 +7 -34
- package/dist/components/workflow-run-summary/workflow-run-summary.js.map +1 -1
- package/dist/components/workflow-status/status-visuals.d.ts.map +1 -1
- package/dist/components/workflow-status/status-visuals.js +0 -9
- package/dist/components/workflow-status/status-visuals.js.map +1 -1
- package/dist/components/workflow-status/workflow-status-icon.d.ts.map +1 -1
- package/dist/components/workflow-status/workflow-status-icon.js +0 -11
- package/dist/components/workflow-status/workflow-status-icon.js.map +1 -1
- package/dist/core/entities/job.d.ts +5 -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 +15 -57
- package/dist/core/entities/workflow-run.d.ts.map +1 -1
- package/dist/core/entities/workflow-run.js +1 -94
- package/dist/core/entities/workflow-run.js.map +1 -1
- package/dist/core/workflow-run.d.ts +2 -2
- package/dist/core/workflow-run.d.ts.map +1 -1
- package/dist/core/workflow-run.js +1 -1
- package/dist/core/workflow-run.js.map +1 -1
- package/dist/hooks/api/workflow-run-mapper.d.ts.map +1 -1
- package/dist/hooks/api/workflow-run-mapper.js +14 -2
- package/dist/hooks/api/workflow-run-mapper.js.map +1 -1
- package/dist/hooks/api/workflow-runs.js +1 -0
- package/dist/hooks/api/workflow-runs.js.map +1 -1
- package/dist/tsconfig.test.tsbuildinfo +1 -1
- package/package.json +2 -2
- package/src/components/job-graph/job-node.test.tsx +2 -2
- package/src/components/workflow-run-duration-label.tsx +21 -44
- package/src/components/workflow-run-list/job-status-strip.tsx +25 -12
- package/src/components/workflow-run-list/workflow-run-list-view.test.tsx +121 -0
- package/src/components/workflow-run-list/workflow-run-list.stories.tsx +31 -0
- package/src/components/workflow-run-list/workflow-run-row.tsx +7 -6
- package/src/components/workflow-run-summary/workflow-run-summary.stories.tsx +0 -38
- package/src/components/workflow-run-summary/workflow-run-summary.test.tsx +73 -21
- package/src/components/workflow-run-summary/workflow-run-summary.tsx +6 -27
- package/src/components/workflow-status/status-visuals.ts +0 -4
- package/src/components/workflow-status/workflow-status-icon.stories.tsx +0 -1
- package/src/components/workflow-status/workflow-status-icon.tsx +0 -18
- package/src/core/entities/job-status.test.ts +47 -1
- package/src/core/entities/job.ts +15 -3
- package/src/core/entities/workflow-run.ts +21 -134
- package/src/core/workflow-run.test.ts +15 -0
- package/src/core/workflow-run.ts +0 -8
- package/src/hooks/api/workflow-run-mapper.ts +20 -1
- package/src/hooks/api/workflow-runs.ts +1 -1
- package/test/fixtures/workflow-run.ts +60 -13
- package/tsconfig.build.tsbuildinfo +1 -1
- package/src/core/entities/workflow-run-display.test.ts +0 -159
|
@@ -96,7 +96,10 @@ export function toWorkflowRunRecord(dto: WorkflowRunResponseDto): WorkflowRunRec
|
|
|
96
96
|
}
|
|
97
97
|
|
|
98
98
|
export function toWorkflowRunListItem(dto: WorkflowRunListItemDto): WorkflowRunListItem {
|
|
99
|
-
const
|
|
99
|
+
const hasDisplayStatusCounts = dto.job_display_status_counts !== undefined;
|
|
100
|
+
const statusCounts = (dto.job_display_status_counts ?? dto.job_status_counts).map(
|
|
101
|
+
({status, count}) => ({status, count}),
|
|
102
|
+
);
|
|
100
103
|
return {
|
|
101
104
|
...toWorkflowRunRecord(dto),
|
|
102
105
|
jobs: {
|
|
@@ -105,9 +108,18 @@ export function toWorkflowRunListItem(dto: WorkflowRunListItemDto): WorkflowRunL
|
|
|
105
108
|
key: job.key,
|
|
106
109
|
name: job.name,
|
|
107
110
|
status: job.status,
|
|
111
|
+
mode: job.mode ?? 'one_shot',
|
|
112
|
+
listenerStatus: job.listener_status ?? 'inactive',
|
|
113
|
+
// The optional display-count field is the rollout capability signal. Pre-display API
|
|
114
|
+
// responses only carry raw verdict counts, so mirror their non-terminal verdict into
|
|
115
|
+
// execution evidence to keep each legacy glyph aligned with those fallback counts.
|
|
116
|
+
executionStatus: hasDisplayStatusCounts
|
|
117
|
+
? (job.execution_status ?? null)
|
|
118
|
+
: legacyExecutionStatus(job.status),
|
|
108
119
|
position: job.position,
|
|
109
120
|
})),
|
|
110
121
|
statusCounts,
|
|
122
|
+
hasStartedJobExecution: dto.has_started_job_execution ?? true,
|
|
111
123
|
// Derived rather than sent: the counts already cover every job, and a separate total
|
|
112
124
|
// would be a second source of truth that could disagree with them.
|
|
113
125
|
total: statusCounts.reduce((sum, entry) => sum + entry.count, 0),
|
|
@@ -115,6 +127,12 @@ export function toWorkflowRunListItem(dto: WorkflowRunListItemDto): WorkflowRunL
|
|
|
115
127
|
};
|
|
116
128
|
}
|
|
117
129
|
|
|
130
|
+
function legacyExecutionStatus(
|
|
131
|
+
status: WorkflowRunListItemDto['jobs'][number]['status'],
|
|
132
|
+
): 'pending' | 'running' | null {
|
|
133
|
+
return status === 'pending' || status === 'running' ? status : null;
|
|
134
|
+
}
|
|
135
|
+
|
|
118
136
|
export function toWorkflowRunListPage(dto: WorkflowRunListResponseDto): WorkflowRunListPage {
|
|
119
137
|
return {
|
|
120
138
|
runs: dto.runs.map(toWorkflowRunListItem),
|
|
@@ -129,6 +147,7 @@ export function toWorkflowRunDetail(dto: WorkflowRunDetailResponseDto): Workflow
|
|
|
129
147
|
latestAttempt: dto.latest_attempt,
|
|
130
148
|
runAttempt: toWorkflowRunAttempt(dto.run_attempt),
|
|
131
149
|
jobs: dto.jobs.map(toJob),
|
|
150
|
+
hasStartedJobExecution: dto.has_started_job_execution ?? true,
|
|
132
151
|
};
|
|
133
152
|
}
|
|
134
153
|
|
|
@@ -358,7 +358,7 @@ function buildTempRun({
|
|
|
358
358
|
updatedAt: createdAt,
|
|
359
359
|
isTemporary: true,
|
|
360
360
|
// The optimistic row genuinely has no jobs yet: the server has not planned the graph.
|
|
361
|
-
jobs: {preview: [], statusCounts: [], total: 0},
|
|
361
|
+
jobs: {preview: [], statusCounts: [], hasStartedJobExecution: false, total: 0},
|
|
362
362
|
runAttempt: new WorkflowRunAttemptSummary({
|
|
363
363
|
workflowRunId: id,
|
|
364
364
|
attempt: 1,
|
|
@@ -81,6 +81,8 @@ export function workflowRunDto(
|
|
|
81
81
|
finished_at: null,
|
|
82
82
|
jobs: [],
|
|
83
83
|
job_status_counts: [],
|
|
84
|
+
job_display_status_counts: [],
|
|
85
|
+
has_started_job_execution: false,
|
|
84
86
|
...overrides,
|
|
85
87
|
};
|
|
86
88
|
}
|
|
@@ -89,11 +91,15 @@ export function workflowRunJobSummaryDto(
|
|
|
89
91
|
overrides: Partial<WorkflowRunJobSummaryDto> = {},
|
|
90
92
|
): WorkflowRunJobSummaryDto {
|
|
91
93
|
jobSummarySequence += 1;
|
|
94
|
+
const status = overrides.status ?? 'succeeded';
|
|
92
95
|
return {
|
|
93
96
|
id: `${JOB_SUMMARY_ID_PREFIX}${String(jobSummarySequence).padStart(11, '0')}`,
|
|
94
97
|
key: `job-${jobSummarySequence}`,
|
|
95
98
|
name: null,
|
|
96
|
-
status
|
|
99
|
+
status,
|
|
100
|
+
mode: 'one_shot',
|
|
101
|
+
listener_status: 'inactive',
|
|
102
|
+
execution_status: executionStatusForFixtureStatus(status),
|
|
97
103
|
position: jobSummarySequence - 1,
|
|
98
104
|
...overrides,
|
|
99
105
|
};
|
|
@@ -104,13 +110,25 @@ export function workflowRunJobSummaryDtos(
|
|
|
104
110
|
count: number,
|
|
105
111
|
statuses: readonly JobStatusDto[] = [],
|
|
106
112
|
): WorkflowRunJobSummaryDto[] {
|
|
107
|
-
return Array.from({length: count}, (_, index) =>
|
|
108
|
-
|
|
113
|
+
return Array.from({length: count}, (_, index) => {
|
|
114
|
+
const status = statuses[index];
|
|
115
|
+
return workflowRunJobSummaryDto({
|
|
109
116
|
key: `job-${index + 1}`,
|
|
110
117
|
position: index,
|
|
111
|
-
...(
|
|
112
|
-
|
|
113
|
-
|
|
118
|
+
...(status
|
|
119
|
+
? {
|
|
120
|
+
status,
|
|
121
|
+
execution_status: executionStatusForFixtureStatus(status),
|
|
122
|
+
}
|
|
123
|
+
: {}),
|
|
124
|
+
});
|
|
125
|
+
});
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
function executionStatusForFixtureStatus(
|
|
129
|
+
status: JobStatusDto,
|
|
130
|
+
): WorkflowRunJobSummaryDto['execution_status'] {
|
|
131
|
+
return status === 'pending' || status === 'running' ? status : null;
|
|
114
132
|
}
|
|
115
133
|
|
|
116
134
|
/**
|
|
@@ -119,19 +137,33 @@ export function workflowRunJobSummaryDtos(
|
|
|
119
137
|
*
|
|
120
138
|
* Built from one list so the two can never disagree. A fixture whose counts contradicted its
|
|
121
139
|
* preview would hide exactly the bug the split exists to prevent.
|
|
140
|
+
*
|
|
141
|
+
* `has_started_job_execution` follows the statuses where they settle it: `succeeded` and `failed`
|
|
142
|
+
* cannot be reached without running. `pending`, `skipped`, and `cancelled` leave it open, which is
|
|
143
|
+
* the ambiguity the server flag exists to resolve, so those default to not started and a case that
|
|
144
|
+
* needs the other reading overrides it.
|
|
122
145
|
*/
|
|
123
146
|
export function workflowRunJobsFixture(
|
|
124
147
|
statuses: readonly JobStatusDto[],
|
|
125
|
-
): Pick<
|
|
148
|
+
): Pick<
|
|
149
|
+
WorkflowRunListItemDto,
|
|
150
|
+
'jobs' | 'job_status_counts' | 'job_display_status_counts' | 'has_started_job_execution'
|
|
151
|
+
> {
|
|
126
152
|
const counts = new Map<JobStatusDto, number>();
|
|
127
153
|
for (const status of statuses) counts.set(status, (counts.get(status) ?? 0) + 1);
|
|
128
154
|
|
|
155
|
+
const preview = workflowRunJobSummaryDtos(
|
|
156
|
+
Math.min(statuses.length, WORKFLOW_RUN_JOB_PREVIEW_LIMIT),
|
|
157
|
+
statuses,
|
|
158
|
+
);
|
|
159
|
+
|
|
129
160
|
return {
|
|
130
|
-
jobs:
|
|
131
|
-
Math.min(statuses.length, WORKFLOW_RUN_JOB_PREVIEW_LIMIT),
|
|
132
|
-
statuses,
|
|
133
|
-
),
|
|
161
|
+
jobs: preview,
|
|
134
162
|
job_status_counts: [...counts.entries()].map(([status, count]) => ({status, count})),
|
|
163
|
+
job_display_status_counts: [...counts.entries()].map(([status, count]) => ({status, count})),
|
|
164
|
+
has_started_job_execution: statuses.some(
|
|
165
|
+
(status) => status === 'running' || status === 'succeeded' || status === 'failed',
|
|
166
|
+
),
|
|
135
167
|
};
|
|
136
168
|
}
|
|
137
169
|
|
|
@@ -139,7 +171,10 @@ export function workflowRunJobsFixture(
|
|
|
139
171
|
export function workflowRunJobsOfStatus(
|
|
140
172
|
count: number,
|
|
141
173
|
status: JobStatusDto = 'succeeded',
|
|
142
|
-
): Pick<
|
|
174
|
+
): Pick<
|
|
175
|
+
WorkflowRunListItemDto,
|
|
176
|
+
'jobs' | 'job_status_counts' | 'job_display_status_counts' | 'has_started_job_execution'
|
|
177
|
+
> {
|
|
143
178
|
return workflowRunJobsFixture(Array.from({length: count}, () => status));
|
|
144
179
|
}
|
|
145
180
|
|
|
@@ -169,7 +204,12 @@ export function workflowRunListPage(
|
|
|
169
204
|
export function workflowRunDetailDto(
|
|
170
205
|
overrides: Partial<WorkflowRunDetailResponseDto> = {},
|
|
171
206
|
): WorkflowRunDetailResponseDto {
|
|
172
|
-
const {
|
|
207
|
+
const {
|
|
208
|
+
jobs,
|
|
209
|
+
run_attempt: runAttemptOverride,
|
|
210
|
+
has_started_job_execution: hasStartedOverride,
|
|
211
|
+
...runOverrides
|
|
212
|
+
} = overrides;
|
|
173
213
|
const run = workflowRunDto(runOverrides);
|
|
174
214
|
|
|
175
215
|
return {
|
|
@@ -185,6 +225,13 @@ export function workflowRunDetailDto(
|
|
|
185
225
|
finished_at: run.finished_at,
|
|
186
226
|
}),
|
|
187
227
|
jobs: jobs ?? [],
|
|
228
|
+
// Follows the executions the case actually built, so the fixture cannot claim a run started
|
|
229
|
+
// while carrying no execution that did.
|
|
230
|
+
has_started_job_execution:
|
|
231
|
+
hasStartedOverride ??
|
|
232
|
+
(jobs ?? []).some((job) =>
|
|
233
|
+
job.job_executions.some((execution) => execution.started_at != null),
|
|
234
|
+
),
|
|
188
235
|
};
|
|
189
236
|
}
|
|
190
237
|
|