A composite GitHub Action that wraps the official slackapi/slack-github-action to send notifications to Slack channels.
- Go to https://api.slack.com/apps
- Click "Create New App" β "From scratch"
- Name your app (e.g., "GitHub Notifications") and select your workspace
- Click "Create App"
- Navigate to "OAuth & Permissions" in the left sidebar
- Scroll to "Scopes" β "Bot Token Scopes"
- Add the following scopes:
chat:write- Send messageschat:write.public- Send messages to public channels without joiningchannels:read- (Optional) List public channels
- Click "Install to Workspace" at the top
- Copy the "Bot User OAuth Token" (starts with
xoxb-)
Method 1: From Slack UI
- Open the Slack channel
- Click the channel name at the top
- Scroll down to find the Channel ID (e.g.,
C1234567890)
Method 2: Right-click method
- Right-click on the channel name
- Select "Copy Link"
- The URL contains the channel ID:
https://workspace.slack.com/archives/C1234567890
- Go to your GitHub repository
- Navigate to Settings β Secrets and variables β Actions
- Click "New repository secret"
- Name:
SLACK_BOT_TOKEN - Value: Your Bot User OAuth Token (from step 2)
- Click "Add secret"
name: Slack Notification
on:
push:
branches: [main]
jobs:
notify:
runs-on: ubuntu-latest
steps:
- uses: NVIDIA/dsx-github-actions/.github/actions/slack-notify@main
with:
slack-bot-token: ${{ secrets.SLACK_BOT_TOKEN }}
channel-id: C1234567890
message: "β
Build completed successfully for ${{ github.repository }}!"The action automatically injects the channel field into your payloads, so you don't need to include it manually:
- Simple messages: Just provide
messageinput - channel is added automatically - Custom payloads: Provide JSON in
payloadinput - channel is merged automatically
Example: You provide this:
{
"blocks": [
{ "type": "section", "text": { "type": "mrkdwn", "text": "Hello!" } }
]
}The action automatically merges it to:
{
"channel": "C1234567890",
"blocks": [
{ "type": "section", "text": { "type": "mrkdwn", "text": "Hello!" } }
]
}| Input | Description | Required | Default |
|---|---|---|---|
slack-bot-token |
Slack Bot User OAuth Token (xoxb-...) | Yes | - |
channel-id |
Slack channel ID (e.g., C1234567890) | Yes | - |
message |
Simple text message (supports Slack mrkdwn) | No | '' |
payload |
Custom JSON payload for advanced formatting | No | '' |
method |
Slack API method to call | No | chat.postMessage |
errors |
Whether to fail the step on errors | No | true |
| Output | Description |
|---|---|
time |
Time the message was sent |
thread_ts |
Thread timestamp (for threaded replies) |
ts |
Message timestamp |
name: Deploy and Notify
on:
push:
branches: [main]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Deploy Application
run: ./deploy.sh
- name: Notify Success
if: success()
uses: NVIDIA/dsx-github-actions/.github/actions/slack-notify@main
with:
slack-bot-token: ${{ secrets.SLACK_BOT_TOKEN }}
channel-id: C1234567890
message: |
π *Deployment Successful*
*Repository:* ${{ github.repository }}
*Branch:* ${{ github.ref_name }}
*Commit:* ${{ github.sha }}
*Author:* ${{ github.actor }}
<${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}|View Workflow>- name: Notify Failure
if: failure()
uses: NVIDIA/dsx-github-actions/.github/actions/slack-notify@main
with:
slack-bot-token: ${{ secrets.SLACK_BOT_TOKEN }}
channel-id: C1234567890
message: |
β *Build Failed*
*Repository:* ${{ github.repository }}
*Branch:* ${{ github.ref_name }}
*Triggered by:* ${{ github.actor }}
<${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}|View Logs>name: PR Notifications
on:
pull_request:
types: [opened, closed]
jobs:
notify:
runs-on: ubuntu-latest
steps:
- name: PR Opened
if: github.event.action == 'opened'
uses: NVIDIA/dsx-github-actions/.github/actions/slack-notify@main
with:
slack-bot-token: ${{ secrets.SLACK_BOT_TOKEN }}
channel-id: C1234567890
message: |
π *New Pull Request*
*Title:* ${{ github.event.pull_request.title }}
*Author:* ${{ github.event.pull_request.user.login }}
*Repository:* ${{ github.repository }}
<${{ github.event.pull_request.html_url }}|View Pull Request>
- name: PR Merged
if: github.event.pull_request.merged == true
uses: NVIDIA/dsx-github-actions/.github/actions/slack-notify@main
with:
slack-bot-token: ${{ secrets.SLACK_BOT_TOKEN }}
channel-id: C1234567890
message: |
β
*Pull Request Merged*
*Title:* ${{ github.event.pull_request.title }}
*Merged by:* ${{ github.actor }}
*Branch:* ${{ github.event.pull_request.head.ref }} β ${{ github.event.pull_request.base.ref }}- name: Send Rich Message
uses: NVIDIA/dsx-github-actions/.github/actions/slack-notify@main
with:
slack-bot-token: ${{ secrets.SLACK_BOT_TOKEN }}
channel-id: C1234567890
payload: |
{
"blocks": [
{
"type": "header",
"text": {
"type": "plain_text",
"text": "π Release Published"
}
},
{
"type": "section",
"fields": [
{
"type": "mrkdwn",
"text": "*Version:*\nv1.2.3"
},
{
"type": "mrkdwn",
"text": "*Repository:*\n${{ github.repository }}"
},
{
"type": "mrkdwn",
"text": "*Released by:*\n${{ github.actor }}"
},
{
"type": "mrkdwn",
"text": "*Date:*\n$(date -u +'%Y-%m-%d %H:%M:%S UTC')"
}
]
},
{
"type": "actions",
"elements": [
{
"type": "button",
"text": {
"type": "plain_text",
"text": "View Release"
},
"url": "${{ github.server_url }}/${{ github.repository }}/releases/tag/v1.2.3"
}
]
}
]
}- name: Send Build Status
if: always()
uses: NVIDIA/dsx-github-actions/.github/actions/slack-notify@main
with:
slack-bot-token: ${{ secrets.SLACK_BOT_TOKEN }}
channel-id: C1234567890
message: |
${{ job.status == 'success' && 'β
' || 'β' }} *Build ${{ job.status }}*
*Repository:* ${{ github.repository }}
*Workflow:* ${{ github.workflow }}
*Status:* ${{ job.status }}
<${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}|View Details>- name: Initial Message
id: initial-message
uses: NVIDIA/dsx-github-actions/.github/actions/slack-notify@main
with:
slack-bot-token: ${{ secrets.SLACK_BOT_TOKEN }}
channel-id: C1234567890
message: "π Deployment started..."
- name: Deploy
run: ./deploy.sh
- name: Thread Reply
uses: NVIDIA/dsx-github-actions/.github/actions/slack-notify@main
with:
slack-bot-token: ${{ secrets.SLACK_BOT_TOKEN }}
channel-id: C1234567890
payload: |
{
"thread_ts": "${{ steps.initial-message.outputs.ts }}",
"text": "β
Deployment completed successfully!"
}- name: Notify Multiple Channels
uses: NVIDIA/dsx-github-actions/.github/actions/slack-notify@main
with:
slack-bot-token: ${{ secrets.SLACK_BOT_TOKEN }}
channel-id: C1234567890
message: "π’ Important update!"
- name: Notify Dev Channel
uses: NVIDIA/dsx-github-actions/.github/actions/slack-notify@main
with:
slack-bot-token: ${{ secrets.SLACK_BOT_TOKEN }}
channel-id: C0987654321
message: "π©βπ» Dev team: deployment completed"name: Daily Report
on:
schedule:
- cron: "0 9 * * MON-FRI" # 9 AM UTC, Monday-Friday
jobs:
daily-report:
runs-on: ubuntu-latest
steps:
- name: Generate Report
id: report
run: |
# Generate your report data
echo "report_data=Sample report data" >> $GITHUB_OUTPUT
- name: Send Daily Report
uses: NVIDIA/dsx-github-actions/.github/actions/slack-notify@main
with:
slack-bot-token: ${{ secrets.SLACK_BOT_TOKEN }}
channel-id: C1234567890
message: |
π *Daily Report* - $(date +'%Y-%m-%d')
${{ steps.report.outputs.report_data }}# Update a message
- name: Update Message
uses: NVIDIA/dsx-github-actions/.github/actions/slack-notify@main
with:
slack-bot-token: ${{ secrets.SLACK_BOT_TOKEN }}
channel-id: C1234567890
method: chat.update
payload: |
{
"ts": "${{ steps.previous-message.outputs.ts }}",
"text": "Updated message content"
}*bold text*
_italic text_
~strikethrough~
`code`
```code block```
> quote
β’ bullet
<https://example.com|Link Text>
<@U1234567890> - Mention user
<!channel> - Mention channel
<!here> - Mention active users
:smile: :rocket: :tada: :white_check_mark: :x:
Use the Slack Block Kit Builder to design rich interactive messages.
Solution: Either:
- Add the bot to the channel (invite it like a regular user), OR
- Add the
chat:write.publicscope to post to public channels without joining
Solution:
- Verify the channel ID is correct (not the channel name)
- Ensure the bot has access to the channel
- For private channels, the bot must be invited
Solution:
- Ensure you're using the Bot User OAuth Token (starts with
xoxb-) - Verify the token is added to GitHub Secrets correctly
- Check that required scopes are added to the bot
Solution:
- For simple formatting, use the
messageinput with mrkdwn syntax - For advanced formatting, use the
payloadinput with Block Kit JSON - Don't mix
messageandpayload-payloadtakes precedence
Solution:
- Slack has rate limits on API calls
- Use the
retriesinput to handle temporary failures - Consider batching notifications or using webhooks for high-volume scenarios
Always store Slack tokens in GitHub Secrets, never hardcode them:
slack-bot-token: ${{ secrets.SLACK_BOT_TOKEN }}Always use channel IDs (e.g., C1234567890) instead of names (e.g., #general).
Include relevant information in your notifications:
message: |
*Repository:* ${{ github.repository }}
*Branch:* ${{ github.ref_name }}
*Commit:* ${{ github.sha }}
*Author:* ${{ github.actor }}Only send notifications when necessary:
if: success() # Only on success
if: failure() # Only on failure
if: always() # Always sendFor non-critical notifications, set errors: 'false':
with:
errors: "false" # Don't fail workflow if notification failsKeep related messages organized using threads:
thread_ts: ${{ steps.initial-message.outputs.ts }}Keep messages concise and scannable - many users will read them on mobile devices.
- Token Storage: Always use GitHub Secrets for Slack tokens
- Token Scope: Use the minimum required scopes for your bot
- Channel Access: Only give bot access to channels it needs
- Sensitive Data: Avoid including secrets or sensitive data in messages
- Token Rotation: Periodically rotate your Slack bot tokens
Besides chat.postMessage, you can use other methods:
chat.update- Update an existing messagechat.delete- Delete a messagechat.scheduleMessage- Schedule a messagefiles.upload- Upload a filereactions.add- Add a reaction to a message
Refer to the Slack API documentation for all available methods.
- Slack API Documentation
- Slack Block Kit Builder
- slackapi/slack-github-action
- Slack Message Formatting
- Slack OAuth Scopes
Copyright (c) 2025, NVIDIA CORPORATION. All rights reserved.
Licensed under the Apache License, Version 2.0.