Skip to content

Commit 9a993c3

Browse files
committed
fix(deploy): track first-pass fills to prevent stale baseConfig bypassing required-field validation
Use a dedicated `filledSubBlockIds` Set populated during the first pass so the second-pass skip guard is based solely on live `getConfigValue` results, not on stale entries spread from `baseConfig` (`triggerConfig`).
1 parent b159e1b commit 9a993c3

File tree

1 file changed

+35
-17
lines changed

1 file changed

+35
-17
lines changed

apps/sim/lib/webhooks/deploy.ts

Lines changed: 35 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import {
1313
} from '@/lib/webhooks/provider-subscriptions'
1414
import { getProviderHandler } from '@/lib/webhooks/providers'
1515
import { syncWebhooksForCredentialSet } from '@/lib/webhooks/utils.server'
16+
import { buildCanonicalIndex } from '@/lib/workflows/subblocks/visibility'
1617
import { getBlock } from '@/blocks'
1718
import type { SubBlockConfig } from '@/blocks/types'
1819
import type { BlockState } from '@/stores/workflows/workflow/types'
@@ -181,23 +182,40 @@ function buildProviderConfig(
181182
Object.entries(block.subBlocks || {}).map(([key, value]) => [key, { value: value.value }])
182183
)
183184

184-
triggerDef.subBlocks
185-
.filter(
186-
(subBlock) =>
187-
(subBlock.mode === 'trigger' || subBlock.mode === 'trigger-advanced') &&
188-
!SYSTEM_SUBBLOCK_IDS.includes(subBlock.id)
189-
)
190-
.forEach((subBlock) => {
191-
const valueToUse = getConfigValue(block, subBlock)
192-
if (valueToUse !== null && valueToUse !== undefined && valueToUse !== '') {
193-
providerConfig[subBlock.id] = valueToUse
194-
} else {
195-
delete providerConfig[subBlock.id]
196-
if (isFieldRequired(subBlock, subBlockValues)) {
197-
missingFields.push(subBlock.title || subBlock.id)
198-
}
199-
}
200-
})
185+
const canonicalIndex = buildCanonicalIndex(triggerDef.subBlocks)
186+
const satisfiedCanonicalIds = new Set<string>()
187+
const filledSubBlockIds = new Set<string>()
188+
189+
const relevantSubBlocks = triggerDef.subBlocks.filter(
190+
(subBlock) =>
191+
(subBlock.mode === 'trigger' || subBlock.mode === 'trigger-advanced') &&
192+
!SYSTEM_SUBBLOCK_IDS.includes(subBlock.id)
193+
)
194+
195+
// First pass: populate providerConfig, clear stale baseConfig entries, and track which
196+
// subblocks and canonical groups have a value.
197+
for (const subBlock of relevantSubBlocks) {
198+
const valueToUse = getConfigValue(block, subBlock)
199+
if (valueToUse !== null && valueToUse !== undefined && valueToUse !== '') {
200+
providerConfig[subBlock.id] = valueToUse
201+
filledSubBlockIds.add(subBlock.id)
202+
const canonicalId = canonicalIndex.canonicalIdBySubBlockId[subBlock.id]
203+
if (canonicalId) satisfiedCanonicalIds.add(canonicalId)
204+
} else {
205+
delete providerConfig[subBlock.id]
206+
}
207+
}
208+
209+
// Second pass: validate required fields. Skip subblocks that are filled or whose canonical
210+
// group is satisfied by another member.
211+
for (const subBlock of relevantSubBlocks) {
212+
if (filledSubBlockIds.has(subBlock.id)) continue
213+
const canonicalId = canonicalIndex.canonicalIdBySubBlockId[subBlock.id]
214+
if (canonicalId && satisfiedCanonicalIds.has(canonicalId)) continue
215+
if (isFieldRequired(subBlock, subBlockValues)) {
216+
missingFields.push(subBlock.title || subBlock.id)
217+
}
218+
}
201219

202220
const credentialConfig = triggerDef.subBlocks.find(
203221
(subBlock) => subBlock.id === 'triggerCredentials'

0 commit comments

Comments
 (0)