diff --git a/.changeset/warn-failed-requests.md b/.changeset/warn-failed-requests.md new file mode 100644 index 00000000..81c80d0b --- /dev/null +++ b/.changeset/warn-failed-requests.md @@ -0,0 +1,5 @@ +--- +"@slack/slack-github-action": minor +--- + +feat: log a warning with the reason a request failed when the "errors" option is not true diff --git a/docs/additional-configurations.md b/docs/additional-configurations.md index 08045f4b..bf7a1fbd 100644 --- a/docs/additional-configurations.md +++ b/docs/additional-configurations.md @@ -6,7 +6,7 @@ There are some additional, possibly useful, customization options for workflows. Invalid API requests or unexpected webhook payloads cause a failing response that can be used to fail the GitHub Actions step with the `errors` option. -The `errors` option defaults to `false` so failed requests do not cause the step to fail. This result can still be gathered from the `ok` output. +The `errors` option defaults to `false` so failed requests log a warning but don't cause the step to fail. The step's result can still be gathered from the `ok` output. ```yaml - name: Attempt to call an unknown method diff --git a/src/send.js b/src/send.js index 4127ce65..9efc0803 100644 --- a/src/send.js +++ b/src/send.js @@ -19,6 +19,7 @@ export default async function send(core) { core.setFailed(error); throw new SlackError(core, error); } + core.warning(`Failed to send the request: ${error.message}`); } } diff --git a/test/send.spec.js b/test/send.spec.js index 157c3c96..c8d1b33f 100644 --- a/test/send.spec.js +++ b/test/send.spec.js @@ -1,5 +1,6 @@ import assert from "node:assert"; import { beforeEach, describe, it } from "node:test"; +import webapi from "@slack/web-api"; import send from "../src/send.js"; import { mocks } from "./index.spec.js"; @@ -75,4 +76,45 @@ describe("send", () => { assert.ok(mocks.core.setOutput.getCall(2).lastArg >= 0); }); }); + + describe("logging", async () => { + it("warns of the failed request when errors are not fatal", async () => { + mocks.core.getInput.withArgs("method").returns("chat.postMessage"); + mocks.core.getInput.withArgs("token").returns("xoxb-example"); + mocks.core.getInput.withArgs("payload").returns('"text": "hello"'); + mocks.calls.rejects( + new webapi.WebAPIPlatformError({ ok: false, error: "invalid_auth" }), + ); + await send(mocks.core); + assert.strictEqual(mocks.core.setFailed.called, false); + assert.equal(mocks.core.warning.getCalls().length, 1); + assert.match(mocks.core.warning.getCall(0).firstArg, /invalid_auth/); + }); + + it("warns of the failed webhook when errors are not fatal", async () => { + mocks.core.getInput + .withArgs("webhook") + .returns("https://hooks.slack.com"); + mocks.core.getInput.withArgs("webhook-type").returns("webhook-trigger"); + mocks.core.getInput.withArgs("payload").returns('"greetings": "hello"'); + mocks.webhook.trigger.rejects(new Error("invalid_payload")); + await send(mocks.core); + assert.strictEqual(mocks.core.setFailed.called, false); + assert.equal(mocks.core.warning.getCalls().length, 1); + assert.match(mocks.core.warning.getCall(0).firstArg, /invalid_payload/); + }); + + it("fails the step without warning when errors are fatal", async () => { + mocks.core.getBooleanInput.withArgs("errors").returns(true); + mocks.core.getInput.withArgs("method").returns("chat.postMessage"); + mocks.core.getInput.withArgs("token").returns("xoxb-example"); + mocks.core.getInput.withArgs("payload").returns('"text": "hello"'); + mocks.calls.rejects( + new webapi.WebAPIPlatformError({ ok: false, error: "invalid_auth" }), + ); + await assert.rejects(send(mocks.core)); + assert.ok(mocks.core.setFailed.called); + assert.strictEqual(mocks.core.warning.called, false); + }); + }); });