diff --git a/CHANGELOG b/CHANGELOG
index f709758abf621d993759cd0e241de7ffe4bd36b9..cc87ff3ecb75bad0791f5d1cf310e8d0e1f620c4 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -66,6 +66,7 @@ v 8.12.0 (unreleased)
   - Align add button on repository view (ClemMakesApps)
   - Fix contributions calendar month label truncation (ClemMakesApps)
   - Added tests for diff notes
+  - Add pipeline events to Slack integration !5525
   - Add a button to download latest successful artifacts for branches and tags !5142
   - Remove redundant pipeline tooltips (ClemMakesApps)
   - Expire commit info views after one day, instead of two weeks, to allow for user email updates
diff --git a/app/models/project_services/slack_service.rb b/app/models/project_services/slack_service.rb
index e6c943db2bfc9be8ec584a16e99cae2be190b796..e1b937817f4649d7bfd4adbdd10665da35b023ef 100644
--- a/app/models/project_services/slack_service.rb
+++ b/app/models/project_services/slack_service.rb
@@ -1,6 +1,6 @@
 class SlackService < Service
   prop_accessor :webhook, :username, :channel
-  boolean_accessor :notify_only_broken_builds
+  boolean_accessor :notify_only_broken_builds, :notify_only_broken_pipelines
   validates :webhook, presence: true, url: true, if: :activated?
 
   def initialize_properties
@@ -10,6 +10,7 @@ class SlackService < Service
     if properties.nil?
       self.properties = {}
       self.notify_only_broken_builds = true
+      self.notify_only_broken_pipelines = true
     end
   end
 
@@ -38,13 +39,15 @@ class SlackService < Service
         { type: 'text', name: 'username', placeholder: 'username' },
         { type: 'text', name: 'channel', placeholder: "#general" },
         { type: 'checkbox', name: 'notify_only_broken_builds' },
+        { type: 'checkbox', name: 'notify_only_broken_pipelines' },
       ]
 
     default_fields + build_event_channels
   end
 
   def supported_events
-    %w(push issue confidential_issue merge_request note tag_push build wiki_page)
+    %w[push issue confidential_issue merge_request note tag_push
+       build pipeline wiki_page]
   end
 
   def execute(data)
@@ -62,32 +65,22 @@ class SlackService < Service
     # 'close' action. Ignore update events for now to prevent duplicate
     # messages from arriving.
 
-    message = \
-      case object_kind
-      when "push", "tag_push"
-        PushMessage.new(data)
-      when "issue"
-        IssueMessage.new(data) unless is_update?(data)
-      when "merge_request"
-        MergeMessage.new(data) unless is_update?(data)
-      when "note"
-        NoteMessage.new(data)
-      when "build"
-        BuildMessage.new(data) if should_build_be_notified?(data)
-      when "wiki_page"
-        WikiPageMessage.new(data)
-      end
-
-    opt = {}
-
-    event_channel = get_channel_field(object_kind) || channel
-
-    opt[:channel] = event_channel if event_channel
-    opt[:username] = username if username
+    message = get_message(object_kind, data)
 
     if message
+      opt = {}
+
+      event_channel = get_channel_field(object_kind) || channel
+
+      opt[:channel] = event_channel if event_channel
+      opt[:username] = username if username
+
       notifier = Slack::Notifier.new(webhook, opt)
       notifier.ping(message.pretext, attachments: message.attachments, fallback: message.fallback)
+
+      true
+    else
+      false
     end
   end
 
@@ -105,6 +98,25 @@ class SlackService < Service
 
   private
 
+  def get_message(object_kind, data)
+    case object_kind
+    when "push", "tag_push"
+      PushMessage.new(data)
+    when "issue"
+      IssueMessage.new(data) unless is_update?(data)
+    when "merge_request"
+      MergeMessage.new(data) unless is_update?(data)
+    when "note"
+      NoteMessage.new(data)
+    when "build"
+      BuildMessage.new(data) if should_build_be_notified?(data)
+    when "pipeline"
+      PipelineMessage.new(data) if should_pipeline_be_notified?(data)
+    when "wiki_page"
+      WikiPageMessage.new(data)
+    end
+  end
+
   def get_channel_field(event)
     field_name = event_channel_name(event)
     self.public_send(field_name)
@@ -142,6 +154,17 @@ class SlackService < Service
       false
     end
   end
+
+  def should_pipeline_be_notified?(data)
+    case data[:object_attributes][:status]
+    when 'success'
+      !notify_only_broken_pipelines?
+    when 'failed'
+      true
+    else
+      false
+    end
+  end
 end
 
 require "slack_service/issue_message"
@@ -149,4 +172,5 @@ require "slack_service/push_message"
 require "slack_service/merge_message"
 require "slack_service/note_message"
 require "slack_service/build_message"
+require "slack_service/pipeline_message"
 require "slack_service/wiki_page_message"
diff --git a/app/models/project_services/slack_service/build_message.rb b/app/models/project_services/slack_service/build_message.rb
index 69c21b3fc387fdf4ecbf98773ebf468ed8812f87..0fca4267bad8eb3f9246c40cf09e24a823526d0a 100644
--- a/app/models/project_services/slack_service/build_message.rb
+++ b/app/models/project_services/slack_service/build_message.rb
@@ -9,7 +9,7 @@ class SlackService
     attr_reader :user_name
     attr_reader :duration
 
-    def initialize(params, commit = true)
+    def initialize(params)
       @sha = params[:sha]
       @ref_type = params[:tag] ? 'tag' : 'branch'
       @ref = params[:ref]
@@ -36,7 +36,7 @@ class SlackService
 
     def message
       "#{project_link}: Commit #{commit_link} of #{branch_link} #{ref_type} by #{user_name} #{humanized_status} in #{duration} #{'second'.pluralize(duration)}"
-    end   
+    end
 
     def format(string)
       Slack::Notifier::LinkFormatter.format(string)
diff --git a/app/models/project_services/slack_service/pipeline_message.rb b/app/models/project_services/slack_service/pipeline_message.rb
new file mode 100644
index 0000000000000000000000000000000000000000..f06b3562965292b549c0781dc5467c65df282455
--- /dev/null
+++ b/app/models/project_services/slack_service/pipeline_message.rb
@@ -0,0 +1,79 @@
+class SlackService
+  class PipelineMessage < BaseMessage
+    attr_reader :sha, :ref_type, :ref, :status, :project_name, :project_url,
+                :user_name, :duration, :pipeline_id
+
+    def initialize(data)
+      pipeline_attributes = data[:object_attributes]
+      @sha = pipeline_attributes[:sha]
+      @ref_type = pipeline_attributes[:tag] ? 'tag' : 'branch'
+      @ref = pipeline_attributes[:ref]
+      @status = pipeline_attributes[:status]
+      @duration = pipeline_attributes[:duration]
+      @pipeline_id = pipeline_attributes[:id]
+
+      @project_name = data[:project][:path_with_namespace]
+      @project_url = data[:project][:web_url]
+      @user_name = data[:commit] && data[:commit][:author_name]
+    end
+
+    def pretext
+      ''
+    end
+
+    def fallback
+      format(message)
+    end
+
+    def attachments
+      [{ text: format(message), color: attachment_color }]
+    end
+
+    private
+
+    def message
+      "#{project_link}: Pipeline #{pipeline_link} of #{branch_link} #{ref_type} by #{user_name} #{humanized_status} in #{duration} #{'second'.pluralize(duration)}"
+    end
+
+    def format(string)
+      Slack::Notifier::LinkFormatter.format(string)
+    end
+
+    def humanized_status
+      case status
+      when 'success'
+        'passed'
+      else
+        status
+      end
+    end
+
+    def attachment_color
+      if status == 'success'
+        'good'
+      else
+        'danger'
+      end
+    end
+
+    def branch_url
+      "#{project_url}/commits/#{ref}"
+    end
+
+    def branch_link
+      "[#{ref}](#{branch_url})"
+    end
+
+    def project_link
+      "[#{project_name}](#{project_url})"
+    end
+
+    def pipeline_url
+      "#{project_url}/pipelines/#{pipeline_id}"
+    end
+
+    def pipeline_link
+      "[#{Commit.truncate_sha(sha)}](#{pipeline_url})"
+    end
+  end
+end
diff --git a/features/steps/admin/settings.rb b/features/steps/admin/settings.rb
index 03f87df7a60cf02657e813000516fea7dacef500..11dc7f580f03293119157ba1a3cd72744d8907de 100644
--- a/features/steps/admin/settings.rb
+++ b/features/steps/admin/settings.rb
@@ -33,6 +33,7 @@ class Spinach::Features::AdminSettings < Spinach::FeatureSteps
     page.check('Issue')
     page.check('Merge request')
     page.check('Build')
+    page.check('Pipeline')
     click_on 'Save'
   end
 
diff --git a/spec/models/project_services/slack_service/build_message_spec.rb b/spec/models/project_services/slack_service/build_message_spec.rb
index 7fcfdf0eacdd76b11b3b4a0d53278384d7fb1ca7..452f4e2782c80568f71bffc76f8deeaa6438b0ed 100644
--- a/spec/models/project_services/slack_service/build_message_spec.rb
+++ b/spec/models/project_services/slack_service/build_message_spec.rb
@@ -10,7 +10,7 @@ describe SlackService::BuildMessage do
       tag: false,
 
       project_name: 'project_name',
-      project_url: 'somewhere.com',
+      project_url: 'example.gitlab.com',
 
       commit: {
         status: status,
@@ -20,42 +20,38 @@ describe SlackService::BuildMessage do
     }
   end
 
-  context 'succeeded' do
+  let(:message) { build_message }
+
+  context 'build succeeded' do
     let(:status) { 'success' }
     let(:color) { 'good' }
     let(:duration) { 10 }
-    
+    let(:message) { build_message('passed') }
+
     it 'returns a message with information about succeeded build' do
-      message = '<somewhere.com|project_name>: Commit <somewhere.com/commit/97de212e80737a608d939f648d959671fb0a0142/builds|97de212e> of <somewhere.com/commits/develop|develop> branch by hacker passed in 10 seconds'
       expect(subject.pretext).to be_empty
       expect(subject.fallback).to eq(message)
       expect(subject.attachments).to eq([text: message, color: color])
     end
   end
 
-  context 'failed' do
+  context 'build failed' do
     let(:status) { 'failed' }
     let(:color) { 'danger' }
     let(:duration) { 10 }
 
     it 'returns a message with information about failed build' do
-      message = '<somewhere.com|project_name>: Commit <somewhere.com/commit/97de212e80737a608d939f648d959671fb0a0142/builds|97de212e> of <somewhere.com/commits/develop|develop> branch by hacker failed in 10 seconds'
       expect(subject.pretext).to be_empty
       expect(subject.fallback).to eq(message)
       expect(subject.attachments).to eq([text: message, color: color])
     end
-  end 
-  
-  describe '#seconds_name' do
-    let(:status) { 'failed' }
-    let(:color) { 'danger' }
-    let(:duration) { 1 }
+  end
 
-    it 'returns seconds as singular when there is only one' do
-      message = '<somewhere.com|project_name>: Commit <somewhere.com/commit/97de212e80737a608d939f648d959671fb0a0142/builds|97de212e> of <somewhere.com/commits/develop|develop> branch by hacker failed in 1 second'
-      expect(subject.pretext).to be_empty
-      expect(subject.fallback).to eq(message)
-      expect(subject.attachments).to eq([text: message, color: color])
-    end
+  def build_message(status_text = status)
+    "<example.gitlab.com|project_name>:" \
+    " Commit <example.gitlab.com/commit/" \
+    "97de212e80737a608d939f648d959671fb0a0142/builds|97de212e>" \
+    " of <example.gitlab.com/commits/develop|develop> branch" \
+    " by hacker #{status_text} in #{duration} #{'second'.pluralize(duration)}"
   end
 end
diff --git a/spec/models/project_services/slack_service/pipeline_message_spec.rb b/spec/models/project_services/slack_service/pipeline_message_spec.rb
new file mode 100644
index 0000000000000000000000000000000000000000..babb3909f5681eda53d10cb1a47a92bffec15d17
--- /dev/null
+++ b/spec/models/project_services/slack_service/pipeline_message_spec.rb
@@ -0,0 +1,55 @@
+require 'spec_helper'
+
+describe SlackService::PipelineMessage do
+  subject { SlackService::PipelineMessage.new(args) }
+
+  let(:args) do
+    {
+      object_attributes: {
+        id: 123,
+        sha: '97de212e80737a608d939f648d959671fb0a0142',
+        tag: false,
+        ref: 'develop',
+        status: status,
+        duration: duration
+      },
+      project: { path_with_namespace: 'project_name',
+                 web_url: 'example.gitlab.com' },
+      commit: { author_name: 'hacker' }
+    }
+  end
+
+  let(:message) { build_message }
+
+  context 'pipeline succeeded' do
+    let(:status) { 'success' }
+    let(:color) { 'good' }
+    let(:duration) { 10 }
+    let(:message) { build_message('passed') }
+
+    it 'returns a message with information about succeeded build' do
+      expect(subject.pretext).to be_empty
+      expect(subject.fallback).to eq(message)
+      expect(subject.attachments).to eq([text: message, color: color])
+    end
+  end
+
+  context 'pipeline failed' do
+    let(:status) { 'failed' }
+    let(:color) { 'danger' }
+    let(:duration) { 10 }
+
+    it 'returns a message with information about failed build' do
+      expect(subject.pretext).to be_empty
+      expect(subject.fallback).to eq(message)
+      expect(subject.attachments).to eq([text: message, color: color])
+    end
+  end
+
+  def build_message(status_text = status)
+    "<example.gitlab.com|project_name>:" \
+    " Pipeline <example.gitlab.com/pipelines/123|97de212e>" \
+    " of <example.gitlab.com/commits/develop|develop> branch" \
+    " by hacker #{status_text} in #{duration} #{'second'.pluralize(duration)}"
+  end
+end
diff --git a/spec/models/project_services/slack_service_spec.rb b/spec/models/project_services/slack_service_spec.rb
index 28af68d13b49b64ff9fbb0076e528012f5e5d1a2..5afdc4b2f7b6112b022ec3a77e92828466ed8294 100644
--- a/spec/models/project_services/slack_service_spec.rb
+++ b/spec/models/project_services/slack_service_spec.rb
@@ -21,6 +21,9 @@
 require 'spec_helper'
 
 describe SlackService, models: true do
+  let(:slack) { SlackService.new }
+  let(:webhook_url) { 'https://example.gitlab.com/' }
+
   describe "Associations" do
     it { is_expected.to belong_to :project }
     it { is_expected.to have_one :service_hook }
@@ -42,15 +45,14 @@ describe SlackService, models: true do
   end
 
   describe "Execute" do
-    let(:slack)   { SlackService.new }
     let(:user)    { create(:user) }
     let(:project) { create(:project) }
+    let(:username) { 'slack_username' }
+    let(:channel)  { 'slack_channel' }
+
     let(:push_sample_data) do
       Gitlab::DataBuilder::Push.build_sample(project, user)
     end
-    let(:webhook_url) { 'https://hooks.slack.com/services/SVRWFV0VVAR97N/B02R25XN3/ZBqu7xMupaEEICInN685' }
-    let(:username) { 'slack_username' }
-    let(:channel) { 'slack_channel' }
 
     before do
       allow(slack).to receive_messages(
@@ -212,10 +214,8 @@ describe SlackService, models: true do
   end
 
   describe "Note events" do
-    let(:slack)   { SlackService.new }
     let(:user) { create(:user) }
     let(:project) { create(:project, creator_id: user.id) }
-    let(:webhook_url) { 'https://hooks.slack.com/services/SVRWFV0VVAR97N/B02R25XN3/ZBqu7xMupaEEICInN685' }
 
     before do
       allow(slack).to receive_messages(
@@ -285,4 +285,63 @@ describe SlackService, models: true do
       end
     end
   end
+
+  describe 'Pipeline events' do
+    let(:user) { create(:user) }
+    let(:project) { create(:project) }
+
+    let(:pipeline) do
+      create(:ci_pipeline,
+             project: project, status: status,
+             sha: project.commit.sha, ref: project.default_branch)
+    end
+
+    before do
+      allow(slack).to receive_messages(
+        project: project,
+        service_hook: true,
+        webhook: webhook_url
+      )
+    end
+
+    shared_examples 'call Slack API' do
+      before do
+        WebMock.stub_request(:post, webhook_url)
+      end
+
+      it 'calls Slack API for pipeline events' do
+        data = Gitlab::DataBuilder::Pipeline.build(pipeline)
+        slack.execute(data)
+
+        expect(WebMock).to have_requested(:post, webhook_url).once
+      end
+    end
+
+    context 'with failed pipeline' do
+      let(:status) { 'failed' }
+
+      it_behaves_like 'call Slack API'
+    end
+
+    context 'with succeeded pipeline' do
+      let(:status) { 'success' }
+
+      context 'with default to notify_only_broken_pipelines' do
+        it 'does not call Slack API for pipeline events' do
+          data = Gitlab::DataBuilder::Pipeline.build(pipeline)
+          result = slack.execute(data)
+
+          expect(result).to be_falsy
+        end
+      end
+
+      context 'with setting notify_only_broken_pipelines to false' do
+        before do
+          slack.notify_only_broken_pipelines = false
+        end
+
+        it_behaves_like 'call Slack API'
+      end
+    end
+  end
 end