Make the frontend resilient to old workflow run output formats (#10522)
- Create zod schemas for everything related to a workflow run - Update the types to be inferred from the zod schemas - Improper workflow run outputs will render a blank screen; we could show an error in the future https://github.com/user-attachments/assets/8e666c3e-82b0-4ab5-8804-2f70130ea257
This commit is contained in:
committed by
GitHub
parent
5a39903d42
commit
8bd9bc9d31
@ -11,175 +11,6 @@ jest.mock('uuid', () => ({
|
||||
}));
|
||||
|
||||
describe('generateWorkflowRunDiagram', () => {
|
||||
it('marks node as failed when not at least one attempt is in output', () => {
|
||||
const trigger: WorkflowTrigger = {
|
||||
name: 'Company created',
|
||||
type: 'DATABASE_EVENT',
|
||||
settings: {
|
||||
eventName: 'company.created',
|
||||
outputSchema: {},
|
||||
},
|
||||
};
|
||||
const steps: WorkflowStep[] = [
|
||||
{
|
||||
id: 'step1',
|
||||
name: 'Step 1',
|
||||
type: 'CODE',
|
||||
valid: true,
|
||||
settings: {
|
||||
errorHandlingOptions: {
|
||||
retryOnFailure: { value: true },
|
||||
continueOnFailure: { value: false },
|
||||
},
|
||||
input: {
|
||||
serverlessFunctionId: 'a5434be2-c10b-465c-acec-46492782a997',
|
||||
serverlessFunctionVersion: '1',
|
||||
serverlessFunctionInput: {},
|
||||
},
|
||||
outputSchema: {},
|
||||
},
|
||||
},
|
||||
{
|
||||
id: 'step2',
|
||||
name: 'Step 2',
|
||||
type: 'CODE',
|
||||
valid: true,
|
||||
settings: {
|
||||
errorHandlingOptions: {
|
||||
retryOnFailure: { value: true },
|
||||
continueOnFailure: { value: false },
|
||||
},
|
||||
input: {
|
||||
serverlessFunctionId: 'a5434be2-c10b-465c-acec-46492782a997',
|
||||
serverlessFunctionVersion: '1',
|
||||
serverlessFunctionInput: {},
|
||||
},
|
||||
outputSchema: {},
|
||||
},
|
||||
},
|
||||
{
|
||||
id: 'step3',
|
||||
name: 'Step 3',
|
||||
type: 'CODE',
|
||||
valid: true,
|
||||
settings: {
|
||||
errorHandlingOptions: {
|
||||
retryOnFailure: { value: true },
|
||||
continueOnFailure: { value: false },
|
||||
},
|
||||
input: {
|
||||
serverlessFunctionId: 'a5434be2-c10b-465c-acec-46492782a997',
|
||||
serverlessFunctionVersion: '1',
|
||||
serverlessFunctionInput: {},
|
||||
},
|
||||
outputSchema: {},
|
||||
},
|
||||
},
|
||||
];
|
||||
const stepsOutput: WorkflowRunOutputStepsOutput = {
|
||||
step1: {
|
||||
id: 'step1',
|
||||
outputs: [],
|
||||
},
|
||||
};
|
||||
|
||||
const result = generateWorkflowRunDiagram({ trigger, steps, stepsOutput });
|
||||
|
||||
expect(result).toMatchInlineSnapshot(`
|
||||
{
|
||||
"edges": [
|
||||
{
|
||||
"deletable": false,
|
||||
"id": "8f3b2121-f194-4ba4-9fbf-0",
|
||||
"markerEnd": "workflow-edge-green-arrow-rounded",
|
||||
"markerStart": "workflow-edge-green-circle",
|
||||
"selectable": false,
|
||||
"source": "trigger",
|
||||
"target": "step1",
|
||||
"type": "success",
|
||||
},
|
||||
{
|
||||
"deletable": false,
|
||||
"id": "8f3b2121-f194-4ba4-9fbf-1",
|
||||
"markerEnd": "workflow-edge-arrow-rounded",
|
||||
"markerStart": "workflow-edge-gray-circle",
|
||||
"selectable": false,
|
||||
"source": "step1",
|
||||
"target": "step2",
|
||||
},
|
||||
{
|
||||
"deletable": false,
|
||||
"id": "8f3b2121-f194-4ba4-9fbf-2",
|
||||
"markerEnd": "workflow-edge-arrow-rounded",
|
||||
"markerStart": "workflow-edge-gray-circle",
|
||||
"selectable": false,
|
||||
"source": "step2",
|
||||
"target": "step3",
|
||||
},
|
||||
],
|
||||
"nodes": [
|
||||
{
|
||||
"data": {
|
||||
"icon": "IconPlaylistAdd",
|
||||
"isLeafNode": false,
|
||||
"name": "Company created",
|
||||
"nodeType": "trigger",
|
||||
"runStatus": "success",
|
||||
"triggerType": "DATABASE_EVENT",
|
||||
},
|
||||
"id": "trigger",
|
||||
"position": {
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
},
|
||||
},
|
||||
{
|
||||
"data": {
|
||||
"actionType": "CODE",
|
||||
"isLeafNode": false,
|
||||
"name": "Step 1",
|
||||
"nodeType": "action",
|
||||
"runStatus": "failure",
|
||||
},
|
||||
"id": "step1",
|
||||
"position": {
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
},
|
||||
},
|
||||
{
|
||||
"data": {
|
||||
"actionType": "CODE",
|
||||
"isLeafNode": false,
|
||||
"name": "Step 2",
|
||||
"nodeType": "action",
|
||||
"runStatus": "not-executed",
|
||||
},
|
||||
"id": "step2",
|
||||
"position": {
|
||||
"x": 0,
|
||||
"y": 150,
|
||||
},
|
||||
},
|
||||
{
|
||||
"data": {
|
||||
"actionType": "CODE",
|
||||
"isLeafNode": false,
|
||||
"name": "Step 3",
|
||||
"nodeType": "action",
|
||||
"runStatus": "not-executed",
|
||||
},
|
||||
"id": "step3",
|
||||
"position": {
|
||||
"x": 0,
|
||||
"y": 300,
|
||||
},
|
||||
},
|
||||
],
|
||||
}
|
||||
`);
|
||||
});
|
||||
|
||||
it('marks node as failed when the last attempt failed', () => {
|
||||
const trigger: WorkflowTrigger = {
|
||||
name: 'Company created',
|
||||
@ -247,14 +78,8 @@ describe('generateWorkflowRunDiagram', () => {
|
||||
];
|
||||
const stepsOutput: WorkflowRunOutputStepsOutput = {
|
||||
step1: {
|
||||
id: 'step1',
|
||||
outputs: [
|
||||
{
|
||||
attemptCount: 1,
|
||||
result: undefined,
|
||||
error: '',
|
||||
},
|
||||
],
|
||||
result: undefined,
|
||||
error: '',
|
||||
},
|
||||
};
|
||||
|
||||
@ -265,7 +90,7 @@ describe('generateWorkflowRunDiagram', () => {
|
||||
"edges": [
|
||||
{
|
||||
"deletable": false,
|
||||
"id": "8f3b2121-f194-4ba4-9fbf-3",
|
||||
"id": "8f3b2121-f194-4ba4-9fbf-0",
|
||||
"markerEnd": "workflow-edge-green-arrow-rounded",
|
||||
"markerStart": "workflow-edge-green-circle",
|
||||
"selectable": false,
|
||||
@ -275,7 +100,7 @@ describe('generateWorkflowRunDiagram', () => {
|
||||
},
|
||||
{
|
||||
"deletable": false,
|
||||
"id": "8f3b2121-f194-4ba4-9fbf-4",
|
||||
"id": "8f3b2121-f194-4ba4-9fbf-1",
|
||||
"markerEnd": "workflow-edge-arrow-rounded",
|
||||
"markerStart": "workflow-edge-gray-circle",
|
||||
"selectable": false,
|
||||
@ -284,7 +109,7 @@ describe('generateWorkflowRunDiagram', () => {
|
||||
},
|
||||
{
|
||||
"deletable": false,
|
||||
"id": "8f3b2121-f194-4ba4-9fbf-5",
|
||||
"id": "8f3b2121-f194-4ba4-9fbf-2",
|
||||
"markerEnd": "workflow-edge-arrow-rounded",
|
||||
"markerStart": "workflow-edge-gray-circle",
|
||||
"selectable": false,
|
||||
@ -422,34 +247,16 @@ describe('generateWorkflowRunDiagram', () => {
|
||||
];
|
||||
const stepsOutput: WorkflowRunOutputStepsOutput = {
|
||||
step1: {
|
||||
id: 'step1',
|
||||
outputs: [
|
||||
{
|
||||
attemptCount: 1,
|
||||
result: {},
|
||||
error: undefined,
|
||||
},
|
||||
],
|
||||
result: {},
|
||||
error: undefined,
|
||||
},
|
||||
step2: {
|
||||
id: 'step2',
|
||||
outputs: [
|
||||
{
|
||||
attemptCount: 1,
|
||||
result: {},
|
||||
error: undefined,
|
||||
},
|
||||
],
|
||||
result: {},
|
||||
error: undefined,
|
||||
},
|
||||
step3: {
|
||||
id: 'step3',
|
||||
outputs: [
|
||||
{
|
||||
attemptCount: 1,
|
||||
result: {},
|
||||
error: undefined,
|
||||
},
|
||||
],
|
||||
result: {},
|
||||
error: undefined,
|
||||
},
|
||||
};
|
||||
|
||||
@ -460,7 +267,7 @@ describe('generateWorkflowRunDiagram', () => {
|
||||
"edges": [
|
||||
{
|
||||
"deletable": false,
|
||||
"id": "8f3b2121-f194-4ba4-9fbf-6",
|
||||
"id": "8f3b2121-f194-4ba4-9fbf-3",
|
||||
"markerEnd": "workflow-edge-green-arrow-rounded",
|
||||
"markerStart": "workflow-edge-green-circle",
|
||||
"selectable": false,
|
||||
@ -470,7 +277,7 @@ describe('generateWorkflowRunDiagram', () => {
|
||||
},
|
||||
{
|
||||
"deletable": false,
|
||||
"id": "8f3b2121-f194-4ba4-9fbf-7",
|
||||
"id": "8f3b2121-f194-4ba4-9fbf-4",
|
||||
"markerEnd": "workflow-edge-green-arrow-rounded",
|
||||
"markerStart": "workflow-edge-green-circle",
|
||||
"selectable": false,
|
||||
@ -480,7 +287,7 @@ describe('generateWorkflowRunDiagram', () => {
|
||||
},
|
||||
{
|
||||
"deletable": false,
|
||||
"id": "8f3b2121-f194-4ba4-9fbf-8",
|
||||
"id": "8f3b2121-f194-4ba4-9fbf-5",
|
||||
"markerEnd": "workflow-edge-green-arrow-rounded",
|
||||
"markerStart": "workflow-edge-green-circle",
|
||||
"selectable": false,
|
||||
@ -626,7 +433,7 @@ describe('generateWorkflowRunDiagram', () => {
|
||||
"edges": [
|
||||
{
|
||||
"deletable": false,
|
||||
"id": "8f3b2121-f194-4ba4-9fbf-9",
|
||||
"id": "8f3b2121-f194-4ba4-9fbf-6",
|
||||
"markerEnd": "workflow-edge-green-arrow-rounded",
|
||||
"markerStart": "workflow-edge-green-circle",
|
||||
"selectable": false,
|
||||
@ -636,7 +443,7 @@ describe('generateWorkflowRunDiagram', () => {
|
||||
},
|
||||
{
|
||||
"deletable": false,
|
||||
"id": "8f3b2121-f194-4ba4-9fbf-10",
|
||||
"id": "8f3b2121-f194-4ba4-9fbf-7",
|
||||
"markerEnd": "workflow-edge-arrow-rounded",
|
||||
"markerStart": "workflow-edge-gray-circle",
|
||||
"selectable": false,
|
||||
@ -645,7 +452,7 @@ describe('generateWorkflowRunDiagram', () => {
|
||||
},
|
||||
{
|
||||
"deletable": false,
|
||||
"id": "8f3b2121-f194-4ba4-9fbf-11",
|
||||
"id": "8f3b2121-f194-4ba4-9fbf-8",
|
||||
"markerEnd": "workflow-edge-arrow-rounded",
|
||||
"markerStart": "workflow-edge-gray-circle",
|
||||
"selectable": false,
|
||||
@ -801,14 +608,8 @@ describe('generateWorkflowRunDiagram', () => {
|
||||
];
|
||||
const stepsOutput: WorkflowRunOutputStepsOutput = {
|
||||
step1: {
|
||||
id: 'step1',
|
||||
outputs: [
|
||||
{
|
||||
attemptCount: 1,
|
||||
result: {},
|
||||
error: undefined,
|
||||
},
|
||||
],
|
||||
result: {},
|
||||
error: undefined,
|
||||
},
|
||||
};
|
||||
|
||||
@ -819,7 +620,7 @@ describe('generateWorkflowRunDiagram', () => {
|
||||
"edges": [
|
||||
{
|
||||
"deletable": false,
|
||||
"id": "8f3b2121-f194-4ba4-9fbf-12",
|
||||
"id": "8f3b2121-f194-4ba4-9fbf-9",
|
||||
"markerEnd": "workflow-edge-green-arrow-rounded",
|
||||
"markerStart": "workflow-edge-green-circle",
|
||||
"selectable": false,
|
||||
@ -829,7 +630,7 @@ describe('generateWorkflowRunDiagram', () => {
|
||||
},
|
||||
{
|
||||
"deletable": false,
|
||||
"id": "8f3b2121-f194-4ba4-9fbf-13",
|
||||
"id": "8f3b2121-f194-4ba4-9fbf-10",
|
||||
"markerEnd": "workflow-edge-green-arrow-rounded",
|
||||
"markerStart": "workflow-edge-green-circle",
|
||||
"selectable": false,
|
||||
@ -839,7 +640,7 @@ describe('generateWorkflowRunDiagram', () => {
|
||||
},
|
||||
{
|
||||
"deletable": false,
|
||||
"id": "8f3b2121-f194-4ba4-9fbf-14",
|
||||
"id": "8f3b2121-f194-4ba4-9fbf-11",
|
||||
"markerEnd": "workflow-edge-arrow-rounded",
|
||||
"markerStart": "workflow-edge-gray-circle",
|
||||
"selectable": false,
|
||||
@ -848,7 +649,7 @@ describe('generateWorkflowRunDiagram', () => {
|
||||
},
|
||||
{
|
||||
"deletable": false,
|
||||
"id": "8f3b2121-f194-4ba4-9fbf-15",
|
||||
"id": "8f3b2121-f194-4ba4-9fbf-12",
|
||||
"markerEnd": "workflow-edge-arrow-rounded",
|
||||
"markerStart": "workflow-edge-gray-circle",
|
||||
"selectable": false,
|
||||
|
||||
@ -86,12 +86,7 @@ export const generateWorkflowRunDiagram = ({
|
||||
} else if (!isDefined(runResult)) {
|
||||
runStatus = 'running';
|
||||
} else {
|
||||
const lastAttempt = runResult.outputs.at(-1);
|
||||
|
||||
if (!isDefined(lastAttempt)) {
|
||||
// Should never happen. Should we throw instead?
|
||||
runStatus = 'failure';
|
||||
} else if (isDefined(lastAttempt.error)) {
|
||||
if (isDefined(runResult.error)) {
|
||||
runStatus = 'failure';
|
||||
} else {
|
||||
runStatus = 'success';
|
||||
|
||||
Reference in New Issue
Block a user