Skip to content

feat(triggers): add GitLab, PagerDuty, and Zendesk webhook triggers#5150

Open
waleedlatif1 wants to merge 2 commits into
stagingfrom
worktree-add-triggers
Open

feat(triggers): add GitLab, PagerDuty, and Zendesk webhook triggers#5150
waleedlatif1 wants to merge 2 commits into
stagingfrom
worktree-add-triggers

Conversation

@waleedlatif1

Copy link
Copy Markdown
Collaborator

Summary

  • Add webhook triggers for GitLab, PagerDuty, and Zendesk — three integrations that had blocks but no trigger support.
  • GitLab: push, merge request, issue, pipeline, comment, and all-events. Verifies the X-Gitlab-Token secret token; filters by object_kind.
  • PagerDuty: incident triggered / acknowledged / resolved / escalated / reassigned, and all-events. Verifies X-PagerDuty-Signature (HMAC-SHA256 over the raw body, handles comma-separated rotation signatures); dedups on event id.
  • Zendesk: ticket created / status changed / comment added / priority changed, and all-events. Verifies X-Zendesk-Webhook-Signature (base64 HMAC-SHA256 over timestamp + body); dedups on event id.
  • Register GitLab's X-Gitlab-Event-UUID delivery header for webhook idempotency.

All three use the manual-registration model (user creates the webhook in the provider UI, pastes the signing secret) consistent with the existing GitHub trigger — no fragile auto-create API calls. Every signature scheme, event string, and payload field was verified against the providers' live docs.

Type of Change

  • New feature

Testing

Tested manually: bun run type-check passes; idempotency + provider handler tests pass. Output schema ↔ formatInput alignment verified for all triggers. First real delivery from each provider is the standard post-merge smoke test.

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)

Add webhook trigger support for three integrations that previously had
blocks but no triggers:

- GitLab: push, merge request, issue, pipeline, comment, and all-events.
  Verifies the X-Gitlab-Token secret token; filters by object_kind.
- PagerDuty: incident triggered/acknowledged/resolved/escalated/reassigned
  and all-events. Verifies X-PagerDuty-Signature (HMAC-SHA256 over raw body,
  comma-separated rotation); idempotency on event id.
- Zendesk: ticket created/status changed/comment added/priority changed and
  all-events. Verifies X-Zendesk-Webhook-Signature (base64 HMAC-SHA256 over
  timestamp+body); idempotency on event id.

Register GitLab's X-Gitlab-Event-UUID delivery header for webhook
idempotency dedup.
@vercel

vercel Bot commented Jun 20, 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 Jun 20, 2026 6:42am

Request Review

@cursor

cursor Bot commented Jun 20, 2026

Copy link
Copy Markdown

PR Summary

Medium Risk
Touches inbound webhook authentication and event routing for three providers; mistakes could reject valid deliveries or accept forgeries, though the changes mirror existing GitHub-style patterns and optional secrets when unset.

Overview
Adds webhook-based workflow triggers for integrations that previously had tool blocks only: GitLab, PagerDuty, and Zendesk.

The GitLab, PagerDuty, and Zendesk blocks now allow triggers (triggerAllowed: true), expose trigger sub-blocks via getTrigger(...), and declare triggers.enabled with their event IDs. GitLab gains push, merge request, issue, pipeline, comment, and catch-all events; PagerDuty gains incident lifecycle events plus a catch-all; Zendesk gains ticket created/status/comment/priority events plus a catch-all.

New webhook provider handlers (gitlab, pagerduty, zendesk) are registered and implement provider-specific auth (GitLab X-Gitlab-Token, PagerDuty HMAC v3 with rotation, Zendesk HMAC + timestamp replay window), event filtering by trigger type, and normalized workflow inputs aligned with trigger output schemas. PagerDuty and Zendesk also supply body-based idempotency IDs; GitLab dedup uses the new x-gitlab-event-uuid header in the shared idempotency helper.

Trigger definitions, setup copy, and shared utils live under triggers/gitlab, triggers/pagerduty, and triggers/zendesk, and all new triggers are wired into TRIGGER_REGISTRY. Setup follows the existing manual webhook registration model (user configures the provider UI and pastes secrets).

Reviewed by Cursor Bugbot for commit c2e7e01. Configure here.

@waleedlatif1

Copy link
Copy Markdown
Collaborator Author

@greptile review

@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 fd4de8d. Configure here.

@greptile-apps

greptile-apps Bot commented Jun 20, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

Adds first-class webhook triggers for GitLab, PagerDuty, and Zendesk — three integrations that had block definitions but no trigger support. All three follow the same manual-registration model as the existing GitHub trigger: the user creates the webhook in the provider UI, pastes the signing secret, and the platform verifies each delivery before dispatching.

  • GitLab: plain-equality X-Gitlab-Token check; object_kind field drives per-trigger event filtering; X-Gitlab-Event-UUID registered in the idempotency service for delivery dedup; 6 triggers (push, merge request, issue, pipeline, comment, all-events).
  • PagerDuty: HMAC-SHA256 over the raw body with comma-separated v1= rotation support; event dedup on event.id; 6 triggers mapping V3 event_type strings.
  • Zendesk: base64 HMAC-SHA256 over timestamp + body; ISO-8601 timestamp freshness check (≤ 5 min skew); event dedup on body.id; 5 triggers mapping zen:event-type:* strings; paramVisibility: 'user-only' applied to all three signing-secret fields.

Confidence Score: 5/5

The change is safe to merge; all three signature verification schemes are correctly implemented and consistent with the existing GitHub handler pattern.

All three providers implement correct HMAC/token verification, event filtering, and idempotency extraction. The Zendesk timestamp freshness check is properly implemented. The only gap is that PagerDuty lacks an equivalent timestamp staleness guard that Zendesk added in this same PR, but idempotency dedup on event.id provides a first line of replay protection — this is a hardening improvement rather than a blocking defect.

apps/sim/lib/webhooks/providers/pagerduty.ts — lacks a timestamp freshness guard that the Zendesk handler in this same PR added.

Important Files Changed

Filename Overview
apps/sim/lib/webhooks/providers/pagerduty.ts New PagerDuty V3 provider: HMAC-SHA256 with comma-separated rotation support; no timestamp freshness guard alongside the idempotency dedup (unlike Zendesk handler in this same PR).
apps/sim/lib/webhooks/providers/zendesk.ts New Zendesk provider: base64 HMAC-SHA256 over timestamp+body with ISO-8601 timestamp freshness check (5 min window), idempotency extraction via body.id.
apps/sim/lib/webhooks/providers/gitlab.ts New GitLab provider: plain-equality token check via safeCompare, object_kind-based event matching, full-body passthrough with injected event_type/branch fields.
apps/sim/triggers/gitlab/utils.ts GitLab trigger utilities: object_kind mapping, setup instructions builder, extra fields with paramVisibility user-only, and structured output schemas for all event types.
apps/sim/triggers/pagerduty/utils.ts PagerDuty trigger utilities: V3 event_type mapping, setup instructions, extra fields with paramVisibility user-only, and shared incident output schema.
apps/sim/triggers/zendesk/utils.ts Zendesk trigger utilities: zen:event-type:* mapping, setup instructions, extra fields with paramVisibility user-only, and shared ticket output schema.
apps/sim/lib/core/idempotency/service.ts Registers X-Gitlab-Event-UUID as a delivery dedup header alongside existing GitHub and Shopify delivery ID headers.
apps/sim/triggers/registry.ts Registers all 17 new triggers (6 GitLab, 6 PagerDuty, 5 Zendesk) in the global TRIGGER_REGISTRY.

Sequence Diagram

%%{init: {'theme': 'neutral'}}%%
sequenceDiagram
    participant P as Provider
    participant W as Webhook Route
    participant H as Provider Handler
    participant IS as Idempotency Service
    participant ME as matchEvent
    participant FI as formatInput
    participant WF as Workflow Executor

    P->>W: "POST /webhook/{id}"
    W->>H: verifyAuth(request, rawBody)
    note over H: GitLab: safeCompare X-Gitlab-Token
    note over H: PagerDuty: HMAC-SHA256 v1= rotation
    note over H: Zendesk: base64 HMAC + timestamp freshness
    H-->>W: null (ok) or 401
    W->>IS: checkIdempotency(headers, body)
    note over IS: GitLab: X-Gitlab-Event-UUID header
    note over IS: PagerDuty: event.id body field
    note over IS: Zendesk: body.id field
    IS-->>W: isDuplicate?
    W->>ME: matchEvent(body, triggerId)
    note over ME: GitLab: object_kind == expected
    note over ME: PagerDuty: event.event_type == expected
    note over ME: Zendesk: body.type == expected
    ME-->>W: true/false
    W->>FI: formatInput(body, headers)
    FI-->>W: structured input
    W->>WF: execute(workflow, input)
Loading
%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%%
sequenceDiagram
    participant P as Provider
    participant W as Webhook Route
    participant H as Provider Handler
    participant IS as Idempotency Service
    participant ME as matchEvent
    participant FI as formatInput
    participant WF as Workflow Executor

    P->>W: "POST /webhook/{id}"
    W->>H: verifyAuth(request, rawBody)
    note over H: GitLab: safeCompare X-Gitlab-Token
    note over H: PagerDuty: HMAC-SHA256 v1= rotation
    note over H: Zendesk: base64 HMAC + timestamp freshness
    H-->>W: null (ok) or 401
    W->>IS: checkIdempotency(headers, body)
    note over IS: GitLab: X-Gitlab-Event-UUID header
    note over IS: PagerDuty: event.id body field
    note over IS: Zendesk: body.id field
    IS-->>W: isDuplicate?
    W->>ME: matchEvent(body, triggerId)
    note over ME: GitLab: object_kind == expected
    note over ME: PagerDuty: event.event_type == expected
    note over ME: Zendesk: body.type == expected
    ME-->>W: true/false
    W->>FI: formatInput(body, headers)
    FI-->>W: structured input
    W->>WF: execute(workflow, input)
Loading

Reviews (4): Last reviewed commit: "fix(triggers): scope webhook secrets to ..." | Re-trigger Greptile

Comment thread apps/sim/triggers/gitlab/utils.ts
Comment thread apps/sim/lib/webhooks/providers/zendesk.ts
@waleedlatif1

Copy link
Copy Markdown
Collaborator Author

@greptile review

@greptile-apps

greptile-apps Bot commented Jun 20, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

Adds webhook trigger support for GitLab, PagerDuty, and Zendesk — three integrations that previously had blocks but no inbound trigger capability. Each follows the existing manual-registration pattern (user pastes the signing secret, no fragile auto-create calls).

  • GitLab: six triggers (push, merge request, issue, pipeline, comment, all-events) verified via plain X-Gitlab-Token comparison; X-Gitlab-Event-UUID registered for idempotency dedup.
  • PagerDuty: six triggers (five specific incident states + all-events) using HMAC-SHA256 over the raw body with comma-separated rotation-signature support.
  • Zendesk: five triggers (four ticket events + all-events) using base64 HMAC-SHA256 over timestamp + rawBody, with idempotency dedup on body.id.

Confidence Score: 4/5

The three new integrations are well-structured and follow the established provider pattern; the only issues are a dead function parameter and a minor inconsistency in the Zendesk body guard.

The signature verification logic for all three providers is correct, the event-matching maps align with documented payload shapes, and idempotency is wired up consistently. The triggerLabel dead parameter in gitlabSetupInstructions has no runtime effect but could mislead future contributors. The Zendesk validator's missing !body check is an inconsistency with the PagerDuty counterpart; it cannot bypass authentication (a wrong body still produces a mismatched HMAC) but it diverges from the pattern set everywhere else. Neither finding breaks functionality today.

apps/sim/triggers/gitlab/utils.ts (unused triggerLabel parameter) and apps/sim/lib/webhooks/providers/zendesk.ts (missing body guard in validateZendeskSignature).

Important Files Changed

Filename Overview
apps/sim/lib/webhooks/providers/gitlab.ts New GitLab webhook provider: verifies X-Gitlab-Token via safeCompare, routes by object_kind; duplicates the asRecord helper that could live in shared utils.
apps/sim/lib/webhooks/providers/pagerduty.ts New PagerDuty V3 provider: HMAC-SHA256 verification with rotation support (comma-separated v1= signatures), correct body guard, clean extraction of event_type and incident fields.
apps/sim/lib/webhooks/providers/zendesk.ts New Zendesk provider: base64 HMAC-SHA256 over timestamp+body; missing empty-body guard in validateZendeskSignature unlike the PagerDuty counterpart.
apps/sim/triggers/gitlab/utils.ts Shared GitLab trigger utilities: gitlabSetupInstructions has an unused first parameter (triggerLabel) that is never interpolated; only checkboxLabel is used.
apps/sim/triggers/pagerduty/utils.ts Shared PagerDuty trigger utilities: correct V3 event_type strings, clean output schema matching formatInput in the provider.
apps/sim/triggers/zendesk/utils.ts Shared Zendesk trigger utilities: zen:event-type strings align with provider matchEvent, output schema consistent with formatInput.
apps/sim/lib/core/idempotency/service.ts Adds x-gitlab-event-uuid to the delivery-header idempotency chain; minimal, correct one-liner change.
apps/sim/triggers/registry.ts Registers all 17 new triggers (6 GitLab, 6 PagerDuty, 5 Zendesk) into the global TRIGGER_REGISTRY; no conflicts or missing entries.
apps/sim/lib/webhooks/providers/registry.ts Registers three new webhook provider handlers (gitlab, pagerduty, zendesk) in alphabetical order; consistent with existing pattern.
apps/sim/blocks/blocks/gitlab.ts Enables trigger support for the GitLab block: sets triggerAllowed: true, spreads all six trigger subBlocks, and declares the triggers config.
apps/sim/blocks/blocks/pagerduty.ts Enables trigger support for the PagerDuty block; adds triggerAllowed, spreads five incident trigger subBlocks plus webhook, declares triggers config.
apps/sim/blocks/blocks/zendesk.ts Enables trigger support for the Zendesk block; adds four ticket-event trigger subBlocks and the catch-all webhook trigger.

Sequence Diagram

%%{init: {'theme': 'neutral'}}%%
sequenceDiagram
    participant P as Provider<br/>(GitLab/PagerDuty/Zendesk)
    participant W as Webhook Route
    participant R as Provider Registry
    participant H as Provider Handler
    participant I as Idempotency Service
    participant Q as Execution Queue

    P->>W: "POST /webhook/{id}"
    W->>R: getHandler(provider)
    R-->>W: gitlabHandler / pagerdutyHandler / zendeskHandler
    W->>H: verifyAuth(secret, headers, rawBody)
    alt Signature valid
        H-->>W: null (pass)
    else Invalid
        H-->>W: 401 Unauthorized
    end
    W->>H: matchEvent(triggerId, body)
    alt Event matches trigger
        H-->>W: true
    else No match
        H-->>W: false (skip)
    end
    W->>I: checkIdempotency(x-gitlab-event-uuid / event.id / body.id)
    alt Not a duplicate
        I-->>W: proceed
        W->>H: formatInput(body, headers)
        H-->>W: "{ input: { ... } }"
        W->>Q: enqueue execution
    else Duplicate
        I-->>W: skip (already processed)
    end
Loading
%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%%
sequenceDiagram
    participant P as Provider<br/>(GitLab/PagerDuty/Zendesk)
    participant W as Webhook Route
    participant R as Provider Registry
    participant H as Provider Handler
    participant I as Idempotency Service
    participant Q as Execution Queue

    P->>W: "POST /webhook/{id}"
    W->>R: getHandler(provider)
    R-->>W: gitlabHandler / pagerdutyHandler / zendeskHandler
    W->>H: verifyAuth(secret, headers, rawBody)
    alt Signature valid
        H-->>W: null (pass)
    else Invalid
        H-->>W: 401 Unauthorized
    end
    W->>H: matchEvent(triggerId, body)
    alt Event matches trigger
        H-->>W: true
    else No match
        H-->>W: false (skip)
    end
    W->>I: checkIdempotency(x-gitlab-event-uuid / event.id / body.id)
    alt Not a duplicate
        I-->>W: proceed
        W->>H: formatInput(body, headers)
        H-->>W: "{ input: { ... } }"
        W->>Q: enqueue execution
    else Duplicate
        I-->>W: skip (already processed)
    end
Loading

Comments Outside Diff (3)

  1. apps/sim/triggers/gitlab/utils.ts, line 758 (link)

    P2 Unused triggerLabel parameter

    The first parameter triggerLabel is declared but never referenced in the function body — only checkboxLabel appears in the template string. Every call site passes two strings, but the first string has no effect. This creates misleading dead code; callers might believe the first argument controls something visible in the instructions.

    Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

  2. apps/sim/lib/webhooks/providers/zendesk.ts, line 428 (link)

    P2 Missing empty-body guard in validateZendeskSignature

    Unlike the PagerDuty validator (which includes !body in its guard clause), this function does not bail out when body is empty. If rawBody arrives as "", the HMAC is computed over only the timestamp — a different message than Zendesk actually signed, so verification still fails. The real risk is a subtle divergence: a future change that pre-computes or caches the HMAC could accidentally match the truncated input. Adding || !body to the guard brings this in line with validatePagerDutySignature and makes the invariant explicit.

  3. apps/sim/lib/webhooks/providers/gitlab.ts, line 181-183 (link)

    P2 asRecord helper duplicated across all three new provider files

    The exact same three-line asRecord helper is copy-pasted into gitlab.ts, pagerduty.ts, and zendesk.ts. The shared utils.ts in this directory is the right home for it — any future change (e.g. adding a runtime typeof check) would need to be applied in three places today.

    Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

Reviews (2): Last reviewed commit: "feat(triggers): add GitLab, PagerDuty, a..." | Re-trigger Greptile

…protection

Address review feedback:
- Add paramVisibility: 'user-only' to the webhookSecret fields for GitLab,
  PagerDuty, and Zendesk so signing secrets are scoped to the credential
  owner and not exposed to workspace collaborators (repo convention).
- Reject Zendesk deliveries whose signed timestamp is more than 5 minutes
  from now, closing a replay window once an event id ages out of the
  idempotency cache. The X-Zendesk-Webhook-Signature-Timestamp header is
  ISO-8601, so it is parsed with Date.parse (matches the Slack handler's
  skew-check convention).
@waleedlatif1

Copy link
Copy Markdown
Collaborator Author

@greptile review

@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 c2e7e01. Configure here.

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