diff --git a/.changeset/proxy-fetch-undici-version-mismatch.md b/.changeset/proxy-fetch-undici-version-mismatch.md new file mode 100644 index 00000000..df5719ff --- /dev/null +++ b/.changeset/proxy-fetch-undici-version-mismatch.md @@ -0,0 +1,5 @@ +--- +"@slack/slack-github-action": patch +--- + +fix: proxy input always fails due to an undici version mismatch diff --git a/src/proxies.js b/src/proxies.js index d3b64e0e..5296dbbd 100644 --- a/src/proxies.js +++ b/src/proxies.js @@ -1,19 +1,22 @@ -import { ProxyAgent } from "undici"; +import { ProxyAgent, fetch as undiciFetch } from "undici"; import SlackError from "./errors.js"; /** * Return a fetch function that routes requests through a configured proxy. * + * Uses undici's own fetch, not the global fetch, since Node may bundle a + * different (incompatible) undici version for the latter. + * * @param {import("./config.js").default} config * @param {string?} [destination] - A provided request destination. - * @returns {typeof globalThis.fetch | undefined} + * @returns {typeof undiciFetch | undefined} */ export function fetch(config, destination) { const dispatcher = proxies(config, destination); if (!dispatcher) { return undefined; } - return (url, init) => globalThis.fetch(url, { ...init, dispatcher }); + return (url, init) => undiciFetch(url, { ...init, dispatcher }); } /** diff --git a/test/proxies.spec.js b/test/proxies.spec.js index f4ae9227..4d5c84bd 100644 --- a/test/proxies.spec.js +++ b/test/proxies.spec.js @@ -1,5 +1,6 @@ import assert from "node:assert"; import { beforeEach, describe, it } from "node:test"; +import { errors as undiciErrors } from "undici"; import Config from "../src/config.js"; import SlackError from "../src/errors.js"; import { fetch, proxies } from "../src/proxies.js"; @@ -20,6 +21,24 @@ describe("proxies", () => { assert.strictEqual(typeof fetchFn, "function"); }); + it("dispatches requests through the proxy without a request handler mismatch", async () => { + mocks.core.getInput.withArgs("method").returns("chat.postMessage"); + mocks.core.getInput.withArgs("token").returns("xoxb-example"); + mocks.core.getInput.withArgs("proxy").returns("http://127.0.0.1:1"); + const config = new Config(mocks.core); + const fetchFn = fetch(config); + await assert.rejects( + // ".invalid" is reserved by RFC 2606 to never resolve. + fetchFn("https://slack-github-action.invalid/api/chat.postMessage", { + method: "POST", + }), + (err) => { + assert.ok(!(err.cause instanceof undiciErrors.InvalidArgumentError)); + return true; + }, + ); + }); + it("returns undefined when no proxy is configured", async () => { mocks.core.getInput.withArgs("method").returns("chat.postMessage"); mocks.core.getInput.withArgs("token").returns("xoxb-example");