@shipfox/client-workflows 15.0.0 → 17.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/.turbo/turbo-build.log +1 -1
- package/.turbo/turbo-type.log +1 -0
- package/CHANGELOG.md +41 -0
- package/dist/components/identifier/identifier.js +2 -2
- package/dist/components/identifier/identifier.js.map +1 -1
- package/dist/components/job-detail/agent-config-failure-callout.d.ts.map +1 -1
- package/dist/components/job-detail/agent-config-failure-callout.js +1 -1
- package/dist/components/job-detail/agent-config-failure-callout.js.map +1 -1
- package/dist/components/job-detail/job-context-panel.d.ts +6 -0
- package/dist/components/job-detail/job-context-panel.d.ts.map +1 -0
- package/dist/components/job-detail/job-context-panel.js +224 -0
- package/dist/components/job-detail/job-context-panel.js.map +1 -0
- package/dist/components/job-detail/job-detail-header.d.ts +10 -1
- package/dist/components/job-detail/job-detail-header.d.ts.map +1 -1
- package/dist/components/job-detail/job-detail-header.js +58 -39
- package/dist/components/job-detail/job-detail-header.js.map +1 -1
- package/dist/components/job-detail/job-detail-view.d.ts +1 -1
- package/dist/components/job-detail/job-detail-view.d.ts.map +1 -1
- package/dist/components/job-detail/job-detail-view.js +92 -41
- package/dist/components/job-detail/job-detail-view.js.map +1 -1
- package/dist/components/job-detail/job-empty-states.d.ts.map +1 -1
- package/dist/components/job-detail/job-empty-states.js +19 -10
- package/dist/components/job-detail/job-empty-states.js.map +1 -1
- package/dist/components/job-detail/job-execution-switcher.js +4 -4
- package/dist/components/job-detail/job-execution-switcher.js.map +1 -1
- package/dist/components/job-detail/json-code.d.ts +14 -0
- package/dist/components/job-detail/json-code.d.ts.map +1 -0
- package/dist/components/job-detail/json-code.js +93 -0
- package/dist/components/job-detail/json-code.js.map +1 -0
- package/dist/components/job-detail/step-attempt-log-panel.d.ts.map +1 -1
- package/dist/components/job-detail/step-attempt-log-panel.js +9 -6
- package/dist/components/job-detail/step-attempt-log-panel.js.map +1 -1
- package/dist/components/job-detail/step-troubleshooting.d.ts +18 -0
- package/dist/components/job-detail/step-troubleshooting.d.ts.map +1 -0
- package/dist/components/job-detail/step-troubleshooting.js +493 -0
- package/dist/components/job-detail/step-troubleshooting.js.map +1 -0
- package/dist/components/job-graph/job-graph-content.d.ts.map +1 -1
- package/dist/components/job-graph/job-graph-content.js +5 -4
- package/dist/components/job-graph/job-graph-content.js.map +1 -1
- package/dist/components/job-graph/job-node.js +3 -3
- package/dist/components/job-graph/job-node.js.map +1 -1
- package/dist/components/step-list/index.d.ts +1 -0
- package/dist/components/step-list/index.d.ts.map +1 -1
- package/dist/components/step-list/index.js.map +1 -1
- package/dist/components/step-list/step-list-model.d.ts.map +1 -1
- package/dist/components/step-list/step-list-model.js +5 -0
- package/dist/components/step-list/step-list-model.js.map +1 -1
- package/dist/components/step-list/step-list.d.ts +5 -1
- package/dist/components/step-list/step-list.d.ts.map +1 -1
- package/dist/components/step-list/step-list.js +117 -82
- package/dist/components/step-list/step-list.js.map +1 -1
- package/dist/components/workflow-run-duration-label.js +1 -1
- package/dist/components/workflow-run-duration-label.js.map +1 -1
- package/dist/components/workflow-run-list/job-status-strip.js +6 -6
- package/dist/components/workflow-run-list/job-status-strip.js.map +1 -1
- package/dist/components/workflow-run-list/workflow-run-filter-menu.js +1 -1
- package/dist/components/workflow-run-list/workflow-run-filter-menu.js.map +1 -1
- package/dist/components/workflow-run-list/workflow-run-filters.js +4 -4
- package/dist/components/workflow-run-list/workflow-run-filters.js.map +1 -1
- package/dist/components/workflow-run-list/workflow-run-list-states.js +6 -6
- package/dist/components/workflow-run-list/workflow-run-list-states.js.map +1 -1
- package/dist/components/workflow-run-list/workflow-run-list-view.js +1 -1
- package/dist/components/workflow-run-list/workflow-run-list-view.js.map +1 -1
- package/dist/components/workflow-run-list/workflow-run-row.js +7 -7
- package/dist/components/workflow-run-list/workflow-run-row.js.map +1 -1
- package/dist/components/workflow-run-summary/workflow-run-attempt-switcher.js +1 -1
- 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 +0 -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 +9 -13
- package/dist/components/workflow-run-summary/workflow-run-summary.js.map +1 -1
- package/dist/components/workflow-run-tabs/index.d.ts +3 -0
- package/dist/components/workflow-run-tabs/index.d.ts.map +1 -1
- package/dist/components/workflow-run-tabs/index.js +3 -0
- 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 +39 -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 +211 -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 +90 -25
- package/dist/components/workflow-run-tabs/run-annotation-summary-line.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/run-workspace-nav.d.ts +1 -1
- package/dist/components/workflow-run-view/run-workspace-nav.d.ts.map +1 -1
- package/dist/components/workflow-run-view/run-workspace-nav.js +16 -10
- package/dist/components/workflow-run-view/run-workspace-nav.js.map +1 -1
- package/dist/components/workflow-run-view/workflow-run-states.js +6 -6
- package/dist/components/workflow-run-view/workflow-run-states.js.map +1 -1
- package/dist/components/workflow-run-view/workflow-run-view.d.ts +1 -3
- package/dist/components/workflow-run-view/workflow-run-view.d.ts.map +1 -1
- package/dist/components/workflow-run-view/workflow-run-view.js +217 -59
- package/dist/components/workflow-run-view/workflow-run-view.js.map +1 -1
- package/dist/core/entities/job-execution.d.ts +7 -0
- package/dist/core/entities/job-execution.d.ts.map +1 -1
- package/dist/core/entities/job-execution.js.map +1 -1
- package/dist/core/entities/job.d.ts +9 -0
- package/dist/core/entities/job.d.ts.map +1 -1
- package/dist/core/entities/job.js.map +1 -1
- package/dist/core/entities/step-attempt.d.ts +29 -0
- package/dist/core/entities/step-attempt.d.ts.map +1 -1
- package/dist/core/entities/step-attempt.js.map +1 -1
- package/dist/core/entities/step.d.ts +3 -1
- package/dist/core/entities/step.d.ts.map +1 -1
- package/dist/core/entities/step.js.map +1 -1
- package/dist/core/run-annotation.d.ts +79 -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 +1 -1
- package/dist/core/workflow-run.d.ts.map +1 -1
- package/dist/core/workflow-run.js.map +1 -1
- package/dist/hooks/api/annotations.d.ts +63 -0
- package/dist/hooks/api/annotations.d.ts.map +1 -0
- package/dist/hooks/api/annotations.js +145 -0
- package/dist/hooks/api/annotations.js.map +1 -0
- 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/step-attempt-detail.d.ts +14 -0
- package/dist/hooks/api/step-attempt-detail.d.ts.map +1 -0
- package/dist/hooks/api/step-attempt-detail.js +43 -0
- package/dist/hooks/api/step-attempt-detail.js.map +1 -0
- package/dist/hooks/api/workflow-run-mapper.d.ts +9 -2
- package/dist/hooks/api/workflow-run-mapper.d.ts.map +1 -1
- package/dist/hooks/api/workflow-run-mapper.js +47 -0
- package/dist/hooks/api/workflow-run-mapper.js.map +1 -1
- package/dist/pages/project-workflows-page.js +19 -19
- package/dist/pages/project-workflows-page.js.map +1 -1
- package/dist/pages/workflow-run-list-page.js +1 -1
- package/dist/pages/workflow-run-list-page.js.map +1 -1
- package/dist/routes/inputs.d.ts +7 -2
- package/dist/routes/inputs.d.ts.map +1 -1
- package/dist/routes/inputs.js +5 -6
- package/dist/routes/inputs.js.map +1 -1
- package/dist/tsconfig.test.tsbuildinfo +1 -1
- package/package.json +10 -9
- package/src/components/identifier/identifier.tsx +2 -2
- package/src/components/job-detail/agent-config-failure-callout.tsx +5 -1
- package/src/components/job-detail/job-context-panel.test.tsx +72 -0
- package/src/components/job-detail/job-context-panel.tsx +237 -0
- package/src/components/job-detail/job-detail-header.test.tsx +3 -0
- package/src/components/job-detail/job-detail-header.tsx +65 -34
- package/src/components/job-detail/job-detail-view.stories.tsx +555 -48
- package/src/components/job-detail/job-detail-view.tsx +101 -42
- package/src/components/job-detail/job-empty-states.tsx +23 -10
- package/src/components/job-detail/job-execution-switcher.tsx +5 -5
- package/src/components/job-detail/json-code.tsx +120 -0
- package/src/components/job-detail/step-attempt-log-panel.test.tsx +1 -0
- package/src/components/job-detail/step-attempt-log-panel.tsx +17 -6
- package/src/components/job-detail/step-troubleshooting.stories.tsx +120 -0
- package/src/components/job-detail/step-troubleshooting.test.tsx +337 -0
- package/src/components/job-detail/step-troubleshooting.tsx +537 -0
- package/src/components/job-graph/job-graph-content.tsx +4 -3
- package/src/components/job-graph/job-node.tsx +3 -3
- package/src/components/step-list/index.ts +1 -0
- package/src/components/step-list/step-list-model.ts +5 -0
- package/src/components/step-list/step-list.test.tsx +75 -2
- package/src/components/step-list/step-list.tsx +73 -20
- package/src/components/workflow-run-duration-label.tsx +1 -1
- package/src/components/workflow-run-list/job-status-strip.tsx +6 -6
- package/src/components/workflow-run-list/workflow-run-filter-menu.tsx +1 -1
- package/src/components/workflow-run-list/workflow-run-filters.tsx +4 -4
- package/src/components/workflow-run-list/workflow-run-list-states.tsx +6 -6
- package/src/components/workflow-run-list/workflow-run-list-view.tsx +1 -1
- package/src/components/workflow-run-list/workflow-run-row.tsx +7 -7
- package/src/components/workflow-run-summary/workflow-run-attempt-switcher.tsx +1 -1
- package/src/components/workflow-run-summary/workflow-run-summary.test.tsx +1 -1
- package/src/components/workflow-run-summary/workflow-run-summary.tsx +12 -12
- package/src/components/workflow-run-tabs/index.ts +7 -0
- 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 +273 -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 +95 -20
- 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/run-workspace-nav.test.tsx +44 -0
- package/src/components/workflow-run-view/run-workspace-nav.tsx +22 -9
- package/src/components/workflow-run-view/workflow-run-states.tsx +6 -6
- package/src/components/workflow-run-view/workflow-run-view.test.tsx +246 -20
- package/src/components/workflow-run-view/workflow-run-view.tsx +255 -37
- package/src/core/entities/job-execution.ts +7 -0
- package/src/core/entities/job.ts +9 -0
- package/src/core/entities/step-attempt.ts +33 -0
- package/src/core/entities/step.ts +3 -1
- package/src/core/run-annotation.test.ts +315 -0
- package/src/core/run-annotation.ts +244 -0
- package/src/core/workflow-run.ts +4 -0
- package/src/hooks/api/annotations.test.ts +84 -0
- package/src/hooks/api/annotations.ts +240 -0
- package/src/hooks/api/run-annotation-mapper.ts +30 -0
- package/src/hooks/api/run-annotations.ts +137 -0
- package/src/hooks/api/step-attempt-detail.ts +67 -0
- package/src/hooks/api/workflow-run-mapper.ts +46 -0
- package/src/hooks/api/workflow-runs.test.tsx +61 -1
- package/src/pages/project-workflows-page.tsx +19 -19
- package/src/pages/workflow-job-detail-page.test.tsx +118 -1
- package/src/pages/workflow-run-list-page.tsx +1 -1
- package/src/routes/inputs.ts +7 -2
- package/test/fixtures/workflow-run.ts +7 -0
- package/tsconfig.build.tsbuildinfo +1 -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/core/workflow-run-tabs.ts +0 -8
|
@@ -0,0 +1,537 @@
|
|
|
1
|
+
import {Button} from '@shipfox/react-ui/button';
|
|
2
|
+
import {Callout, CalloutContent, CalloutDescription, CalloutTitle} from '@shipfox/react-ui/callout';
|
|
3
|
+
import {
|
|
4
|
+
Sheet,
|
|
5
|
+
SheetBody,
|
|
6
|
+
SheetContent,
|
|
7
|
+
SheetDescription,
|
|
8
|
+
SheetHeader,
|
|
9
|
+
SheetTitle,
|
|
10
|
+
} from '@shipfox/react-ui/sheet';
|
|
11
|
+
import {Skeleton} from '@shipfox/react-ui/skeleton';
|
|
12
|
+
import {Code, Text} from '@shipfox/react-ui/typography';
|
|
13
|
+
import {cn} from '@shipfox/react-ui/utils';
|
|
14
|
+
import {Link} from '@tanstack/react-router';
|
|
15
|
+
import type {ReactNode} from 'react';
|
|
16
|
+
import type {
|
|
17
|
+
EvaluationTraceEntry,
|
|
18
|
+
JobStatusReason,
|
|
19
|
+
Step,
|
|
20
|
+
StepAttempt,
|
|
21
|
+
StepError,
|
|
22
|
+
} from '#core/workflow-run.js';
|
|
23
|
+
import {useStepAttemptDetailQuery} from '#hooks/api/step-attempt-detail.js';
|
|
24
|
+
import {workflowRunSearchParams} from '#routes/inputs.js';
|
|
25
|
+
import {humanizeStatus, type StepListEntryModel} from '../step-list/step-list-model.js';
|
|
26
|
+
import {AgentConfigFailureCallout} from './agent-config-failure-callout.js';
|
|
27
|
+
import {toSelectedAttemptError} from './job-empty-states.js';
|
|
28
|
+
import {JsonCode, type JsonCodeEntry, JsonCodeTabs} from './json-code.js';
|
|
29
|
+
|
|
30
|
+
export interface StepInspectorSheetProps {
|
|
31
|
+
entry: StepListEntryModel;
|
|
32
|
+
open: boolean;
|
|
33
|
+
onOpenChange: (open: boolean) => void;
|
|
34
|
+
workspaceSlug: string;
|
|
35
|
+
projectSlug: string;
|
|
36
|
+
workflowRunId: string;
|
|
37
|
+
runAttempt: number;
|
|
38
|
+
jobId: string;
|
|
39
|
+
annotationCount?: number | undefined;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export function StepInspectorSheet({
|
|
43
|
+
entry,
|
|
44
|
+
open,
|
|
45
|
+
onOpenChange,
|
|
46
|
+
workspaceSlug,
|
|
47
|
+
projectSlug,
|
|
48
|
+
workflowRunId,
|
|
49
|
+
runAttempt,
|
|
50
|
+
jobId,
|
|
51
|
+
annotationCount,
|
|
52
|
+
}: StepInspectorSheetProps) {
|
|
53
|
+
const error = selectedStepError(entry.step, entry.error);
|
|
54
|
+
const inspectorQuery = useStepAttemptDetailQuery(entry.step.id, entry.attempt, {
|
|
55
|
+
enabled: open,
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
return (
|
|
59
|
+
<Sheet open={open} onOpenChange={onOpenChange}>
|
|
60
|
+
<SheetContent side="right" className="w-full sm:max-w-[560px]">
|
|
61
|
+
<SheetHeader>
|
|
62
|
+
<SheetTitle>{entry.step.label}</SheetTitle>
|
|
63
|
+
<SheetDescription>
|
|
64
|
+
Attempt #{entry.attempt} · {humanizeStatus(entry.statusVisual.kind)}
|
|
65
|
+
</SheetDescription>
|
|
66
|
+
</SheetHeader>
|
|
67
|
+
<SheetBody className="gap-section">
|
|
68
|
+
<StepInspector
|
|
69
|
+
step={entry.step}
|
|
70
|
+
attempt={entry}
|
|
71
|
+
error={error}
|
|
72
|
+
showFailure={entry.statusVisual.kind === 'failed' || entry.error !== null}
|
|
73
|
+
query={inspectorQuery}
|
|
74
|
+
workspaceSlug={workspaceSlug}
|
|
75
|
+
projectSlug={projectSlug}
|
|
76
|
+
workflowRunId={workflowRunId}
|
|
77
|
+
runAttempt={runAttempt}
|
|
78
|
+
jobId={jobId}
|
|
79
|
+
annotationCount={annotationCount}
|
|
80
|
+
/>
|
|
81
|
+
</SheetBody>
|
|
82
|
+
</SheetContent>
|
|
83
|
+
</Sheet>
|
|
84
|
+
);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
function StepFailureCallout({
|
|
88
|
+
step,
|
|
89
|
+
attempt,
|
|
90
|
+
error,
|
|
91
|
+
workspaceSlug,
|
|
92
|
+
projectSlug,
|
|
93
|
+
workflowRunId,
|
|
94
|
+
runAttempt,
|
|
95
|
+
}: {
|
|
96
|
+
step: Step;
|
|
97
|
+
attempt: StepAttempt;
|
|
98
|
+
error: StepError | null;
|
|
99
|
+
workspaceSlug: string;
|
|
100
|
+
projectSlug: string;
|
|
101
|
+
workflowRunId: string;
|
|
102
|
+
runAttempt: number;
|
|
103
|
+
}) {
|
|
104
|
+
const reason = error?.reason ?? step.statusReason ?? 'unknown';
|
|
105
|
+
const title = failureTitle(reason);
|
|
106
|
+
const sourceLink = sourceLinkForFailure(reason) && step.sourceLocation;
|
|
107
|
+
|
|
108
|
+
if (step.type === 'agent' && reason === 'agent_config_invalid') {
|
|
109
|
+
return (
|
|
110
|
+
<AgentConfigFailureCallout
|
|
111
|
+
workspaceSlug={workspaceSlug}
|
|
112
|
+
config={step.agentConfig}
|
|
113
|
+
error={error}
|
|
114
|
+
/>
|
|
115
|
+
);
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
return (
|
|
119
|
+
<Callout
|
|
120
|
+
role="alert"
|
|
121
|
+
type="error"
|
|
122
|
+
variant="secondary"
|
|
123
|
+
className="rounded-8 border border-tag-error-border p-panel-compact shadow-none"
|
|
124
|
+
>
|
|
125
|
+
<CalloutContent>
|
|
126
|
+
<CalloutTitle>{title}</CalloutTitle>
|
|
127
|
+
<CalloutDescription>
|
|
128
|
+
<div className="flex min-w-0 flex-wrap items-center gap-x-inline gap-y-tight">
|
|
129
|
+
<div className="flex min-w-0 flex-col gap-tight">
|
|
130
|
+
<span>{failureDescription(reason)}</span>
|
|
131
|
+
{error?.message ? (
|
|
132
|
+
<span className="text-foreground-neutral-muted">{error.message}</span>
|
|
133
|
+
) : null}
|
|
134
|
+
</div>
|
|
135
|
+
<Code as="span" variant="label" className="text-tag-error-text">
|
|
136
|
+
{reason}
|
|
137
|
+
</Code>
|
|
138
|
+
{sourceLink ? (
|
|
139
|
+
<Link
|
|
140
|
+
to="/w/$workspaceSlug/p/$projectSlug/runs/$workflowRunId"
|
|
141
|
+
params={{workspaceSlug, projectSlug, workflowRunId}}
|
|
142
|
+
search={
|
|
143
|
+
workflowRunSearchParams(
|
|
144
|
+
{tab: 'source'},
|
|
145
|
+
{stepId: step.id, stepAttemptId: attempt.id, runAttempt},
|
|
146
|
+
) as never
|
|
147
|
+
}
|
|
148
|
+
className="font-medium text-foreground-highlight-interactive underline-offset-2 hover:underline"
|
|
149
|
+
>
|
|
150
|
+
View in source
|
|
151
|
+
</Link>
|
|
152
|
+
) : null}
|
|
153
|
+
</div>
|
|
154
|
+
</CalloutDescription>
|
|
155
|
+
</CalloutContent>
|
|
156
|
+
</Callout>
|
|
157
|
+
);
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
function StepInspector({
|
|
161
|
+
step,
|
|
162
|
+
attempt,
|
|
163
|
+
error,
|
|
164
|
+
showFailure,
|
|
165
|
+
query,
|
|
166
|
+
workspaceSlug,
|
|
167
|
+
projectSlug,
|
|
168
|
+
workflowRunId,
|
|
169
|
+
runAttempt,
|
|
170
|
+
jobId,
|
|
171
|
+
annotationCount,
|
|
172
|
+
}: {
|
|
173
|
+
step: Step;
|
|
174
|
+
attempt: StepAttempt;
|
|
175
|
+
error: StepError | null;
|
|
176
|
+
showFailure: boolean;
|
|
177
|
+
query: ReturnType<typeof useStepAttemptDetailQuery>;
|
|
178
|
+
workspaceSlug: string;
|
|
179
|
+
projectSlug: string;
|
|
180
|
+
workflowRunId: string;
|
|
181
|
+
runAttempt: number;
|
|
182
|
+
jobId: string;
|
|
183
|
+
annotationCount: number | undefined;
|
|
184
|
+
}) {
|
|
185
|
+
const detail = query.data;
|
|
186
|
+
const trace = detail?.evaluationTrace ?? null;
|
|
187
|
+
const resolvedConfig = detail?.config ?? null;
|
|
188
|
+
const hasInputs =
|
|
189
|
+
detail !== undefined &&
|
|
190
|
+
(countConfigValues(detail.authoredConfig) > 0 || countConfigValues(resolvedConfig) > 0);
|
|
191
|
+
const hasOutputs =
|
|
192
|
+
attempt.outputs !== null || attempt.output !== null || attempt.response !== null;
|
|
193
|
+
const hasTrace = trace !== null && trace.length > 0;
|
|
194
|
+
const hasAnnotations = annotationCount !== undefined && annotationCount > 0;
|
|
195
|
+
const detailCount = Number(hasInputs) + Number(hasOutputs) + Number(hasTrace);
|
|
196
|
+
|
|
197
|
+
return (
|
|
198
|
+
<div className="flex min-w-0 flex-col gap-section">
|
|
199
|
+
{showFailure ? (
|
|
200
|
+
<StepFailureCallout
|
|
201
|
+
step={step}
|
|
202
|
+
attempt={attempt}
|
|
203
|
+
error={error}
|
|
204
|
+
workspaceSlug={workspaceSlug}
|
|
205
|
+
projectSlug={projectSlug}
|
|
206
|
+
workflowRunId={workflowRunId}
|
|
207
|
+
runAttempt={runAttempt}
|
|
208
|
+
/>
|
|
209
|
+
) : null}
|
|
210
|
+
{query.isPending ? <InspectorLoading /> : null}
|
|
211
|
+
{query.isError ? (
|
|
212
|
+
<Callout
|
|
213
|
+
role="alert"
|
|
214
|
+
type="warning"
|
|
215
|
+
variant="secondary"
|
|
216
|
+
className="rounded-8 border border-tag-warning-border p-panel-compact shadow-none"
|
|
217
|
+
>
|
|
218
|
+
<CalloutContent>
|
|
219
|
+
<CalloutTitle>Details unavailable</CalloutTitle>
|
|
220
|
+
<CalloutDescription className="flex items-center justify-between gap-inline">
|
|
221
|
+
<span>We could not load the resolved configuration for this attempt.</span>
|
|
222
|
+
<Button
|
|
223
|
+
type="button"
|
|
224
|
+
size="2xs"
|
|
225
|
+
variant="secondary"
|
|
226
|
+
onClick={() => void query.refetch()}
|
|
227
|
+
>
|
|
228
|
+
Retry
|
|
229
|
+
</Button>
|
|
230
|
+
</CalloutDescription>
|
|
231
|
+
</CalloutContent>
|
|
232
|
+
</Callout>
|
|
233
|
+
) : null}
|
|
234
|
+
{detail ? (
|
|
235
|
+
<div className="flex min-w-0 flex-col gap-group">
|
|
236
|
+
{hasInputs ? (
|
|
237
|
+
<InspectorSection title="Inputs">
|
|
238
|
+
<ConfigCode authoredConfig={detail.authoredConfig} resolvedConfig={resolvedConfig} />
|
|
239
|
+
</InspectorSection>
|
|
240
|
+
) : null}
|
|
241
|
+
{hasOutputs ? (
|
|
242
|
+
<InspectorSection title="Outputs">
|
|
243
|
+
{attempt.outputs !== null || attempt.output !== null ? (
|
|
244
|
+
<JsonCode
|
|
245
|
+
value={attempt.outputs ?? attempt.output ?? {}}
|
|
246
|
+
emptyMessage="No outputs declared; the `outputs:` mapping is empty."
|
|
247
|
+
/>
|
|
248
|
+
) : null}
|
|
249
|
+
{attempt.response !== null ? (
|
|
250
|
+
<div className="flex min-w-0 flex-col gap-tight">
|
|
251
|
+
<Text size="xs" className="text-foreground-neutral-muted">
|
|
252
|
+
Response
|
|
253
|
+
</Text>
|
|
254
|
+
<pre className="max-h-160 min-w-0 overflow-auto rounded-6 border border-border-neutral-base bg-background-neutral-subtle p-tight font-code text-xs leading-18 text-foreground-neutral-muted scrollbar">
|
|
255
|
+
{attempt.response}
|
|
256
|
+
</pre>
|
|
257
|
+
</div>
|
|
258
|
+
) : null}
|
|
259
|
+
</InspectorSection>
|
|
260
|
+
) : null}
|
|
261
|
+
{hasTrace ? (
|
|
262
|
+
<InspectorSection title="Evaluation">
|
|
263
|
+
<EvaluationTrace trace={trace ?? []} />
|
|
264
|
+
</InspectorSection>
|
|
265
|
+
) : null}
|
|
266
|
+
{detailCount === 0 && !showFailure && !hasAnnotations ? <EmptyInspector /> : null}
|
|
267
|
+
</div>
|
|
268
|
+
) : null}
|
|
269
|
+
{hasAnnotations ? (
|
|
270
|
+
<Link
|
|
271
|
+
to="/w/$workspaceSlug/p/$projectSlug/runs/$workflowRunId"
|
|
272
|
+
params={{workspaceSlug, projectSlug, workflowRunId}}
|
|
273
|
+
search={workflowRunSearchParams({tab: 'annotations'}, {jobId, runAttempt}) as never}
|
|
274
|
+
className="inline-flex w-fit rounded-4 text-xs text-foreground-highlight-interactive underline-offset-2 hover:underline focus-visible:shadow-button-neutral-focus"
|
|
275
|
+
>
|
|
276
|
+
View {annotationCount} annotation{annotationCount === 1 ? '' : 's'}
|
|
277
|
+
</Link>
|
|
278
|
+
) : null}
|
|
279
|
+
{!query.isPending && !query.isError && !detail && !showFailure && !hasAnnotations ? (
|
|
280
|
+
<EmptyInspector />
|
|
281
|
+
) : null}
|
|
282
|
+
</div>
|
|
283
|
+
);
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
function InspectorSection({title, children}: {title: string; children: ReactNode}) {
|
|
287
|
+
return (
|
|
288
|
+
<section className="flex min-w-0 flex-col gap-inline" aria-label={title}>
|
|
289
|
+
<Text size="xs" bold className="text-foreground-neutral-base">
|
|
290
|
+
{title}
|
|
291
|
+
</Text>
|
|
292
|
+
{children}
|
|
293
|
+
</section>
|
|
294
|
+
);
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
function ConfigCode({
|
|
298
|
+
authoredConfig,
|
|
299
|
+
resolvedConfig,
|
|
300
|
+
}: {
|
|
301
|
+
authoredConfig: Record<string, unknown> | null;
|
|
302
|
+
resolvedConfig: Record<string, unknown> | null;
|
|
303
|
+
}) {
|
|
304
|
+
const entries: JsonCodeEntry[] = [
|
|
305
|
+
...(authoredConfig
|
|
306
|
+
? [
|
|
307
|
+
{
|
|
308
|
+
filename: 'authored.json',
|
|
309
|
+
label: 'Authored configuration',
|
|
310
|
+
value: authoredConfig,
|
|
311
|
+
},
|
|
312
|
+
]
|
|
313
|
+
: []),
|
|
314
|
+
...(resolvedConfig
|
|
315
|
+
? [
|
|
316
|
+
{
|
|
317
|
+
filename: 'resolved.json',
|
|
318
|
+
label: 'Resolved configuration',
|
|
319
|
+
value: resolvedConfig,
|
|
320
|
+
},
|
|
321
|
+
]
|
|
322
|
+
: []),
|
|
323
|
+
];
|
|
324
|
+
|
|
325
|
+
if (entries.length === 0) return null;
|
|
326
|
+
return <JsonCodeTabs entries={entries} />;
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
export function EvaluationTrace({trace}: {trace: readonly EvaluationTraceEntry[]}) {
|
|
330
|
+
const keyCounts = new Map<string, number>();
|
|
331
|
+
|
|
332
|
+
return (
|
|
333
|
+
<dl className="flex min-w-0 flex-col divide-y divide-border-neutral-base rounded-6 border border-border-neutral-base">
|
|
334
|
+
{trace.map((entry) => {
|
|
335
|
+
if ('dropped' in entry) {
|
|
336
|
+
const keyBase = `limit-${entry.dropped}`;
|
|
337
|
+
const occurrence = keyCounts.get(keyBase) ?? 0;
|
|
338
|
+
keyCounts.set(keyBase, occurrence + 1);
|
|
339
|
+
return (
|
|
340
|
+
<div
|
|
341
|
+
key={`${keyBase}-${occurrence}`}
|
|
342
|
+
className="px-row py-row text-xs text-foreground-neutral-muted"
|
|
343
|
+
>
|
|
344
|
+
{entry.dropped} more evaluation{entry.dropped === 1 ? '' : 's'} not recorded
|
|
345
|
+
</div>
|
|
346
|
+
);
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
const empty = entry.value === undefined || entry.value === '';
|
|
350
|
+
const keyBase = `evaluation-${entry.field}-${entry.expression}-${entry.evaluatedAt}-${entry.fillTarget}`;
|
|
351
|
+
const occurrence = keyCounts.get(keyBase) ?? 0;
|
|
352
|
+
keyCounts.set(keyBase, occurrence + 1);
|
|
353
|
+
return (
|
|
354
|
+
<div
|
|
355
|
+
key={`${keyBase}-${occurrence}`}
|
|
356
|
+
className={cn(
|
|
357
|
+
'grid min-w-0 grid-cols-1 gap-inline px-row py-row min-[768px]:grid-cols-[160px_minmax(0,1fr)]',
|
|
358
|
+
entry.degraded && 'border-l border-tag-error-icon',
|
|
359
|
+
)}
|
|
360
|
+
>
|
|
361
|
+
<dt
|
|
362
|
+
className="flex min-w-0 flex-col gap-tight font-code text-xs text-foreground-neutral-muted"
|
|
363
|
+
title={entry.field}
|
|
364
|
+
>
|
|
365
|
+
<span className="block truncate">{entry.field}</span>
|
|
366
|
+
<span className="block break-all text-foreground-neutral-subtle">
|
|
367
|
+
{entry.expression}
|
|
368
|
+
</span>
|
|
369
|
+
</dt>
|
|
370
|
+
<dd className="flex min-w-0 flex-col gap-tight text-xs text-foreground-neutral-base">
|
|
371
|
+
{entry.degraded ? <span className="sr-only">Degraded evaluation</span> : null}
|
|
372
|
+
<div className="break-words font-code">
|
|
373
|
+
{empty ? <span className="text-tag-error-text">(empty)</span> : entry.value}
|
|
374
|
+
</div>
|
|
375
|
+
<div className="flex min-w-0 flex-wrap gap-x-inline gap-y-tight text-foreground-neutral-muted">
|
|
376
|
+
{entry.degraded ? <span className="text-tag-error-text">degraded</span> : null}
|
|
377
|
+
{entry.truncated || entry.exprTruncated ? <span>truncated</span> : null}
|
|
378
|
+
</div>
|
|
379
|
+
</dd>
|
|
380
|
+
</div>
|
|
381
|
+
);
|
|
382
|
+
})}
|
|
383
|
+
</dl>
|
|
384
|
+
);
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
function InspectorLoading() {
|
|
388
|
+
return (
|
|
389
|
+
<div
|
|
390
|
+
role="status"
|
|
391
|
+
aria-label="Loading troubleshooting details"
|
|
392
|
+
className="flex flex-col gap-inline"
|
|
393
|
+
>
|
|
394
|
+
<Skeleton className="h-16 w-120" />
|
|
395
|
+
<Skeleton className="h-120 w-full" />
|
|
396
|
+
</div>
|
|
397
|
+
);
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
function EmptyInspector() {
|
|
401
|
+
return (
|
|
402
|
+
<Text size="xs" className="text-foreground-neutral-muted">
|
|
403
|
+
No additional troubleshooting details were recorded.
|
|
404
|
+
</Text>
|
|
405
|
+
);
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
function selectedStepError(
|
|
409
|
+
step: Step,
|
|
410
|
+
attemptError: Record<string, unknown> | null,
|
|
411
|
+
): StepError | null {
|
|
412
|
+
return toSelectedAttemptError(step, attemptError) ?? step.error;
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
function failureTitle(reason: string | JobStatusReason): string {
|
|
416
|
+
switch (reason) {
|
|
417
|
+
case 'checkout_failed':
|
|
418
|
+
return 'Checkout failed';
|
|
419
|
+
case 'checkout_auth_failed':
|
|
420
|
+
return 'Checkout authentication failed';
|
|
421
|
+
case 'checkout_unavailable':
|
|
422
|
+
return 'Checkout service unavailable';
|
|
423
|
+
case 'checkout_path_invalid':
|
|
424
|
+
return 'Checkout path is invalid';
|
|
425
|
+
case 'checkout_destination_occupied':
|
|
426
|
+
return 'Checkout destination is already occupied';
|
|
427
|
+
case 'git_unavailable':
|
|
428
|
+
return 'Git was unavailable';
|
|
429
|
+
case 'workspace_prep_failed':
|
|
430
|
+
return 'Workspace preparation failed';
|
|
431
|
+
case 'setup_aborted':
|
|
432
|
+
return 'Step setup was aborted';
|
|
433
|
+
case 'config_unresolvable':
|
|
434
|
+
return 'Step configuration could not be resolved';
|
|
435
|
+
case 'output_invalid':
|
|
436
|
+
return 'Step output was invalid';
|
|
437
|
+
case 'agent_config_invalid':
|
|
438
|
+
return 'Agent configuration is invalid';
|
|
439
|
+
case 'agent_invocation_failed':
|
|
440
|
+
return 'Agent invocation failed';
|
|
441
|
+
case 'agent_harness_unavailable':
|
|
442
|
+
return 'Agent harness was unavailable';
|
|
443
|
+
case 'runner_lost':
|
|
444
|
+
return 'Runner stopped responding';
|
|
445
|
+
case 'timed_out':
|
|
446
|
+
return 'Step timed out';
|
|
447
|
+
case 'step_failed':
|
|
448
|
+
return 'A step failed';
|
|
449
|
+
case 'dependency_not_completed':
|
|
450
|
+
return 'A dependency did not complete';
|
|
451
|
+
case 'condition_false':
|
|
452
|
+
return 'The job condition was false';
|
|
453
|
+
case 'default_gate_rejected':
|
|
454
|
+
return 'The default gate rejected this job';
|
|
455
|
+
case 'condition_rejected':
|
|
456
|
+
return 'The job condition rejected this job';
|
|
457
|
+
case 'condition_errored':
|
|
458
|
+
return 'The job condition could not be evaluated';
|
|
459
|
+
case 'user_cancelled':
|
|
460
|
+
return 'The job was cancelled by a user';
|
|
461
|
+
case 'run_cancelled':
|
|
462
|
+
return 'The run was cancelled';
|
|
463
|
+
case 'unknown':
|
|
464
|
+
return 'The failure reason was not recorded';
|
|
465
|
+
default:
|
|
466
|
+
return 'Step failed';
|
|
467
|
+
}
|
|
468
|
+
}
|
|
469
|
+
|
|
470
|
+
function failureDescription(reason: string | JobStatusReason): string {
|
|
471
|
+
switch (reason) {
|
|
472
|
+
case 'checkout_auth_failed':
|
|
473
|
+
return 'Checkout credentials were rejected. Verify repository access before re-running.';
|
|
474
|
+
case 'checkout_unavailable':
|
|
475
|
+
return 'The checkout service was unavailable. Retry after the service recovers.';
|
|
476
|
+
case 'git_unavailable':
|
|
477
|
+
return 'The runner could not start Git. Check the runner image before re-running.';
|
|
478
|
+
case 'workspace_prep_failed':
|
|
479
|
+
return 'The runner could not prepare its workspace. Review the runner setup details.';
|
|
480
|
+
case 'config_unresolvable':
|
|
481
|
+
return 'The resolved configuration contains a value that could not be evaluated.';
|
|
482
|
+
case 'output_invalid':
|
|
483
|
+
return 'The step returned output that did not match the declared contract.';
|
|
484
|
+
case 'agent_config_invalid':
|
|
485
|
+
return 'The agent configuration is not valid for this step.';
|
|
486
|
+
case 'agent_invocation_failed':
|
|
487
|
+
return 'The agent invocation failed after configuration was accepted.';
|
|
488
|
+
case 'agent_harness_unavailable':
|
|
489
|
+
return 'The runner could not start the agent harness.';
|
|
490
|
+
case 'runner_lost':
|
|
491
|
+
return 'The runner stopped responding before the step completed.';
|
|
492
|
+
case 'timed_out':
|
|
493
|
+
return 'The step exceeded its configured time limit.';
|
|
494
|
+
case 'dependency_not_completed':
|
|
495
|
+
return 'A required job did not complete, so this job could not start.';
|
|
496
|
+
case 'condition_false':
|
|
497
|
+
case 'condition_rejected':
|
|
498
|
+
return 'The job condition did not allow this job to run.';
|
|
499
|
+
case 'condition_errored':
|
|
500
|
+
return 'The job condition could not be evaluated.';
|
|
501
|
+
case 'default_gate_rejected':
|
|
502
|
+
return 'A required job did not succeed, so this job was not allowed to run.';
|
|
503
|
+
case 'step_failed':
|
|
504
|
+
return 'A step failed before this job could complete.';
|
|
505
|
+
case 'user_cancelled':
|
|
506
|
+
case 'run_cancelled':
|
|
507
|
+
return 'The run was cancelled before this work completed.';
|
|
508
|
+
case 'unknown':
|
|
509
|
+
return 'No machine-readable failure reason was recorded.';
|
|
510
|
+
default:
|
|
511
|
+
return `${humanize(reason)}. Review the details below and re-run after resolving the cause.`;
|
|
512
|
+
}
|
|
513
|
+
}
|
|
514
|
+
|
|
515
|
+
function sourceLinkForFailure(reason: string | JobStatusReason): boolean {
|
|
516
|
+
return (
|
|
517
|
+
reason === 'config_unresolvable' ||
|
|
518
|
+
reason === 'agent_config_invalid' ||
|
|
519
|
+
reason === 'output_invalid' ||
|
|
520
|
+
reason === 'default_gate_rejected' ||
|
|
521
|
+
reason === 'condition_rejected' ||
|
|
522
|
+
reason === 'condition_errored'
|
|
523
|
+
);
|
|
524
|
+
}
|
|
525
|
+
|
|
526
|
+
function humanize(value: string): string {
|
|
527
|
+
return value.replaceAll('_', ' ').replace(/\b\w/g, (letter) => letter.toUpperCase());
|
|
528
|
+
}
|
|
529
|
+
|
|
530
|
+
function countConfigValues(value: unknown): number {
|
|
531
|
+
if (Array.isArray(value))
|
|
532
|
+
return value.reduce((total, item) => total + countConfigValues(item), 0);
|
|
533
|
+
if (value !== null && typeof value === 'object') {
|
|
534
|
+
return Object.values(value).reduce((total, item) => total + countConfigValues(item), 0);
|
|
535
|
+
}
|
|
536
|
+
return value === undefined ? 0 : 1;
|
|
537
|
+
}
|
|
@@ -12,6 +12,7 @@ import type {JobGraphSelectionSource} from './types.js';
|
|
|
12
12
|
const NODE_WIDTH = 208;
|
|
13
13
|
const NODE_HEIGHT = 48;
|
|
14
14
|
const COLUMN_GAP = 64;
|
|
15
|
+
/** Fixed graph spacing shared by the DOM rows and the edge geometry below. */
|
|
15
16
|
const ROW_GAP = 20;
|
|
16
17
|
const TRIGGER_WIDTH = 36;
|
|
17
18
|
const PADDING = 16;
|
|
@@ -36,7 +37,7 @@ export function JobGraphContent({
|
|
|
36
37
|
if (model.nodes.length === 0) {
|
|
37
38
|
return (
|
|
38
39
|
<EmptyState
|
|
39
|
-
className="min-h-160
|
|
40
|
+
className="min-h-160 p-panel"
|
|
40
41
|
icon="componentLine"
|
|
41
42
|
title="No jobs yet"
|
|
42
43
|
description="This run has not materialized jobs."
|
|
@@ -93,8 +94,8 @@ export function JobGraphContent({
|
|
|
93
94
|
{model.columns.map((column, columnIndex) => (
|
|
94
95
|
<div
|
|
95
96
|
key={column.map((node) => node.id).join(':')}
|
|
96
|
-
className="absolute flex flex-col
|
|
97
|
-
style={{left: jobLeft(columnIndex), top: PADDING}}
|
|
97
|
+
className="absolute flex flex-col"
|
|
98
|
+
style={{left: jobLeft(columnIndex), top: PADDING, rowGap: ROW_GAP}}
|
|
98
99
|
>
|
|
99
100
|
{column.map((node) => (
|
|
100
101
|
<JobNode
|
|
@@ -106,7 +106,7 @@ export function JobNode({
|
|
|
106
106
|
onPointerEnter={onHoverStart}
|
|
107
107
|
onPointerLeave={onHoverEnd}
|
|
108
108
|
className={cn(
|
|
109
|
-
'group relative flex h-48 w-208 cursor-pointer items-center gap-
|
|
109
|
+
'group relative flex h-48 w-208 cursor-pointer items-center gap-inline rounded-8 bg-background-neutral-base px-[10px] text-left shadow-button-neutral transition-colors hover:bg-background-components-hover focus-visible:shadow-button-neutral-focus focus-visible:outline-none',
|
|
110
110
|
selected && 'bg-background-components-hover hover:bg-background-components-pressed',
|
|
111
111
|
node.carriedOver && 'opacity-[0.55]',
|
|
112
112
|
)}
|
|
@@ -117,7 +117,7 @@ export function JobNode({
|
|
|
117
117
|
className="absolute inset-y-6 left-0 w-px rounded-full bg-border-highlights-interactive"
|
|
118
118
|
/>
|
|
119
119
|
) : null}
|
|
120
|
-
<div className="flex min-w-0 flex-1 items-center gap-
|
|
120
|
+
<div className="flex min-w-0 flex-1 items-center gap-inline">
|
|
121
121
|
<WorkflowStatusIcon status={status} size={14} />
|
|
122
122
|
<JobLabel label={node.displayName} />
|
|
123
123
|
</div>
|
|
@@ -136,7 +136,7 @@ function ExecutionCountText({executions}: {executions: JobExecution[]}) {
|
|
|
136
136
|
<TooltipTrigger asChild>
|
|
137
137
|
<span
|
|
138
138
|
aria-hidden="true"
|
|
139
|
-
className="inline-flex h-20 min-w-28 shrink-0 items-center justify-end gap-
|
|
139
|
+
className="inline-flex h-20 min-w-28 shrink-0 items-center justify-end gap-tight text-foreground-neutral-subtle"
|
|
140
140
|
>
|
|
141
141
|
<Icon name="loopRightLine" className="size-12" />
|
|
142
142
|
<Code as="span" variant="label" className="text-current">
|
|
@@ -77,11 +77,14 @@ export function emptyJobExecutionForJob(job: Job): JobExecution {
|
|
|
77
77
|
name: job.name ?? job.key,
|
|
78
78
|
status: job.status === 'skipped' ? 'cancelled' : job.status,
|
|
79
79
|
statusReason: job.statusReason,
|
|
80
|
+
runner: job.runner,
|
|
81
|
+
outputs: job.outputs,
|
|
80
82
|
triggerEvents: [],
|
|
81
83
|
queuedAt: null,
|
|
82
84
|
startedAt: null,
|
|
83
85
|
finishedAt: null,
|
|
84
86
|
timedOutAt: null,
|
|
87
|
+
evaluationTrace: job.evaluationTrace,
|
|
85
88
|
createdAt: job.createdAt,
|
|
86
89
|
updatedAt: job.updatedAt,
|
|
87
90
|
steps: [],
|
|
@@ -158,6 +161,8 @@ function toStepEntries(step: StepModel, carriedOverJob: boolean): StepListEntryM
|
|
|
158
161
|
status: step.status,
|
|
159
162
|
exitCode: null,
|
|
160
163
|
output: null,
|
|
164
|
+
outputs: null,
|
|
165
|
+
response: null,
|
|
161
166
|
error: null,
|
|
162
167
|
gateResult: null,
|
|
163
168
|
restartFeedback: null,
|