Slack GitHub Actions: The Complete Guide
How to send Slack notifications from GitHub Actions — with step-by-step setup, YAML examples, Block Kit templates, and best practices for every approach.
Table of Contents
What Are Slack GitHub Actions?
Slack GitHub Actions are workflow steps in GitHub Actions that send notifications, alerts, or data to Slack channels. They let you automate Slack messages triggered by GitHub events — pushes, pull requests, deployments, releases, CI/CD results, and more — all defined in your repository's YAML workflow files.
Instead of manually posting build results or deployment status in Slack, you define a workflow step that automatically sends a formatted message whenever the event occurs. The most common tool for this is the official slackapi/slack-github-action, maintained by Slack, which supports three different integration methods.
Why automate Slack notifications from CI/CD?
Teams that automate status notifications respond to failures 60% faster and spend less time context-switching between GitHub and Slack. Real-time alerts mean your team knows the moment something breaks — not whenever someone remembers to check GitHub.
Common use cases
Pull request notifications
Notify your team when PRs are opened, reviewed, or merged. Include PR title, author, and direct links.
CI/CD build status
Alert on test failures or successful builds. Use conditional steps to only notify on failure.
Deployment alerts
Announce production deployments with environment, version, and commit details to your ops channel.
Release announcements
Automatically post release notes to Slack when a new GitHub release is published.
Failure-only alerts
Skip the noise — only send Slack messages when workflows fail, so your team can respond fast.
Scheduled monitoring
Run health checks on a cron schedule and post results to Slack. Great for uptime monitoring.
Three Approaches to Slack GitHub Actions
There are three ways to send Slack notifications from GitHub Actions. Each has different tradeoffs around simplicity, flexibility, and features:
| Feature | Incoming Webhook | Bot Token (API) | Workflow Builder |
|---|---|---|---|
| Setup complexity | Low | Medium | Medium |
| Channel targeting | Fixed (one per webhook) | Any channel (dynamic) | Configured in Slack |
| Message updates | No | Yes (chat.update) | No |
| Threaded replies | No | Yes (thread_ts) | No |
| File uploads | No | Yes (files.uploadV2) | No |
| User lookups | No | Yes (users.lookupByEmail) | No |
| DMs to users | No | Yes | No |
| Block Kit support | Yes | Yes | Limited |
| Auth method | Webhook URL | xoxb- OAuth token | Trigger URL |
| Slack plan needed | Free | Free | Paid |
| Best for | Simple, single-channel alerts | Advanced, multi-channel workflows | Triggering Slack automations |
Method 1: Incoming Webhook (Simplest)
Incoming Webhooks are the simplest way to get Slack notifications from GitHub Actions. Each webhook is tied to a specific channel — you post a JSON/YAML payload to the webhook URL, and Slack delivers the message. No bot user or OAuth scopes needed.
Part A: Create the Slack Webhook
Create a Slack App
Go to api.slack.com/apps and click Create New App. Select From scratch, enter an app name (e.g., "GitHub Actions Notifier"), and choose your workspace. Click Create App.
Enable Incoming Webhooks
In the left sidebar, click Incoming Webhooks. Toggle Activate Incoming Webhooks to On.
Add a Webhook to a Channel
Click Add New Webhook to Workspace at the bottom of the page. Select the target channel (e.g., #ci-alerts) from the dropdown and click Allow. Copy the generated webhook URL — it looks like:
https://hooks.slack.com/services/T00000000/B00000000/XXXXXXXXXXXXXXXXXXXXXXXXPart B: Add the Webhook to GitHub
Store the Webhook as a GitHub Secret
In your GitHub repository, navigate to Settings > Secrets and variables > Actions. Click New repository secret.
- Name:
SLACK_WEBHOOK_URL - Value: paste the webhook URL from the previous step
Click Add secret. The URL is now encrypted and accessible in your workflows via ${{ secrets.SLACK_WEBHOOK_URL }}.
Add a Workflow Step
In your .github/workflows/ directory, add a notification step to your workflow YAML:
.github/workflows/notify.yml
name: Notify Slack
on:
push:
branches: [main]
jobs:
notify:
runs-on: ubuntu-latest
steps:
- name: Send Slack notification
uses: slackapi/slack-github-action@v2.1.1
with:
webhook: ${{ secrets.SLACK_WEBHOOK_URL }}
webhook-type: incoming-webhook
payload: |
text: "New push to main by ${{ github.actor }}"
blocks:
- type: "section"
text:
type: "mrkdwn"
text: ":rocket: *Push to main*\nBy: ${{ github.actor }}\nRepo: ${{ github.repository }}""Test It
Push a commit to your main branch. Within seconds, a notification should appear in your Slack channel. Check the GitHub Actions log for the notification step if nothing arrives.
Webhook limitations
Each webhook is locked to a single channel. You cannot update messages, post threads, upload files, or send DMs. For those features, use the Bot Token method below.
Method 2: Bot Token / Slack API (Most Powerful)
The Bot Token approach gives you full access to the Slack API — post to any channel, update messages, send threaded replies, upload files, look up users by email, and send DMs. It requires a few more setup steps but unlocks the most flexibility.
Create a Slack App (if you haven't already)
Go to api.slack.com/apps, click Create New App > From scratch, name your app, and select your workspace.
Add Bot Token Scopes
Navigate to OAuth & Permissions in the left sidebar. Under Bot Token Scopes, add the scopes you need:
| Scope | Purpose |
|---|---|
chat:write | Post messages to channels |
chat:write.public | Post to channels without joining |
files:write | Upload files |
users:read.email | Look up users by email |
At minimum, you need chat:write. Add others as needed for your use case.
Install the App & Copy the Token
Click Install to Workspace at the top of the OAuth & Permissions page. After authorizing, copy the Bot User OAuth Token (starts with xoxb-).
Invite the Bot to Your Channel
In Slack, go to the channel where you want notifications and type /invite @YourBotName. The bot must be in the channel to post messages (unless you added the chat:write.public scope).
Store the Token and Channel ID as GitHub Secrets
Add two secrets in your GitHub repository (Settings > Secrets > Actions):
SLACK_BOT_TOKEN— thexoxb-tokenSLACK_CHANNEL_ID— the channel ID (right-click channel name > Copy link, the ID is the last segment)
Add the Workflow Step
.github/workflows/notify.yml
- name: Notify Slack
uses: slackapi/slack-github-action@v2.1.1
with:
method: chat.postMessage
token: ${{ secrets.SLACK_BOT_TOKEN }}
payload: |
channel: ${{ secrets.SLACK_CHANNEL_ID }}
text: "Build ${{ job.status }} for ${{ github.repository }}"
blocks:
- type: "section"
text:
type: "mrkdwn"
text: "*Build ${{ job.status }}*\nRepo: ${{ github.repository }}\nBranch: `${{ github.ref_name }}`"Method 3: Slack Workflow Builder
Slack Workflow Builder lets you create automations directly inside Slack. You can trigger a Slack workflow from GitHub Actions by sending data to a webhook trigger URL. The workflow then runs steps you define in Slack — like posting a formatted message, creating a channel, or starting an approval process.
Webhook triggers for Workflow Builder require a paid Slack plan. The trigger URL format is https://hooks.slack.com/triggers/... (different from incoming webhooks).
This approach is best when you want Slack-side logic — like routing notifications based on data, requesting approvals, or triggering multi-step Slack workflows from a GitHub event.
Workflow Builder Trigger Example
- name: Trigger Slack Workflow
uses: slackapi/slack-github-action@v2.1.1
with:
webhook: ${{ secrets.SLACK_WEBHOOK_URL }}
webhook-type: webhook-trigger
payload: |
status: "${{ job.status }}"
repository: "${{ github.repository }}"
branch: "${{ github.ref_name }}"
actor: "${{ github.actor }}"
run_url: "${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}"Complete YAML Workflow Examples
Copy-paste these workflow files into your .github/workflows/ directory. Each example is a complete, self-contained workflow that you can customize for your project.
Basic push notification (Webhook)
on: pushname: Slack Notification on Push
on:
push:
branches: [main]
jobs:
notify:
runs-on: ubuntu-latest
steps:
- name: Notify Slack
uses: slackapi/slack-github-action@v2.1.1
with:
webhook: ${{ secrets.SLACK_WEBHOOK_URL }}
webhook-type: incoming-webhook
payload: |
text: "New push to main by ${{ github.actor }}"
blocks:
- type: "section"
text:
type: "mrkdwn"
text: ":rocket: *New push to main*\nRepo: `${{ github.repository }}`\nBy: ${{ github.actor }}\nCommit: `${{ github.sha }}`"Rich Messages with Block Kit
Slack's Block Kit lets you build richly formatted messages with sections, headers, fields, buttons, images, and more. Block Kit payloads work with both Incoming Webhooks and the Bot Token method.
Key block types
| Block Type | Purpose | Example Use |
|---|---|---|
| header | Large, bold title text | "CI Build Result" |
| section | Text content with optional fields | Repo, branch, status details |
| actions | Interactive buttons | "View Run" / "Review PR" buttons |
| context | Secondary, smaller text | Timestamps, author attribution |
| divider | Horizontal rule separator | Between sections |
| image | Full-width image | Charts, screenshots |
Slack mrkdwn vs Markdown
Slack uses its own markup format called mrkdwn — not standard Markdown. Key differences: bold is *text*, italic is _text_, strikethrough is ~text~, and links use <url|text> (not [text](url)). Code blocks use triple backticks.
Example: Full Block Kit message
blocks:
- type: "header"
text:
type: "plain_text"
text: "Deployment Complete"
- type: "section"
fields:
- type: "mrkdwn"
text: "*Status:*\n:white_check_mark: Success"
- type: "mrkdwn"
text: "*Environment:*\nProduction"
- type: "mrkdwn"
text: "*Branch:*\n`main`"
- type: "mrkdwn"
text: "*Deployed by:*\n${{ github.actor }}"
- type: "actions"
elements:
- type: "button"
text:
type: "plain_text"
text: "View Deployment"
url: "${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}"
- type: "button"
text:
type: "plain_text"
text: "Open Repository"
url: "${{ github.server_url }}/${{ github.repository }}"
- type: "context"
elements:
- type: "mrkdwn"
text: "Commit: `${{ github.sha }}` | ${{ github.repository }}""Advanced Configurations
Update an existing message (in-place)
Post a "deployment in progress" message, then update it when the deployment finishes. This reduces channel noise by keeping everything in one message.
Message update pattern
- name: Post initial message
id: slack_initial
uses: slackapi/slack-github-action@v2.1.1
with:
method: chat.postMessage
token: ${{ secrets.SLACK_BOT_TOKEN }}
payload: |
channel: ${{ secrets.SLACK_CHANNEL_ID }}
text: ":hourglass_flowing_sand: Deployment in progress..."
# ... your deployment steps here ...
- name: Update message with result
uses: slackapi/slack-github-action@v2.1.1
with:
method: chat.update
token: ${{ secrets.SLACK_BOT_TOKEN }}
payload: |
channel: ${{ secrets.SLACK_CHANNEL_ID }}
ts: "${{ steps.slack_initial.outputs.ts }}"
text: ":white_check_mark: Deployment complete!"Threaded replies
Post a parent message and then add replies in a thread — useful for multi-step deployments where you want to track progress without spamming the channel.
Threaded replies
- name: Post parent message
id: parent
uses: slackapi/slack-github-action@v2.1.1
with:
method: chat.postMessage
token: ${{ secrets.SLACK_BOT_TOKEN }}
payload: |
channel: ${{ secrets.SLACK_CHANNEL_ID }}
text: ":rocket: Deployment started for v1.2.0"
- name: Post thread reply
uses: slackapi/slack-github-action@v2.1.1
with:
method: chat.postMessage
token: ${{ secrets.SLACK_BOT_TOKEN }}
payload: |
channel: ${{ secrets.SLACK_CHANNEL_ID }}
thread_ts: "${{ fromJSON(steps.parent.outputs.response).ts }}"
text: ":white_check_mark: Database migration complete"DM the commit author
Look up the commit author by email and send them a direct message — useful for notifying developers about build failures on their commits.
DM commit author
- name: Look up Slack user by email
id: lookup
uses: slackapi/slack-github-action@v2.1.1
with:
method: users.lookupByEmail
token: ${{ secrets.SLACK_BOT_TOKEN }}
payload: |
email: ${{ github.event.pusher.email }}
- name: DM the author
if: ${{ steps.lookup.outputs.ok }}
uses: slackapi/slack-github-action@v2.1.1
with:
method: chat.postMessage
token: ${{ secrets.SLACK_BOT_TOKEN }}
payload: |
channel: "${{ fromJSON(steps.lookup.outputs.response).user.id }}"
text: ":warning: Your commit to ${{ github.repository }} failed CI"
blocks:
- type: "section"
text:
type: "mrkdwn"
text: ":x: *CI Failed* on your commit to `${{ github.ref_name }}`\n<${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}|View the failed run>"Conditional notifications by branch
Branch-based routing
- name: Notify production channel
if: github.ref == 'refs/heads/main' && success()
uses: slackapi/slack-github-action@v2.1.1
with:
webhook: ${{ secrets.SLACK_PROD_WEBHOOK }}
webhook-type: incoming-webhook
payload: |
text: ":white_check_mark: Production deploy successful"
- name: Notify staging channel
if: github.ref == 'refs/heads/develop'
uses: slackapi/slack-github-action@v2.1.1
with:
webhook: ${{ secrets.SLACK_STAGING_WEBHOOK }}
webhook-type: incoming-webhook
payload: |
text: ":construction: Staging deploy complete"File upload to Slack
Upload test report
- name: Upload test report
uses: slackapi/slack-github-action@v2.1.1
with:
method: files.uploadV2
token: ${{ secrets.SLACK_BOT_TOKEN }}
payload: |
channel_id: ${{ secrets.SLACK_CHANNEL_ID }}
filename: "test-report.txt"
file: "./test-results/report.txt"Popular GitHub Actions for Slack
While the official slackapi/slack-github-action covers most use cases, several community actions offer opinionated defaults or specialized features. Here's how they compare:
slackapi/slack-github-action
Official (by Slack)v2.1.1RecommendedThe official GitHub Action maintained by Slack. Supports all three integration methods: Bot Token API, Incoming Webhooks, and Workflow Builder triggers. The v2 release added YAML payload support, retry logic, and improved error handling.
Best for: Most teams — the official, most maintained option · Used by 21,400+ repos
rtCamp/action-slack-notify
Communityv2Environment-variable-driven action with opinionated defaults. Configure everything through env vars — no YAML payloads needed. Supports status-specific messages, markdown conversion, and file uploads.
Best for: Quick setup with sensible defaults · Used by 1,200+ repos
ravsamhq/notify-slack-action
Communityv2Template-variable-driven action for status-based conditional notifications. Use variables like {workflow}, {status_message}, {repo}, and {branch} in your messages. Supports per-status icons and user mentions.
Best for: Status-based notifications with template variables · Used by 300+ repos
voxmedia/github-action-slack-notify-build
Communityv2Focused on build status reporting with a unique message-update capability. Post an initial "in progress" message and update it when the build completes — reducing channel noise.
Best for: Build status with message updates (reduce noise) · Used by 200+ repos
Best Practices for Slack GitHub Actions
Store secrets securely
Never hard-code webhook URLs or bot tokens in workflow files. Always use GitHub Secrets (Settings > Secrets and variables > Actions). GitHub encrypts secrets using Libsodium sealed boxes.
Always include a text fallback
When using Block Kit blocks, always include a top-level text field alongside your blocks array. The text serves as a fallback for notifications, accessibility readers, and Slack clients that cannot render blocks.
Use conditional notifications
Use if: failure() for failure-only alerts to reduce notification fatigue. Use if: always() when you want notifications regardless of outcome. Place notification steps at the end of your job.
Route to the right channels
Send deployment alerts to #deploys, CI failures to #ci-alerts, and release notes to #releases. Avoid dumping everything into a single channel — it leads to alert fatigue.
Use channel IDs, not names
When using the Bot Token method, pass the channel ID (e.g., C01234ABCDE) rather than the channel name. Channel IDs are stable — names can change and break your workflow.
Include actionable links
Always include a link back to the GitHub Actions run: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}. This lets teammates jump directly to the relevant context.
Escape dynamic content
Use ${{ toJSON(value) }} to safely escape strings containing special characters — especially commit messages that may include quotes, newlines, or Slack mrkdwn syntax.
Security reminder
Never commit webhook URLs or bot tokens to your repository. GitHub Secrets are encrypted using Libsodium sealed boxes and are automatically redacted from workflow logs. Use descriptive secret names like SLACK_DEPLOY_WEBHOOK or SLACK_CI_BOT_TOKEN to avoid confusion.
Troubleshooting
Common issues when setting up Slack GitHub Actions and how to fix them:
Skip the YAML: Use PullNotifier for GitHub Slack Notifications
GitHub Actions Slack integrations are powerful — but they require YAML configuration, webhook management, and ongoing maintenance for every notification you want. If your primary need is pull request notifications in Slack, there's a faster way.
PullNotifier sends real-time GitHub PR notifications directly to Slack — new PRs, review requests, approvals, CI status changes, and merges — with zero YAML, zero webhook setup, and zero maintenance. It takes 30 seconds to set up and works with both public and private repositories.
30-second setup
Single-message PR updates
No YAML or webhooks
Frequently Asked Questions
What are Slack GitHub Actions?
Slack GitHub Actions are GitHub Actions workflow steps that send notifications or data to Slack channels. They let you automate Slack messages triggered by GitHub events like pushes, pull requests, deployments, and CI/CD pipeline results — all defined in YAML workflow files.
How do I send a Slack notification from GitHub Actions?
The simplest way is to use the official slackapi/slack-github-action with an Incoming Webhook. Create a Slack app, enable Incoming Webhooks, copy the webhook URL, store it as a GitHub secret, and add a step in your workflow YAML that sends a message using the webhook. See the step-by-step guide above for detailed instructions.
Should I use a webhook or a bot token for Slack GitHub Actions?
Use an Incoming Webhook for simple, single-channel notifications (deploy alerts, build status). Use a Bot Token when you need advanced features like posting to multiple channels, updating messages, sending threaded replies, uploading files, or looking up users by email. Webhooks are simpler to set up; bot tokens are more powerful.
Which GitHub Action for Slack is best?
The official slackapi/slack-github-action (v2) is recommended for most teams. It supports all three integration methods, has built-in retry logic, and is actively maintained by Slack. For simpler setups, rtCamp/action-slack-notify offers a quick env-var-driven configuration. For status-based conditional notifications, ravsamhq/notify-slack-action provides template variables.
Can I send Slack notifications only when a GitHub Actions workflow fails?
Yes. Use the if: failure() condition on your Slack notification step. This ensures the step only runs when a previous step in the job has failed. You can also use if: success() for success-only messages, or if: always() to send regardless of outcome.
How do I update an existing Slack message from GitHub Actions?
Use the Bot Token method with the chat.postMessage API to send an initial message, capture the ts (timestamp) output, then use chat.update with the same ts to modify the message in place. This is useful for "deployment in progress → deployment complete" patterns that reduce channel noise.
Can I send Slack messages to multiple channels from GitHub Actions?
With the Bot Token method, yes — add separate steps for each channel, changing the channel parameter. With Incoming Webhooks, you need a separate webhook URL for each channel. The Bot Token approach is more flexible for multi-channel notifications.
Is there a no-code alternative to Slack GitHub Actions?
Yes. PullNotifier sends GitHub pull request notifications to Slack without any YAML configuration. It takes 30 seconds to set up, handles PR events automatically (new PRs, reviews, approvals, CI status, merges), and delivers real-time alerts to your Slack channels. No webhook setup or workflow files needed.
How do I format Slack messages from GitHub Actions?
Slack uses its own markup format called mrkdwn (not standard Markdown). Bold is *text*, italic is _text_, and links are <url|text>. For rich layouts, use Block Kit — a JSON/YAML structure with sections, headers, buttons, and more. Design messages visually at app.slack.com/block-kit-builder.
What is the difference between slack-github-action v1 and v2?
Version 2 introduced several breaking changes: webhook-type must be explicitly set, method is required for API calls, token is now a step input (not just an env var), YAML payloads are supported alongside JSON, and template variable replacement is disabled by default. V2 also added retry logic, proxy support, and improved error handling. See the migration section in the official docs.
Built by PullNotifier— get GitHub pull request notifications directly on Slack.
Never miss a PR review, merge, or CI failure again.
PullNotifier
© 2026 PullNotifier. All rights reserved
