From ae5f124e96504f20500df282d34dce7b0627c212 Mon Sep 17 00:00:00 2001
From: Lin Jen-Shin <godfat@godfat.org>
Date: Thu, 28 Jul 2016 01:16:31 +0800
Subject: [PATCH] WIP, initial work to implement pipeline hooks:

I might be squashing this commit in the future.
---
 app/controllers/projects/hooks_controller.rb  |  1 +
 app/models/ci/pipeline.rb                     |  6 ++
 app/models/hooks/project_hook.rb              |  1 +
 app/models/hooks/web_hook.rb                  |  1 +
 app/models/service.rb                         |  1 +
 ...081025_add_pipeline_events_to_web_hooks.rb | 16 +++++
 ...8103734_add_pipeline_events_to_services.rb | 16 +++++
 .../data_builder/pipeline_data_builder.rb     | 65 +++++++++++++++++++
 8 files changed, 107 insertions(+)
 create mode 100644 db/migrate/20160728081025_add_pipeline_events_to_web_hooks.rb
 create mode 100644 db/migrate/20160728103734_add_pipeline_events_to_services.rb
 create mode 100644 lib/gitlab/data_builder/pipeline_data_builder.rb

diff --git a/app/controllers/projects/hooks_controller.rb b/app/controllers/projects/hooks_controller.rb
index a60027ff477..b5624046387 100644
--- a/app/controllers/projects/hooks_controller.rb
+++ b/app/controllers/projects/hooks_controller.rb
@@ -56,6 +56,7 @@ class Projects::HooksController < Projects::ApplicationController
   def hook_params
     params.require(:hook).permit(
       :build_events,
+      :pipeline_events,
       :enable_ssl_verification,
       :issues_events,
       :merge_requests_events,
diff --git a/app/models/ci/pipeline.rb b/app/models/ci/pipeline.rb
index bce6a992af6..bf6d872dece 100644
--- a/app/models/ci/pipeline.rb
+++ b/app/models/ci/pipeline.rb
@@ -213,6 +213,12 @@ module Ci
       ]
     end
 
+    def execute_hooks
+      pipeline_data = Gitlab::DataBuilder::PipelineDataBuilder.build(self)
+      project.execute_hooks(pipeline_data.dup, :pipeline_hooks)
+      project.execute_services(pipeline_data.dup, :pipeline_hooks)
+    end
+
     private
 
     def build_builds_for_stages(stages, user, status, trigger_request)
diff --git a/app/models/hooks/project_hook.rb b/app/models/hooks/project_hook.rb
index ba42a8eeb70..836a75b0608 100644
--- a/app/models/hooks/project_hook.rb
+++ b/app/models/hooks/project_hook.rb
@@ -5,5 +5,6 @@ class ProjectHook < WebHook
   scope :note_hooks, -> { where(note_events: true) }
   scope :merge_request_hooks, -> { where(merge_requests_events: true) }
   scope :build_hooks, -> { where(build_events: true) }
+  scope :pipeline_hooks, -> { where(pipeline_events: true) }
   scope :wiki_page_hooks, ->  { where(wiki_page_events: true) }
 end
diff --git a/app/models/hooks/web_hook.rb b/app/models/hooks/web_hook.rb
index 8b87b6c3d64..f365dee3141 100644
--- a/app/models/hooks/web_hook.rb
+++ b/app/models/hooks/web_hook.rb
@@ -8,6 +8,7 @@ class WebHook < ActiveRecord::Base
   default_value_for :merge_requests_events, false
   default_value_for :tag_push_events, false
   default_value_for :build_events, false
+  default_value_for :pipeline_events, false
   default_value_for :enable_ssl_verification, true
 
   scope :push_hooks, -> { where(push_events: true) }
diff --git a/app/models/service.rb b/app/models/service.rb
index 40cd9b861f0..4a63abb2724 100644
--- a/app/models/service.rb
+++ b/app/models/service.rb
@@ -36,6 +36,7 @@ class Service < ActiveRecord::Base
   scope :merge_request_hooks, -> { where(merge_requests_events: true, active: true) }
   scope :note_hooks, -> { where(note_events: true, active: true) }
   scope :build_hooks, -> { where(build_events: true, active: true) }
+  scope :pipeline_hooks, -> { where(pipeline_events: true, active: true) }
   scope :wiki_page_hooks, -> { where(wiki_page_events: true, active: true) }
   scope :external_issue_trackers, -> { issue_trackers.active.without_defaults }
 
diff --git a/db/migrate/20160728081025_add_pipeline_events_to_web_hooks.rb b/db/migrate/20160728081025_add_pipeline_events_to_web_hooks.rb
new file mode 100644
index 00000000000..b800e6d7283
--- /dev/null
+++ b/db/migrate/20160728081025_add_pipeline_events_to_web_hooks.rb
@@ -0,0 +1,16 @@
+class AddPipelineEventsToWebHooks < ActiveRecord::Migration
+  include Gitlab::Database::MigrationHelpers
+
+  DOWNTIME = false
+
+  disable_ddl_transaction!
+
+  def up
+    add_column_with_default(:web_hooks, :pipeline_events, :boolean,
+                            default: false, allow_null: false)
+  end
+
+  def down
+    remove_column(:web_hooks, :pipeline_events)
+  end
+end
diff --git a/db/migrate/20160728103734_add_pipeline_events_to_services.rb b/db/migrate/20160728103734_add_pipeline_events_to_services.rb
new file mode 100644
index 00000000000..bcd24fe1566
--- /dev/null
+++ b/db/migrate/20160728103734_add_pipeline_events_to_services.rb
@@ -0,0 +1,16 @@
+class AddPipelineEventsToServices < ActiveRecord::Migration
+  include Gitlab::Database::MigrationHelpers
+
+  DOWNTIME = false
+
+  disable_ddl_transaction!
+
+  def up
+    add_column_with_default(:services, :pipeline_events, :boolean,
+                            default: false, allow_null: false)
+  end
+
+  def down
+    remove_column(:services, :pipeline_events)
+  end
+end
diff --git a/lib/gitlab/data_builder/pipeline_data_builder.rb b/lib/gitlab/data_builder/pipeline_data_builder.rb
new file mode 100644
index 00000000000..a9c1bc7acee
--- /dev/null
+++ b/lib/gitlab/data_builder/pipeline_data_builder.rb
@@ -0,0 +1,65 @@
+module Gitlab
+  module DataBuilder
+    module PipelineDataBuilder
+      module_function
+
+      def build(pipeline)
+        {
+          object_kind: 'pipeline',
+          user: pipeline.user.hook_attrs,
+          project: pipeline.project.hook_attrs(backward: false),
+          commit: pipeline.commit.hook_attrs,
+          object_attributes: hook_attrs(pipeline),
+          builds: pipeline.builds.map(&method(:build_hook_attrs))
+        }
+      end
+
+      def hook_attrs(pipeline)
+        first_pending_build = pipeline.builds.first_pending
+        config_processor = pipeline.config_processor
+
+        {
+          id: pipeline.id,
+          ref: pipeline.ref,
+          tag: pipeline.tag,
+          sha: pipeline.sha,
+          before_sha: pipeline.before_sha,
+          status: pipeline.status,
+          stage: first_pending_build.try(:stage),
+          stages: config_processor.try(:stages),
+          created_at: pipeline.created_at,
+          finished_at: pipeline.finished_at
+        }
+      end
+
+      def build_hook_attrs(build)
+        {
+          id: build.id,
+          stage: build.stage,
+          name: build.name,
+          status: build.status,
+          created_at: build.created_at,
+          started_at: build.started_at,
+          finished_at: build.finished_at,
+          when: build.when,
+          manual: build.manual?,
+          user: build.user.hook_attrs,
+          runner: runner_hook_attrs(build.runner),
+          artifacts_file: {
+            filename: build.artifacts_file.filename,
+            size: build.artifacts_size
+          }
+        }
+      end
+
+      def runner_hook_attrs(runner)
+        {
+          id: runner.id,
+          description: runner.description,
+          active: runner.active?,
+          is_shared: runner.is_shared?
+        }
+      end
+    end
+  end
+end
-- 
GitLab