Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
64 commits
Select commit Hold shift + click to select a range
6f4c460
feat(deployments): make deployed state source of truth for non-manual…
icecrasher321 Sep 4, 2025
430ec03
fix lint
icecrasher321 Sep 4, 2025
4847a1f
fix test
icecrasher321 Sep 4, 2025
3b964ab
add script to migrate to deployed vesions
icecrasher321 Sep 4, 2025
7c46324
fix deployed chat
icecrasher321 Sep 4, 2025
912a475
address greptile commands
icecrasher321 Sep 5, 2025
609f7f3
Remove 84th migration files to prepare for regeneration
icecrasher321 Sep 5, 2025
301f514
Merge branch 'staging' into feat/deployment-management
icecrasher321 Sep 5, 2025
3162800
fix script + update migration
icecrasher321 Sep 5, 2025
c8b4604
fix script
icecrasher321 Sep 5, 2025
969e6bf
cleanup typing
icecrasher321 Sep 5, 2025
86f63f3
use shared helper
icecrasher321 Sep 5, 2025
131479e
fix tests
icecrasher321 Sep 5, 2025
3446d8f
fix duplicate route
icecrasher321 Sep 5, 2025
0c62fd2
Merge branch 'staging' into feat/deployment-management
icecrasher321 Sep 8, 2025
5c7cfa3
revert migrations prep
icecrasher321 Sep 8, 2025
6b712d9
Merge remote-tracking branch 'origin/staging' into feat/deployment-ma…
icecrasher321 Sep 8, 2025
136bc13
add migration back
icecrasher321 Sep 8, 2025
8b5cac8
add workflow in workflow block func
icecrasher321 Sep 8, 2025
bbc9202
fix UI
icecrasher321 Sep 8, 2025
120e9a3
fix lint
icecrasher321 Sep 8, 2025
81f162e
make migration idempotent
icecrasher321 Sep 9, 2025
043db69
remove migrations
icecrasher321 Sep 10, 2025
0e7d9d1
Merge remote-tracking branch 'origin/staging' into feat/deployment-ma…
icecrasher321 Sep 10, 2025
9a3c8fe
add migrations back'
icecrasher321 Sep 10, 2025
ad54226
adjust script to reuse helper
icecrasher321 Sep 10, 2025
310dbbc
add test webhook URL functionality
icecrasher321 Sep 10, 2025
26aed16
consolidate test URL + prod URL code for webhooks
icecrasher321 Sep 10, 2025
4878d14
fixes
icecrasher321 Sep 10, 2025
2348707
update trigger config save with correct dependencies
icecrasher321 Sep 11, 2025
5666520
make frozen canvas respect trigger mode
icecrasher321 Sep 11, 2025
430d53f
chore(db): remove latest migration 0088, snapshot, journal entry; del…
icecrasher321 Sep 11, 2025
7c92db5
Merge branch 'staging' into feat/deployment-management
icecrasher321 Sep 11, 2025
1966de6
separate parent id cleanup migration
icecrasher321 Sep 11, 2025
d040dcc
chore(db): remove 0089 migration, snapshot, and prune journal entry
icecrasher321 Sep 15, 2025
ab9d9ef
merge(staging): resolve conflicts for deployment APIs and modal
icecrasher321 Sep 15, 2025
7169d9e
chore(db): generate 0090 migration after removing 0089 and merging st…
icecrasher321 Sep 15, 2025
0332380
fix
icecrasher321 Sep 15, 2025
93822c8
chore(db): remove 0090 migration, snapshot, and prune journal entry
icecrasher321 Sep 16, 2025
5da91c0
merge(staging): resolve webhook trigger and background execution conf…
icecrasher321 Sep 16, 2025
861096b
chore(db): generate 0091 migration after merging staging and restorin…
icecrasher321 Sep 16, 2025
3ea41cc
feat: merge staging into feat/deployment-management
icecrasher321 Sep 17, 2025
1ea253e
fix some imports
icecrasher321 Sep 17, 2025
1ee74f8
remove dead code
icecrasher321 Sep 17, 2025
c124f3e
fix tests
icecrasher321 Sep 18, 2025
9297e43
remove comment
icecrasher321 Sep 18, 2025
766f231
working test url functionality restored
icecrasher321 Sep 18, 2025
755bd22
works
icecrasher321 Sep 18, 2025
729c982
some styling changes
icecrasher321 Sep 18, 2025
c56176f
make deploy text accurate
icecrasher321 Sep 18, 2025
ad5a9f9
chore(db): remove latest migration 0091 and snapshot; update journal …
icecrasher321 Sep 24, 2025
32e9370
merge: resolve webhook trigger route conflict by deferring to central…
icecrasher321 Sep 24, 2025
2a2d718
db(migrations): generate 0093_medical_sentinel and snapshots after me…
icecrasher321 Sep 24, 2025
f07a07a
reconcile with other merge
icecrasher321 Sep 24, 2025
6965e5b
fix trigger test
icecrasher321 Sep 24, 2025
de9c825
remove extra use effect
icecrasher321 Sep 24, 2025
dbe1568
fix test url"
icecrasher321 Sep 25, 2025
bc2d9a2
don't swallow serializer errors
icecrasher321 Sep 25, 2025
efdc3cb
fix lint
icecrasher321 Sep 25, 2025
9a2d954
fix tests
icecrasher321 Sep 25, 2025
74c369b
fix tests
icecrasher321 Sep 25, 2025
d2e9fc5
expose root for generic webhook
icecrasher321 Sep 25, 2025
319da4f
root access for webhook
icecrasher321 Sep 25, 2025
7789c47
add is workflow ready check correctly
icecrasher321 Sep 25, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
88 changes: 76 additions & 12 deletions apps/sim/app/api/__test-utils__/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -147,20 +147,63 @@ export const sampleWorkflowState = {
isDeployed: false,
}

// Global mock data that can be configured by tests
export const globalMockData = {
webhooks: [] as any[],
workflows: [] as any[],
schedules: [] as any[],
shouldThrowError: false,
errorMessage: 'Database error',
}

export const mockDb = {
select: vi.fn().mockImplementation(() => ({
from: vi.fn().mockImplementation(() => ({
where: vi.fn().mockImplementation(() => ({
limit: vi.fn().mockImplementation(() => [
{
id: 'workflow-id',
userId: 'user-id',
state: sampleWorkflowState,
},
]),
select: vi.fn().mockImplementation(() => {
if (globalMockData.shouldThrowError) {
throw new Error(globalMockData.errorMessage)
}
return {
from: vi.fn().mockImplementation(() => ({
innerJoin: vi.fn().mockImplementation(() => ({
where: vi.fn().mockImplementation(() => ({
limit: vi.fn().mockImplementation(() => {
// Return webhook/workflow join data if available
if (globalMockData.webhooks.length > 0) {
return [
{
webhook: globalMockData.webhooks[0],
workflow: globalMockData.workflows[0] || {
id: 'test-workflow',
userId: 'test-user',
},
},
]
}
return []
}),
})),
})),
where: vi.fn().mockImplementation(() => ({
limit: vi.fn().mockImplementation(() => {
// Return schedules if available
if (globalMockData.schedules.length > 0) {
return globalMockData.schedules
}
// Return simple workflow data
if (globalMockData.workflows.length > 0) {
return globalMockData.workflows
}
return [
{
id: 'workflow-id',
userId: 'user-id',
state: sampleWorkflowState,
},
]
}),
})),
})),
})),
})),
}
}),
update: vi.fn().mockImplementation(() => ({
set: vi.fn().mockImplementation(() => ({
where: vi.fn().mockResolvedValue([]),
Expand Down Expand Up @@ -351,6 +394,27 @@ export function mockExecutionDependencies() {

vi.mock('@sim/db', () => ({
db: mockDb,
// Add common schema exports that tests might need
webhook: {
id: 'id',
path: 'path',
workflowId: 'workflowId',
isActive: 'isActive',
provider: 'provider',
providerConfig: 'providerConfig',
},
workflow: { id: 'id', userId: 'userId' },
workflowSchedule: {
id: 'id',
workflowId: 'workflowId',
nextRunAt: 'nextRunAt',
status: 'status',
},
userStats: {
userId: 'userId',
totalScheduledExecutions: 'totalScheduledExecutions',
lastActive: 'lastActive',
},
}))
}

Expand Down
20 changes: 10 additions & 10 deletions apps/sim/app/api/chat/utils.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ describe('Chat API Utils', () => {
})

describe('Auth token utils', () => {
it.concurrent('should encrypt and validate auth tokens', async () => {
it('should encrypt and validate auth tokens', async () => {
const { encryptAuthToken, validateAuthToken } = await import('@/app/api/chat/utils')

const subdomainId = 'test-subdomain-id'
Expand All @@ -85,7 +85,7 @@ describe('Chat API Utils', () => {
expect(isInvalidSubdomain).toBe(false)
})

it.concurrent('should reject expired tokens', async () => {
it('should reject expired tokens', async () => {
const { validateAuthToken } = await import('@/app/api/chat/utils')

const subdomainId = 'test-subdomain-id'
Expand All @@ -100,7 +100,7 @@ describe('Chat API Utils', () => {
})

describe('Cookie handling', () => {
it.concurrent('should set auth cookie correctly', async () => {
it('should set auth cookie correctly', async () => {
const { setChatAuthCookie } = await import('@/app/api/chat/utils')

const mockSet = vi.fn()
Expand Down Expand Up @@ -129,7 +129,7 @@ describe('Chat API Utils', () => {
})

describe('CORS handling', () => {
it.concurrent('should add CORS headers for localhost in development', async () => {
it('should add CORS headers for localhost in development', async () => {
const { addCorsHeaders } = await import('@/app/api/chat/utils')

const mockRequest = {
Expand Down Expand Up @@ -164,7 +164,7 @@ describe('Chat API Utils', () => {
)
})

it.concurrent('should handle OPTIONS request', async () => {
it('should handle OPTIONS request', async () => {
const { OPTIONS } = await import('@/app/api/chat/utils')

const mockRequest = {
Expand Down Expand Up @@ -198,7 +198,7 @@ describe('Chat API Utils', () => {
})
})

it.concurrent('should allow access to public chats', async () => {
it('should allow access to public chats', async () => {
const utils = await import('@/app/api/chat/utils')
const { validateChatAuth } = utils

Expand All @@ -218,7 +218,7 @@ describe('Chat API Utils', () => {
expect(result.authorized).toBe(true)
})

it.concurrent('should request password auth for GET requests', async () => {
it('should request password auth for GET requests', async () => {
const { validateChatAuth } = await import('@/app/api/chat/utils')

const deployment = {
Expand Down Expand Up @@ -266,7 +266,7 @@ describe('Chat API Utils', () => {
expect(result.authorized).toBe(true)
})

it.concurrent('should reject incorrect password', async () => {
it('should reject incorrect password', async () => {
const { validateChatAuth } = await import('@/app/api/chat/utils')

const deployment = {
Expand All @@ -292,7 +292,7 @@ describe('Chat API Utils', () => {
expect(result.error).toBe('Invalid password')
})

it.concurrent('should request email auth for email-protected chats', async () => {
it('should request email auth for email-protected chats', async () => {
const { validateChatAuth } = await import('@/app/api/chat/utils')

const deployment = {
Expand All @@ -314,7 +314,7 @@ describe('Chat API Utils', () => {
expect(result.error).toBe('auth_required_email')
})

it.concurrent('should check allowed emails for email auth', async () => {
it('should check allowed emails for email auth', async () => {
const { validateChatAuth } = await import('@/app/api/chat/utils')

const deployment = {
Expand Down
16 changes: 10 additions & 6 deletions apps/sim/app/api/chat/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -399,11 +399,10 @@ export async function executeWorkflowForChat(
`[${requestId}] Using ${outputBlockIds.length} output blocks and ${selectedOutputIds.length} selected output IDs for extraction`
)

// Find the workflow (deployedState is NOT deprecated - needed for chat execution)
// Find the workflow to check if it's deployed
const workflowResult = await db
.select({
isDeployed: workflow.isDeployed,
deployedState: workflow.deployedState,
variables: workflow.variables,
})
.from(workflow)
Expand All @@ -415,13 +414,17 @@ export async function executeWorkflowForChat(
throw new Error('Workflow not available')
}

// For chat execution, use ONLY the deployed state (no fallback)
if (!workflowResult[0].deployedState) {
// Load the active deployed state from the deployment versions table
const { loadDeployedWorkflowState } = await import('@/lib/workflows/db-helpers')

let deployedState: WorkflowState
try {
deployedState = await loadDeployedWorkflowState(workflowId)
} catch (error) {
logger.error(`[${requestId}] Failed to load deployed state for workflow ${workflowId}:`, error)
throw new Error(`Workflow must be deployed to be available for chat`)
}

// Use deployed state for chat execution (this is the stable, deployed version)
const deployedState = workflowResult[0].deployedState as WorkflowState
const { blocks, edges, loops, parallels } = deployedState

// Prepare for execution, similar to use-workflow-execution.ts
Expand Down Expand Up @@ -611,6 +614,7 @@ export async function executeWorkflowForChat(
target: e.target,
})),
onStream,
isDeployedContext: true,
},
})

Expand Down
Loading