Skip to content

chore: provide proxied configurations in update to "@slack/web-api@v8" and "@slack/webhook@v8" packages#619

Draft
zimeg wants to merge 19 commits into
mainfrom
support-web-api-v8
Draft

chore: provide proxied configurations in update to "@slack/web-api@v8" and "@slack/webhook@v8" packages#619
zimeg wants to merge 19 commits into
mainfrom
support-web-api-v8

Conversation

@zimeg

@zimeg zimeg commented Jun 1, 2026

Copy link
Copy Markdown
Member

Summary

This pull request upgrades to the @slack/web-api and @slack/webhook v8 release candidates (slackapi/node-slack-sdk#2603), maintaining full proxy support by migrating from axios/https-proxy-agent to native fetch with the undici ProxyAgent.

Changes:

  • Send API method requests with the @slack/web-api v8 WebClient, using its fetch option instead of the removed agent option
  • Send webhook requests with the @slack/webhook v8 IncomingWebhook and WebhookTrigger clients, using their fetch option and retryConfig retry policies
  • Extract a shared, side-effect-free proxiedFetch factory (src/proxies.js) that returns a custom fetch backed by an undici ProxyAgent dispatcher — injected into both the API and webhook clients so proxying stays opt-in and testable without any global dispatcher state
  • Instrument both clients through the v8 addAppMetadata exports (rc.2 restores addAppMetadata, WebhookTrigger, and retryPolicies), so the SDK sets the User-Agent internally
  • Update API error handling to use the v8 Error subclasses (WebAPIPlatformError, WebAPIHTTPError, etc.)

Dependencies removed: axios, axios-retry, https-proxy-agent
Dependencies added: undici (for ProxyAgent)
Dependencies upgraded: @slack/web-api ^7 → ^8.0.0-rc.2, @slack/webhook ^7 → ^8.0.0-rc.2, @slack/logger ^4 → ^5.0.0-rc.1

The proxy input and HTTPS_PROXY environment variable continue to work unchanged for end users.

Requirements

Migrate from axios/https-proxy-agent to native fetch with undici
ProxyAgent, supporting the @slack/web-api v8 release candidate
(slackapi/node-slack-sdk#2603).

Breaking changes addressed:
- Replace `agent` option with `fetch` option for WebClient proxy support
- Replace axios with native fetch + undici ProxyAgent for webhook requests
- Replace axios-retry with built-in retry logic for webhook requests
- Update error handling to use v8 Error subclasses

Dependencies removed: axios, axios-retry, https-proxy-agent
Dependencies added: undici (for ProxyAgent)
Dependencies upgraded: @slack/web-api ^7 → ^8.0.0-rc.1, @slack/logger ^4 → ^5.0.0-rc.1

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

changeset-bot Bot commented Jun 1, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: e589900

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

This PR includes changesets to release 1 package
Name Type
@slack/slack-github-action Patch

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

Cast ProxyAgent to `any` to avoid type mismatch between undici's
Dispatcher and undici-types' Dispatcher in Node's fetch signature.
Initialize userAgent property to satisfy strict property checks.

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

codecov Bot commented Jun 1, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 99.86%. Comparing base (be88bdd) to head (e589900).
⚠️ Report is 4 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff             @@
##             main     #619      +/-   ##
==========================================
- Coverage   99.86%   99.86%   -0.01%     
==========================================
  Files           7        8       +1     
  Lines         730      725       -5     
==========================================
- Hits          729      724       -5     
  Misses          1        1              

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Tests must explicitly configure mocks.fetch for their specific
scenario rather than relying on a hidden default response.

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.

🪄 A comment about webhook implementations while we explore changes-

Comment thread src/webhook.js Outdated
Replace the manual fetch-with-retry implementation with IncomingWebhook
from @slack/webhook v8 RC. The SDK handles HTTP internally while we
inject a custom fetch wrapper for User-Agent and proxy support.

Note: @slack/webhook v8 does not export addAppMetadata, so there is no
public way to register custom app metadata in the SDK's User-Agent. We
supplement by prepending our action identity in the custom fetch wrapper.

Co-Authored-By: Claude <svc-devxp-claude@slack-corp.com>
Use @slack/webhook IncomingWebhook only for the incoming-webhook type.
Webhook triggers use a direct fetch since the SDK has no class for them
and the response shape differs (JSON vs plain text).

Co-Authored-By: Claude <svc-devxp-claude@slack-corp.com>
@zimeg zimeg self-assigned this Jul 13, 2026
@zimeg zimeg added the dependencies Pull requests that update a dependency file label Jul 13, 2026
# Conflicts:
#	package-lock.json
#	package.json
@zimeg zimeg changed the title feat: upgrade to @slack/web-api v8 with proxy support via undici chore: provide proxied configurations in update to "@slack/web-api@v8" and "@slack/webhook@v8" packages Jul 13, 2026

@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 💯 I'm a fan of how this is taking shape 🥇

Only true feedback I have is around the proxies.js file it really seems like it could be some sort of builder or factory pattern 🤔

Comment thread src/proxies.js
switch (new URL(proxy).protocol) {
case "https:":
case "http:":
return new ProxyAgent(proxy);

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.

I'm a fan of this dispatcher approach 💯

Comment thread src/proxies.js
return undefined;
}
return (url, init) => globalThis.fetch(url, { ...init, dispatcher });
}

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.

This function seems like it wants to be some sort of factory method pattern but it isn't because it returns undefined 🤔

What do you think about renaming and changing it to something like

export function buildFetch(config, destination) {
  const dispatcher = proxies(config, destination);
  if (!dispatcher) {
    return (url, init) => globalThis.fetch(url, { ...init });
  }
  return (url, init) => globalThis.fetch(url, { ...init, dispatcher });
}

We could also fully embrace the factory pattern and name this file FetchFactory or FetchBuilder but this might not align with the rest of the project 🤔

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.

@WilliamBergamin I poked into updating each case with a meaningful return but think keeping undefined is easiest in fallbacks to the SDK implementation for now!

These are curious patterns shared - and new to me - but for now I want to hold off on extending this part of the implementation 🎁

Comment thread src/client.js
* @returns {import("axios").AxiosRequestConfig | undefined}
* @see {@link https://github.com/slackapi/slack-github-action/pull/205}
*/
proxies(config) {

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.

Praise for drying things up 🙏

Replace the hand-written fetch signature with typeof globalThis.fetch so
the return type stays sourced from the lib types. The precise type surfaces
a ProxyAgent/Dispatcher mismatch from the duplicate undici type packages,
so cast the dispatcher field to keep proxying working.

Co-Authored-By: Claude <svc-devxp-claude@slack-corp.com>
@types/node pulls undici-types transitively at a version that trails the
undici we depend on directly, so their Dispatcher types are nominally
distinct and passing a ProxyAgent to globalThis.fetch failed to type check.
Override undici-types to the matching 7.28 line — its .d.ts is byte-identical
to the runtime undici's bundled types — so the dispatcher field type checks
without the any cast.

Co-Authored-By: Claude <svc-devxp-claude@slack-corp.com>
Bump the declared undici range to match the version already resolved in the
lockfile and the undici-types override, so the dependency range, the lockfile,
and the override all point at the same 7.28 line.

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

zimeg commented Jul 13, 2026

Copy link
Copy Markdown
Member Author

[DRAFT — do not submit yet] Why the undici-types override exists

@types/node pulls undici-types transitively at a version (7.18) that trails the undici we depend on directly (7.28). Their Dispatcher types are nominally distinct, so passing a ProxyAgent to globalThis.fetch failed to type check.

Ruled out the alternatives:

  • Downgrade @types/node — every version pins undici-types ≤7.18; older pins even lower. Can't reach 7.28.
  • Downgrade undici — would sacrifice runtime fixes to appease the type checker; also must be frozen forever.
  • Add undici-types as a devDep — npm can't reconcile ~7.18 (from @types/node) with ^7.28, so it installs two copies; fetch's types still resolve the nested 7.18. No effect.

overrides is the only mechanism that rewrites the transitive pin, forcing the nested undici-types to 7.28 — verified byte-identical to runtime undici@7.28's bundled types. Lets the dispatcher field type check without an any cast.

Maintenance note: the override is a literal ^7.28.0, not self-following. If a future undici major outpaces it the mismatch returns — but CI's npm run check fails loudly, so it can't regress silently.

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

dependencies Pull requests that update a dependency file

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants