Skip to content

fix(triggers): stop cloned trigger blocks reusing the source's webhook URL - #6091

Merged
waleedlatif1 merged 1 commit into
stagingfrom
worktree-webhook-clone-url
Jul 30, 2026
Merged

fix(triggers): stop cloned trigger blocks reusing the source's webhook URL#6091
waleedlatif1 merged 1 commit into
stagingfrom
worktree-webhook-clone-url

Conversation

@waleedlatif1

@waleedlatif1 waleedlatif1 commented Jul 30, 2026

Copy link
Copy Markdown
Collaborator

Summary

Copy/pasting or duplicating a deployed webhook trigger block gave the clone the source's webhook URL instead of a fresh one. The precondition is deploy, which is what made it look intermittent:

  • Before deploy the URL is derived. use-webhook-management.ts:103-109 and the canvas both fall back to ${baseUrl}/api/webhooks/trigger/${blockId}, and cloning already regenerates block ids — so copying an undeployed trigger yields a fresh URL on its own.
  • After deploy the URL is stored. Deploy registers the webhook at path = triggerPath || block.id (deploy.ts:321-325) and the effect at use-webhook-management.ts:151 writes that literal path back into the source's triggerPath. Paste copies the string verbatim, the clone stops deriving, and it renders the source's URL.

Fix: clear triggerPath on in-canvas clones so the clone derives from its new block id again. Two lines of behavior, one new function.

  • Clears both the subBlocks structure and the sub-block value map. The value map is authoritative in mergeSubblockStateWithValues (a null there overrides the structure), and since no trigger declares triggerPath as a subblock it normally lives only in the store. Clearing one without the other leaves the source's path in effect.
  • Deliberately unconditional, and limited to triggerPath. Zero blocks declare that subblock id, so there is nothing to collide with and no need to classify the block first — no predicate, no gate.
  • The sibling TRIGGER_RUNTIME_SUBBLOCK_IDS entries are left alone on purpose. triggerConfig/triggerId are user configuration (and triggerConfig can be a legacy trigger's only config home). webhookId is a user-entered action field on Attio, Vercel, and Discord — and Attio/Vercel are trigger-capable, so clearing it by trigger-ness would destroy real config — while being unused as trigger state: deploy mints its own row id via generateShortId() and matches existing rows by block id, and useWebhookManagement overwrites the field from the server anyway.

Scope

Clone paths only. No deploy-side, server-side, or import/export behavior change — regenerateWorkflowIds (export/import), sanitizeSubBlocksForDuplicate (server duplicate + workspace forking), and the copilot edit path are untouched.

Type of Change

  • Bug fix

Testing

  • 8610 tests pass across stores + lib + triggers (612 files); tsc --noEmit clean; check:boundaries, check:realtime-prune, check:client-boundary, check:api-validation, check:utils all pass; biome clean.
  • Verified non-vacuous by mutation testing — zero coverage holes. Every mutation is caught, including two that would re-introduce a regression:
Mutation Tests failed
Drop the structure clear 4
Drop the value-map clear 5
Helper early-return 6
Delete the regenerateBlockIds call site 5
Delete the duplicateBlock call site 1
Also clear webhookId (would wipe Attio/Vercel config) 4
Also clear triggerConfig (would drop trigger setup) 1
Write undefined instead of null 5
  • Coverage includes both triggerMode: true (the shape the toolbar actually creates — confirmed against production rows) and triggerMode: false (API/import rows), the value-map-only shape, the structure-only shape, and explicit preservation tests for webhookId on both a trigger-capable block in trigger mode and an action block.

Checklist

  • Code follows project style guidelines
  • Self-reviewed my changes
  • Tests added/updated and passing
  • No new warnings introduced
  • I confirm that I have read and agree to the terms outlined in the Contributor License Agreement (CLA)

@vercel

vercel Bot commented Jul 30, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
Project Deployment Actions Updated (UTC)
docs Skipped Skipped Jul 30, 2026 5:52am

Request Review

@cursor

cursor Bot commented Jul 30, 2026

Copy link
Copy Markdown

PR Summary

Medium Risk
Changes clone/paste/duplicate behavior for trigger webhook identity; scope is narrow (only triggerPath) with broad test coverage including mutation-style cases.

Overview
Fixes copy/paste and duplicate of deployed webhook trigger blocks showing the source webhook URL on the clone. After deploy, triggerPath stores the registered path; cloning copied it verbatim instead of deriving from the new block id.

Adds clearClonedWebhookPath, which nulls triggerPath on both the block subBlocks entry and the sub-block value map (both are needed for merge semantics). Wired into regenerateBlockIds (canvas paste) and duplicateBlock.

triggerConfig, triggerId, token, and user webhookId on action/trigger-capable blocks are not cleared—only runtime-deployed path identity.

Reviewed by Cursor Bugbot for commit 14afed6. Configure here.

@greptile-apps

greptile-apps Bot commented Jul 30, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

Clears stored triggerPath on in-canvas clones so duplicated deployed webhook triggers get a fresh URL derived from the new block id.

  • Adds clearClonedWebhookPath and calls it from regenerateBlockIds (paste/copy) and duplicateBlock.
  • Nulls triggerPath in both subBlocks structure and sub-block value map; leaves webhookId/triggerConfig/triggerId intact.
  • Adds unit coverage for value-map-only, structure-only, triggerMode true/false, and preservation of action/config fields.

Confidence Score: 5/5

This PR appears safe to merge; no blocking failures remain from prior review or the current clone-path fix.

No blocking failure remains. The change narrowly clears cloned triggerPath in both structure and value map on paste and duplicate paths, with tests covering the bug shapes and intentional non-clears.

Important Files Changed

Filename Overview
apps/sim/stores/workflows/utils.ts Introduces clearClonedWebhookPath and applies it after id regeneration so clones drop stored webhook paths.
apps/sim/stores/workflows/workflow/store.ts Invokes the same clear on duplicateBlock so the store public API matches paste behavior.
apps/sim/stores/workflows/utils.test.ts Covers clearing both stores of triggerPath and preserving webhookId/trigger config.
apps/sim/stores/workflows/workflow/store.test.ts Covers duplicateBlock clearing triggerPath while keeping source identity and webhookId.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
  A[Copy/paste or duplicate block] --> B[regenerateBlockIds / duplicateBlock]
  B --> C[clearClonedWebhookPath]
  C --> D[Null triggerPath in subBlocks]
  C --> E[Null triggerPath in value map]
  D --> F[Clone derives URL from new block id]
  E --> F
Loading

Reviews (2): Last reviewed commit: "fix(triggers): stop cloned trigger block..." | Re-trigger Greptile

…k URL

Before a deploy, a trigger block's webhook URL is DERIVED — useWebhookManagement
and the canvas both fall back to the block's own id, which cloning already
regenerates, so copying an undeployed trigger yields a fresh URL. Deploy then
registers the webhook at `path = triggerPath || block.id` and writes that literal
path back into the source block's `triggerPath`. From then on the URL is STORED,
and copy/paste copies it verbatim, so the clone renders the source's URL.

Clear `triggerPath` on in-canvas clones so the clone derives a path from its new
block id again.

- Clears both the subBlocks structure and the sub-block value map: the value map
  is authoritative in mergeSubblockStateWithValues, and since no trigger declares
  `triggerPath` as a subblock it normally lives only in the store.
- Deliberately unconditional and limited to `triggerPath`. No block declares that
  id, so there is nothing to collide with and no need to classify the block.
- The sibling TRIGGER_RUNTIME_SUBBLOCK_IDS entries are left alone on purpose.
  `triggerConfig`/`triggerId` are user configuration. `webhookId` is a
  user-entered action field on Attio, Vercel, and Discord — and Attio/Vercel are
  trigger-capable, so clearing it by trigger-ness would destroy real config —
  while being unused as trigger state, since deploy mints its own row id and
  matches existing rows by block id.

Scoped to the clone paths. No deploy-side, server-side, or import/export change.
@waleedlatif1
waleedlatif1 force-pushed the worktree-webhook-clone-url branch from df7a868 to 14afed6 Compare July 30, 2026 05:52
@waleedlatif1

Copy link
Copy Markdown
Collaborator Author

@greptile

@waleedlatif1

Copy link
Copy Markdown
Collaborator Author

@cursor review

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ Bugbot reviewed your changes and found no new issues!

Comment @cursor review or bugbot run to trigger another review on this PR

Reviewed by Cursor Bugbot for commit 14afed6. Configure here.

@waleedlatif1
waleedlatif1 merged commit 1ce2aef into staging Jul 30, 2026
28 checks passed
@waleedlatif1
waleedlatif1 deleted the worktree-webhook-clone-url branch July 30, 2026 06:03
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant