Skip to content

feat: post webhooks via the @slack/webhook SDK with action-side retries#630

Draft
zimeg wants to merge 43 commits into
mainfrom
webhook-trigger-sdk
Draft

feat: post webhooks via the @slack/webhook SDK with action-side retries#630
zimeg wants to merge 43 commits into
mainfrom
webhook-trigger-sdk

Conversation

@zimeg

@zimeg zimeg commented Jun 30, 2026

Copy link
Copy Markdown
Member

Summary

Converts both webhook techniques to the @slack/webhook SDK and removes axios / axios-retry as direct dependencies of the action:

  • incoming-webhookIncomingWebhook class
  • webhook-triggerWebhookTrigger class

Retry behavior (0 / 5 / 10 / RAPID) and HTTPS proxy support are preserved, so this is not a regression. Since the webhook SDK classes don't accept a retryConfig (unlike WebClient), retries run in the action via p-retry, reusing @slack/web-api's named retry policies. Non-retryable responses (4xx other than 429) abort immediately; request errors and 5xx/429 are retried.

src/config.js no longer owns an axios client or builds the webhook User-Agent — the SDKs set their own. The action still registers app metadata with @slack/web-api.

⚠️ Before merge

  • @slack/webhook is pinned to a local file:../node-slack-sdk/packages/webhook path for development. It MUST be swapped to a published version (one that exports WebhookTrigger) before this merges.

Notes

  • No @slack/web-api version bump in this PR; client.js (the API-method technique) is unchanged and still uses @slack/web-api@7 (axios transitively).
  • dist/ is rebuilt as part of release, not committed here.

Requirements

🤖 Generated with Claude Code

zimeg and others added 6 commits June 30, 2026 04:02
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>
Co-Authored-By: Claude <svc-devxp-claude@slack-corp.com>
Co-Authored-By: Claude <svc-devxp-claude@slack-corp.com>
@zimeg zimeg added enhancement New feature or request javascript Pull requests that update Javascript code semver:minor tests labels Jun 30, 2026
@changeset-bot

changeset-bot Bot commented Jun 30, 2026

Copy link
Copy Markdown

⚠️ No Changeset found

Latest commit: 7c83ef1

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

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

Retries now live in the @slack/webhook package via retryConfig, matching
how the API-method technique passes retryConfig to @slack/web-api. The
action maps its 0/5/10/RAPID input to the SDK's exported retry policies.

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

zimeg commented Jul 2, 2026

Copy link
Copy Markdown
Member Author

Retries now live upstream in @slack/webhook (node-slack-sdk branch eden/webhook-retries, off the WWFB eden/webhook-trigger WIP) rather than in the action.

  • Both IncomingWebhook and WebhookTrigger now accept a retryConfig?: RetryOptions option (mirroring @slack/web-api's WebClient), defaulting to no retries (opt-in).
  • The webhook package re-exports the same named policies (fiveRetriesInFiveMinutes, tenRetriesInAboutThirtyMinutes, rapidRetryPolicy).
  • Retry conditions match transient failures: 429 + 5xx retry, other 4xx abort, network errors retry.

This PR now just passes retryConfig through to the SDK constructors and maps 0/5/10/RAPID to the exported policies — no action-side p-retry wrapper. Pre-merge gate is unchanged: swap the file: link for a published @slack/webhook that includes these retry policies.

Co-Authored-By: Claude <svc-devxp-claude@slack-corp.com>
zimeg and others added 7 commits July 6, 2026 21:49
The action already registered its app metadata with @slack/web-api via
addAppMetadata, but webhook requests went out without the action's
identifier. @slack/webhook now exports the same addAppMetadata API, so
register the package name and version with it too using the shared
package.json values. Adds a test covering the webhook registration.

Co-Authored-By: Claude <svc-devxp-claude@slack-corp.com>
The SDK migration collapsed proxies() to pass any proxy URL straight to
HttpsProxyAgent, dropping the http:/https: protocol check that main had.
Restore the switch so an unsupported proxy protocol throws the same
'Unsupported URL protocol' error instead of leaking a raw agent failure.
Both http: and https: proxies map to a single HttpsProxyAgent; the old
axios-only 'proxy: false' branch is unneeded since @slack/webhook sets
proxy: false on its own axios instance.

Co-Authored-By: Claude <svc-devxp-claude@slack-corp.com>
Collapse postIncomingWebhook/postWebhookTrigger into a single post():
construct each client through the config.webhook module namespace, send,
and write outputs inline within the type switch, sharing the options and
one try/catch. Drops the direct IncomingWebhook/WebhookTrigger imports
and the redundant webhook URL type cast.

Co-Authored-By: Claude <svc-devxp-claude@slack-corp.com>
Co-Authored-By: Claude <svc-devxp-claude@slack-corp.com>
The SDK migration (074e58f) dropped two behaviors main had: the guard
that throws when no webhook is provided, and the skip that returns
undefined (no proxy) when the webhook destination is not HTTPS. Restore
both for parity — an HttpsProxyAgent only tunnels HTTPS destinations, so
a non-HTTPS webhook should bypass the proxy. Adds a test for the skip.

Co-Authored-By: Claude <svc-devxp-claude@slack-corp.com>
Restore the @see link to #132 alongside #205 so both PRs that shaped the
proxy behavior are documented on proxies().

Co-Authored-By: Claude <svc-devxp-claude@slack-corp.com>
Each case is the last action in post(), so return makes the intent
explicit and guards against fall-through if code is added later.

Co-Authored-By: Claude <svc-devxp-claude@slack-corp.com>
Restore the payload deep-equal (drinks: coffee / text: hi) and the
"response" output assertion in the webhook failure tests that were lost
in the axios to @slack/webhook migration.

Co-Authored-By: Claude <svc-devxp-claude@slack-corp.com>
Restore main's "textt: oops" input and { textt: "oops" } assertion so
the incoming failure test still exercises the malformed-payload case.

Co-Authored-By: Claude <svc-devxp-claude@slack-corp.com>
Move the non-HTTPS webhook skip test back to its position after the
missing-webhook case and restore its original name, matching main's
proxies ordering.

Co-Authored-By: Claude <svc-devxp-claude@slack-corp.com>
Place "sets up the proxy agent for the provided https proxy" ahead of
the returns-undefined case to match main's proxies ordering.

Co-Authored-By: Claude <svc-devxp-claude@slack-corp.com>
Add a test that an http proxy also yields an HttpsProxyAgent (beside the
https case) and one asserting post() throws for an unknown webhook type,
bringing src/webhook.js to full branch coverage.

Co-Authored-By: Claude <svc-devxp-claude@slack-corp.com>
Use a bare assert.fail() in the unknown webhook type test.

Co-Authored-By: Claude <svc-devxp-claude@slack-corp.com>
Bump to @slack/webhook 7.2.0-rc.2 and consume retry policies via the
new retryPolicies namespace (webhook.retryPolicies.<policy>), mirroring
the @slack/web-api client. Updates src/webhook.js and the retries tests.

Co-Authored-By: Claude <svc-devxp-claude@slack-corp.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request javascript Pull requests that update Javascript code semver:minor tests

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant