Skip to content

Conversation

@icecrasher321
Copy link
Collaborator

Summary

Will do webhook lifecycle management as part of deploy process.

Type of Change

  • Other: UX Improvement

Testing

Tested manually

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
Copy link

vercel bot commented Jan 15, 2026

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

1 Skipped Deployment
Project Deployment Review Updated (UTC)
docs Skipped Skipped Jan 15, 2026 5:36am

@greptile-apps
Copy link
Contributor

greptile-apps bot commented Jan 15, 2026

Greptile Summary

Refactors webhook lifecycle management to occur during workflow deployment rather than requiring a separate "Save Configuration" button. This significantly improves UX by removing a manual step.

Key Changes

  • Centralized webhook management: Created saveTriggerWebhooksForDeploy() in apps/sim/lib/webhooks/deploy.ts to handle all trigger webhook configuration during deployment
  • Provider subscription abstraction: Extracted external webhook subscription logic into apps/sim/lib/webhooks/provider-subscriptions.ts with unified createExternalWebhookSubscription() and cleanupExternalWebhook() functions
  • Automatic webhook updates: Webhooks are now created, updated, or recreated automatically when workflows are deployed based on configuration changes
  • Cleanup on edit/delete: Added logic in workflow state route to clean up webhooks when trigger blocks are deleted or edited
  • UI simplification: Removed the "Save Configuration" button (trigger-save component) and related instructions from all trigger setup guides

Implementation Details

The new flow:

  1. User configures trigger settings in the editor
  2. User clicks Deploy
  3. Backend validates trigger configuration and creates/updates webhooks with external providers
  4. Deployment succeeds or fails with clear error messaging

Webhook recreation is intelligently triggered when relevant config changes are detected (via shouldRecreateExternalWebhookSubscription()), ensuring external subscriptions stay in sync with the workflow state.

Issues Found

  • Potential credential override bug in apps/sim/lib/webhooks/deploy.ts:359-368 where existing credentials always take precedence over new values during updates

Confidence Score: 4/5

  • Safe to merge with one logic issue that should be reviewed
  • The refactoring is well-structured with proper error handling and cleanup logic. Code follows consistent patterns and removes significant technical debt. One potential bug with credential merging logic needs attention but is isolated and has a clear fix. The change improves UX substantially while maintaining system reliability.
  • apps/sim/lib/webhooks/deploy.ts - review credential merge logic at line 359

Important Files Changed

Filename Overview
apps/sim/lib/webhooks/deploy.ts New file implementing webhook lifecycle management during deployment, handles trigger configuration validation, credential sets, and external webhook subscriptions
apps/sim/lib/webhooks/provider-subscriptions.ts New centralized provider subscription management for external webhooks (Teams, Telegram, Airtable, Typeform, Calendly, Grain, Lemlist, Webflow)
apps/sim/app/api/workflows/[id]/deploy/route.ts Integrated saveTriggerWebhooksForDeploy into deployment flow, webhooks now created/updated during deploy instead of separately
apps/sim/app/api/webhooks/route.ts Refactored to use centralized createExternalWebhookSubscription, removed provider-specific code duplication
apps/sim/app/api/webhooks/[id]/route.ts Added webhook recreation logic on config changes using shouldRecreateExternalWebhookSubscription
apps/sim/app/api/workflows/[id]/state/route.ts Added webhook cleanup on block deletion/edit, removed old syncWorkflowWebhooks function

Sequence Diagram

sequenceDiagram
    participant User
    participant UI as Deploy Modal
    participant API as Deploy API
    participant Deploy as saveTriggerWebhooksForDeploy
    participant Provider as Provider Subscriptions
    participant External as External Provider APIs
    participant DB as Database

    User->>UI: Click Deploy
    UI->>API: POST /api/workflows/{id}/deploy
    API->>API: Validate permissions & schedules
    API->>Deploy: saveTriggerWebhooksForDeploy()
    
    loop For each trigger block
        Deploy->>Deploy: Resolve trigger ID & build config
        Deploy->>Deploy: Validate required fields
        
        alt Credential Set
            Deploy->>DB: syncWebhooksForCredentialSet()
            DB->>DB: Create webhooks for each credential
        else Single Credential
            Deploy->>DB: Query existing webhook
            
            alt Webhook exists
                Deploy->>Provider: shouldRecreateExternalWebhookSubscription()
                
                alt Config changed
                    Provider->>External: cleanupExternalWebhook()
                    Provider->>External: createExternalWebhookSubscription()
                    External-->>Provider: Return external ID
                end
                
                Deploy->>DB: Update webhook record
            else New webhook
                Provider->>External: createExternalWebhookSubscription()
                External-->>Provider: Return external ID
                Deploy->>DB: Insert webhook record
            end
        end
    end
    
    Deploy-->>API: Success/Error
    API->>DB: deployWorkflow()
    API->>DB: createSchedulesForDeploy()
    API-->>UI: Deployment result
    UI-->>User: Show success or error
Loading

Copy link
Contributor

@greptile-apps greptile-apps bot left a comment

Choose a reason for hiding this comment

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

17 files reviewed, 1 comment

Edit Code Review Agent Settings | Greptile

Comment on lines +359 to +368
const finalProviderConfig = {
...nextProviderConfig,
credentialId: existingConfig.credentialId,
credentialSetId: existingConfig.credentialSetId,
userId: existingConfig.userId,
historyId: existingConfig.historyId,
lastCheckedTimestamp: existingConfig.lastCheckedTimestamp,
setupCompleted: existingConfig.setupCompleted,
externalId: nextProviderConfig.externalId ?? existingConfig.externalId,
}
Copy link
Contributor

Choose a reason for hiding this comment

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

logic: Credential fields from existingConfig always override nextProviderConfig, even when new credentials are provided

The merge logic preserves credentialId and credentialSetId from the existing config unconditionally. If a user updates credentials during redeployment, the new values in providerConfig will be overwritten with old values.

Consider checking if new credential values are present in providerConfig before falling back to existing ones:

Suggested change
const finalProviderConfig = {
...nextProviderConfig,
credentialId: existingConfig.credentialId,
credentialSetId: existingConfig.credentialSetId,
userId: existingConfig.userId,
historyId: existingConfig.historyId,
lastCheckedTimestamp: existingConfig.lastCheckedTimestamp,
setupCompleted: existingConfig.setupCompleted,
externalId: nextProviderConfig.externalId ?? existingConfig.externalId,
}
const finalProviderConfig = {
...nextProviderConfig,
credentialId: providerConfig.credentialId ?? existingConfig.credentialId,
credentialSetId: providerConfig.credentialSetId ?? existingConfig.credentialSetId,
userId: existingConfig.userId,
historyId: existingConfig.historyId,
lastCheckedTimestamp: existingConfig.lastCheckedTimestamp,
setupCompleted: existingConfig.setupCompleted,
externalId: nextProviderConfig.externalId ?? existingConfig.externalId,
}
Prompt To Fix With AI
This is a comment left during a code review.
Path: apps/sim/lib/webhooks/deploy.ts
Line: 359:368

Comment:
**logic:** Credential fields from `existingConfig` always override `nextProviderConfig`, even when new credentials are provided

The merge logic preserves `credentialId` and `credentialSetId` from the existing config unconditionally. If a user updates credentials during redeployment, the new values in `providerConfig` will be overwritten with old values.

Consider checking if new credential values are present in `providerConfig` before falling back to existing ones:

```suggestion
    const finalProviderConfig = {
      ...nextProviderConfig,
      credentialId: providerConfig.credentialId ?? existingConfig.credentialId,
      credentialSetId: providerConfig.credentialSetId ?? existingConfig.credentialSetId,
      userId: existingConfig.userId,
      historyId: existingConfig.historyId,
      lastCheckedTimestamp: existingConfig.lastCheckedTimestamp,
      setupCompleted: existingConfig.setupCompleted,
      externalId: nextProviderConfig.externalId ?? existingConfig.externalId,
    }
```

How can I resolve this? If you propose a fix, please make it concise.

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.

2 participants