Skip to content

Commit 5f75d0b

Browse files
fix(tables): pin table workflow deployment state
1 parent 4c9e494 commit 5f75d0b

4 files changed

Lines changed: 34 additions & 1 deletion

File tree

apps/sim/background/workflow-column-execution.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -993,6 +993,7 @@ async function runWorkflowAndWriteTerminal(
993993
workflowTriggerType: 'table',
994994
triggerBlockId: startBlock.id,
995995
useDraftState: false,
996+
workflowStateOverride: normalizedData,
996997
abortSignal: attemptSignal,
997998
onBlockStart: progressWriter.onBlockStart,
998999
onBlockComplete: progressWriter.onBlockComplete,

apps/sim/lib/workflows/executor/execute-workflow.test.ts

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -234,6 +234,28 @@ describe('executeWorkflow', () => {
234234
)
235235
})
236236

237+
it('forwards a trusted immutable workflow state to the execution snapshot', async () => {
238+
const workflowStateOverride = {
239+
blocks: { 'block-1': { id: 'block-1', type: 'start_trigger' } },
240+
edges: [],
241+
loops: {},
242+
parallels: {},
243+
deploymentVersionId: 'deployment-version-1',
244+
}
245+
246+
await executeWorkflow(workflow, 'request-1', { prompt: 'hello' }, 'actor-1', {
247+
enabled: true,
248+
principal,
249+
billingAttribution,
250+
workflowStateOverride,
251+
})
252+
253+
const coreParams = executeWorkflowCoreMock.mock.calls[0]?.[0] as {
254+
snapshot: ExecutionSnapshot
255+
}
256+
expect(coreParams.snapshot.metadata.workflowStateOverride).toEqual(workflowStateOverride)
257+
})
258+
237259
it('waits for post-execution persistence before resolving', async () => {
238260
let resolvePostExecution!: () => void
239261
waitForPostExecutionMock.mockReturnValueOnce(

apps/sim/lib/workflows/executor/execute-workflow.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,8 @@ export interface ExecuteWorkflowOptions {
4848
abortSignal?: AbortSignal
4949
/** Use the live/draft workflow state instead of the deployed state. Used by copilot. */
5050
useDraftState?: boolean
51+
/** Immutable workflow state selected by a trusted server-side trigger boundary. */
52+
workflowStateOverride?: NonNullable<ExecutionMetadata['workflowStateOverride']>
5153
/** Stop execution after this block completes. Used for "run until block" feature. */
5254
stopAfterBlockId?: string
5355
/** Run-from-block configuration using a prior execution snapshot. */
@@ -142,6 +144,7 @@ export async function executeWorkflow(
142144
triggerType,
143145
triggerBlockId: streamConfig?.triggerBlockId,
144146
useDraftState: streamConfig?.useDraftState ?? false,
147+
workflowStateOverride: streamConfig?.workflowStateOverride,
145148
startTime: new Date().toISOString(),
146149
isClientSession: false,
147150
enforceCredentialAccess: streamConfig?.enforceCredentialAccess ?? false,

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

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,14 @@ async function assertTableWorkflowIntegrity(): Promise<void> {
115115
WHERE jsonb_typeof(workflow_group.value) IS DISTINCT FROM 'object'
116116
OR NOT (workflow_group.value ? 'workflowId')
117117
OR jsonb_typeof(workflow_group.value->'workflowId') IS DISTINCT FROM 'string'
118-
OR workflow_group.value->>'workflowId' = ''
118+
OR (
119+
workflow_group.value->>'workflowId' = ''
120+
AND (
121+
NOT (workflow_group.value ? 'enrichmentId')
122+
OR jsonb_typeof(workflow_group.value->'enrichmentId') IS DISTINCT FROM 'string'
123+
OR workflow_group.value->>'enrichmentId' = ''
124+
)
125+
)
119126
LIMIT 1
120127
`)
121128
if (invalidGroup) {

0 commit comments

Comments
 (0)