Skip to content

Commit 66e5aef

Browse files
committed
fix more edge cases
1 parent 71bee4c commit 66e5aef

File tree

5 files changed

+222
-31
lines changed

5 files changed

+222
-31
lines changed

apps/sim/app/api/v1/admin/workflows/[id]/deploy/route.ts

Lines changed: 80 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,12 @@
1-
import { db, workflow } from '@sim/db'
1+
import { db, workflow, workflowDeploymentVersion } from '@sim/db'
22
import { createLogger } from '@sim/logger'
3-
import { eq } from 'drizzle-orm'
3+
import { and, eq } from 'drizzle-orm'
44
import { generateRequestId } from '@/lib/core/utils/request'
5-
import { cleanupWebhooksForWorkflow } from '@/lib/webhooks/deploy'
5+
import {
6+
cleanupWebhooksForWorkflow,
7+
restorePreviousVersionWebhooks,
8+
saveTriggerWebhooksForDeploy,
9+
} from '@/lib/webhooks/deploy'
610
import {
711
deployWorkflow,
812
loadWorkflowFromNormalizedTables,
@@ -32,10 +36,11 @@ interface RouteParams {
3236

3337
export const POST = withAdminAuthParams<RouteParams>(async (request, context) => {
3438
const { id: workflowId } = await context.params
39+
const requestId = generateRequestId()
3540

3641
try {
3742
const [workflowRecord] = await db
38-
.select({ id: workflow.id, name: workflow.name })
43+
.select()
3944
.from(workflow)
4045
.where(eq(workflow.id, workflowId))
4146
.limit(1)
@@ -54,6 +59,18 @@ export const POST = withAdminAuthParams<RouteParams>(async (request, context) =>
5459
return badRequestResponse(`Invalid schedule configuration: ${scheduleValidation.error}`)
5560
}
5661

62+
const [currentActiveVersion] = await db
63+
.select({ id: workflowDeploymentVersion.id })
64+
.from(workflowDeploymentVersion)
65+
.where(
66+
and(
67+
eq(workflowDeploymentVersion.workflowId, workflowId),
68+
eq(workflowDeploymentVersion.isActive, true)
69+
)
70+
)
71+
.limit(1)
72+
const previousVersionId = currentActiveVersion?.id
73+
5774
const deployResult = await deployWorkflow({
5875
workflowId,
5976
deployedBy: ADMIN_ACTOR_ID,
@@ -69,6 +86,32 @@ export const POST = withAdminAuthParams<RouteParams>(async (request, context) =>
6986
return internalErrorResponse('Failed to resolve deployment version')
7087
}
7188

89+
const workflowData = workflowRecord as Record<string, unknown>
90+
91+
const triggerSaveResult = await saveTriggerWebhooksForDeploy({
92+
request,
93+
workflowId,
94+
workflow: workflowData,
95+
userId: workflowRecord.userId,
96+
blocks: normalizedData.blocks,
97+
requestId,
98+
deploymentVersionId: deployResult.deploymentVersionId,
99+
previousVersionId,
100+
})
101+
102+
if (!triggerSaveResult.success) {
103+
await cleanupDeploymentVersion({
104+
workflowId,
105+
workflow: workflowData,
106+
requestId,
107+
deploymentVersionId: deployResult.deploymentVersionId,
108+
})
109+
await undeployWorkflow({ workflowId })
110+
return internalErrorResponse(
111+
triggerSaveResult.error?.message || 'Failed to sync trigger configuration'
112+
)
113+
}
114+
72115
const scheduleResult = await createSchedulesForDeploy(
73116
workflowId,
74117
normalizedData.blocks,
@@ -77,19 +120,48 @@ export const POST = withAdminAuthParams<RouteParams>(async (request, context) =>
77120
)
78121
if (!scheduleResult.success) {
79122
logger.error(
80-
`Admin API: Schedule creation failed for workflow ${workflowId}: ${scheduleResult.error}`
123+
`[${requestId}] Admin API: Schedule creation failed for workflow ${workflowId}: ${scheduleResult.error}`
81124
)
82125
await cleanupDeploymentVersion({
83126
workflowId,
84-
workflow: normalizedData as unknown as Record<string, unknown>,
85-
requestId: generateRequestId(),
127+
workflow: workflowData,
128+
requestId,
86129
deploymentVersionId: deployResult.deploymentVersionId,
87130
})
131+
if (previousVersionId) {
132+
await restorePreviousVersionWebhooks({
133+
request,
134+
workflow: workflowData,
135+
userId: workflowRecord.userId,
136+
previousVersionId,
137+
requestId,
138+
})
139+
}
88140
await undeployWorkflow({ workflowId })
89141
return internalErrorResponse(scheduleResult.error || 'Failed to create schedule')
90142
}
91143

92-
logger.info(`Admin API: Deployed workflow ${workflowId} as v${deployResult.version}`)
144+
if (previousVersionId && previousVersionId !== deployResult.deploymentVersionId) {
145+
try {
146+
logger.info(`[${requestId}] Admin API: Cleaning up previous version ${previousVersionId}`)
147+
await cleanupDeploymentVersion({
148+
workflowId,
149+
workflow: workflowData,
150+
requestId,
151+
deploymentVersionId: previousVersionId,
152+
skipExternalCleanup: true,
153+
})
154+
} catch (cleanupError) {
155+
logger.error(
156+
`[${requestId}] Admin API: Failed to clean up previous version ${previousVersionId}`,
157+
cleanupError
158+
)
159+
}
160+
}
161+
162+
logger.info(
163+
`[${requestId}] Admin API: Deployed workflow ${workflowId} as v${deployResult.version}`
164+
)
93165

94166
const response: AdminDeployResult = {
95167
isDeployed: true,
@@ -119,7 +191,6 @@ export const DELETE = withAdminAuthParams<RouteParams>(async (request, context)
119191
return notFoundResponse('Workflow')
120192
}
121193

122-
// Clean up external webhook subscriptions before undeploying
123194
await cleanupWebhooksForWorkflow(
124195
workflowId,
125196
workflowRecord as Record<string, unknown>,

apps/sim/app/api/v1/admin/workflows/[id]/versions/[versionId]/activate/route.ts

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import { createLogger } from '@sim/logger'
33
import { and, eq } from 'drizzle-orm'
44
import { generateRequestId } from '@/lib/core/utils/request'
55
import { syncMcpToolsForWorkflow } from '@/lib/mcp/workflow-mcp-sync'
6-
import { saveTriggerWebhooksForDeploy } from '@/lib/webhooks/deploy'
6+
import { restorePreviousVersionWebhooks, saveTriggerWebhooksForDeploy } from '@/lib/webhooks/deploy'
77
import { activateWorkflowVersion } from '@/lib/workflows/persistence/utils'
88
import {
99
cleanupDeploymentVersion,
@@ -121,6 +121,15 @@ export const POST = withAdminAuthParams<RouteParams>(async (request, context) =>
121121
requestId,
122122
deploymentVersionId: versionRow.id,
123123
})
124+
if (previousVersionId) {
125+
await restorePreviousVersionWebhooks({
126+
request,
127+
workflow: workflowData,
128+
userId: workflowRecord.userId,
129+
previousVersionId,
130+
requestId,
131+
})
132+
}
124133
return internalErrorResponse(scheduleResult.error || 'Failed to sync schedules')
125134
}
126135

@@ -132,6 +141,15 @@ export const POST = withAdminAuthParams<RouteParams>(async (request, context) =>
132141
requestId,
133142
deploymentVersionId: versionRow.id,
134143
})
144+
if (previousVersionId) {
145+
await restorePreviousVersionWebhooks({
146+
request,
147+
workflow: workflowData,
148+
userId: workflowRecord.userId,
149+
previousVersionId,
150+
requestId,
151+
})
152+
}
135153
if (result.error === 'Deployment version not found') {
136154
return notFoundResponse('Deployment version')
137155
}

apps/sim/app/api/workflows/[id]/deploy/route.ts

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,11 @@ import { and, desc, eq } from 'drizzle-orm'
44
import type { NextRequest } from 'next/server'
55
import { generateRequestId } from '@/lib/core/utils/request'
66
import { removeMcpToolsForWorkflow, syncMcpToolsForWorkflow } from '@/lib/mcp/workflow-mcp-sync'
7-
import { cleanupWebhooksForWorkflow, saveTriggerWebhooksForDeploy } from '@/lib/webhooks/deploy'
7+
import {
8+
cleanupWebhooksForWorkflow,
9+
restorePreviousVersionWebhooks,
10+
saveTriggerWebhooksForDeploy,
11+
} from '@/lib/webhooks/deploy'
812
import {
913
deployWorkflow,
1014
loadWorkflowFromNormalizedTables,
@@ -207,6 +211,15 @@ export async function POST(request: NextRequest, { params }: { params: Promise<{
207211
requestId,
208212
deploymentVersionId,
209213
})
214+
if (previousVersionId) {
215+
await restorePreviousVersionWebhooks({
216+
request,
217+
workflow: workflowData as Record<string, unknown>,
218+
userId: actorUserId,
219+
previousVersionId,
220+
requestId,
221+
})
222+
}
210223
await undeployWorkflow({ workflowId: id })
211224
return createErrorResponse(scheduleResult.error || 'Failed to create schedule', 500)
212225
}

apps/sim/app/api/workflows/[id]/deployments/[version]/activate/route.ts

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import { and, eq } from 'drizzle-orm'
44
import type { NextRequest } from 'next/server'
55
import { generateRequestId } from '@/lib/core/utils/request'
66
import { syncMcpToolsForWorkflow } from '@/lib/mcp/workflow-mcp-sync'
7-
import { saveTriggerWebhooksForDeploy } from '@/lib/webhooks/deploy'
7+
import { restorePreviousVersionWebhooks, saveTriggerWebhooksForDeploy } from '@/lib/webhooks/deploy'
88
import { activateWorkflowVersion } from '@/lib/workflows/persistence/utils'
99
import {
1010
cleanupDeploymentVersion,
@@ -118,6 +118,15 @@ export async function POST(
118118
requestId,
119119
deploymentVersionId: versionRow.id,
120120
})
121+
if (previousVersionId) {
122+
await restorePreviousVersionWebhooks({
123+
request,
124+
workflow: workflowData as Record<string, unknown>,
125+
userId: actorUserId,
126+
previousVersionId,
127+
requestId,
128+
})
129+
}
121130
return createErrorResponse(scheduleResult.error || 'Failed to sync schedules', 500)
122131
}
123132

@@ -129,6 +138,15 @@ export async function POST(
129138
requestId,
130139
deploymentVersionId: versionRow.id,
131140
})
141+
if (previousVersionId) {
142+
await restorePreviousVersionWebhooks({
143+
request,
144+
workflow: workflowData as Record<string, unknown>,
145+
userId: actorUserId,
146+
previousVersionId,
147+
requestId,
148+
})
149+
}
132150
return createErrorResponse(result.error || 'Failed to activate deployment', 400)
133151
}
134152

0 commit comments

Comments
 (0)