Slack can actually receive notifications from CircleCI without needing a dedicated Slack app integration or a complex webhook setup.

Here’s a CircleCI build running and sending a notification to Slack, all configured within CircleCI’s own settings:

jobs:
  build_and_test:
    docker:
      - image: cimg/node:18.17.0
    steps:
      - checkout
      - run: echo "Running tests..."
      - run: echo "Tests passed!"

workflows:
  version: 2
  build_workflow:
    jobs:
      - build_and_test
    filters:
      branches:
        only: main
  notify_slack:
    jobs:
      - run:
          name: "Notify Slack on Success"
          command: echo "Build succeeded!"
          filters:
            branches:
              only: main
          when: on_success
      - run:
          name: "Notify Slack on Failure"
          command: echo "Build failed!"
          filters:
            branches:
              only: main
          when: on_failure

This setup uses CircleCI’s built-in slack_notification feature, which, despite its name, doesn’t require a separate Slack app installation within CircleCI itself. Instead, it leverages a pre-existing mechanism that connects your CircleCI project to a Slack workspace. The key is that CircleCI handles the token exchange and payload formatting behind the scenes.

To make this work, you need to:

  1. Add a Slack Incoming Webhook URL to your CircleCI Project Environment Variables:

    • Go to your CircleCI project settings.
    • Navigate to "Environment Variables."
    • Add a new variable with the key SLACK_KEY and the value being your Slack Incoming Webhook URL. This URL looks like https://hooks.slack.com/services/T00000000/B00000000/XXXXXXXXXXXXXXXXXXXXXXXX.
    • Ensure this variable is set for the specific project and is not "Protected" if you want it to be available in all branches.
  2. Configure the slack_notification in your .circleci/config.yml:

    • You can add this at the workflow level or job level. For a workflow-level notification that triggers on any job completion within that workflow:
    workflows:
      version: 2
      build_and_test_workflow:
        jobs:
          - build_and_test
        slack_notification:
          branch_pattern: main  # Or use default to notify on all branches
          only_on_branch: main  # Optional: only notify on 'main' branch
          # You can also specify job-level notifications if needed
          # jobs:
          #   - build_and_test:
          #       notify_on: [success, failure]
    
    • Or, if you prefer job-level notifications:
    jobs:
      build_and_test:
        docker:
          - image: cimg/node:18.17.0
        steps:
          - checkout
          - run: echo "Running tests..."
          - run: echo "Tests passed!"
        notify_on: [success, failure] # This triggers slack_notification for this job
    
    workflows:
      version: 2
      build_workflow:
        jobs:
          - build_and_test
    
    • The slack_notification block, when present in a workflow or job, automatically uses the SLACK_KEY environment variable. It sends a message to the Slack channel associated with the webhook URL when the specified when condition is met (e.g., on_success, on_failure). CircleCI formats the message with build status, commit details, and a link back to the build.

The most surprising thing about this feature is how seamlessly it integrates without requiring you to manually construct API calls or manage complex OAuth flows. CircleCI handles the payload generation and the HTTP POST request to Slack’s endpoint using just the webhook URL you provide.

When a build starts, CircleCI prepares a payload. If the build succeeds, it sends a JSON object like this to your Slack webhook URL:

{
  "attachments": [
    {
      "fallback": "Build #123 succeeded on branch main",
      "color": "good",
      "title": "Build #123 succeeded",
      "title_link": "https://circleci.com/gh/your-username/your-repo/123",
      "fields": [
        {
          "title": "Project",
          "value": "your-username/your-repo",
          "short": true
        },
        {
          "title": "Branch",
          "value": "main",
          "short": true
        },
        {
          "title": "Commit",
          "value": "abcdef123 (Commit message here)",
          "short": false
        }
      ]
    }
  ]
}

If it fails, the color would be danger, and the title would indicate failure. This JSON is generated by CircleCI itself, based on the build’s metadata.

The branch_pattern and only_on_branch filters in the slack_notification block are crucial for controlling when these notifications are sent. branch_pattern uses globbing (e.g., main, release/*) to match branches, while only_on_branch is a more direct string match. If you omit these, CircleCI will attempt to send notifications for all branches, which can be noisy.

What many users overlook is that the slack_notification directive is a top-level key within a workflow, or can be specified as notify_on within a job. It’s not a separate job itself but a configuration for how a workflow or job should behave in terms of notifications. This means you don’t need to define a whole new job just to send a Slack message; it’s a declarative instruction to CircleCI.

The next step you’ll likely encounter is customizing the Slack message content beyond the default, which involves using a separate run job with curl to post a custom JSON payload to your webhook URL.

Want structured learning?

Take the full Circleci course →