Skip to content

Commit 22fa504

Browse files
fix(scripts): skip undeployable table workflows
1 parent 2efa0d7 commit 22fa504

2 files changed

Lines changed: 70 additions & 6 deletions

File tree

‎apps/sim/scripts/backfill-table-workflow-deployments.test.ts‎

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,7 @@ describe('backfillTableWorkflowDeployments', () => {
179179
deployed: 3,
180180
alreadyDeployed: 0,
181181
skippedLocked: 0,
182+
skippedUndeployable: 0,
182183
})
183184
expect(listCandidates.mock.calls).toEqual([
184185
['', 2],
@@ -215,6 +216,7 @@ describe('backfillTableWorkflowDeployments', () => {
215216
deployed: 0,
216217
alreadyDeployed: 1,
217218
skippedLocked: 0,
219+
skippedUndeployable: 0,
218220
})
219221
expect(deploy).not.toHaveBeenCalled()
220222
})
@@ -256,6 +258,56 @@ describe('backfillTableWorkflowDeployments', () => {
256258
deployed: 1,
257259
alreadyDeployed: 0,
258260
skippedLocked: 1,
261+
skippedUndeployable: 0,
262+
})
263+
expect(deploy.mock.calls.map(([workflow]) => workflow.workflowId)).toEqual([
264+
'workflow-a',
265+
'workflow-b',
266+
])
267+
expect(listCandidates.mock.calls.slice(-2)).toEqual([
268+
['', 1],
269+
['workflow-a', 1],
270+
])
271+
})
272+
273+
it('reports and skips undeployable workflows while continuing the backfill', async () => {
274+
const listCandidates = vi
275+
.fn<TableWorkflowDeploymentStore['listCandidates']>()
276+
.mockResolvedValueOnce([candidate('workflow-a'), candidate('workflow-b')])
277+
.mockResolvedValueOnce([])
278+
.mockResolvedValueOnce([candidate('workflow-a')])
279+
.mockResolvedValueOnce([])
280+
const deploymentState = new Map<string, boolean>()
281+
const isDeployed = vi
282+
.fn<TableWorkflowDeploymentStore['isDeployed']>()
283+
.mockImplementation(async (workflowId) => deploymentState.get(workflowId) ?? false)
284+
const deploy = vi.fn(async (workflow: TableWorkflowDeploymentCandidate) => {
285+
if (workflow.workflowId === 'workflow-a') {
286+
return {
287+
success: false,
288+
error: 'Missing required fields for WhatsApp Webhook: Verification Token, App Secret',
289+
errorCode: 'validation' as const,
290+
}
291+
}
292+
deploymentState.set(workflow.workflowId, true)
293+
return {
294+
success: true,
295+
activeDeployment: {
296+
deploymentVersionId: `version-${workflow.workflowId}`,
297+
version: 1,
298+
deployedAt: new Date().toISOString(),
299+
},
300+
}
301+
})
302+
303+
await expect(
304+
backfillTableWorkflowDeployments(store({ listCandidates, isDeployed }), deploy)
305+
).resolves.toEqual({
306+
scanned: 2,
307+
deployed: 1,
308+
alreadyDeployed: 0,
309+
skippedLocked: 0,
310+
skippedUndeployable: 1,
259311
})
260312
expect(deploy.mock.calls.map(([workflow]) => workflow.workflowId)).toEqual([
261313
'workflow-a',

‎apps/sim/scripts/backfill-table-workflow-deployments.ts‎

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ export interface TableWorkflowDeploymentSummary {
5959
deployed: number
6060
alreadyDeployed: number
6161
skippedLocked: number
62+
skippedUndeployable: number
6263
}
6364

6465
interface TableWorkflowDeploymentBackfillOptions {
@@ -194,9 +195,9 @@ function validateCandidatePage(
194195
return lastWorkflowId
195196
}
196197

197-
async function assertOnlyLockedCandidatesRemain(
198+
async function assertOnlySkippedCandidatesRemain(
198199
store: TableWorkflowDeploymentStore,
199-
lockedWorkflowIds: ReadonlySet<string>
200+
skippedWorkflowIds: ReadonlySet<string>
200201
): Promise<void> {
201202
let afterWorkflowId = ''
202203
for (;;) {
@@ -205,7 +206,7 @@ async function assertOnlyLockedCandidatesRemain(
205206
if (!lastWorkflowId) return
206207

207208
const unexpectedCandidate = candidates.find(
208-
(candidate) => !lockedWorkflowIds.has(candidate.workflowId)
209+
(candidate) => !skippedWorkflowIds.has(candidate.workflowId)
209210
)
210211
if (unexpectedCandidate) {
211212
throw new Error(
@@ -420,8 +421,9 @@ export async function backfillTableWorkflowDeployments(
420421
deployed: 0,
421422
alreadyDeployed: 0,
422423
skippedLocked: 0,
424+
skippedUndeployable: 0,
423425
}
424-
const lockedWorkflowIds = new Set<string>()
426+
const skippedWorkflowIds = new Set<string>()
425427
let afterWorkflowId = ''
426428

427429
for (;;) {
@@ -441,7 +443,7 @@ export async function backfillTableWorkflowDeployments(
441443
const result = await deploy(candidate)
442444
if (!result.success) {
443445
if (result.errorCode === 'locked') {
444-
lockedWorkflowIds.add(candidate.workflowId)
446+
skippedWorkflowIds.add(candidate.workflowId)
445447
summary.skippedLocked += 1
446448
logger.warn('Skipping locked workflow referenced by a table workflow group', {
447449
workflowId: candidate.workflowId,
@@ -450,6 +452,16 @@ export async function backfillTableWorkflowDeployments(
450452
})
451453
continue
452454
}
455+
if (result.errorCode === 'validation') {
456+
skippedWorkflowIds.add(candidate.workflowId)
457+
summary.skippedUndeployable += 1
458+
logger.warn('Skipping undeployable workflow referenced by a table workflow group', {
459+
workflowId: candidate.workflowId,
460+
workspaceId: candidate.workspaceId,
461+
reason: result.error ?? 'Workflow deployment validation failed',
462+
})
463+
continue
464+
}
453465
throw new Error(
454466
`Failed to deploy table workflow ${candidate.workflowId}: ${result.error ?? 'deployment returned no error'}`
455467
)
@@ -472,7 +484,7 @@ export async function backfillTableWorkflowDeployments(
472484
}
473485

474486
await store.assertIntegrity()
475-
await assertOnlyLockedCandidatesRemain(store, lockedWorkflowIds)
487+
await assertOnlySkippedCandidatesRemain(store, skippedWorkflowIds)
476488

477489
return summary
478490
}

0 commit comments

Comments
 (0)