Skip to content

feat(webhook): add WebhookTrigger class for Workflow Builder triggers#2615

Open
zimeg wants to merge 17 commits into
mainfrom
eden/webhook-trigger
Open

feat(webhook): add WebhookTrigger class for Workflow Builder triggers#2615
zimeg wants to merge 17 commits into
mainfrom
eden/webhook-trigger

Conversation

@zimeg

@zimeg zimeg commented Jun 2, 2026

Copy link
Copy Markdown
Member

Summary

This pull request adds a minimal WebhookTrigger class to @slack/webhook for Workflow Builder webhook triggers.

The package previously only supported incoming webhooks (IncomingWebhook). Workflow Builder triggers accept arbitrary JSON payloads and return JSON responses, so consumers like slack-github-action currently fall back to raw fetch.

The implementation is intentionally small and mirrors IncomingWebhook:

  • Constructor takes a URL and optional defaults (timeout, agent); rejects a missing or empty URL.
  • send(payload?) POSTs the payload (defaults to {}) and resolves to { ok, body }; HTTP and request failures reject.
  • Reuses the existing error infrastructure and User-Agent instrumentation, adding WebhookTrigger-named error types.

Preview

🔗 https://github.com/slackapi/node-slack-sdk/tree/eden/webhook-trigger/packages/webhook#trigger-a-workflow-builder-workflow

const { WebhookTrigger } = require('@slack/webhook');
const url = process.env.SLACK_WEBHOOK_TRIGGER_URL;

const trigger = new WebhookTrigger(url);

(async () => {
  // Keys should match the variables your workflow expects
  const result = await trigger.send({
    customer_name: 'Ada Lovelace',
    order_id: '1024',
  });
})();

Requirements

Add a new WebhookTrigger class that mirrors IncomingWebhook but handles
Workflow Builder webhook triggers which return JSON responses with
arbitrary payloads (vs plain text "ok" from incoming webhooks).

- Constructor takes URL + defaults (timeout, agent) — same pattern
- send() accepts arbitrary key-value payload, returns { ok, body }
- Reuses existing error infrastructure and User-Agent instrumentation
- Enables consumers like slack-github-action to use the SDK instead
  of raw fetch for WFB triggers

Co-Authored-By: Claude <svc-devxp-claude@slack-corp.com>
@changeset-bot

changeset-bot Bot commented Jun 2, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 7968168

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
@slack/webhook Minor

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@codecov

codecov Bot commented Jun 2, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 92.43697% with 9 lines in your changes missing coverage. Please review.
✅ Project coverage is 88.96%. Comparing base (a795b86) to head (7968168).
✅ All tests successful. No failed tests found.

Additional details and impacted files
@@            Coverage Diff             @@
##             main    #2615      +/-   ##
==========================================
+ Coverage   88.90%   88.96%   +0.05%     
==========================================
  Files          63       64       +1     
  Lines       10256    10375     +119     
  Branches      452      464      +12     
==========================================
+ Hits         9118     9230     +112     
- Misses       1117     1123       +6     
- Partials       21       22       +1     
Flag Coverage Δ
cli-hooks 88.96% <92.43%> (+0.05%) ⬆️
cli-test 88.96% <92.43%> (+0.05%) ⬆️
logger 88.96% <92.43%> (+0.05%) ⬆️
oauth 88.96% <92.43%> (+0.05%) ⬆️
socket-mode 88.96% <92.43%> (+0.05%) ⬆️
web-api 88.96% <92.43%> (+0.05%) ⬆️
webhook 88.96% <92.43%> (+0.05%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

🚀 New features to boost your workflow:
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

zimeg and others added 2 commits June 2, 2026 14:20
Co-Authored-By: Claude <svc-devxp-claude@slack-corp.com>
Workflow Builder webhook trigger inputs are always string values.

Co-Authored-By: Claude <svc-devxp-claude@slack-corp.com>

@WilliamBergamin WilliamBergamin left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Gave this a quick look and it looks good 💯

if we need to dry this up in the future we can look into it at that time

# Conflicts:
#	packages/webhook/package.json
#	packages/webhook/src/index.ts
@zimeg zimeg added enhancement M-T: A feature request for new functionality pkg:webhook applies to `@slack/webhook` semver:minor labels Jun 30, 2026
@zimeg zimeg self-assigned this Jun 30, 2026
@zimeg zimeg added the javascript Pull requests that update Javascript code label Jun 30, 2026
@zimeg zimeg modified the milestones: webhook@next, webhook@7.1.0 Jun 30, 2026
zimeg and others added 12 commits July 3, 2026 10:05
Allow send() to be called with no arguments, POSTing an empty body.
send({}) continues to work unchanged.

Co-Authored-By: Claude <svc-devxp-claude@slack-corp.com>
Use a falsy check so an empty-string URL is rejected up front rather
than failing later at request time. Adds a guard test.

Co-Authored-By: Claude <svc-devxp-claude@slack-corp.com>
…s test

Add a test that a 401 with { ok: false, error: 'invalid_auth' } rejects
with an HTTPError exposing the response status and body. Remove the
success test asserting workflow_run_id so success cases only assert
result.ok === true.

Co-Authored-By: Claude <svc-devxp-claude@slack-corp.com>
WebhookTrigger throws the same coded errors as IncomingWebhook but had
no correspondingly named types. Add WebhookTriggerSendError /
WebhookTriggerHTTPError / WebhookTriggerRequestError aliases and export
them so consumers have properly-named errors to catch.

Co-Authored-By: Claude <svc-devxp-claude@slack-corp.com>
…source

Co-Authored-By: Claude <svc-devxp-claude@slack-corp.com>
Co-Authored-By: Claude <svc-devxp-claude@slack-corp.com>
Co-Authored-By: Claude <svc-devxp-claude@slack-corp.com>
Co-Authored-By: Claude <svc-devxp-claude@slack-corp.com>
Coerce result.ok from body.ok instead of defaulting a missing field to
true, so only an explicit ok:true reports success.

Co-Authored-By: Claude <svc-devxp-claude@slack-corp.com>

@zimeg zimeg left a comment

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

🗣️ Words I think for the readers and reviewers!

}

export type IncomingWebhookSendError = IncomingWebhookRequestError | IncomingWebhookHTTPError;
export type WebhookTriggerSendError = WebhookTriggerRequestError | WebhookTriggerHTTPError;

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

⚠️ note: The error handling is shared between webhook techniques but so we export these values under a similar namespace.

* Processes an HTTP response into a WebhookTriggerResult.
*/
private buildResult(response: AxiosResponse): WebhookTriggerResult {
const body = typeof response.data === 'string' ? JSON.parse(response.data) : response.data;

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

🔬 note: This feels defensive to me and might be removed as response is unpacked to match standard "fetch"!

@zimeg zimeg marked this pull request as ready for review July 3, 2026 19:45
@zimeg zimeg requested a review from a team as a code owner July 3, 2026 19:45

@WilliamBergamin WilliamBergamin left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Nice work 💯

Left one comment on test coverage but its possible my comment is redundent

code: ErrorCode.RequestError;
original: Error;
}
export type WebhookTriggerRequestError = IncomingWebhookRequestError;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Safe move 🧠 I like it 💯

});
});

describe('User-Agent header', () => {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Nice 💯

should we also add a tests that covers using addAppMetadata to expand the user-agent value?

* A client for Slack's Workflow Builder webhook triggers
* @see {@link https://slack.com/help/articles/360041352714-Build-a-workflow--Create-a-workflow-that-starts-outside-of-Slack}
*/
export class WebhookTrigger {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Paise for mirroring existing behaviors 💯

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement M-T: A feature request for new functionality javascript Pull requests that update Javascript code pkg:webhook applies to `@slack/webhook` semver:minor

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants