From 0602f116516de933703f14801fb281f2a521865e Mon Sep 17 00:00:00 2001 From: Shubham Rana <118822906+Ranashubham19@users.noreply.github.com> Date: Thu, 17 Jul 2025 17:56:00 +0530 Subject: [PATCH 1/3] Update README.md --- README.md | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/README.md b/README.md index 6dadf2c8..de68bac3 100644 --- a/README.md +++ b/README.md @@ -32,6 +32,22 @@ jobs: uses: rtCamp/action-slack-notify@v2 env: SLACK_WEBHOOK: ${{ secrets.SLACK_WEBHOOK }} + +### 📢 Send Notification to Multiple Slack Channels + +You can notify multiple Slack channels by providing a comma-separated list of channel names: + +```yaml +jobs: + notify: + runs-on: ubuntu-latest + steps: + - uses: rtCamp/action-slack-notify@v2 + env: + SLACK_WEBHOOK: ${{ secrets.SLACK_WEBHOOK }} + SLACK_CHANNEL: "#general,#build-status" + SLACK_MESSAGE: "🚀 Deployment completed successfully!" + ``` 3. Create `SLACK_WEBHOOK` secret using [GitHub Action's Secret](https://help.github.com/en/actions/configuring-and-managing-workflows/creating-and-storing-encrypted-secrets#creating-encrypted-secrets-for-a-repository). You can [generate a Slack incoming webhook token from here](https://slack.com/apps/A0F7XDUAZ-incoming-webhooks). From ed29f798acea7745d7d02f067069935f7b1a5e39 Mon Sep 17 00:00:00 2001 From: Shubham Rana <118822906+Ranashubham19@users.noreply.github.com> Date: Thu, 17 Jul 2025 23:34:06 +0530 Subject: [PATCH 2/3] Update main.go --- main.go | 109 +++++++++++++++++++------------------------------------- 1 file changed, 36 insertions(+), 73 deletions(-) diff --git a/main.go b/main.go index 51eff17e..eff27df9 100644 --- a/main.go +++ b/main.go @@ -106,21 +106,18 @@ func main() { switch strings.ToLower(getEnv(EnvSlackColor)) { case "success": color = "good" - // If exists, override with on success success_msg := envOr(EnvSlackOnSuccess, "") if success_msg != "" { text = success_msg } case "cancelled": color = "#808080" - // If exists, override with on cancel cancel_msg := envOr(EnvSlackOnCancel, "") if cancel_msg != "" { text = cancel_msg } case "failure": color = "danger" - // If exists, override with on failure failure_msg := envOr(EnvSlackOnFailure, "") if failure_msg != "" { text = failure_msg @@ -156,96 +153,58 @@ func main() { for _, requiredField := range requiredFields { switch strings.ToLower(requiredField) { case "ref": - field := []Field{ - { - Title: "Ref", - Value: getEnv("GITHUB_REF"), - Short: true, - }, - } - mainFields = append(field, mainFields...) + field := Field{"Ref", getEnv("GITHUB_REF"), true} + mainFields = append([]Field{field}, mainFields...) case "event": - field := []Field{ - { - Title: "Event", - Value: getEnv("GITHUB_EVENT_NAME"), - Short: true, - }, - } - mainFields = append(field, mainFields...) + field := Field{"Event", getEnv("GITHUB_EVENT_NAME"), true} + mainFields = append([]Field{field}, mainFields...) case "actions url": - field := []Field{ - { - Title: "Actions URL", - Value: "<" + getEnv("GITHUB_SERVER_URL") + "/" + getEnv("GITHUB_REPOSITORY") + "/commit/" + getEnv("GITHUB_SHA") + "/checks|" + getEnv("GITHUB_WORKFLOW") + ">", - Short: true, - }, + field := Field{ + "Actions URL", + "<" + getEnv("GITHUB_SERVER_URL") + "/" + getEnv("GITHUB_REPOSITORY") + "/commit/" + getEnv("GITHUB_SHA") + "/checks|" + getEnv("GITHUB_WORKFLOW") + ">", + true, } - mainFields = append(field, mainFields...) + mainFields = append([]Field{field}, mainFields...) case "commit": - field := []Field{ - { - Title: "Commit", - Value: "<" + getEnv("GITHUB_SERVER_URL") + "/" + getEnv("GITHUB_REPOSITORY") + "/commit/" + getEnv("GITHUB_SHA") + "|" + commit_sha + ">", - Short: true, - }, + field := Field{ + "Commit", + "<" + getEnv("GITHUB_SERVER_URL") + "/" + getEnv("GITHUB_REPOSITORY") + "/commit/" + getEnv("GITHUB_SHA") + "|" + commit_sha + ">", + true, } - mainFields = append(field, mainFields...) + mainFields = append([]Field{field}, mainFields...) } } fields = append(mainFields, fields...) } else { mainFields := []Field{ + {"Ref", getEnv("GITHUB_REF"), true}, + {"Event", getEnv("GITHUB_EVENT_NAME"), true}, { - Title: "Ref", - Value: getEnv("GITHUB_REF"), - Short: true, - }, { - Title: "Event", - Value: getEnv("GITHUB_EVENT_NAME"), - Short: true, + "Actions URL", + "<" + getEnv("GITHUB_SERVER_URL") + "/" + getEnv("GITHUB_REPOSITORY") + "/commit/" + getEnv("GITHUB_SHA") + "/checks|" + getEnv("GITHUB_WORKFLOW") + ">", + true, }, { - Title: "Actions URL", - Value: "<" + getEnv("GITHUB_SERVER_URL") + "/" + getEnv("GITHUB_REPOSITORY") + "/commit/" + getEnv("GITHUB_SHA") + "/checks|" + getEnv("GITHUB_WORKFLOW") + ">", - Short: true, - }, - { - Title: "Commit", - Value: "<" + getEnv("GITHUB_SERVER_URL") + "/" + getEnv("GITHUB_REPOSITORY") + "/commit/" + getEnv("GITHUB_SHA") + "|" + commit_sha + ">", - Short: true, - }, - { - Title: getEnv(EnvSlackTitle), - Value: text, - Short: false, + "Commit", + "<" + getEnv("GITHUB_SERVER_URL") + "/" + getEnv("GITHUB_REPOSITORY") + "/commit/" + getEnv("GITHUB_SHA") + "|" + commit_sha + ">", + true, }, + {getEnv(EnvSlackTitle), text, false}, } fields = append(mainFields, fields...) } - hostName := getEnv(EnvHostName) - if hostName != "" { - newfields := []Field{ - { - Title: getEnv("SITE_TITLE"), - Value: getEnv(EnvSiteName), - Short: true, - }, - { - Title: getEnv("HOST_TITLE"), - Value: getEnv(EnvHostName), - Short: true, - }, - } - fields = append(newfields, fields...) + if getEnv(EnvHostName) != "" { + fields = append(fields, + Field{getEnv("SITE_TITLE"), getEnv(EnvSiteName), true}, + Field{getEnv("HOST_TITLE"), getEnv(EnvHostName), true}, + ) } msg := Webhook{ UserName: getEnv(EnvSlackUserName), IconURL: getEnv(EnvSlackIcon), IconEmoji: getEnv(EnvSlackIconEmoji), - Channel: getEnv(EnvSlackChannel), LinkNames: getEnv(EnvSlackLinkNames), ThreadTs: getEnv(EnvThreadTs), Attachments: []Attachment{ @@ -261,9 +220,14 @@ func main() { }, } - if err := send(endpoint, msg); err != nil { - fmt.Fprintf(os.Stderr, "Error sending message: %s\n", err) - os.Exit(1) + // ✅ Loop through comma-separated channels and send message to each + channels := strings.Split(getEnv(EnvSlackChannel), ",") + for _, ch := range channels { + msg.Channel = strings.TrimSpace(ch) + if err := send(endpoint, msg); err != nil { + fmt.Fprintf(os.Stderr, "Error sending message to channel %s: %s\n", ch, err) + os.Exit(1) + } } } fmt.Fprintf(os.Stdout, "Successfully sent the message!") @@ -369,7 +333,6 @@ func sendFile(filename string, message string, channel string, thread_ts string) } req, err := http.NewRequest("POST", "https://slack.com/api/files.upload", fileData) - if err != nil { return err } From 2048b1aa6ccc7a2d39c8b5a943b63f081aa5820e Mon Sep 17 00:00:00 2001 From: Shubham Rana <118822906+Ranashubham19@users.noreply.github.com> Date: Sun, 20 Jul 2025 15:56:15 +0530 Subject: [PATCH 3/3] Update README.md --- README.md | 87 ++++++++++++++++++++++++++++++++++++------------------- 1 file changed, 58 insertions(+), 29 deletions(-) diff --git a/README.md b/README.md index de68bac3..d02afc1c 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,8 @@ This action is a part of [GitHub Actions Library](https://github.com/rtCamp/github-actions-library/) created by [rtCamp](https://github.com/rtCamp/). # Slack Notify - GitHub Action -[![Project Status: Active – The project has reached a stable, usable state and is being actively developed.](https://www.repostatus.org/badges/latest/active.svg)](https://www.repostatus.org/#active) +[![Project Status: Active – The project has reached a stable, usable state and is being actively developed.](https://www.repostatus.org/badges/latest/active.svg)](https://www.repostatus.org/#active) A [GitHub Action](https://github.com/features/actions) to send a message to a Slack channel. @@ -32,6 +32,7 @@ jobs: uses: rtCamp/action-slack-notify@v2 env: SLACK_WEBHOOK: ${{ secrets.SLACK_WEBHOOK }} +``` ### 📢 Send Notification to Multiple Slack Channels @@ -47,39 +48,66 @@ jobs: SLACK_WEBHOOK: ${{ secrets.SLACK_WEBHOOK }} SLACK_CHANNEL: "#general,#build-status" SLACK_MESSAGE: "🚀 Deployment completed successfully!" +``` + +### 💡 Advanced: Send Different Messages to Different Channels (Matrix Strategy) +If you'd like to send **custom messages to different Slack channels**, use GitHub Actions' matrix strategy. Here's how: + +```yaml +on: push +name: Slack Notification Matrix Example + +jobs: + notify: + runs-on: ubuntu-latest + strategy: + matrix: + include: + - channel: '#build' + message: '✅ Build completed successfully!' + - channel: '#deployments' + message: '🚀 Deployment finished without errors!' + steps: + - uses: actions/checkout@v4 + - name: Notify Slack + uses: rtCamp/action-slack-notify@v2 + env: + SLACK_WEBHOOK: ${{ secrets.SLACK_WEBHOOK }} + SLACK_CHANNEL: ${{ matrix.channel }} + SLACK_MESSAGE: ${{ matrix.message }} ``` -3. Create `SLACK_WEBHOOK` secret using [GitHub Action's Secret](https://help.github.com/en/actions/configuring-and-managing-workflows/creating-and-storing-encrypted-secrets#creating-encrypted-secrets-for-a-repository). You can [generate a Slack incoming webhook token from here](https://slack.com/apps/A0F7XDUAZ-incoming-webhooks). +This setup will send **two different messages** to two different channels. It's ideal when you want CI messages in `#build` and deployment updates in `#deployments`. +3. Create `SLACK_WEBHOOK` secret using [GitHub Action's Secret](https://help.github.com/en/actions/configuring-and-managing-workflows/creating-and-storing-encrypted-secrets#creating-encrypted-secrets-for-a-repository). You can [generate a Slack incoming webhook token from here](https://slack.com/apps/A0F7XDUAZ-incoming-webhooks). ## Environment Variables By default, action is designed to run with minimal configuration but you can alter Slack notification using following environment variables: -| Variable | Default | Purpose | -| ------------------------ | ----------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | -| SLACK_CHANNEL | Set during Slack webhook creation | Specify Slack channel in which message needs to be sent | -| SLACK_USERNAME | `rtBot` | Custom Slack Username sending the message. Does not need to be a "real" username. | -| SLACK_MSG_AUTHOR | `$GITHUB_ACTOR` (The person who triggered action). | GitHub username of the person who has triggered the action. In case you want to modify it, please specify correct GitHub username. | -| SLACK_ICON | ![rtBot Avatar](https://github.com/rtBot.png?size=32) | User/Bot icon shown with Slack message. It uses the URL supplied to this env variable to display the icon in slack message. | -| SLACK_ICON_EMOJI | - | User/Bot icon shown with Slack message, in case you do not wish to add a URL for slack icon as above, you can set slack emoji in this env variable. Example value: `:bell:` or any other valid slack emoji. | -| SLACK_COLOR | `good` (green) | You can pass `${{ job.status }}` for automatic coloring or an RGB value like `#efefef` which would change color on left side vertical line of Slack message. Other valid values for this field are: `success`, `cancelled` or `failure`. | -| SLACK_LINK_NAMES | - | If set to `true`, enable mention in Slack message. | -| SLACK_MESSAGE | Generated from git commit message. | The main Slack message in attachment. It is advised not to override this. | -| SLACK_TITLE | Message | Title to use before main Slack message. | -| SLACK_FOOTER | Powered By rtCamp's GitHub Actions Library | Slack message footer. | -| MSG_MINIMAL | - | If set to `true`, removes: `Ref`, `Event`, `Actions URL` and `Commit` from the message. You can optionally whitelist any of these 4 removed values by passing it comma separated to the variable instead of `true`. (ex: `MSG_MINIMAL: event` or `MSG_MINIMAL: ref,actions url`, etc.) | -| SLACKIFY_MARKDOWN | - | If set to `true`, it will convert markdown to slack format. (ex: `*bold*` to `bold`) Note: This only works for custom messages and not for the default message generated by the action. Credits: [slackify-markdown-action](https://github.com/marketplace/actions/slack-markdown-converter) | -| SLACK_THREAD_TS | - | If you want to send message in a thread, you can pass the timestamp of the parent message to this variable. You can get the timestamp of the parent message from the message URL in Slack. (ex: `SLACK_THREAD_TS: 1586130833.000100`) | -| SLACK_TOKEN | - | If you want to send message to a channel using a slack token. You will need to pass a channel in order to send messages using token, requiring a value for ``SLACK_CHANNEL``. Note that in case both webhook url and token are provided, webhook url will be prioritized. | -| SLACK_MESSAGE_ON_SUCCESS | - | If set, will send the provided message instead of the default message when the passed status (through ``SLACK_COLOR``) is `success`. | -| SLACK_MESSAGE_ON_FAILURE | - | If set, will send the provided message instead of the default message when the passed status (through ``SLACK_COLOR``) is `failure`. | -| SLACK_MESSAGE_ON_CANCEL | - | If set, will send the provided message instead of the default message when the passed status (through ``SLACK_COLOR``) is `cancelled`. | -| SLACK_CUSTOM_PAYLOAD | - | If you want to send a custom payload to slack, you can pass it as a string to this variable. This will override all other variables and send the custom payload to slack. Example: `SLACK_CUSTOM_PAYLOAD: '{"text": "Hello, World!"}'`, Note: This payload should be in JSON format, and is not validated by the action. | -| SLACK_FILE_UPLOAD | - | If you want to upload a file to slack, you can pass the file path to this variable. Example: `SLACK_FILE_UPLOAD: /path/to/file.txt`. Note: This file should be present in the repository, or github workspace. Otherwise, should be accessable in the container the action is running in. | -| ENABLE_ESCAPES | - | If set to `true`, will enable backslash escape sequences such as `\n`, `\t`, etc. in the message. Note: This only works for custom messages and not for the default message generated by the action. | - +| Variable | Default | Purpose | +| --------------------------- | ----------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | +| SLACK\_CHANNEL | Set during Slack webhook creation | Specify Slack channel in which message needs to be sent | +| SLACK\_USERNAME | `rtBot` | Custom Slack Username sending the message. Does not need to be a "real" username. | +| SLACK\_MSG\_AUTHOR | `$GITHUB_ACTOR` (The person who triggered action). | GitHub username of the person who has triggered the action. In case you want to modify it, please specify correct GitHub username. | +| SLACK\_ICON | ![rtBot Avatar](https://github.com/rtBot.png?size=32) | User/Bot icon shown with Slack message. It uses the URL supplied to this env variable to display the icon in slack message. | +| SLACK\_ICON\_EMOJI | - | User/Bot icon shown with Slack message, in case you do not wish to add a URL for slack icon as above, you can set slack emoji in this env variable. Example value: `:bell:` or any other valid slack emoji. | +| SLACK\_COLOR | `good` (green) | You can pass `${{ job.status }}` for automatic coloring or an RGB value like `#efefef` which would change color on left side vertical line of Slack message. Other valid values for this field are: `success`, `cancelled` or `failure`. | +| SLACK\_LINK\_NAMES | - | If set to `true`, enable mention in Slack message. | +| SLACK\_MESSAGE | Generated from git commit message. | The main Slack message in attachment. It is advised not to override this. | +| SLACK\_TITLE | Message | Title to use before main Slack message. | +| SLACK\_FOOTER | Powered By rtCamp's GitHub Actions Library | Slack message footer. | +| MSG\_MINIMAL | - | If set to `true`, removes: `Ref`, `Event`, `Actions URL` and `Commit` from the message. You can optionally whitelist any of these 4 removed values by passing it comma separated to the variable instead of `true`. (ex: `MSG_MINIMAL: event` or `MSG_MINIMAL: ref,actions url`, etc.) | +| SLACKIFY\_MARKDOWN | - | If set to `true`, it will convert markdown to slack format. (ex: `*bold*` to `bold`) Note: This only works for custom messages and not for the default message generated by the action. Credits: [slackify-markdown-action](https://github.com/marketplace/actions/slack-markdown-converter) | +| SLACK\_THREAD\_TS | - | If you want to send message in a thread, you can pass the timestamp of the parent message to this variable. You can get the timestamp of the parent message from the message URL in Slack. (ex: `SLACK_THREAD_TS: 1586130833.000100`) | +| SLACK\_TOKEN | - | If you want to send message to a channel using a slack token. You will need to pass a channel in order to send messages using token, requiring a value for `SLACK_CHANNEL`. Note that in case both webhook url and token are provided, webhook url will be prioritized. | +| SLACK\_MESSAGE\_ON\_SUCCESS | - | If set, will send the provided message instead of the default message when the passed status (through `SLACK_COLOR`) is `success`. | +| SLACK\_MESSAGE\_ON\_FAILURE | - | If set, will send the provided message instead of the default message when the passed status (through `SLACK_COLOR`) is `failure`. | +| SLACK\_MESSAGE\_ON\_CANCEL | - | If set, will send the provided message instead of the default message when the passed status (through `SLACK_COLOR`) is `cancelled`. | +| SLACK\_CUSTOM\_PAYLOAD | - | If you want to send a custom payload to slack, you can pass it as a string to this variable. This will override all other variables and send the custom payload to slack. Example: `SLACK_CUSTOM_PAYLOAD: '{"text": "Hello, World!"}'`, Note: This payload should be in JSON format, and is not validated by the action. | +| SLACK\_FILE\_UPLOAD | - | If you want to upload a file to slack, you can pass the file path to this variable. Example: `SLACK_FILE_UPLOAD: /path/to/file.txt`. Note: This file should be present in the repository, or github workspace. Otherwise, should be accessable in the container the action is running in. | +| ENABLE\_ESCAPES | - | If set to `true`, will enable backslash escape sequences such as `\n`, `\t`, etc. in the message. Note: This only works for custom messages and not for the default message generated by the action. | You can see the action block with all variables as below: @@ -108,10 +136,10 @@ This GitHub action supports [Hashicorp Vault](https://www.vaultproject.io/). To enable Hashicorp Vault support, please define following GitHub secrets: -Variable | Purpose | Example Vaule ---------------|-------------------------------------------------------------------------------|------------- -`VAULT_ADDR` | [Vault server address](https://www.vaultproject.io/docs/commands/#vault_addr) | `https://example.com:8200` -`VAULT_TOKEN` | [Vault token](https://www.vaultproject.io/docs/concepts/tokens.html) | `s.gIX5MKov9TUp7iiIqhrP1HgN` +| Variable | Purpose | Example Vaule | +| ------------- | ----------------------------------------------------------------------------- | ---------------------------- | +| `VAULT_ADDR` | [Vault server address](https://www.vaultproject.io/docs/commands/#vault_addr) | `https://example.com:8200` | +| `VAULT_TOKEN` | [Vault token](https://www.vaultproject.io/docs/concepts/tokens.html) | `s.gIX5MKov9TUp7iiIqhrP1HgN` | You will need to change `secrets` line in `slack-notify.yml` file to look like below. @@ -136,6 +164,7 @@ GitHub action uses `VAULT_TOKEN` to connect to `VAULT_ADDR` to retrieve slack we In the Vault, the Slack webhook should be setup as field `webhook` on path `secret/slack`. ## Credits + Source: [technosophos/slack-notify](https://github.com/technosophos/slack-notify) ## License