How to Use Jenkins with Slack for Notifications

How to Use Jenkins with Slack for Notifications

If you have ever lost ten minutes refreshing a Jenkins dashboard just to see whether last night’s build passed, you already know why Slack notifications are worth setting up. I went through this exact pain on a team of six engineers, and the day I wired Jenkins into our #builds channel, our stand-ups got shorter and our “who broke the build” arguments basically disappeared. In this guide I will walk you through everything from the basic concept to a production-ready pipeline that pings Slack with rich, color-coded messages.

Why Bother Integrating Jenkins with Slack

Jenkins is excellent at running jobs, but it is terrible at telling people about the results unless someone is actively watching the dashboard. Email notifications get buried, and nobody wants another inbox to check. Slack, on the other hand, is where most engineering teams already live. Piping build status, deployment results, and failure alerts straight into a channel turns Jenkins from a silent worker into a chatty teammate that keeps everyone in the loop.

How Jenkins and Slack Actually Talk to Each Other

Under the hood, this integration is simpler than it looks. Slack exposes “Incoming Webhooks,” which are just URLs that accept a JSON payload and post it as a message in a channel. Jenkins, through the official Slack Notification Plugin, formats build information (job name, status, duration, commit author) into that JSON payload and fires an HTTP POST whenever a build event happens – start, success, failure, unstable, or back-to-normal.

There are two integration paths:

  1. Slack App with Incoming Webhook – the classic, quick way. You install a Slack app, enable an incoming webhook, and paste the URL into Jenkins.
  2. Slack App with Bot Token (OAuth) – the modern, recommended way for workspaces that have tightened webhook permissions. You create a Slack app, give it chat:write scope, install it to the workspace, and use the bot token in Jenkins.

Both end up producing the same result inside Jenkins: a configured connection that the plugin uses to post messages.

Step 1: Create the Slack App

  1. Go to https://api.slack.com/apps and click Create New AppFrom scratch.
  2. Name it something like jenkins-ci and pick your workspace.
  3. Under OAuth & Permissions, add the chat:write, chat:write.public, and channels:read bot scopes.
  4. Click Install to Workspace and authorize it.
  5. Copy the Bot User OAuth Token (it starts with xoxb-). You will need this in Jenkins.
  6. Invite the bot to your channel: /invite @jenkins-ci inside Slack.

If you prefer the simpler webhook route, go to Incoming Webhooks, toggle it on, and click Add New Webhook to Workspace, then choose the channel and copy the generated URL.

Step 2: Install the Slack Notification Plugin in Jenkins

From the Jenkins dashboard:

  1. Navigate to Manage JenkinsPluginsAvailable plugins.
  2. Search for Slack Notification Plugin and install it (restart Jenkins if prompted).

Or via the Jenkins CLI:

java -jar jenkins-cli.jar -s http://localhost:8080/ install-plugin slack -restart

Step 3: Configure the Slack Connection Globally

  1. Go to Manage JenkinsSystem.
  2. Scroll to the Slack section.
  3. Enter your Workspace (your Slack team domain, e.g. mycompany).
  4. Add a Credential of type “Secret text” containing your bot token, and select it in the Credential dropdown.
  5. Set a Default channel such as #builds.
  6. Click Test Connection to confirm Jenkins can reach Slack. You should see a confirmation message appear in the channel.

Step 4: Add Notifications to a Freestyle Job

For a simple job, open the job configuration, scroll to Post-build Actions, and add Slack Notifications. You can pick which events trigger a message: build starts, success, failure, unstable, back to normal, and so on. This is the easiest way to get started if you are not using pipelines yet.

Step 5: Add Notifications to a Jenkinsfile (Declarative Pipeline)

This is where the real power shows up, because you control exactly what gets sent and when. Here is a working example:

pipeline {
    agent any

    environment {
        SLACK_CHANNEL = '#builds'
    }

    stages {
        stage('Checkout') {
            steps {
                git branch: 'main', url: 'https://github.com/myorg/myapp.git'
            }
        }
        stage('Build') {
            steps {
                sh './gradlew build'
            }
        }
        stage('Test') {
            steps {
                sh './gradlew test'
            }
        }
        stage('Deploy') {
            steps {
                sh './deploy.sh production'
            }
        }
    }

    post {
        success {
            slackSend(
                channel: env.SLACK_CHANNEL,
                color: 'good',
                message: "✅ *${env.JOB_NAME}* #${env.BUILD_NUMBER} succeeded in ${currentBuild.durationString}\n<${env.BUILD_URL}|View Build>"
            )
        }
        failure {
            slackSend(
                channel: env.SLACK_CHANNEL,
                color: 'danger',
                message: "❌ *${env.JOB_NAME}* #${env.BUILD_NUMBER} failed\nCommitter: ${env.CHANGE_AUTHOR ?: 'unknown'}\n<${env.BUILD_URL}console|View Console Log>"
            )
        }
        unstable {
            slackSend(
                channel: env.SLACK_CHANNEL,
                color: 'warning',
                message: "⚠️ *${env.JOB_NAME}* #${env.BUILD_NUMBER} is unstable\n<${env.BUILD_URL}|Details>"
            )
        }
    }
}

Notice the color field – Jenkins passes this straight to Slack’s message attachment coloring, so successes show up green, failures red, and unstable builds yellow. That visual cue alone saves people from having to read every message closely.

Sending Richer Messages with Blocks

If you want more than plain text, you can build Slack “Block Kit” JSON and pass it through slackSend using the blocks parameter, or call the Slack Web API directly with httpRequest (from the HTTP Request Plugin). This lets you add buttons like “Rollback” or “View Logs” directly inside the Slack message, which is genuinely useful for on-call engineers reacting to failures at 2 a.m.

Notifying on Pull Request Builds

If you’re running Jenkins with the GitHub Branch Source plugin for multibranch pipelines, you can scope notifications differently for PR builds versus main branch builds:

post {
    failure {
        script {
            if (env.CHANGE_ID) {
                slackSend(channel: '#pr-checks', color: 'danger', message: "PR #${env.CHANGE_ID} build failed: ${env.BUILD_URL}")
            } else {
                slackSend(channel: '#builds', color: 'danger', message: "Main branch build failed: ${env.BUILD_URL}")
            }
        }
    }
}

Integrating with the Broader DevOps Toolchain

Slack notifications rarely live in isolation. In real pipelines, I usually combine this with:

Monitoring and Troubleshooting

Common issues I have run into and how to fix them:

Security Best Practices

Best Practices for Notification Design

FAQs

Do I need a paid Slack plan to use Incoming Webhooks? No, incoming webhooks and basic bot messaging work on free Slack workspaces.

Can I send notifications to multiple channels from one pipeline? Yes, just call slackSend multiple times with different channel values, or loop over a list of channels.

Does this work with scripted pipelines, not just declarative? Yes, slackSend() is a regular pipeline step and works identically in scripted pipelines.

Can Slack trigger a Jenkins build, not just receive notifications? Yes, using Slack slash commands combined with Jenkins’ remote build trigger API, though that’s a separate integration from notifications.

What happens if the Slack API is down? The slackSend step will fail or time out; wrap it in a catchError block if you don’t want a Slack outage to fail your whole pipeline.

Summary

Getting Jenkins to talk to Slack takes about fifteen minutes once you know the steps: create a Slack app, install the Slack Notification Plugin, configure the global connection, and add slackSend calls to your Jenkinsfile’s post block. The payoff is disproportionate to the effort – your whole team gets real-time visibility into build health without anyone having to babysit a dashboard. Start simple with success/failure alerts, then layer in richer Block Kit messages, PR-specific channels, and integration with your Docker/Kubernetes/Terraform pipelines as your workflow matures.

References

Exit mobile version