PRFlow

August 12, 2026 · 5 min read

GitLab pipeline Slack notifications, explained

You want GitLab to tell Slack when a pipeline passes or fails. There are three ways to do it, and they mostly differ on one thing: whether the result lands as its own message, or on the merge request it belongs to. Here's how each works, with the tradeoffs.

"Get pipeline status into Slack" sounds like a single setting. In practice it's a choice between the native app that GitLab ships, a webhook you wire up yourself, and a tool that keeps one message per MR in sync. The right pick depends on how much channel noise you can stand and whether you care about seeing CI status on the merge request rather than in a separate ping.

The 60-second version

  • The native GitLab for Slack app posts pipeline events to a channel, with a "Notify only broken pipelines" filter and a "Notify only when status changes" filter. Free, both editions.
  • DIY webhooks carry the result in object_attributes.status on pipeline events; you relay it to Slack. It works, but every event is its own message.
  • The hard part is putting pipeline pass/fail on the merge request's own message. MR events carry head_pipeline_id, not the status, so you correlate two event streams yourself.

Option 1: the native GitLab for Slack app

The GitLab for Slack app is GitLab's own app, and pipeline events are one of the event types it can post to a channel. It's free on Free, Premium, and Ultimate, and it's the fastest way to get CI results into Slack without writing code.

Two settings make it usable instead of deafening:

  • Notify only broken pipelines limits pipeline notifications to failed pipelines, so a green run stays quiet.
  • Notify only when status changes notifies only when the pipeline status for the ref actually changes, which cuts the repeat pings on retried or restarted pipelines.

You can send each event to up to 10 Slack channels, so a broken-pipeline alert can fan out to the team channel and an on-call channel at once. The tradeoff is the one every native-app user meets: it sends a separate message per event. The pipeline result arrives as its own line in the channel, unconnected to the merge request message that triggered it.

Option 2: DIY with GitLab pipeline webhooks

If you want control over formatting or routing, wire it yourself. Turn on "Pipeline events" in GitLab project webhooks and GitLab POSTs JSON on every pipeline state change. The status you want is in object_attributes.status (values like success, failed, running, canceled), and object_attributes.detailed_status carries a display string such as passed that reads better in a message.

Two things bite here, and both are worth knowing before you build:

  • A Slack incoming webhook can only create a message. Updating a status in place needs the chat.update Web API with a bot token plus the stored channel and message ts. So a plain incoming webhook gives you a new message per state, not a single line that flips from running to passed.
  • GitLab automatically disables a webhook that fails four consecutive times (temporarily, backing off up to 24 hours) and permanently after 40. A flaky receiver stops delivering CI results quietly, so you need monitoring on the receiver, not just the happy path.

The hard part: pipeline status on the MR message

Most teams don't actually want a pipeline ping floating loose in the channel. They want to look at the merge request notification and see whether its build is green. That's the request that's genuinely awkward, because GitLab treats merge request state and pipeline state as separate events.

A "Merge request events" payload does not carry the pipeline status. It carries head_pipeline_id, the identifier of the MR's head pipeline. To render pass/fail on the MR's own Slack message you have to keep state keyed by merge request, match each incoming pipeline event back to the MR that owns it, and edit the existing Slack message with chat.update. That's a small stateful service, not a webhook config. It's doable, but budget it as an engineering project rather than an afternoon.

Full disclosure: we make PRFlow, which does exactly that correlation for you. It posts one Slack message per merge request that updates in place, with the pipeline pass/fail shown on that same message, and it stays read-only on GitLab (the read_api scope, never write). If you're weighing it against GitLab's app, here's the honest comparison with the native GitLab for Slack app.

Which one should you pick?

  • Want CI results in Slack today, no code, and can accept a separate message? The native GitLab for Slack app, with "Notify only broken pipelines" turned on.
  • Have bespoke formatting or routing needs and the engineering time? DIY pipeline webhooks, knowing you'll add a bot token and state to get anything better than create-only messages.
  • Want pass/fail on the merge request message without building the correlation? A consolidation tool that keeps one message per MR in sync.

Bottom line

Getting a pipeline result into Slack is easy. Getting it onto the merge request it belongs to is the part that separates a five-minute setup from a real build. Decide which one you actually want before you start, and if the answer is CI-on-the-MR, don't underestimate the state you'll have to keep. For a wider view of every way to connect the two, see the GitLab Slack integration guide, or the GitLab integration overview.

Frequently asked questions

Getting GitLab pipeline status into Slack, answered

Can the GitLab for Slack app notify only on failed pipelines?
Yes. In the pipeline event settings there is a Notify only broken pipelines checkbox that limits notifications to failed pipelines, and a separate Notify only when status changes checkbox that suppresses repeat notifications for the same status.
Where is the pipeline status in a GitLab webhook?
On Pipeline events the status is in object_attributes.status (for example success or failed), and object_attributes.detailed_status carries a display string such as passed. Merge request events do not include pipeline status; they carry head_pipeline_id, which you use to look the status up.
Why doesn't the merge request message show pipeline status?
Because GitLab sends merge request state and pipeline state as separate webhook events. To show pass or fail on the MR's own Slack message you have to correlate the two event streams yourself and edit the message in place, or use a tool that does it for you.
Do GitLab pipeline Slack notifications work on self-hosted GitLab?
Yes. The native GitLab for Slack app supports self-managed instances since 16.2, and DIY webhooks and third-party tools work on self-hosted GitLab too. The setup for the native app is heavier on self-managed because an administrator has to create and enable the Slack app first.

Want pipeline status on the MR message?

PRFlow posts one Slack message per merge request that updates in place, with CI/CD pipeline status on that same message, on gitlab.com and self-hosted GitLab.

Try PRFlow Free

Or read the native GitLab Slack comparison first.