diff --git a/.github/workflows/0-codeql-analysis.yml b/.github/workflows/0-codeql-analysis.yml index 8fd84f6..0e137eb 100644 --- a/.github/workflows/0-codeql-analysis.yml +++ b/.github/workflows/0-codeql-analysis.yml @@ -22,6 +22,7 @@ on: jobs: analyze: + #if: ${{ false }} name: Analyze runs-on: ubuntu-latest permissions: diff --git a/.github/workflows/1-slack-notification-with-optional-parameters.yml b/.github/workflows/1-slack-notification-with-optional-parameters.yml index b56d237..c7e2804 100644 --- a/.github/workflows/1-slack-notification-with-optional-parameters.yml +++ b/.github/workflows/1-slack-notification-with-optional-parameters.yml @@ -4,6 +4,7 @@ on: [push] jobs: slack-action: + #if: ${{ false }} runs-on: ubuntu-20.04 name: Test 1 [ubuntu-20.04] diff --git a/.github/workflows/10-slack-fake-build-updates.yml b/.github/workflows/10-slack-fake-build-updates.yml index 65d87a6..a8c4781 100644 --- a/.github/workflows/10-slack-fake-build-updates.yml +++ b/.github/workflows/10-slack-fake-build-updates.yml @@ -4,6 +4,7 @@ on: [push] jobs: slack-action: + #if: ${{ false }} runs-on: ubuntu-20.04 name: Test 10 [ubuntu-20.04] @@ -36,5 +37,5 @@ jobs: slack-function: update-message slack-bot-user-oauth-access-token: ${{ secrets.SLACK_BOT_USER_OAUTH_ACCESS_TOKEN }} slack-channel: C036UR31LTD - slack-update-message-text: "${{ format('{0}\n\n```{1}```', ':no_entry_sign: Build status: Failed!', steps.fake-build-process.outputs.BUILD_RESULT) }}" slack-update-message-ts: ${{ fromJson(steps.slack-build-started.outputs.slack-result).response.message.ts }} + slack-update-message-text: "${{ format('{0}\n\n```{1}```', ':no_entry_sign: Build status: Failed!', steps.fake-build-process.outputs.BUILD_RESULT) }}" diff --git a/.github/workflows/11-slack-message-blocks.yml b/.github/workflows/11-slack-message-blocks.yml new file mode 100644 index 0000000..69f8ec0 --- /dev/null +++ b/.github/workflows/11-slack-message-blocks.yml @@ -0,0 +1,52 @@ +name: test-11-slack-message-blocks + +on: [push, issues] + +jobs: + slack-action: + #if: ${{ false }} + runs-on: ubuntu-20.04 + name: Test 11 [ubuntu-20.04] + + steps: + - name: Send Slack Message (Blocks) + uses: archive/github-actions-slack@update_message_with_blocks + id: send-message + with: + slack-bot-user-oauth-access-token: ${{ secrets.SLACK_BOT_USER_OAUTH_ACCESS_TOKEN }} + slack-channel: C046J5U2RGC + slack-blocks: >- + [ + { + "block_id": "text1", + "type": "section", + "text": { + "type": "mrkdwn", + "text": "Building repo *product-service*" + } + }, + { + "type": "divider" + }, + { + "block_id": "text2", + "type": "context", + "elements": [ + { + "type": "image", + "image_url": "https://upload.wikimedia.org/wikipedia/en/thumb/4/4c/Flag_of_Sweden.svg/1200px-Flag_of_Sweden.svg.png", + "alt_text": "images" + }, + { + "type": "plain_text", + "text": "Estimated time: 1 min" + } + ] + }, + { + "type": "divider" + } + ] + + - name: Result from "Send Slack Message" + run: echo '${{ steps.send-message.outputs.slack-result }}' diff --git a/.github/workflows/12-slack-message-blocks-update.yml b/.github/workflows/12-slack-message-blocks-update.yml new file mode 100644 index 0000000..cfd000a --- /dev/null +++ b/.github/workflows/12-slack-message-blocks-update.yml @@ -0,0 +1,51 @@ +name: test-12-slack-message-blocks-update + +on: [push, issues] + +jobs: + slack-action: + #if: ${{ false }} + runs-on: ubuntu-20.04 + name: Test 12 [ubuntu-20.04] + + steps: + - name: Send Slack Message (Blocks) + uses: archive/github-actions-slack@update_message_with_blocks + id: send-message + with: + slack-bot-user-oauth-access-token: ${{ secrets.SLACK_BOT_USER_OAUTH_ACCESS_TOKEN }} + slack-channel: C046FKM3TNF + slack-blocks: >- + [ + { + "block_id": "text1", + "type": "section", + "text": { + "type": "mrkdwn", + "text": "Building... *please wait*" + } + } + ] + + - name: Result from "Send Slack Message" + run: echo '${{ steps.send-message.outputs.slack-result }}' + + - name: Send Slack Message (Blocks) - Update + uses: archive/github-actions-slack@update_message_with_blocks + id: send-message-update + with: + slack-function: update-message + slack-bot-user-oauth-access-token: ${{ secrets.SLACK_BOT_USER_OAUTH_ACCESS_TOKEN }} + slack-channel: C046FKM3TNF + slack-update-message-ts: ${{ fromJson(steps.send-message.outputs.slack-result).response.message.ts }} + slack-update-message-blocks: >- + [ + { + "block_id": "text1", + "type": "section", + "text": { + "type": "mrkdwn", + "text": "Building... *done!*" + } + } + ] diff --git a/.github/workflows/2-slack-notification.yml b/.github/workflows/2-slack-notification.yml index c820f79..fbbdf17 100644 --- a/.github/workflows/2-slack-notification.yml +++ b/.github/workflows/2-slack-notification.yml @@ -4,6 +4,7 @@ on: [push] jobs: slack-action: + #if: ${{ false }} runs-on: windows-latest name: Test 2 [windows-latest] diff --git a/.github/workflows/3-slack-reaction.yml b/.github/workflows/3-slack-reaction.yml index e03d85d..9d2e99e 100644 --- a/.github/workflows/3-slack-reaction.yml +++ b/.github/workflows/3-slack-reaction.yml @@ -4,6 +4,7 @@ on: [push] jobs: slack-action: + #if: ${{ false }} runs-on: ubuntu-latest name: Test 3 [ubuntu-latest] diff --git a/.github/workflows/4-slack-thread.yml b/.github/workflows/4-slack-thread.yml index 6b99dc3..b390aa2 100644 --- a/.github/workflows/4-slack-thread.yml +++ b/.github/workflows/4-slack-thread.yml @@ -4,6 +4,7 @@ on: [push] jobs: slack-action: + #if: ${{ false }} runs-on: macos-latest name: Test 4 [macos-latest] diff --git a/.github/workflows/5-slack-update-message.yml b/.github/workflows/5-slack-update-message.yml index dbc0145..06660ad 100644 --- a/.github/workflows/5-slack-update-message.yml +++ b/.github/workflows/5-slack-update-message.yml @@ -4,6 +4,7 @@ on: [push] jobs: slack-action: + #if: ${{ false }} runs-on: ubuntu-20.04 name: Test 5 [ubuntu-20.04] @@ -30,8 +31,8 @@ jobs: slack-function: update-message slack-bot-user-oauth-access-token: ${{ secrets.SLACK_BOT_USER_OAUTH_ACCESS_TOKEN }} slack-channel: ${{ fromJson(steps.send-message.outputs.slack-result).response.channel }} - slack-update-message-text: Test 5.1 - Message to update - updated slack-update-message-ts: ${{ fromJson(steps.send-message.outputs.slack-result).response.message.ts }} + slack-update-message-text: Test 5.1 - Message to update - updated - name: Send Slack Reaction To Message Result run: echo 'Data - ${{ steps.send-message.outputs.slack-result }}' diff --git a/.github/workflows/6-slack-thread-with-broadcast.yml b/.github/workflows/6-slack-thread-with-broadcast.yml index 2f1ff43..59963c8 100644 --- a/.github/workflows/6-slack-thread-with-broadcast.yml +++ b/.github/workflows/6-slack-thread-with-broadcast.yml @@ -4,6 +4,7 @@ on: [push] jobs: slack-action: + #if: ${{ false }} runs-on: ubuntu-20.04 name: Test 6 [ubuntu-20.04] diff --git a/.github/workflows/7-slack-notification-multi-channel.yml b/.github/workflows/7-slack-notification-multi-channel.yml index 648226f..f466ef0 100644 --- a/.github/workflows/7-slack-notification-multi-channel.yml +++ b/.github/workflows/7-slack-notification-multi-channel.yml @@ -4,6 +4,7 @@ on: [push] jobs: slack-action: + #if: ${{ false }} runs-on: windows-2019 name: Test 7 [windows-2019] diff --git a/.github/workflows/8-slack-notification-line-breaks.yml b/.github/workflows/8-slack-notification-line-breaks.yml index 2ac3e7d..d086c08 100644 --- a/.github/workflows/8-slack-notification-line-breaks.yml +++ b/.github/workflows/8-slack-notification-line-breaks.yml @@ -4,6 +4,7 @@ on: [push] jobs: slack-action: + #if: ${{ false }} runs-on: windows-latest name: Test 8 [windows-latest] diff --git a/.github/workflows/9-slack-update-message-line-breaks.yml b/.github/workflows/9-slack-update-message-line-breaks.yml index 30bfa3c..94816f8 100644 --- a/.github/workflows/9-slack-update-message-line-breaks.yml +++ b/.github/workflows/9-slack-update-message-line-breaks.yml @@ -4,6 +4,7 @@ on: [push] jobs: slack-action: + #if: ${{ false }} runs-on: ubuntu-latest name: Test 9 [ubuntu-latest] @@ -27,13 +28,13 @@ jobs: slack-function: update-message slack-bot-user-oauth-access-token: ${{ secrets.SLACK_BOT_USER_OAUTH_ACCESS_TOKEN }} slack-channel: ${{ fromJson(steps.send-message-1.outputs.slack-result).response.channel }} + slack-update-message-ts: ${{ fromJson(steps.send-message-1.outputs.slack-result).response.message.ts }} slack-update-message-text: | Test 9.1 - 1/2 Message to update Updated! - slack-update-message-ts: ${{ fromJson(steps.send-message-1.outputs.slack-result).response.message.ts }} - name: Send Slack Reaction To Message Result run: echo 'Data - ${{ steps.send-message-1.outputs.slack-result }}' @@ -62,8 +63,8 @@ jobs: slack-function: update-message slack-bot-user-oauth-access-token: ${{ secrets.SLACK_BOT_USER_OAUTH_ACCESS_TOKEN }} slack-channel: ${{ fromJson(steps.send-message-2.outputs.slack-result).response.channel }} - slack-update-message-text: "${{ format('{0}\n\n{1}', 'Test 9.1 - 2/2', toJson(runner)) }}" slack-update-message-ts: ${{ fromJson(steps.send-message-2.outputs.slack-result).response.message.ts }} + slack-update-message-text: "${{ format('{0}\n\n{1}', 'Test 9.1 - 2/2', toJson(runner)) }}" - name: Send Slack Reaction To Message Result run: echo 'Data - ${{ steps.send-message-2.outputs.slack-result }}' diff --git a/README.md b/README.md index 12baf23..1eb67a4 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# Github Action for sending message (and reactions/threads/update) to Slack +# Github Action for sending message (and reactions/threads/update/blocks) to Slack — With support for Slack's optional arguments @@ -7,7 +7,7 @@ ![](https://api.codiga.io/project/30889/status/svg) ![](https://api.codiga.io/project/30889/score/svg) -This Action allows you to send messages (and reactions/threads/update) to Slack from your Github Actions. Supports Slack's required arguments as well as all the optional once. It's JavaScript-based and thus fast to run. +This Action allows you to send messages (and reactions/threads/update/blocks) to Slack from your Github Actions. Supports Slack's required arguments as well as all the optional once. It's JavaScript-based and thus fast to run. ![Slack result](./images/slack-result.png "Slack result") @@ -49,7 +49,7 @@ This action supports: - `slack-channel` - The channel/channels where you want the message (comma separated) -- `slack-text` - The text of the message +- `slack-text` - The text of the message (or use `slack-blocks`) **Optional: Github Action Parameters:** @@ -291,6 +291,15 @@ Similar to Add Reaction, but with text instead. Please see [.github/workflows/5-slack-update-message.yml](.github/workflows/5-slack-update-message.yml) +## 5. Using blocks + +With blocks you can create more rich and complex messages / message layouts: https://api.slack.com/messaging/composing/layouts + +For some examples, please see: + +- [.github/workflows/11-slack-message-blocks.yml](.github/workflows/11-slack-message-blocks.yml) +- [.github/workflows/12-slack-message-blocks-update.yml](.github/workflows/12-slack-message-blocks-update.yml) + ## How to setup your first Github Action in your repository that will call this Action ### 1. Create a Slack bot diff --git a/action.yml b/action.yml index e75d9b1..0123a87 100644 --- a/action.yml +++ b/action.yml @@ -12,7 +12,10 @@ inputs: required: true slack-text: description: "Text" - required: true + required: false + slack-blocks: + description: "Blocks" + required: false slack-optional-as_user: description: "https://api.slack.com/methods/chat.postMessage#arg_as_user" required: false @@ -67,6 +70,9 @@ inputs: slack-update-message-text: description: https://api.slack.com/methods/chat.update#text required: false + slack-update-message-blocks: + description: https://api.slack.com/methods/chat.update#blocks + required: false outputs: slack-result: diff --git a/dist/index.js b/dist/index.js index d287c65..2fe877a 100644 --- a/dist/index.js +++ b/dist/index.js @@ -1,7 +1,7 @@ /******/ (() => { // webpackBootstrap /******/ var __webpack_modules__ = ({ -/***/ 351: +/***/ 7351: /***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { "use strict"; @@ -27,8 +27,8 @@ var __importStar = (this && this.__importStar) || function (mod) { }; Object.defineProperty(exports, "__esModule", ({ value: true })); exports.issue = exports.issueCommand = void 0; -const os = __importStar(__nccwpck_require__(37)); -const utils_1 = __nccwpck_require__(278); +const os = __importStar(__nccwpck_require__(2037)); +const utils_1 = __nccwpck_require__(5278); /** * Commands * @@ -100,7 +100,7 @@ function escapeProperty(s) { /***/ }), -/***/ 186: +/***/ 2186: /***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { "use strict"; @@ -135,12 +135,12 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge }; Object.defineProperty(exports, "__esModule", ({ value: true })); exports.getIDToken = exports.getState = exports.saveState = exports.group = exports.endGroup = exports.startGroup = exports.info = exports.notice = exports.warning = exports.error = exports.debug = exports.isDebug = exports.setFailed = exports.setCommandEcho = exports.setOutput = exports.getBooleanInput = exports.getMultilineInput = exports.getInput = exports.addPath = exports.setSecret = exports.exportVariable = exports.ExitCode = void 0; -const command_1 = __nccwpck_require__(351); +const command_1 = __nccwpck_require__(7351); const file_command_1 = __nccwpck_require__(717); -const utils_1 = __nccwpck_require__(278); -const os = __importStar(__nccwpck_require__(37)); -const path = __importStar(__nccwpck_require__(17)); -const oidc_utils_1 = __nccwpck_require__(41); +const utils_1 = __nccwpck_require__(5278); +const os = __importStar(__nccwpck_require__(2037)); +const path = __importStar(__nccwpck_require__(1017)); +const oidc_utils_1 = __nccwpck_require__(8041); /** * The code to exit an action */ @@ -425,17 +425,17 @@ exports.getIDToken = getIDToken; /** * Summary exports */ -var summary_1 = __nccwpck_require__(327); +var summary_1 = __nccwpck_require__(1327); Object.defineProperty(exports, "summary", ({ enumerable: true, get: function () { return summary_1.summary; } })); /** * @deprecated use core.summary */ -var summary_2 = __nccwpck_require__(327); +var summary_2 = __nccwpck_require__(1327); Object.defineProperty(exports, "markdownSummary", ({ enumerable: true, get: function () { return summary_2.markdownSummary; } })); /** * Path exports */ -var path_utils_1 = __nccwpck_require__(981); +var path_utils_1 = __nccwpck_require__(2981); Object.defineProperty(exports, "toPosixPath", ({ enumerable: true, get: function () { return path_utils_1.toPosixPath; } })); Object.defineProperty(exports, "toWin32Path", ({ enumerable: true, get: function () { return path_utils_1.toWin32Path; } })); Object.defineProperty(exports, "toPlatformPath", ({ enumerable: true, get: function () { return path_utils_1.toPlatformPath; } })); @@ -472,10 +472,10 @@ Object.defineProperty(exports, "__esModule", ({ value: true })); exports.prepareKeyValueMessage = exports.issueFileCommand = void 0; // We use any as a valid input type /* eslint-disable @typescript-eslint/no-explicit-any */ -const fs = __importStar(__nccwpck_require__(147)); -const os = __importStar(__nccwpck_require__(37)); -const uuid_1 = __nccwpck_require__(840); -const utils_1 = __nccwpck_require__(278); +const fs = __importStar(__nccwpck_require__(7147)); +const os = __importStar(__nccwpck_require__(2037)); +const uuid_1 = __nccwpck_require__(5840); +const utils_1 = __nccwpck_require__(5278); function issueFileCommand(command, message) { const filePath = process.env[`GITHUB_${command}`]; if (!filePath) { @@ -508,7 +508,7 @@ exports.prepareKeyValueMessage = prepareKeyValueMessage; /***/ }), -/***/ 41: +/***/ 8041: /***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { "use strict"; @@ -524,9 +524,9 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge }; Object.defineProperty(exports, "__esModule", ({ value: true })); exports.OidcClient = void 0; -const http_client_1 = __nccwpck_require__(255); -const auth_1 = __nccwpck_require__(526); -const core_1 = __nccwpck_require__(186); +const http_client_1 = __nccwpck_require__(6255); +const auth_1 = __nccwpck_require__(5526); +const core_1 = __nccwpck_require__(2186); class OidcClient { static createHttpClient(allowRetry = true, maxRetry = 10) { const requestOptions = { @@ -592,7 +592,7 @@ exports.OidcClient = OidcClient; /***/ }), -/***/ 981: +/***/ 2981: /***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { "use strict"; @@ -618,7 +618,7 @@ var __importStar = (this && this.__importStar) || function (mod) { }; Object.defineProperty(exports, "__esModule", ({ value: true })); exports.toPlatformPath = exports.toWin32Path = exports.toPosixPath = void 0; -const path = __importStar(__nccwpck_require__(17)); +const path = __importStar(__nccwpck_require__(1017)); /** * toPosixPath converts the given path to the posix form. On Windows, \\ will be * replaced with /. @@ -657,7 +657,7 @@ exports.toPlatformPath = toPlatformPath; /***/ }), -/***/ 327: +/***/ 1327: /***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { "use strict"; @@ -673,8 +673,8 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge }; Object.defineProperty(exports, "__esModule", ({ value: true })); exports.summary = exports.markdownSummary = exports.SUMMARY_DOCS_URL = exports.SUMMARY_ENV_VAR = void 0; -const os_1 = __nccwpck_require__(37); -const fs_1 = __nccwpck_require__(147); +const os_1 = __nccwpck_require__(2037); +const fs_1 = __nccwpck_require__(7147); const { access, appendFile, writeFile } = fs_1.promises; exports.SUMMARY_ENV_VAR = 'GITHUB_STEP_SUMMARY'; exports.SUMMARY_DOCS_URL = 'https://docs.github.com/actions/using-workflows/workflow-commands-for-github-actions#adding-a-job-summary'; @@ -947,7 +947,7 @@ exports.summary = _summary; /***/ }), -/***/ 278: +/***/ 5278: /***/ ((__unused_webpack_module, exports) => { "use strict"; @@ -994,7 +994,7 @@ exports.toCommandProperties = toCommandProperties; /***/ }), -/***/ 526: +/***/ 5526: /***/ (function(__unused_webpack_module, exports) { "use strict"; @@ -1082,7 +1082,7 @@ exports.PersonalAccessTokenCredentialHandler = PersonalAccessTokenCredentialHand /***/ }), -/***/ 255: +/***/ 6255: /***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { "use strict"; @@ -1118,10 +1118,10 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge }; Object.defineProperty(exports, "__esModule", ({ value: true })); exports.HttpClient = exports.isHttps = exports.HttpClientResponse = exports.HttpClientError = exports.getProxyUrl = exports.MediaTypes = exports.Headers = exports.HttpCodes = void 0; -const http = __importStar(__nccwpck_require__(685)); -const https = __importStar(__nccwpck_require__(687)); -const pm = __importStar(__nccwpck_require__(835)); -const tunnel = __importStar(__nccwpck_require__(294)); +const http = __importStar(__nccwpck_require__(3685)); +const https = __importStar(__nccwpck_require__(5687)); +const pm = __importStar(__nccwpck_require__(9835)); +const tunnel = __importStar(__nccwpck_require__(4294)); var HttpCodes; (function (HttpCodes) { HttpCodes[HttpCodes["OK"] = 200] = "OK"; @@ -1694,7 +1694,7 @@ const lowercaseKeys = (obj) => Object.keys(obj).reduce((c, k) => ((c[k.toLowerCa /***/ }), -/***/ 835: +/***/ 9835: /***/ ((__unused_webpack_module, exports) => { "use strict"; @@ -1762,27 +1762,27 @@ exports.checkBypass = checkBypass; /***/ }), -/***/ 294: +/***/ 4294: /***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { -module.exports = __nccwpck_require__(219); +module.exports = __nccwpck_require__(4219); /***/ }), -/***/ 219: +/***/ 4219: /***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { "use strict"; -var net = __nccwpck_require__(808); -var tls = __nccwpck_require__(404); -var http = __nccwpck_require__(685); -var https = __nccwpck_require__(687); -var events = __nccwpck_require__(361); -var assert = __nccwpck_require__(491); -var util = __nccwpck_require__(837); +var net = __nccwpck_require__(1808); +var tls = __nccwpck_require__(4404); +var http = __nccwpck_require__(3685); +var https = __nccwpck_require__(5687); +var events = __nccwpck_require__(2361); +var assert = __nccwpck_require__(9491); +var util = __nccwpck_require__(3837); exports.httpOverHttp = httpOverHttp; @@ -2042,7 +2042,7 @@ exports.debug = debug; // for test /***/ }), -/***/ 840: +/***/ 5840: /***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { "use strict"; @@ -2106,29 +2106,29 @@ Object.defineProperty(exports, "parse", ({ } })); -var _v = _interopRequireDefault(__nccwpck_require__(628)); +var _v = _interopRequireDefault(__nccwpck_require__(8628)); -var _v2 = _interopRequireDefault(__nccwpck_require__(409)); +var _v2 = _interopRequireDefault(__nccwpck_require__(6409)); -var _v3 = _interopRequireDefault(__nccwpck_require__(122)); +var _v3 = _interopRequireDefault(__nccwpck_require__(5122)); -var _v4 = _interopRequireDefault(__nccwpck_require__(120)); +var _v4 = _interopRequireDefault(__nccwpck_require__(9120)); -var _nil = _interopRequireDefault(__nccwpck_require__(332)); +var _nil = _interopRequireDefault(__nccwpck_require__(5332)); -var _version = _interopRequireDefault(__nccwpck_require__(595)); +var _version = _interopRequireDefault(__nccwpck_require__(1595)); -var _validate = _interopRequireDefault(__nccwpck_require__(900)); +var _validate = _interopRequireDefault(__nccwpck_require__(6900)); -var _stringify = _interopRequireDefault(__nccwpck_require__(950)); +var _stringify = _interopRequireDefault(__nccwpck_require__(8950)); -var _parse = _interopRequireDefault(__nccwpck_require__(746)); +var _parse = _interopRequireDefault(__nccwpck_require__(2746)); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } /***/ }), -/***/ 569: +/***/ 4569: /***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { "use strict"; @@ -2139,7 +2139,7 @@ Object.defineProperty(exports, "__esModule", ({ })); exports["default"] = void 0; -var _crypto = _interopRequireDefault(__nccwpck_require__(113)); +var _crypto = _interopRequireDefault(__nccwpck_require__(6113)); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } @@ -2158,7 +2158,7 @@ exports["default"] = _default; /***/ }), -/***/ 332: +/***/ 5332: /***/ ((__unused_webpack_module, exports) => { "use strict"; @@ -2173,7 +2173,7 @@ exports["default"] = _default; /***/ }), -/***/ 746: +/***/ 2746: /***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { "use strict"; @@ -2184,7 +2184,7 @@ Object.defineProperty(exports, "__esModule", ({ })); exports["default"] = void 0; -var _validate = _interopRequireDefault(__nccwpck_require__(900)); +var _validate = _interopRequireDefault(__nccwpck_require__(6900)); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } @@ -2251,7 +2251,7 @@ Object.defineProperty(exports, "__esModule", ({ })); exports["default"] = rng; -var _crypto = _interopRequireDefault(__nccwpck_require__(113)); +var _crypto = _interopRequireDefault(__nccwpck_require__(6113)); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } @@ -2271,7 +2271,7 @@ function rng() { /***/ }), -/***/ 274: +/***/ 5274: /***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { "use strict"; @@ -2282,7 +2282,7 @@ Object.defineProperty(exports, "__esModule", ({ })); exports["default"] = void 0; -var _crypto = _interopRequireDefault(__nccwpck_require__(113)); +var _crypto = _interopRequireDefault(__nccwpck_require__(6113)); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } @@ -2301,7 +2301,7 @@ exports["default"] = _default; /***/ }), -/***/ 950: +/***/ 8950: /***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { "use strict"; @@ -2312,7 +2312,7 @@ Object.defineProperty(exports, "__esModule", ({ })); exports["default"] = void 0; -var _validate = _interopRequireDefault(__nccwpck_require__(900)); +var _validate = _interopRequireDefault(__nccwpck_require__(6900)); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } @@ -2347,7 +2347,7 @@ exports["default"] = _default; /***/ }), -/***/ 628: +/***/ 8628: /***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { "use strict"; @@ -2360,7 +2360,7 @@ exports["default"] = void 0; var _rng = _interopRequireDefault(__nccwpck_require__(807)); -var _stringify = _interopRequireDefault(__nccwpck_require__(950)); +var _stringify = _interopRequireDefault(__nccwpck_require__(8950)); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } @@ -2461,7 +2461,7 @@ exports["default"] = _default; /***/ }), -/***/ 409: +/***/ 6409: /***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { "use strict"; @@ -2472,9 +2472,9 @@ Object.defineProperty(exports, "__esModule", ({ })); exports["default"] = void 0; -var _v = _interopRequireDefault(__nccwpck_require__(998)); +var _v = _interopRequireDefault(__nccwpck_require__(5998)); -var _md = _interopRequireDefault(__nccwpck_require__(569)); +var _md = _interopRequireDefault(__nccwpck_require__(4569)); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } @@ -2484,7 +2484,7 @@ exports["default"] = _default; /***/ }), -/***/ 998: +/***/ 5998: /***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { "use strict"; @@ -2496,9 +2496,9 @@ Object.defineProperty(exports, "__esModule", ({ exports["default"] = _default; exports.URL = exports.DNS = void 0; -var _stringify = _interopRequireDefault(__nccwpck_require__(950)); +var _stringify = _interopRequireDefault(__nccwpck_require__(8950)); -var _parse = _interopRequireDefault(__nccwpck_require__(746)); +var _parse = _interopRequireDefault(__nccwpck_require__(2746)); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } @@ -2569,7 +2569,7 @@ function _default(name, version, hashfunc) { /***/ }), -/***/ 122: +/***/ 5122: /***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { "use strict"; @@ -2582,7 +2582,7 @@ exports["default"] = void 0; var _rng = _interopRequireDefault(__nccwpck_require__(807)); -var _stringify = _interopRequireDefault(__nccwpck_require__(950)); +var _stringify = _interopRequireDefault(__nccwpck_require__(8950)); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } @@ -2613,7 +2613,7 @@ exports["default"] = _default; /***/ }), -/***/ 120: +/***/ 9120: /***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { "use strict"; @@ -2624,9 +2624,9 @@ Object.defineProperty(exports, "__esModule", ({ })); exports["default"] = void 0; -var _v = _interopRequireDefault(__nccwpck_require__(998)); +var _v = _interopRequireDefault(__nccwpck_require__(5998)); -var _sha = _interopRequireDefault(__nccwpck_require__(274)); +var _sha = _interopRequireDefault(__nccwpck_require__(5274)); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } @@ -2636,7 +2636,7 @@ exports["default"] = _default; /***/ }), -/***/ 900: +/***/ 6900: /***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { "use strict"; @@ -2660,7 +2660,7 @@ exports["default"] = _default; /***/ }), -/***/ 595: +/***/ 1595: /***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { "use strict"; @@ -2671,7 +2671,7 @@ Object.defineProperty(exports, "__esModule", ({ })); exports["default"] = void 0; -var _validate = _interopRequireDefault(__nccwpck_require__(900)); +var _validate = _interopRequireDefault(__nccwpck_require__(6900)); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } @@ -2688,10 +2688,10 @@ exports["default"] = _default; /***/ }), -/***/ 319: +/***/ 1319: /***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { -const core = __nccwpck_require__(186); +const core = __nccwpck_require__(2186); const getRequired = (name) => core.getInput(name, { required: true }); @@ -2731,10 +2731,10 @@ module.exports = { /***/ }), -/***/ 202: +/***/ 8451: /***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { -const https = __nccwpck_require__(687); +const https = __nccwpck_require__(5687); const getOptions = (token, path) => { return { @@ -2766,10 +2766,22 @@ const post = (token, path, message) => { const result = Buffer.concat(chunks).toString(); const response = JSON.parse(result); + let isOk = res.statusCode >= 200 && res.statusCode <= 299; + + // This solves the issue that block updates returns 200 + // but contains ok = false in the response + if ( + response && + response.hasOwnProperty("ok") && + response.ok === false + ) { + isOk = false; + } + resolve({ statusCode: res.statusCode, statusMessage: res.statusMessage, - ok: res.statusCode >= 200 && res.statusCode <= 299, + ok: isOk, result: result, response: response, }); @@ -2785,37 +2797,53 @@ const post = (token, path, message) => { }); }; +module.exports = { post }; + + +/***/ }), + +/***/ 7202: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +const { post } = __nccwpck_require__(8451); + +const hasErrors = (res) => !res || !res.ok; + +const buildErrorMessage = (res) => { + return `Error! ${JSON.stringify(res)} (response)`; +}; + const apiPostMessage = async (token, message) => { const path = "/api/chat.postMessage"; - const result = await post(token, path, message); + const res = await post(token, path, message); - if (!result || !result.ok) { - throw `Error! ${JSON.stringify(response)}`; + if (hasErrors(res)) { + throw buildErrorMessage(res); } - return result; + return res; }; const apiAddReaction = async (token, message) => { const path = "/api/reactions.add"; - const result = await post(token, path, message); + const res = await post(token, path, message); - if (!result || !result.ok) { - throw `Error! ${JSON.stringify(response)}`; + if (hasErrors(res)) { + throw buildErrorMessage(res); } - return result; + return res; }; const apiUpdateMessage = async (token, message) => { const path = "/api/chat.update"; - const result = await post(token, path, message); + const res = await post(token, path, message); - if (!result || !result.ok) { - throw `Error! ${JSON.stringify(response)}`; + if (hasErrors(res)) { + throw buildErrorMessage(res); } - return result; + return res; }; module.exports = { apiPostMessage, apiAddReaction, apiUpdateMessage }; @@ -2823,13 +2851,13 @@ module.exports = { apiPostMessage, apiAddReaction, apiUpdateMessage }; /***/ }), -/***/ 662: +/***/ 4662: /***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { -const context = __nccwpck_require__(319); -const { postMessage } = __nccwpck_require__(563); -const { addReaction } = __nccwpck_require__(380); -const { updateMessage } = __nccwpck_require__(308); +const context = __nccwpck_require__(1319); +const { postMessage } = __nccwpck_require__(1563); +const { addReaction } = __nccwpck_require__(4380); +const { updateMessage } = __nccwpck_require__(3308); const jsonPretty = (data) => JSON.stringify(data, undefined, 2); @@ -2861,22 +2889,33 @@ module.exports = invoke; /***/ }), -/***/ 690: +/***/ 3690: /***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { const { restoreEscapedNewLine, restoreEscapedTab, -} = __nccwpck_require__(307); +} = __nccwpck_require__(5017); + +const buildMessage = (channel = "", text = "", blocks = "", optional = {}) => { + if (!channel) { + throw new Error("Channel must be set"); + } + + if (text && blocks) { + throw new Error("Text OR Block must be set"); + } -const buildMessage = (channel = "", text = "", optional = {}) => { const message = { channel, text, + blocks, }; - message.text = restoreEscapedNewLine(message.text); - message.text = restoreEscapedTab(message.text); + if (message.text) { + message.text = restoreEscapedNewLine(message.text); + message.text = restoreEscapedTab(message.text); + } Object.keys(optional).forEach((name) => { message[name] = optional[name]; @@ -2890,13 +2929,14 @@ module.exports = buildMessage; /***/ }), -/***/ 563: +/***/ 1563: /***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { -const context = __nccwpck_require__(319); -const { apiPostMessage } = __nccwpck_require__(202); -const buildMessage = __nccwpck_require__(690); -const core = __nccwpck_require__(186); +const context = __nccwpck_require__(1319); +const { apiPostMessage } = __nccwpck_require__(7202); +const buildMessage = __nccwpck_require__(3690); +const core = __nccwpck_require__(2186); +const { optional } = __nccwpck_require__(8300); const jsonPretty = (data) => JSON.stringify(data, undefined, 2); @@ -2904,13 +2944,14 @@ const postMessage = async () => { try { const token = context.getRequired("slack-bot-user-oauth-access-token"); const channels = context.getRequired("slack-channel"); - const text = context.getRequired("slack-text"); + const text = context.getOptional("slack-text"); + const blocks = context.getOptional("slack-blocks"); const results = []; for (let channel of channels.split(",")) { channel = channel.trim(); - const payload = buildMessage(channel, text, optional()); + const payload = buildMessage(channel, text, blocks, optional()); context.debug("Post Message PAYLOAD", payload); const result = await apiPostMessage(token, payload); @@ -2930,27 +2971,12 @@ const postMessage = async () => { } }; -const optional = () => { - let opt = {}; - - const env = context.getEnv(); - Object.keys(env) - .filter((key) => !!env[key]) - .filter((key) => key.toUpperCase().startsWith("INPUT_SLACK-OPTIONAL-")) - .forEach((key) => { - const slackKey = key.replace("INPUT_SLACK-OPTIONAL-", "").toLowerCase(); - opt[slackKey] = env[key]; - }); - - return opt; -}; - module.exports = { postMessage }; /***/ }), -/***/ 179: +/***/ 1179: /***/ ((module) => { const buildReaction = ( @@ -2972,12 +2998,12 @@ module.exports = buildReaction; /***/ }), -/***/ 380: +/***/ 4380: /***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { -const context = __nccwpck_require__(319); -const { apiAddReaction } = __nccwpck_require__(202); -const buildMessage = __nccwpck_require__(179); +const context = __nccwpck_require__(1319); +const { apiAddReaction } = __nccwpck_require__(7202); +const buildMessage = __nccwpck_require__(1179); const jsonPretty = (data) => JSON.stringify(data, undefined, 2); @@ -3006,23 +3032,40 @@ module.exports = { addReaction }; /***/ }), -/***/ 51: +/***/ 4051: /***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { const { restoreEscapedNewLine, restoreEscapedTab, -} = __nccwpck_require__(307); +} = __nccwpck_require__(5017); + +const buildMessage = ( + channel = "", + text = "", + blocks = "", + ts = "", + optional = {} +) => { + if (!channel || !ts) { + throw new Error("Channel and/or TS must be set"); + } + + if (text && blocks) { + throw new Error("Text OR Block must be set"); + } -const buildMessage = (channel = "", text = "", ts = "", optional = {}) => { const message = { channel, text, ts, + blocks, }; - message.text = restoreEscapedNewLine(message.text); - message.text = restoreEscapedTab(message.text); + if (message.text) { + message.text = restoreEscapedNewLine(message.text); + message.text = restoreEscapedTab(message.text); + } Object.keys(optional).forEach((name) => { message[name] = optional[name]; @@ -3036,12 +3079,13 @@ module.exports = buildMessage; /***/ }), -/***/ 308: +/***/ 3308: /***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { -const context = __nccwpck_require__(319); -const { apiUpdateMessage } = __nccwpck_require__(202); -const buildUpdateMessage = __nccwpck_require__(51); +const context = __nccwpck_require__(1319); +const { apiUpdateMessage } = __nccwpck_require__(7202); +const buildUpdateMessage = __nccwpck_require__(4051); +const { optional } = __nccwpck_require__(8300); const jsonPretty = (data) => JSON.stringify(data, undefined, 2); @@ -3049,10 +3093,11 @@ const updateMessage = async () => { try { const token = context.getRequired("slack-bot-user-oauth-access-token"); const channelId = context.getRequired("slack-channel"); - const text = context.getRequired("slack-update-message-text"); const ts = context.getRequired("slack-update-message-ts"); + const text = context.getOptional("slack-update-message-text"); + const blocks = context.getOptional("slack-update-message-blocks"); - const payload = buildUpdateMessage(channelId, text, ts); + const payload = buildUpdateMessage(channelId, text, blocks, ts, optional()); context.debugExtra("Update Message PAYLOAD", payload); const result = await apiUpdateMessage(token, payload); @@ -3071,7 +3116,7 @@ module.exports = { updateMessage }; /***/ }), -/***/ 307: +/***/ 5017: /***/ ((module) => { const restoreEscapedNewLine = (text) => @@ -3084,7 +3129,32 @@ module.exports = { restoreEscapedNewLine, restoreEscapedTab }; /***/ }), -/***/ 491: +/***/ 8300: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +const context = __nccwpck_require__(1319); + +const optional = () => { + let opt = {}; + + const env = context.getEnv(); + Object.keys(env) + .filter((key) => !!env[key]) + .filter((key) => key.toUpperCase().startsWith("INPUT_SLACK-OPTIONAL-")) + .forEach((key) => { + const slackKey = key.replace("INPUT_SLACK-OPTIONAL-", "").toLowerCase(); + opt[slackKey] = env[key]; + }); + + return opt; +}; + +module.exports = { optional }; + + +/***/ }), + +/***/ 9491: /***/ ((module) => { "use strict"; @@ -3092,7 +3162,7 @@ module.exports = require("assert"); /***/ }), -/***/ 113: +/***/ 6113: /***/ ((module) => { "use strict"; @@ -3100,7 +3170,7 @@ module.exports = require("crypto"); /***/ }), -/***/ 361: +/***/ 2361: /***/ ((module) => { "use strict"; @@ -3108,7 +3178,7 @@ module.exports = require("events"); /***/ }), -/***/ 147: +/***/ 7147: /***/ ((module) => { "use strict"; @@ -3116,7 +3186,7 @@ module.exports = require("fs"); /***/ }), -/***/ 685: +/***/ 3685: /***/ ((module) => { "use strict"; @@ -3124,7 +3194,7 @@ module.exports = require("http"); /***/ }), -/***/ 687: +/***/ 5687: /***/ ((module) => { "use strict"; @@ -3132,7 +3202,7 @@ module.exports = require("https"); /***/ }), -/***/ 808: +/***/ 1808: /***/ ((module) => { "use strict"; @@ -3140,7 +3210,7 @@ module.exports = require("net"); /***/ }), -/***/ 37: +/***/ 2037: /***/ ((module) => { "use strict"; @@ -3148,7 +3218,7 @@ module.exports = require("os"); /***/ }), -/***/ 17: +/***/ 1017: /***/ ((module) => { "use strict"; @@ -3156,7 +3226,7 @@ module.exports = require("path"); /***/ }), -/***/ 404: +/***/ 4404: /***/ ((module) => { "use strict"; @@ -3164,7 +3234,7 @@ module.exports = require("tls"); /***/ }), -/***/ 837: +/***/ 3837: /***/ ((module) => { "use strict"; @@ -3213,7 +3283,7 @@ module.exports = require("util"); var __webpack_exports__ = {}; // This entry need to be wrapped in an IIFE because it need to be isolated against other modules in the chunk. (() => { -const invoke = __nccwpck_require__(662); +const invoke = __nccwpck_require__(4662); const run = async () => { await invoke(); diff --git a/integration-test/end-to-end.js b/integration-test/end-to-end.js index d6c5127..b419ece 100644 --- a/integration-test/end-to-end.js +++ b/integration-test/end-to-end.js @@ -10,7 +10,7 @@ const buildReaction = require("../src/reaction/build-reaction"); const buildUpdateMessage = require("../src/update-message/build-update-message"); const testSendMessage = async (channel, token, text, optional = {}) => { - const message = buildMessage(channel, text, { + const message = buildMessage(channel, text, null, { as_user: false, icon_emoji: ":fire:", ...optional, @@ -22,7 +22,7 @@ const testSendMessage = async (channel, token, text, optional = {}) => { }; const testSendReaction = async (channel, token) => { - const message = buildMessage(channel, "Test 2 - testSendReaction 🤓", { + const message = buildMessage(channel, "Test 2 - testSendReaction 🤓", null, { as_user: false, icon_emoji: ":fire:", }); @@ -67,6 +67,7 @@ const testUpdateMessage = async (channel, token) => { const message = buildUpdateMessage( process.env.CHANNEL, "Test 4 - testUpdateMessage - Updated!", + null, messageToUpdate.response.message.ts ); diff --git a/jest.config.js b/jest.config.js index 9327d1b..ddf3fc5 100644 --- a/jest.config.js +++ b/jest.config.js @@ -178,7 +178,7 @@ module.exports = { // unmockedModulePathPatterns: undefined, // Indicates whether each individual test should be reported during the run - // verbose: null, + verbose: true, // An array of regexp patterns that are matched against all source file paths before re-running tests in watch mode // watchPathIgnorePatterns: [], diff --git a/src/integration/slack-api-post.js b/src/integration/slack-api-post.js new file mode 100644 index 0000000..a99b191 --- /dev/null +++ b/src/integration/slack-api-post.js @@ -0,0 +1,64 @@ +const https = require("https"); + +const getOptions = (token, path) => { + return { + hostname: "slack.com", + port: 443, + path: path, + method: "POST", + headers: { + "Content-Type": "application/json; charset=utf-8", + Authorization: `Bearer ${token}`, + }, + }; +}; + +const post = (token, path, message) => { + return new Promise((resolve, reject) => { + const payload = JSON.stringify(message); + + const options = getOptions(token, path); + + const req = https.request(options, (res) => { + const chunks = []; + + res.on("data", (chunk) => { + chunks.push(chunk); + }); + + res.on("end", () => { + const result = Buffer.concat(chunks).toString(); + const response = JSON.parse(result); + + let isOk = res.statusCode >= 200 && res.statusCode <= 299; + + // This solves the issue that block updates returns 200 + // but contains ok = false in the response + if ( + response && + response.hasOwnProperty("ok") && + response.ok === false + ) { + isOk = false; + } + + resolve({ + statusCode: res.statusCode, + statusMessage: res.statusMessage, + ok: isOk, + result: result, + response: response, + }); + }); + }); + + req.on("error", (error) => { + reject(error); + }); + + req.write(payload); + req.end(); + }); +}; + +module.exports = { post }; diff --git a/src/integration/slack-api.js b/src/integration/slack-api.js index 485dadb..621c231 100644 --- a/src/integration/slack-api.js +++ b/src/integration/slack-api.js @@ -1,85 +1,42 @@ -const https = require("https"); +const { post } = require("./slack-api-post"); -const getOptions = (token, path) => { - return { - hostname: "slack.com", - port: 443, - path: path, - method: "POST", - headers: { - "Content-Type": "application/json; charset=utf-8", - Authorization: `Bearer ${token}`, - }, - }; -}; - -const post = (token, path, message) => { - return new Promise((resolve, reject) => { - const payload = JSON.stringify(message); - - const options = getOptions(token, path); - - const req = https.request(options, (res) => { - const chunks = []; - - res.on("data", (chunk) => { - chunks.push(chunk); - }); - - res.on("end", () => { - const result = Buffer.concat(chunks).toString(); - const response = JSON.parse(result); - - resolve({ - statusCode: res.statusCode, - statusMessage: res.statusMessage, - ok: res.statusCode >= 200 && res.statusCode <= 299, - result: result, - response: response, - }); - }); - }); - - req.on("error", (error) => { - reject(error); - }); +const hasErrors = (res) => !res || !res.ok; - req.write(payload); - req.end(); - }); +const buildErrorMessage = (res) => { + return `Error! ${JSON.stringify(res)} (response)`; }; const apiPostMessage = async (token, message) => { const path = "/api/chat.postMessage"; - const result = await post(token, path, message); + const res = await post(token, path, message); - if (!result || !result.ok) { - throw `Error! ${JSON.stringify(response)}`; + if (hasErrors(res)) { + throw buildErrorMessage(res); } - return result; + return res; }; const apiAddReaction = async (token, message) => { const path = "/api/reactions.add"; - const result = await post(token, path, message); + const res = await post(token, path, message); - if (!result || !result.ok) { - throw `Error! ${JSON.stringify(response)}`; + if (hasErrors(res)) { + throw buildErrorMessage(res); } - return result; + return res; }; const apiUpdateMessage = async (token, message) => { const path = "/api/chat.update"; - const result = await post(token, path, message); + const res = await post(token, path, message); - if (!result || !result.ok) { - throw `Error! ${JSON.stringify(response)}`; + if (hasErrors(res)) { + throw buildErrorMessage(res); } - return result; + return res; }; module.exports = { apiPostMessage, apiAddReaction, apiUpdateMessage }; diff --git a/src/integration/slack-api.test.js b/src/integration/slack-api.test.js new file mode 100644 index 0000000..cfacdd8 --- /dev/null +++ b/src/integration/slack-api.test.js @@ -0,0 +1,22 @@ +describe("slack api", () => { + test("fail when slack api wrapper returns ok is false", async () => { + expect.assertions(1); + + const errorResponse = { + ok: false, + }; + + jest.mock("./slack-api-post", () => ({ + post: function (token, path, message) { + return errorResponse; + }, + })); + + const slackApi = require("./slack-api"); + try { + await slackApi.apiUpdateMessage(); + } catch (error) { + expect(error).toContain("Error!"); + } + }); +}); diff --git a/src/message/build-message.js b/src/message/build-message.js index 1ea9b86..ac2482a 100644 --- a/src/message/build-message.js +++ b/src/message/build-message.js @@ -3,14 +3,25 @@ const { restoreEscapedTab, } = require("../util/escaper.js"); -const buildMessage = (channel = "", text = "", optional = {}) => { +const buildMessage = (channel = "", text = "", blocks = "", optional = {}) => { + if (!channel) { + throw new Error("Channel must be set"); + } + + if (text && blocks) { + throw new Error("Text OR Block must be set"); + } + const message = { channel, text, + blocks, }; - message.text = restoreEscapedNewLine(message.text); - message.text = restoreEscapedTab(message.text); + if (message.text) { + message.text = restoreEscapedNewLine(message.text); + message.text = restoreEscapedTab(message.text); + } Object.keys(optional).forEach((name) => { message[name] = optional[name]; diff --git a/src/message/build-message.test.js b/src/message/build-message.test.js index fba737c..73e4998 100644 --- a/src/message/build-message.test.js +++ b/src/message/build-message.test.js @@ -2,22 +2,36 @@ describe("build message", () => { test("with channel and text parameters", () => { const buildMessage = require("./build-message"); - const message = buildMessage("channel", "text"); + const message = buildMessage("channel", "text", null); expect(message).toEqual({ channel: "channel", text: "text", + blocks: null, + }); + }); + + test("with channel and blocks parameters", () => { + const buildMessage = require("./build-message"); + + const message = buildMessage("channel", null, "blocks"); + + expect(message).toEqual({ + channel: "channel", + text: null, + blocks: "blocks", }); }); test("with optional parameters", () => { const buildMessage = require("./build-message"); - const message = buildMessage("channel", "text", { key: "value" }); + const message = buildMessage("channel", "text", null, { key: "value" }); expect(message).toEqual({ channel: "channel", text: "text", + blocks: null, key: "value", }); }); diff --git a/src/message/index.js b/src/message/index.js index 339808b..8c19347 100644 --- a/src/message/index.js +++ b/src/message/index.js @@ -2,6 +2,7 @@ const context = require("../context"); const { apiPostMessage } = require("../integration/slack-api"); const buildMessage = require("./build-message"); const core = require("@actions/core"); +const { optional } = require("../util/optional"); const jsonPretty = (data) => JSON.stringify(data, undefined, 2); @@ -9,13 +10,14 @@ const postMessage = async () => { try { const token = context.getRequired("slack-bot-user-oauth-access-token"); const channels = context.getRequired("slack-channel"); - const text = context.getRequired("slack-text"); + const text = context.getOptional("slack-text"); + const blocks = context.getOptional("slack-blocks"); const results = []; for (let channel of channels.split(",")) { channel = channel.trim(); - const payload = buildMessage(channel, text, optional()); + const payload = buildMessage(channel, text, blocks, optional()); context.debug("Post Message PAYLOAD", payload); const result = await apiPostMessage(token, payload); @@ -35,19 +37,4 @@ const postMessage = async () => { } }; -const optional = () => { - let opt = {}; - - const env = context.getEnv(); - Object.keys(env) - .filter((key) => !!env[key]) - .filter((key) => key.toUpperCase().startsWith("INPUT_SLACK-OPTIONAL-")) - .forEach((key) => { - const slackKey = key.replace("INPUT_SLACK-OPTIONAL-", "").toLowerCase(); - opt[slackKey] = env[key]; - }); - - return opt; -}; - module.exports = { postMessage }; diff --git a/src/update-message/build-update-message.js b/src/update-message/build-update-message.js index 011ddf8..9a2ca46 100644 --- a/src/update-message/build-update-message.js +++ b/src/update-message/build-update-message.js @@ -3,15 +3,32 @@ const { restoreEscapedTab, } = require("../util/escaper.js"); -const buildMessage = (channel = "", text = "", ts = "", optional = {}) => { +const buildMessage = ( + channel = "", + text = "", + blocks = "", + ts = "", + optional = {} +) => { + if (!channel || !ts) { + throw new Error("Channel and/or TS must be set"); + } + + if (text && blocks) { + throw new Error("Text OR Block must be set"); + } + const message = { channel, text, ts, + blocks, }; - message.text = restoreEscapedNewLine(message.text); - message.text = restoreEscapedTab(message.text); + if (message.text) { + message.text = restoreEscapedNewLine(message.text); + message.text = restoreEscapedTab(message.text); + } Object.keys(optional).forEach((name) => { message[name] = optional[name]; diff --git a/src/update-message/index.js b/src/update-message/index.js index bf55c89..c250c2e 100644 --- a/src/update-message/index.js +++ b/src/update-message/index.js @@ -1,6 +1,7 @@ const context = require("../context"); const { apiUpdateMessage } = require("../integration/slack-api"); const buildUpdateMessage = require("./build-update-message"); +const { optional } = require("../util/optional"); const jsonPretty = (data) => JSON.stringify(data, undefined, 2); @@ -8,10 +9,11 @@ const updateMessage = async () => { try { const token = context.getRequired("slack-bot-user-oauth-access-token"); const channelId = context.getRequired("slack-channel"); - const text = context.getRequired("slack-update-message-text"); const ts = context.getRequired("slack-update-message-ts"); + const text = context.getOptional("slack-update-message-text"); + const blocks = context.getOptional("slack-update-message-blocks"); - const payload = buildUpdateMessage(channelId, text, ts); + const payload = buildUpdateMessage(channelId, text, blocks, ts, optional()); context.debugExtra("Update Message PAYLOAD", payload); const result = await apiUpdateMessage(token, payload); diff --git a/src/util/optional.js b/src/util/optional.js new file mode 100644 index 0000000..a1d1717 --- /dev/null +++ b/src/util/optional.js @@ -0,0 +1,18 @@ +const context = require("../context"); + +const optional = () => { + let opt = {}; + + const env = context.getEnv(); + Object.keys(env) + .filter((key) => !!env[key]) + .filter((key) => key.toUpperCase().startsWith("INPUT_SLACK-OPTIONAL-")) + .forEach((key) => { + const slackKey = key.replace("INPUT_SLACK-OPTIONAL-", "").toLowerCase(); + opt[slackKey] = env[key]; + }); + + return opt; +}; + +module.exports = { optional };