Commit cd848910 authored by Robert Speicher's avatar Robert Speicher Committed by Ruben Davila

Merge branch 'pipeline-hooks-without-slack' into 'master'

Implement pipeline hooks, extracted from !5525

Closes #20115

See merge request !5620
parent 24477045
...@@ -95,6 +95,7 @@ v 8.11.0 (unreleased) ...@@ -95,6 +95,7 @@ v 8.11.0 (unreleased)
- The overhead of instrumented method calls has been reduced - The overhead of instrumented method calls has been reduced
- Remove `search_id` of labels dropdown filter to fix 'Missleading URI for labels in Merge Requests and Issues view'. !5368 (Scott Le) - Remove `search_id` of labels dropdown filter to fix 'Missleading URI for labels in Merge Requests and Issues view'. !5368 (Scott Le)
- Load project invited groups and members eagerly in `ProjectTeam#fetch_members` - Load project invited groups and members eagerly in `ProjectTeam#fetch_members`
- Add pipeline events hook
- Bump gitlab_git to speedup DiffCollection iterations - Bump gitlab_git to speedup DiffCollection iterations
- Rewrite description of a blocked user in admin settings. (Elias Werberich) - Rewrite description of a blocked user in admin settings. (Elias Werberich)
- Make branches sortable without push permission !5462 (winniehell) - Make branches sortable without push permission !5462 (winniehell)
......
...@@ -7,11 +7,16 @@ module ServiceParams ...@@ -7,11 +7,16 @@ module ServiceParams
:build_key, :server, :teamcity_url, :drone_url, :build_type, :build_key, :server, :teamcity_url, :drone_url, :build_type,
:description, :issues_url, :new_issue_url, :restrict_to_branch, :channel, :description, :issues_url, :new_issue_url, :restrict_to_branch, :channel,
:colorize_messages, :channels, :colorize_messages, :channels,
:push_events, :issues_events, :merge_requests_events, :tag_push_events, # We're using `issues_events` and `merge_requests_events`
:note_events, :build_events, :wiki_page_events, # in the view so we still need to explicitly state them
:notify_only_broken_builds, :add_pusher, # here. `Service#event_names` would only give
:send_from_committer_email, :disable_diffs, :external_wiki_url, # `issue_events` and `merge_request_events` (singular!)
:notify, :color, # See app/helpers/services_helper.rb for how we
# make those event names plural as special case.
:issues_events, :merge_requests_events,
:notify_only_broken_builds, :notify_only_broken_pipelines,
:add_pusher, :send_from_committer_email, :disable_diffs,
:external_wiki_url, :notify, :color,
:server_host, :server_port, :default_irc_uri, :enable_ssl_verification, :server_host, :server_port, :default_irc_uri, :enable_ssl_verification,
:jira_issue_transition_id] :jira_issue_transition_id]
...@@ -19,9 +24,7 @@ module ServiceParams ...@@ -19,9 +24,7 @@ module ServiceParams
FILTER_BLANK_PARAMS = [:password] FILTER_BLANK_PARAMS = [:password]
def service_params def service_params
dynamic_params = [] dynamic_params = @service.event_channel_names + @service.event_names
dynamic_params.concat(@service.event_channel_names)
service_params = params.permit(:id, service: ALLOWED_PARAMS + dynamic_params) service_params = params.permit(:id, service: ALLOWED_PARAMS + dynamic_params)
if service_params[:service].is_a?(Hash) if service_params[:service].is_a?(Hash)
......
...@@ -56,6 +56,7 @@ class Projects::HooksController < Projects::ApplicationController ...@@ -56,6 +56,7 @@ class Projects::HooksController < Projects::ApplicationController
def hook_params def hook_params
params.require(:hook).permit( params.require(:hook).permit(
:build_events, :build_events,
:pipeline_events,
:enable_ssl_verification, :enable_ssl_verification,
:issues_events, :issues_events,
:merge_requests_events, :merge_requests_events,
......
...@@ -345,7 +345,7 @@ module Ci ...@@ -345,7 +345,7 @@ module Ci
def execute_hooks def execute_hooks
return unless project return unless project
build_data = Gitlab::BuildDataBuilder.build(self) build_data = Gitlab::DataBuilder::Build.build(self)
project.execute_hooks(build_data.dup, :build_hooks) project.execute_hooks(build_data.dup, :build_hooks)
project.execute_services(build_data.dup, :build_hooks) project.execute_services(build_data.dup, :build_hooks)
project.running_or_pending_build_count(force: true) project.running_or_pending_build_count(force: true)
......
...@@ -19,6 +19,8 @@ module Ci ...@@ -19,6 +19,8 @@ module Ci
after_save :keep_around_commits after_save :keep_around_commits
delegate :stages, to: :statuses
state_machine :status, initial: :created do state_machine :status, initial: :created do
event :enqueue do event :enqueue do
transition created: :pending transition created: :pending
...@@ -56,6 +58,10 @@ module Ci ...@@ -56,6 +58,10 @@ module Ci
before_transition do |pipeline| before_transition do |pipeline|
pipeline.update_duration pipeline.update_duration
end end
after_transition do |pipeline, transition|
pipeline.execute_hooks unless transition.loopback?
end
end end
# ref can't be HEAD or SHA, can only be branch/tag name # ref can't be HEAD or SHA, can only be branch/tag name
...@@ -255,8 +261,18 @@ module Ci ...@@ -255,8 +261,18 @@ module Ci
self.duration = calculate_duration self.duration = calculate_duration
end end
def execute_hooks
data = pipeline_data
project.execute_hooks(data, :pipeline_hooks)
project.execute_services(data, :pipeline_hooks)
end
private private
def pipeline_data
Gitlab::DataBuilder::Pipeline.build(self)
end
def latest_builds_status def latest_builds_status
return 'failed' unless yaml_errors.blank? return 'failed' unless yaml_errors.blank?
......
...@@ -5,5 +5,6 @@ class ProjectHook < WebHook ...@@ -5,5 +5,6 @@ class ProjectHook < WebHook
scope :note_hooks, -> { where(note_events: true) } scope :note_hooks, -> { where(note_events: true) }
scope :merge_request_hooks, -> { where(merge_requests_events: true) } scope :merge_request_hooks, -> { where(merge_requests_events: true) }
scope :build_hooks, -> { where(build_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) } scope :wiki_page_hooks, -> { where(wiki_page_events: true) }
end end
...@@ -8,6 +8,7 @@ class WebHook < ActiveRecord::Base ...@@ -8,6 +8,7 @@ class WebHook < ActiveRecord::Base
default_value_for :merge_requests_events, false default_value_for :merge_requests_events, false
default_value_for :tag_push_events, false default_value_for :tag_push_events, false
default_value_for :build_events, false default_value_for :build_events, false
default_value_for :pipeline_events, false
default_value_for :enable_ssl_verification, true default_value_for :enable_ssl_verification, true
scope :push_hooks, -> { where(push_events: true) } scope :push_hooks, -> { where(push_events: true) }
......
...@@ -51,8 +51,7 @@ class BuildsEmailService < Service ...@@ -51,8 +51,7 @@ class BuildsEmailService < Service
end end
def test_data(project = nil, user = nil) def test_data(project = nil, user = nil)
build = project.builds.last Gitlab::DataBuilder::Build.build(project.builds.last)
Gitlab::BuildDataBuilder.build(build)
end end
def fields def fields
......
...@@ -36,6 +36,7 @@ class Service < ActiveRecord::Base ...@@ -36,6 +36,7 @@ class Service < ActiveRecord::Base
scope :merge_request_hooks, -> { where(merge_requests_events: true, active: true) } scope :merge_request_hooks, -> { where(merge_requests_events: true, active: true) }
scope :note_hooks, -> { where(note_events: true, active: true) } scope :note_hooks, -> { where(note_events: true, active: true) }
scope :build_hooks, -> { where(build_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 :wiki_page_hooks, -> { where(wiki_page_events: true, active: true) }
scope :external_issue_trackers, -> { issue_trackers.active.without_defaults } scope :external_issue_trackers, -> { issue_trackers.active.without_defaults }
...@@ -79,13 +80,17 @@ class Service < ActiveRecord::Base ...@@ -79,13 +80,17 @@ class Service < ActiveRecord::Base
end end
def test_data(project, user) def test_data(project, user)
Gitlab::PushDataBuilder.build_sample(project, user) Gitlab::DataBuilder::Push.build_sample(project, user)
end end
def event_channel_names def event_channel_names
[] []
end end
def event_names
supported_events.map { |event| "#{event}_events" }
end
def event_field(event) def event_field(event)
nil nil
end end
......
...@@ -39,7 +39,12 @@ class DeleteBranchService < BaseService ...@@ -39,7 +39,12 @@ class DeleteBranchService < BaseService
end end
def build_push_data(branch) def build_push_data(branch)
Gitlab::PushDataBuilder Gitlab::DataBuilder::Push.build(
.build(project, current_user, branch.target.sha, Gitlab::Git::BLANK_SHA, "#{Gitlab::Git::BRANCH_REF_PREFIX}#{branch.name}", []) project,
current_user,
branch.target.sha,
Gitlab::Git::BLANK_SHA,
"#{Gitlab::Git::BRANCH_REF_PREFIX}#{branch.name}",
[])
end end
end end
...@@ -33,7 +33,12 @@ class DeleteTagService < BaseService ...@@ -33,7 +33,12 @@ class DeleteTagService < BaseService
end end
def build_push_data(tag) def build_push_data(tag)
Gitlab::PushDataBuilder Gitlab::DataBuilder::Push.build(
.build(project, current_user, tag.target.sha, Gitlab::Git::BLANK_SHA, "#{Gitlab::Git::TAG_REF_PREFIX}#{tag.name}", []) project,
current_user,
tag.target.sha,
Gitlab::Git::BLANK_SHA,
"#{Gitlab::Git::TAG_REF_PREFIX}#{tag.name}",
[])
end end
end end
...@@ -138,13 +138,23 @@ class GitPushService < BaseService ...@@ -138,13 +138,23 @@ class GitPushService < BaseService
end end
def build_push_data def build_push_data
@push_data ||= Gitlab::PushDataBuilder. @push_data ||= Gitlab::DataBuilder::Push.build(
build(@project, current_user, params[:oldrev], params[:newrev], params[:ref], push_commits) @project,
current_user,
params[:oldrev],
params[:newrev],
params[:ref],
push_commits)
end end
def build_push_data_system_hook def build_push_data_system_hook
@push_data_system ||= Gitlab::PushDataBuilder. @push_data_system ||= Gitlab::DataBuilder::Push.build(
build(@project, current_user, params[:oldrev], params[:newrev], params[:ref], []) @project,
current_user,
params[:oldrev],
params[:newrev],
params[:ref],
[])
end end
def push_to_existing_branch? def push_to_existing_branch?
......
...@@ -34,12 +34,24 @@ class GitTagPushService < BaseService ...@@ -34,12 +34,24 @@ class GitTagPushService < BaseService
end end
end end
Gitlab::PushDataBuilder. Gitlab::DataBuilder::Push.build(
build(project, current_user, params[:oldrev], params[:newrev], params[:ref], commits, message) project,
current_user,
params[:oldrev],
params[:newrev],
params[:ref],
commits,
message)
end end
def build_system_push_data def build_system_push_data
Gitlab::PushDataBuilder. Gitlab::DataBuilder::Push.build(
build(project, current_user, params[:oldrev], params[:newrev], params[:ref], [], '') project,
current_user,
params[:oldrev],
params[:newrev],
params[:ref],
[],
'')
end end
end end
...@@ -16,7 +16,7 @@ module Notes ...@@ -16,7 +16,7 @@ module Notes
end end
def hook_data def hook_data
Gitlab::NoteDataBuilder.build(@note, @note.author) Gitlab::DataBuilder::Note.build(@note, @note.author)
end end
def execute_note_hooks def execute_note_hooks
......
class TestHookService class TestHookService
def execute(hook, current_user) def execute(hook, current_user)
data = Gitlab::PushDataBuilder.build_sample(hook.project, current_user) data = Gitlab::DataBuilder::Push.build_sample(hook.project, current_user)
hook.execute(data, 'push_hooks') hook.execute(data, 'push_hooks')
end end
end end
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
.col-md-8.col-lg-7 .col-md-8.col-lg-7
%strong.light-header= hook.url %strong.light-header= hook.url
%div %div
- %w(push_events tag_push_events issues_events note_events merge_requests_events build_events wiki_page_events).each do |trigger| - %w(push_events tag_push_events issues_events note_events merge_requests_events build_events pipeline_events wiki_page_events).each do |trigger|
- if hook.send(trigger) - if hook.send(trigger)
%span.label.label-gray.deploy-project-label= trigger.titleize %span.label.label-gray.deploy-project-label= trigger.titleize
.col-md-4.col-lg-5.text-right-lg.prepend-top-5 .col-md-4.col-lg-5.text-right-lg.prepend-top-5
......
...@@ -29,49 +29,56 @@ ...@@ -29,49 +29,56 @@
= f.label :push_events, class: 'list-label' do = f.label :push_events, class: 'list-label' do
%strong Push events %strong Push events
%p.light %p.light
This url will be triggered by a push to the repository This URL will be triggered by a push to the repository
%li %li
= f.check_box :tag_push_events, class: 'pull-left' = f.check_box :tag_push_events, class: 'pull-left'
.prepend-left-20 .prepend-left-20
= f.label :tag_push_events, class: 'list-label' do = f.label :tag_push_events, class: 'list-label' do
%strong Tag push events %strong Tag push events
%p.light %p.light
This url will be triggered when a new tag is pushed to the repository This URL will be triggered when a new tag is pushed to the repository
%li %li
= f.check_box :note_events, class: 'pull-left' = f.check_box :note_events, class: 'pull-left'
.prepend-left-20 .prepend-left-20
= f.label :note_events, class: 'list-label' do = f.label :note_events, class: 'list-label' do
%strong Comments %strong Comments
%p.light %p.light
This url will be triggered when someone adds a comment This URL will be triggered when someone adds a comment
%li %li
= f.check_box :issues_events, class: 'pull-left' = f.check_box :issues_events, class: 'pull-left'
.prepend-left-20 .prepend-left-20
= f.label :issues_events, class: 'list-label' do = f.label :issues_events, class: 'list-label' do
%strong Issues events %strong Issues events
%p.light %p.light
This url will be triggered when an issue is created/updated/merged This URL will be triggered when an issue is created/updated/merged
%li %li
= f.check_box :merge_requests_events, class: 'pull-left' = f.check_box :merge_requests_events, class: 'pull-left'
.prepend-left-20 .prepend-left-20
= f.label :merge_requests_events, class: 'list-label' do = f.label :merge_requests_events, class: 'list-label' do
%strong Merge Request events %strong Merge Request events
%p.light %p.light
This url will be triggered when a merge request is created/updated/merged This URL will be triggered when a merge request is created/updated/merged
%li %li
= f.check_box :build_events, class: 'pull-left' = f.check_box :build_events, class: 'pull-left'
.prepend-left-20 .prepend-left-20
= f.label :build_events, class: 'list-label' do = f.label :build_events, class: 'list-label' do
%strong Build events %strong Build events
%p.light %p.light
This url will be triggered when the build status changes This URL will be triggered when the build status changes
%li
= f.check_box :pipeline_events, class: 'pull-left'
.prepend-left-20
= f.label :pipeline_events, class: 'list-label' do
%strong Pipeline events
%p.light
This URL will be triggered when the pipeline status changes
%li %li
= f.check_box :wiki_page_events, class: 'pull-left' = f.check_box :wiki_page_events, class: 'pull-left'
.prepend-left-20 .prepend-left-20
= f.label :wiki_page_events, class: 'list-label' do = f.label :wiki_page_events, class: 'list-label' do
%strong Wiki Page events %strong Wiki Page events
%p.light %p.light
This url will be triggered when a wiki page is created/updated This URL will be triggered when a wiki page is created/updated
.form-group .form-group
= f.label :enable_ssl_verification, "SSL verification", class: 'label-light checkbox' = f.label :enable_ssl_verification, "SSL verification", class: 'label-light checkbox'
.checkbox .checkbox
......
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
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
...@@ -924,6 +924,7 @@ ActiveRecord::Schema.define(version: 20160818205718) do ...@@ -924,6 +924,7 @@ ActiveRecord::Schema.define(version: 20160818205718) do
t.string "category", default: "common", null: false t.string "category", default: "common", null: false
t.boolean "default", default: false t.boolean "default", default: false
t.boolean "wiki_page_events", default: true t.boolean "wiki_page_events", default: true
t.boolean "pipeline_events", default: false, null: false
end end
add_index "services", ["project_id"], name: "index_services_on_project_id", using: :btree add_index "services", ["project_id"], name: "index_services_on_project_id", using: :btree
...@@ -1138,6 +1139,7 @@ ActiveRecord::Schema.define(version: 20160818205718) do ...@@ -1138,6 +1139,7 @@ ActiveRecord::Schema.define(version: 20160818205718) do
t.boolean "build_events", default: false, null: false t.boolean "build_events", default: false, null: false
t.boolean "wiki_page_events", default: false, null: false t.boolean "wiki_page_events", default: false, null: false
t.string "token" t.string "token"
t.boolean "pipeline_events", default: false, null: false
end end
add_index "web_hooks", ["project_id"], name: "index_web_hooks_on_project_id", using: :btree add_index "web_hooks", ["project_id"], name: "index_web_hooks_on_project_id", using: :btree
......
...@@ -754,6 +754,174 @@ X-Gitlab-Event: Wiki Page Hook ...@@ -754,6 +754,174 @@ X-Gitlab-Event: Wiki Page Hook
} }
``` ```
## Pipeline events
Triggered on status change of Pipeline.
**Request Header**:
```
X-Gitlab-Event: Pipeline Hook
```
**Request Body**:
```json
{
"object_kind": "pipeline",
"object_attributes":{
"id": 31,
"ref": "master",
"tag": false,
"sha": "bcbb5ec396a2c0f828686f14fac9b80b780504f2",
"before_sha": "bcbb5ec396a2c0f828686f14fac9b80b780504f2",
"status": "success",
"stages":[
"build",
"test",
"deploy"
],
"created_at": "2016-08-12 15:23:28 UTC",
"finished_at": "2016-08-12 15:26:29 UTC",
"duration": 63
},
"user":{
"name": "Administrator",
"username": "root",
"avatar_url": "http://www.gravatar.com/avatar/e32bd13e2add097461cb96824b7a829c?s=80\u0026d=identicon"
},
"project":{
"name": "Gitlab Test",
"description": "Atque in sunt eos similique dolores voluptatem.",
"web_url": "http://192.168.64.1:3005/gitlab-org/gitlab-test",
"avatar_url": null,
"git_ssh_url": "git@192.168.64.1:gitlab-org/gitlab-test.git",
"git_http_url": "http://192.168.64.1:3005/gitlab-org/gitlab-test.git",
"namespace": "Gitlab Org",
"visibility_level": 20,
"path_with_namespace": "gitlab-org/gitlab-test",
"default_branch": "master"
},
"commit":{
"id": "bcbb5ec396a2c0f828686f14fac9b80b780504f2",
"message": "test\n",
"timestamp": "2016-08-12T17:23:21+02:00",
"url": "http://example.com/gitlab-org/gitlab-test/commit/bcbb5ec396a2c0f828686f14fac9b80b780504f2",
"author":{
"name": "User",
"email": "user@gitlab.com"
}
},
"builds":[
{
"id": 380,
"stage": "deploy",
"name": "production",
"status": "skipped",
"created_at": "2016-08-12 15:23:28 UTC",
"started_at": null,
"finished_at": null,
"when": "manual",
"manual": true,
"user":{
"name": "Administrator",
"username": "root",
"avatar_url": "http://www.gravatar.com/avatar/e32bd13e2add097461cb96824b7a829c?s=80\u0026d=identicon"
},
"runner": null,
"artifacts_file":{
"filename": null,
"size": null
}
},
{
"id": 377,
"stage": "test",
"name": "test-image",
"status": "success",
"created_at": "2016-08-12 15:23:28 UTC",
"started_at": "2016-08-12 15:26:12 UTC",
"finished_at": null,
"when": "on_success",
"manual": false,
"user":{
"name": "Administrator",
"username": "root",
"avatar_url": "http://www.gravatar.com/avatar/e32bd13e2add097461cb96824b7a829c?s=80\u0026d=identicon"
},
"runner": null,
"artifacts_file":{
"filename": null,
"size": null
}
},
{
"id": 378,
"stage": "test",
"name": "test-build",
"status": "success",
"created_at": "2016-08-12 15:23:28 UTC",
"started_at": "2016-08-12 15:26:12 UTC",
"finished_at": "2016-08-12 15:26:29 UTC",
"when": "on_success",
"manual": false,
"user":{
"name": "Administrator",
"username": "root",
"avatar_url": "http://www.gravatar.com/avatar/e32bd13e2add097461cb96824b7a829c?s=80\u0026d=identicon"
},
"runner": null,
"artifacts_file":{
"filename": null,
"size": null
}
},
{
"id": 376,
"stage": "build",
"name": "build-image",
"status": "success",
"created_at": "2016-08-12 15:23:28 UTC",
"started_at": "2016-08-12 15:24:56 UTC",
"finished_at": "2016-08-12 15:25:26 UTC",
"when": "on_success",
"manual": false,
"user":{
"name": "Administrator",
"username": "root",
"avatar_url": "http://www.gravatar.com/avatar/e32bd13e2add097461cb96824b7a829c?s=80\u0026d=identicon"
},
"runner": null,
"artifacts_file":{
"filename": null,
"size": null
}
},
{
"id": 379,
"stage": "deploy",
"name": "staging",
"status": "created",
"created_at": "2016-08-12 15:23:28 UTC",
"started_at": null,
"finished_at": null,
"when": "on_success",
"manual": false,
"user":{
"name": "Administrator",
"username": "root",
"avatar_url": "http://www.gravatar.com/avatar/e32bd13e2add097461cb96824b7a829c?s=80\u0026d=identicon"
},
"runner": null,
"artifacts_file":{
"filename": null,
"size": null
}
}
]
}
```
#### Example webhook receiver #### Example webhook receiver
If you want to see GitLab's webhooks in action for testing purposes you can use If you want to see GitLab's webhooks in action for testing purposes you can use
......
...@@ -48,7 +48,8 @@ module API ...@@ -48,7 +48,8 @@ module API
class ProjectHook < Hook class ProjectHook < Hook
expose :project_id, :push_events expose :project_id, :push_events
expose :issues_events, :merge_requests_events, :tag_push_events, :note_events, :build_events expose :issues_events, :merge_requests_events, :tag_push_events
expose :note_events, :build_events, :pipeline_events
expose :enable_ssl_verification expose :enable_ssl_verification
end end
...@@ -350,7 +351,8 @@ module API ...@@ -350,7 +351,8 @@ module API
class ProjectService < Grape::Entity class ProjectService < Grape::Entity
expose :id, :title, :created_at, :updated_at, :active expose :id, :title, :created_at, :updated_at, :active
expose :push_events, :issues_events, :merge_requests_events, :tag_push_events, :note_events, :build_events expose :push_events, :issues_events, :merge_requests_events
expose :tag_push_events, :note_events, :build_events, :pipeline_events
# Expose serialized properties # Expose serialized properties
expose :properties do |service, options| expose :properties do |service, options|
field_names = service.fields. field_names = service.fields.
......
...@@ -45,6 +45,7 @@ module API ...@@ -45,6 +45,7 @@ module API
:tag_push_events, :tag_push_events,
:note_events, :note_events,
:build_events, :build_events,
:pipeline_events,
:enable_ssl_verification :enable_ssl_verification
] ]
@hook = user_project.hooks.new(attrs) @hook = user_project.hooks.new(attrs)
...@@ -78,6 +79,7 @@ module API ...@@ -78,6 +79,7 @@ module API
:tag_push_events, :tag_push_events,
:note_events, :note_events,
:build_events, :build_events,
:pipeline_events,
:enable_ssl_verification :enable_ssl_verification
] ]
......
module Gitlab module Gitlab
class BuildDataBuilder module DataBuilder
class << self module Build
extend self
def build(build) def build(build)
project = build.project project = build.project
commit = build.pipeline commit = build.pipeline
......
module Gitlab module Gitlab
class NoteDataBuilder module DataBuilder
class << self module Note
extend self
# Produce a hash of post-receive data # Produce a hash of post-receive data
# #
# For all notes: # For all notes:
......
module Gitlab
module DataBuilder
module Pipeline
extend self
def build(pipeline)
{
object_kind: 'pipeline',
object_attributes: hook_attrs(pipeline),
user: pipeline.user.try(:hook_attrs),
project: pipeline.project.hook_attrs(backward: false),
commit: pipeline.commit.try(:hook_attrs),
builds: pipeline.builds.map(&method(:build_hook_attrs))
}
end
def hook_attrs(pipeline)
{
id: pipeline.id,
ref: pipeline.ref,
tag: pipeline.tag,
sha: pipeline.sha,
before_sha: pipeline.before_sha,
status: pipeline.status,
stages: pipeline.stages,
created_at: pipeline.created_at,
finished_at: pipeline.finished_at,
duration: pipeline.duration
}
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.try(:hook_attrs),
runner: build.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
module Gitlab module Gitlab
class PushDataBuilder module DataBuilder
class << self module Push
extend self
# Produce a hash of post-receive data # Produce a hash of post-receive data
# #
# data = { # data = {
......
...@@ -5,5 +5,15 @@ FactoryGirl.define do ...@@ -5,5 +5,15 @@ FactoryGirl.define do
trait :token do trait :token do
token { SecureRandom.hex(10) } token { SecureRandom.hex(10) }
end end
trait :all_events_enabled do
push_events true
merge_requests_events true
tag_push_events true
issues_events true
note_events true
build_events true
pipeline_events true
end
end end
end end
...@@ -38,6 +38,11 @@ describe NotesHelper do ...@@ -38,6 +38,11 @@ describe NotesHelper do
end end
describe '#preload_max_access_for_authors' do describe '#preload_max_access_for_authors' do
before do
# This method reads cache from RequestStore, so make sure it's clean.
RequestStore.clear!
end
it 'loads multiple users' do it 'loads multiple users' do
expected_access = { expected_access = {
owner.id => Gitlab::Access::OWNER, owner.id => Gitlab::Access::OWNER,
......
require 'spec_helper' require 'spec_helper'
describe 'Gitlab::BuildDataBuilder' do describe Gitlab::DataBuilder::Build do
let(:build) { create(:ci_build) } let(:build) { create(:ci_build) }
describe '.build' do describe '.build' do
let(:data) do let(:data) do
Gitlab::BuildDataBuilder.build(build) described_class.build(build)
end end
it { expect(data).to be_a(Hash) } it { expect(data).to be_a(Hash) }
......
require 'spec_helper' require 'spec_helper'
describe 'Gitlab::NoteDataBuilder', lib: true do describe Gitlab::DataBuilder::Note, lib: true do
let(:project) { create(:project) } let(:project) { create(:project) }
let(:user) { create(:user) } let(:user) { create(:user) }
let(:data) { Gitlab::NoteDataBuilder.build(note, user) } let(:data) { described_class.build(note, user) }
let(:fixed_time) { Time.at(1425600000) } # Avoid time precision errors let(:fixed_time) { Time.at(1425600000) } # Avoid time precision errors
before(:each) do before(:each) do
......
require 'spec_helper'
describe Gitlab::DataBuilder::Pipeline do
let(:user) { create(:user) }
let(:project) { create(:project) }
let(:pipeline) do
create(:ci_pipeline,
project: project,
status: 'success',
sha: project.commit.sha,
ref: project.default_branch)
end
let!(:build) { create(:ci_build, pipeline: pipeline) }
describe '.build' do
let(:data) { described_class.build(pipeline) }
let(:attributes) { data[:object_attributes] }
let(:build_data) { data[:builds].first }
let(:project_data) { data[:project] }
it { expect(attributes).to be_a(Hash) }
it { expect(attributes[:ref]).to eq(pipeline.ref) }
it { expect(attributes[:sha]).to eq(pipeline.sha) }
it { expect(attributes[:tag]).to eq(pipeline.tag) }
it { expect(attributes[:id]).to eq(pipeline.id) }
it { expect(attributes[:status]).to eq(pipeline.status) }
it { expect(build_data).to be_a(Hash) }
it { expect(build_data[:id]).to eq(build.id) }
it { expect(build_data[:status]).to eq(build.status) }
it { expect(project_data).to eq(project.hook_attrs(backward: false)) }
end
end
require 'spec_helper' require 'spec_helper'
describe Gitlab::PushDataBuilder, lib: true do describe Gitlab::DataBuilder::Push, lib: true do
let(:project) { create(:project) } let(:project) { create(:project) }
let(:user) { create(:user) } let(:user) { create(:user) }
......
...@@ -42,7 +42,7 @@ describe Ci::Build, models: true do ...@@ -42,7 +42,7 @@ describe Ci::Build, models: true do
describe '#ignored?' do describe '#ignored?' do
subject { build.ignored? } subject { build.ignored? }
context 'if build is not allowed to fail' do context 'when build is not allowed to fail' do
before do before do
build.allow_failure = false build.allow_failure = false
end end
...@@ -64,7 +64,7 @@ describe Ci::Build, models: true do ...@@ -64,7 +64,7 @@ describe Ci::Build, models: true do
end end
end end
context 'if build is allowed to fail' do context 'when build is allowed to fail' do
before do before do
build.allow_failure = true build.allow_failure = true
end end
...@@ -92,7 +92,7 @@ describe Ci::Build, models: true do ...@@ -92,7 +92,7 @@ describe Ci::Build, models: true do
it { is_expected.to be_empty } it { is_expected.to be_empty }
context 'if build.trace contains text' do context 'when build.trace contains text' do
let(:text) { 'example output' } let(:text) { 'example output' }
before do before do
build.trace = text build.trace = text
...@@ -102,7 +102,7 @@ describe Ci::Build, models: true do ...@@ -102,7 +102,7 @@ describe Ci::Build, models: true do
it { expect(subject.length).to be >= text.length } it { expect(subject.length).to be >= text.length }
end end
context 'if build.trace hides token' do context 'when build.trace hides token' do
let(:token) { 'my_secret_token' } let(:token) { 'my_secret_token' }
before do before do
...@@ -283,13 +283,13 @@ describe Ci::Build, models: true do ...@@ -283,13 +283,13 @@ describe Ci::Build, models: true do
stub_ci_pipeline_yaml_file(config) stub_ci_pipeline_yaml_file(config)
end end
context 'if config is not found' do context 'when config is not found' do
let(:config) { nil } let(:config) { nil }
it { is_expected.to eq(predefined_variables) } it { is_expected.to eq(predefined_variables) }
end end
context 'if config does not have a questioned job' do context 'when config does not have a questioned job' do
let(:config) do let(:config) do
YAML.dump({ YAML.dump({
test_other: { test_other: {
...@@ -301,7 +301,7 @@ describe Ci::Build, models: true do ...@@ -301,7 +301,7 @@ describe Ci::Build, models: true do
it { is_expected.to eq(predefined_variables) } it { is_expected.to eq(predefined_variables) }
end end
context 'if config has variables' do context 'when config has variables' do
let(:config) do let(:config) do
YAML.dump({ YAML.dump({
test: { test: {
...@@ -393,7 +393,7 @@ describe Ci::Build, models: true do ...@@ -393,7 +393,7 @@ describe Ci::Build, models: true do
it { is_expected.to be_falsey } it { is_expected.to be_falsey }
end end
context 'if there are runner' do context 'when there are runners' do
let(:runner) { create(:ci_runner) } let(:runner) { create(:ci_runner) }
before do before do
...@@ -423,29 +423,27 @@ describe Ci::Build, models: true do ...@@ -423,29 +423,27 @@ describe Ci::Build, models: true do
describe '#stuck?' do describe '#stuck?' do
subject { build.stuck? } subject { build.stuck? }
%w(pending).each do |state| context "when commit_status.status is pending" do
context "if commit_status.status is #{state}" do before do
before do build.status = 'pending'
build.status = state end
end
it { is_expected.to be_truthy }
context "and there are specific runner" do it { is_expected.to be_truthy }
let(:runner) { create(:ci_runner, contacted_at: 1.second.ago) }
before do context "and there are specific runner" do
build.project.runners << runner let(:runner) { create(:ci_runner, contacted_at: 1.second.ago) }
runner.save
end
it { is_expected.to be_falsey } before do
build.project.runners << runner
runner.save
end end
it { is_expected.to be_falsey }
end end
end end
%w(success failed canceled running).each do |state| %w[success failed canceled running].each do |state|
context "if commit_status.status is #{state}" do context "when commit_status.status is #{state}" do
before do before do
build.status = state build.status = state
end end
...@@ -767,7 +765,7 @@ describe Ci::Build, models: true do ...@@ -767,7 +765,7 @@ describe Ci::Build, models: true do
describe '#when' do describe '#when' do
subject { build.when } subject { build.when }
context 'if is undefined' do context 'when `when` is undefined' do
before do before do
build.when = nil build.when = nil
end end
...@@ -777,13 +775,13 @@ describe Ci::Build, models: true do ...@@ -777,13 +775,13 @@ describe Ci::Build, models: true do
stub_ci_pipeline_yaml_file(config) stub_ci_pipeline_yaml_file(config)
end end
context 'if config is not found' do context 'when config is not found' do
let(:config) { nil } let(:config) { nil }
it { is_expected.to eq('on_success') } it { is_expected.to eq('on_success') }
end end
context 'if config does not have a questioned job' do context 'when config does not have a questioned job' do
let(:config) do let(:config) do
YAML.dump({ YAML.dump({
test_other: { test_other: {
...@@ -795,7 +793,7 @@ describe Ci::Build, models: true do ...@@ -795,7 +793,7 @@ describe Ci::Build, models: true do
it { is_expected.to eq('on_success') } it { is_expected.to eq('on_success') }
end end
context 'if config has when' do context 'when config has `when`' do
let(:config) do let(:config) do
YAML.dump({ YAML.dump({
test: { test: {
...@@ -881,7 +879,7 @@ describe Ci::Build, models: true do ...@@ -881,7 +879,7 @@ describe Ci::Build, models: true do
subject { build.play } subject { build.play }
it 'enques a build' do it 'enqueues a build' do
is_expected.to be_pending is_expected.to be_pending
is_expected.to eq(build) is_expected.to eq(build)
end end
...@@ -901,7 +899,7 @@ describe Ci::Build, models: true do ...@@ -901,7 +899,7 @@ describe Ci::Build, models: true do
describe '#when' do describe '#when' do
subject { build.when } subject { build.when }
context 'if is undefined' do context 'when `when` is undefined' do
before do before do
build.when = nil build.when = nil
end end
...@@ -911,13 +909,13 @@ describe Ci::Build, models: true do ...@@ -911,13 +909,13 @@ describe Ci::Build, models: true do
stub_ci_pipeline_yaml_file(config) stub_ci_pipeline_yaml_file(config)
end end
context 'if config is not found' do context 'when config is not found' do
let(:config) { nil } let(:config) { nil }
it { is_expected.to eq('on_success') } it { is_expected.to eq('on_success') }
end end
context 'if config does not have a questioned job' do context 'when config does not have a questioned job' do
let(:config) do let(:config) do
YAML.dump({ YAML.dump({
test_other: { test_other: {
...@@ -929,7 +927,7 @@ describe Ci::Build, models: true do ...@@ -929,7 +927,7 @@ describe Ci::Build, models: true do
it { is_expected.to eq('on_success') } it { is_expected.to eq('on_success') }
end end
context 'if config has when' do context 'when config has when' do
let(:config) do let(:config) do
YAML.dump({ YAML.dump({
test: { test: {
......
...@@ -2,7 +2,7 @@ require 'spec_helper' ...@@ -2,7 +2,7 @@ require 'spec_helper'
describe Ci::Pipeline, models: true do describe Ci::Pipeline, models: true do
let(:project) { FactoryGirl.create :empty_project } let(:project) { FactoryGirl.create :empty_project }
let(:pipeline) { FactoryGirl.create :ci_empty_pipeline, project: project } let(:pipeline) { FactoryGirl.create :ci_empty_pipeline, status: 'created', project: project }
it { is_expected.to belong_to(:project) } it { is_expected.to belong_to(:project) }
it { is_expected.to belong_to(:user) } it { is_expected.to belong_to(:user) }
...@@ -18,6 +18,8 @@ describe Ci::Pipeline, models: true do ...@@ -18,6 +18,8 @@ describe Ci::Pipeline, models: true do
it { is_expected.to respond_to :git_author_email } it { is_expected.to respond_to :git_author_email }
it { is_expected.to respond_to :short_sha } it { is_expected.to respond_to :short_sha }
it { is_expected.to delegate_method(:stages).to(:statuses) }
describe '#valid_commit_sha' do describe '#valid_commit_sha' do
context 'commit.sha can not start with 00000000' do context 'commit.sha can not start with 00000000' do
before do before do
...@@ -314,4 +316,87 @@ describe Ci::Pipeline, models: true do ...@@ -314,4 +316,87 @@ describe Ci::Pipeline, models: true do
it { is_expected.to eq('running') } it { is_expected.to eq('running') }
end end
end end
describe '#execute_hooks' do
let!(:build_a) { create_build('a') }
let!(:build_b) { create_build('b') }
let!(:hook) do
create(:project_hook, project: project, pipeline_events: enabled)
end
before do
ProjectWebHookWorker.drain
end
context 'with pipeline hooks enabled' do
let(:enabled) { true }
before do
WebMock.stub_request(:post, hook.url)
end
context 'with multiple builds' do
context 'when build is queued' do
before do
build_a.enqueue
build_b.enqueue
end
it 'receive a pending event once' do
expect(WebMock).to have_requested_pipeline_hook('pending').once
end
end
context 'when build is run' do
before do
build_a.enqueue
build_a.run
build_b.enqueue
build_b.run
end
it 'receive a running event once' do
expect(WebMock).to have_requested_pipeline_hook('running').once
end
end
context 'when all builds succeed' do
before do
build_a.success
build_b.success
end
it 'receive a success event once' do
expect(WebMock).to have_requested_pipeline_hook('success').once
end
end
def have_requested_pipeline_hook(status)
have_requested(:post, hook.url).with do |req|
json_body = JSON.parse(req.body)
json_body['object_attributes']['status'] == status &&
json_body['builds'].length == 2
end
end
end
end
context 'with pipeline hooks disabled' do
let(:enabled) { false }
before do
build_a.enqueue
build_b.enqueue
end
it 'did not execute pipeline_hook after touched' do
expect(WebMock).not_to have_requested(:post, hook.url)
end
end
def create_build(name)
create(:ci_build, :created, pipeline: pipeline, name: name)
end
end
end end
...@@ -39,7 +39,7 @@ describe AssemblaService, models: true do ...@@ -39,7 +39,7 @@ describe AssemblaService, models: true do
token: 'verySecret', token: 'verySecret',
subdomain: 'project_name' subdomain: 'project_name'
) )
@sample_data = Gitlab::PushDataBuilder.build_sample(project, user) @sample_data = Gitlab::DataBuilder::Push.build_sample(project, user)
@api_url = 'https://atlas.assembla.com/spaces/project_name/github_tool?secret_key=verySecret' @api_url = 'https://atlas.assembla.com/spaces/project_name/github_tool?secret_key=verySecret'
WebMock.stub_request(:post, @api_url) WebMock.stub_request(:post, @api_url)
end end
......
require 'spec_helper' require 'spec_helper'
describe BuildsEmailService do describe BuildsEmailService do
let(:data) { Gitlab::BuildDataBuilder.build(create(:ci_build)) } let(:data) do
Gitlab::DataBuilder::Build.build(create(:ci_build))
end
describe 'Validations' do describe 'Validations' do
context 'when service is active' do context 'when service is active' do
...@@ -39,7 +41,7 @@ describe BuildsEmailService do ...@@ -39,7 +41,7 @@ describe BuildsEmailService do
describe '#test' do describe '#test' do
it 'sends email' do it 'sends email' do
data = Gitlab::BuildDataBuilder.build(create(:ci_build)) data = Gitlab::DataBuilder::Build.build(create(:ci_build))
subject.recipients = 'test@gitlab.com' subject.recipients = 'test@gitlab.com'
expect(BuildEmailWorker).to receive(:perform_async) expect(BuildEmailWorker).to receive(:perform_async)
...@@ -49,7 +51,7 @@ describe BuildsEmailService do ...@@ -49,7 +51,7 @@ describe BuildsEmailService do
context 'notify only failed builds is true' do context 'notify only failed builds is true' do
it 'sends email' do it 'sends email' do
data = Gitlab::BuildDataBuilder.build(create(:ci_build)) data = Gitlab::DataBuilder::Build.build(create(:ci_build))
data[:build_status] = "success" data[:build_status] = "success"
subject.recipients = 'test@gitlab.com' subject.recipients = 'test@gitlab.com'
......
...@@ -54,7 +54,7 @@ describe CampfireService, models: true do ...@@ -54,7 +54,7 @@ describe CampfireService, models: true do
subdomain: 'project-name', subdomain: 'project-name',
room: 'test-room' room: 'test-room'
) )
@sample_data = Gitlab::PushDataBuilder.build_sample(project, user) @sample_data = Gitlab::DataBuilder::Push.build_sample(project, user)
@rooms_url = 'https://verySecret:X@project-name.campfirenow.com/rooms.json' @rooms_url = 'https://verySecret:X@project-name.campfirenow.com/rooms.json'
@headers = { 'Content-Type' => 'application/json; charset=utf-8' } @headers = { 'Content-Type' => 'application/json; charset=utf-8' }
end end
......
...@@ -84,7 +84,9 @@ describe DroneCiService, models: true do ...@@ -84,7 +84,9 @@ describe DroneCiService, models: true do
include_context :drone_ci_service include_context :drone_ci_service
let(:user) { create(:user, username: 'username') } let(:user) { create(:user, username: 'username') }
let(:push_sample_data) { Gitlab::PushDataBuilder.build_sample(project, user) } let(:push_sample_data) do
Gitlab::DataBuilder::Push.build_sample(project, user)
end
it do it do
service_hook = double service_hook = double
......
...@@ -52,7 +52,7 @@ describe FlowdockService, models: true do ...@@ -52,7 +52,7 @@ describe FlowdockService, models: true do
service_hook: true, service_hook: true,
token: 'verySecret' token: 'verySecret'
) )
@sample_data = Gitlab::PushDataBuilder.build_sample(project, user) @sample_data = Gitlab::DataBuilder::Push.build_sample(project, user)
@api_url = 'https://api.flowdock.com/v1/messages' @api_url = 'https://api.flowdock.com/v1/messages'
WebMock.stub_request(:post, @api_url) WebMock.stub_request(:post, @api_url)
end end
......
...@@ -55,7 +55,7 @@ describe GemnasiumService, models: true do ...@@ -55,7 +55,7 @@ describe GemnasiumService, models: true do
token: 'verySecret', token: 'verySecret',
api_key: 'GemnasiumUserApiKey' api_key: 'GemnasiumUserApiKey'
) )
@sample_data = Gitlab::PushDataBuilder.build_sample(project, user) @sample_data = Gitlab::DataBuilder::Push.build_sample(project, user)
end end
it "calls Gemnasium service" do it "calls Gemnasium service" do
expect(Gemnasium::GitlabService).to receive(:execute).with(an_instance_of(Hash)).once expect(Gemnasium::GitlabService).to receive(:execute).with(an_instance_of(Hash)).once
......
...@@ -48,7 +48,9 @@ describe HipchatService, models: true do ...@@ -48,7 +48,9 @@ describe HipchatService, models: true do
let(:project_name) { project.name_with_namespace.gsub(/\s/, '') } let(:project_name) { project.name_with_namespace.gsub(/\s/, '') }
let(:token) { 'verySecret' } let(:token) { 'verySecret' }
let(:server_url) { 'https://hipchat.example.com'} let(:server_url) { 'https://hipchat.example.com'}
let(:push_sample_data) { Gitlab::PushDataBuilder.build_sample(project, user) } let(:push_sample_data) do
Gitlab::DataBuilder::Push.build_sample(project, user)
end
before(:each) do before(:each) do
allow(hipchat).to receive_messages( allow(hipchat).to receive_messages(
...@@ -108,7 +110,15 @@ describe HipchatService, models: true do ...@@ -108,7 +110,15 @@ describe HipchatService, models: true do
end end
context 'tag_push events' do context 'tag_push events' do
let(:push_sample_data) { Gitlab::PushDataBuilder.build(project, user, Gitlab::Git::BLANK_SHA, '1' * 40, 'refs/tags/test', []) } let(:push_sample_data) do
Gitlab::DataBuilder::Push.build(
project,
user,
Gitlab::Git::BLANK_SHA,
'1' * 40,
'refs/tags/test',
[])
end
it "calls Hipchat API for tag push events" do it "calls Hipchat API for tag push events" do
hipchat.execute(push_sample_data) hipchat.execute(push_sample_data)
...@@ -185,7 +195,7 @@ describe HipchatService, models: true do ...@@ -185,7 +195,7 @@ describe HipchatService, models: true do
end end
it "calls Hipchat API for commit comment events" do it "calls Hipchat API for commit comment events" do
data = Gitlab::NoteDataBuilder.build(commit_note, user) data = Gitlab::DataBuilder::Note.build(commit_note, user)
hipchat.execute(data) hipchat.execute(data)
expect(WebMock).to have_requested(:post, api_url).once expect(WebMock).to have_requested(:post, api_url).once
...@@ -217,7 +227,7 @@ describe HipchatService, models: true do ...@@ -217,7 +227,7 @@ describe HipchatService, models: true do
end end
it "calls Hipchat API for merge request comment events" do it "calls Hipchat API for merge request comment events" do
data = Gitlab::NoteDataBuilder.build(merge_request_note, user) data = Gitlab::DataBuilder::Note.build(merge_request_note, user)
hipchat.execute(data) hipchat.execute(data)
expect(WebMock).to have_requested(:post, api_url).once expect(WebMock).to have_requested(:post, api_url).once
...@@ -244,7 +254,7 @@ describe HipchatService, models: true do ...@@ -244,7 +254,7 @@ describe HipchatService, models: true do
end end
it "calls Hipchat API for issue comment events" do it "calls Hipchat API for issue comment events" do
data = Gitlab::NoteDataBuilder.build(issue_note, user) data = Gitlab::DataBuilder::Note.build(issue_note, user)
hipchat.execute(data) hipchat.execute(data)
message = hipchat.send(:create_message, data) message = hipchat.send(:create_message, data)
...@@ -270,7 +280,7 @@ describe HipchatService, models: true do ...@@ -270,7 +280,7 @@ describe HipchatService, models: true do
end end
it "calls Hipchat API for snippet comment events" do it "calls Hipchat API for snippet comment events" do
data = Gitlab::NoteDataBuilder.build(snippet_note, user) data = Gitlab::DataBuilder::Note.build(snippet_note, user)
hipchat.execute(data) hipchat.execute(data)
expect(WebMock).to have_requested(:post, api_url).once expect(WebMock).to have_requested(:post, api_url).once
...@@ -293,7 +303,7 @@ describe HipchatService, models: true do ...@@ -293,7 +303,7 @@ describe HipchatService, models: true do
context 'build events' do context 'build events' do
let(:pipeline) { create(:ci_empty_pipeline) } let(:pipeline) { create(:ci_empty_pipeline) }
let(:build) { create(:ci_build, pipeline: pipeline) } let(:build) { create(:ci_build, pipeline: pipeline) }
let(:data) { Gitlab::BuildDataBuilder.build(build) } let(:data) { Gitlab::DataBuilder::Build.build(build) }
context 'for failed' do context 'for failed' do
before { build.drop } before { build.drop }
......
...@@ -46,7 +46,9 @@ describe IrkerService, models: true do ...@@ -46,7 +46,9 @@ describe IrkerService, models: true do
let(:irker) { IrkerService.new } let(:irker) { IrkerService.new }
let(:user) { create(:user) } let(:user) { create(:user) }
let(:project) { create(:project) } let(:project) { create(:project) }
let(:sample_data) { Gitlab::PushDataBuilder.build_sample(project, user) } let(:sample_data) do
Gitlab::DataBuilder::Push.build_sample(project, user)
end
let(:recipients) { '#commits irc://test.net/#test ftp://bad' } let(:recipients) { '#commits irc://test.net/#test ftp://bad' }
let(:colorize_messages) { '1' } let(:colorize_messages) { '1' }
......
...@@ -66,7 +66,7 @@ describe JiraService, models: true do ...@@ -66,7 +66,7 @@ describe JiraService, models: true do
password: 'gitlab_jira_password' password: 'gitlab_jira_password'
) )
@jira_service.save # will build API URL, as api_url was not specified above @jira_service.save # will build API URL, as api_url was not specified above
@sample_data = Gitlab::PushDataBuilder.build_sample(project, user) @sample_data = Gitlab::DataBuilder::Push.build_sample(project, user)
# https://github.com/bblimke/webmock#request-with-basic-authentication # https://github.com/bblimke/webmock#request-with-basic-authentication
@api_url = 'http://gitlab_jira_username:gitlab_jira_password@jira.example.com/rest/api/2/issue/JIRA-123/transitions' @api_url = 'http://gitlab_jira_username:gitlab_jira_password@jira.example.com/rest/api/2/issue/JIRA-123/transitions'
@comment_url = 'http://gitlab_jira_username:gitlab_jira_password@jira.example.com/rest/api/2/issue/JIRA-123/comment' @comment_url = 'http://gitlab_jira_username:gitlab_jira_password@jira.example.com/rest/api/2/issue/JIRA-123/comment'
......
...@@ -48,7 +48,9 @@ describe PushoverService, models: true do ...@@ -48,7 +48,9 @@ describe PushoverService, models: true do
let(:pushover) { PushoverService.new } let(:pushover) { PushoverService.new }
let(:user) { create(:user) } let(:user) { create(:user) }
let(:project) { create(:project) } let(:project) { create(:project) }
let(:sample_data) { Gitlab::PushDataBuilder.build_sample(project, user) } let(:sample_data) do
Gitlab::DataBuilder::Push.build_sample(project, user)
end
let(:api_key) { 'verySecret' } let(:api_key) { 'verySecret' }
let(:user_key) { 'verySecret' } let(:user_key) { 'verySecret' }
......
...@@ -45,7 +45,9 @@ describe SlackService, models: true do ...@@ -45,7 +45,9 @@ describe SlackService, models: true do
let(:slack) { SlackService.new } let(:slack) { SlackService.new }
let(:user) { create(:user) } let(:user) { create(:user) }
let(:project) { create(:project) } let(:project) { create(:project) }
let(:push_sample_data) { Gitlab::PushDataBuilder.build_sample(project, user) } 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(:webhook_url) { 'https://hooks.slack.com/services/SVRWFV0VVAR97N/B02R25XN3/ZBqu7xMupaEEICInN685' }
let(:username) { 'slack_username' } let(:username) { 'slack_username' }
let(:channel) { 'slack_channel' } let(:channel) { 'slack_channel' }
...@@ -195,7 +197,7 @@ describe SlackService, models: true do ...@@ -195,7 +197,7 @@ describe SlackService, models: true do
it "uses the right channel" do it "uses the right channel" do
slack.update_attributes(note_channel: "random") slack.update_attributes(note_channel: "random")
note_data = Gitlab::NoteDataBuilder.build(issue_note, user) note_data = Gitlab::DataBuilder::Note.build(issue_note, user)
expect(Slack::Notifier).to receive(:new). expect(Slack::Notifier).to receive(:new).
with(webhook_url, channel: "random"). with(webhook_url, channel: "random").
...@@ -235,7 +237,7 @@ describe SlackService, models: true do ...@@ -235,7 +237,7 @@ describe SlackService, models: true do
end end
it "calls Slack API for commit comment events" do it "calls Slack API for commit comment events" do
data = Gitlab::NoteDataBuilder.build(commit_note, user) data = Gitlab::DataBuilder::Note.build(commit_note, user)
slack.execute(data) slack.execute(data)
expect(WebMock).to have_requested(:post, webhook_url).once expect(WebMock).to have_requested(:post, webhook_url).once
...@@ -249,7 +251,7 @@ describe SlackService, models: true do ...@@ -249,7 +251,7 @@ describe SlackService, models: true do
end end
it "calls Slack API for merge request comment events" do it "calls Slack API for merge request comment events" do
data = Gitlab::NoteDataBuilder.build(merge_request_note, user) data = Gitlab::DataBuilder::Note.build(merge_request_note, user)
slack.execute(data) slack.execute(data)
expect(WebMock).to have_requested(:post, webhook_url).once expect(WebMock).to have_requested(:post, webhook_url).once
...@@ -262,7 +264,7 @@ describe SlackService, models: true do ...@@ -262,7 +264,7 @@ describe SlackService, models: true do
end end
it "calls Slack API for issue comment events" do it "calls Slack API for issue comment events" do
data = Gitlab::NoteDataBuilder.build(issue_note, user) data = Gitlab::DataBuilder::Note.build(issue_note, user)
slack.execute(data) slack.execute(data)
expect(WebMock).to have_requested(:post, webhook_url).once expect(WebMock).to have_requested(:post, webhook_url).once
...@@ -276,7 +278,7 @@ describe SlackService, models: true do ...@@ -276,7 +278,7 @@ describe SlackService, models: true do
end end
it "calls Slack API for snippet comment events" do it "calls Slack API for snippet comment events" do
data = Gitlab::NoteDataBuilder.build(snippet_note, user) data = Gitlab::DataBuilder::Note.build(snippet_note, user)
slack.execute(data) slack.execute(data)
expect(WebMock).to have_requested(:post, webhook_url).once expect(WebMock).to have_requested(:post, webhook_url).once
......
...@@ -895,7 +895,9 @@ describe User, models: true do ...@@ -895,7 +895,9 @@ describe User, models: true do
subject { create(:user) } subject { create(:user) }
let!(:project1) { create(:project) } let!(:project1) { create(:project) }
let!(:project2) { create(:project, forked_from_project: project1) } let!(:project2) { create(:project, forked_from_project: project1) }
let!(:push_data) { Gitlab::PushDataBuilder.build_sample(project2, subject) } let!(:push_data) do
Gitlab::DataBuilder::Push.build_sample(project2, subject)
end
let!(:push_event) { create(:event, action: Event::PUSHED, project: project2, target: project1, author: subject, data: push_data) } let!(:push_event) { create(:event, action: Event::PUSHED, project: project2, target: project1, author: subject, data: push_data) }
before do before do
......
...@@ -7,9 +7,9 @@ describe API::API, 'ProjectHooks', api: true do ...@@ -7,9 +7,9 @@ describe API::API, 'ProjectHooks', api: true do
let!(:project) { create(:project, creator_id: user.id, namespace: user.namespace) } let!(:project) { create(:project, creator_id: user.id, namespace: user.namespace) }
let!(:hook) do let!(:hook) do
create(:project_hook, create(:project_hook,
project: project, url: "http://example.com", :all_events_enabled,
push_events: true, merge_requests_events: true, tag_push_events: true, project: project,
issues_events: true, note_events: true, build_events: true, url: 'http://example.com',
enable_ssl_verification: true) enable_ssl_verification: true)
end end
...@@ -33,6 +33,7 @@ describe API::API, 'ProjectHooks', api: true do ...@@ -33,6 +33,7 @@ describe API::API, 'ProjectHooks', api: true do
expect(json_response.first['tag_push_events']).to eq(true) expect(json_response.first['tag_push_events']).to eq(true)
expect(json_response.first['note_events']).to eq(true) expect(json_response.first['note_events']).to eq(true)
expect(json_response.first['build_events']).to eq(true) expect(json_response.first['build_events']).to eq(true)
expect(json_response.first['pipeline_events']).to eq(true)
expect(json_response.first['enable_ssl_verification']).to eq(true) expect(json_response.first['enable_ssl_verification']).to eq(true)
end end
end end
...@@ -91,6 +92,7 @@ describe API::API, 'ProjectHooks', api: true do ...@@ -91,6 +92,7 @@ describe API::API, 'ProjectHooks', api: true do
expect(json_response['tag_push_events']).to eq(false) expect(json_response['tag_push_events']).to eq(false)
expect(json_response['note_events']).to eq(false) expect(json_response['note_events']).to eq(false)
expect(json_response['build_events']).to eq(false) expect(json_response['build_events']).to eq(false)
expect(json_response['pipeline_events']).to eq(false)
expect(json_response['enable_ssl_verification']).to eq(true) expect(json_response['enable_ssl_verification']).to eq(true)
end end
......
...@@ -5,7 +5,7 @@ describe BuildEmailWorker do ...@@ -5,7 +5,7 @@ describe BuildEmailWorker do
let(:build) { create(:ci_build) } let(:build) { create(:ci_build) }
let(:user) { create(:user) } let(:user) { create(:user) }
let(:data) { Gitlab::BuildDataBuilder.build(build) } let(:data) { Gitlab::DataBuilder::Build.build(build) }
subject { BuildEmailWorker.new } subject { BuildEmailWorker.new }
......
...@@ -6,7 +6,7 @@ describe EmailsOnPushWorker do ...@@ -6,7 +6,7 @@ describe EmailsOnPushWorker do
let(:project) { create(:project) } let(:project) { create(:project) }
let(:user) { create(:user) } let(:user) { create(:user) }
let(:data) { Gitlab::PushDataBuilder.build_sample(project, user) } let(:data) { Gitlab::DataBuilder::Push.build_sample(project, user) }
let(:recipients) { user.email } let(:recipients) { user.email }
let(:perform) { subject.perform(project.id, recipients, data.stringify_keys) } let(:perform) { subject.perform(project.id, recipients, data.stringify_keys) }
let(:email) { ActionMailer::Base.deliveries.last } let(:email) { ActionMailer::Base.deliveries.last }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment