Commit ee1090e2 authored by Gabriel Mazetto's avatar Gabriel Mazetto Committed by Dmitriy Zaporozhets

Added System Hooks for push and tag_push

Code is based on Project Webhooks, removing deprecations and without
commits listing.
parent 53a1d705
......@@ -19,4 +19,10 @@
#
class SystemHook < WebHook
scope :push_hooks, -> { where(push_events: true) }
scope :tag_push_hooks, -> { where(tag_push_events: true) }
def async_execute(data, hook_name)
Sidekiq::Client.enqueue(SystemHookWorker, id, data, hook_name)
end
end
......@@ -831,8 +831,8 @@ class Project < ActiveRecord::Base
end
end
def hook_attrs
{
def hook_attrs(backward: true)
attrs = {
name: name,
description: description,
web_url: web_url,
......@@ -843,12 +843,19 @@ class Project < ActiveRecord::Base
visibility_level: visibility_level,
path_with_namespace: path_with_namespace,
default_branch: default_branch,
# Backward compatibility
homepage: web_url,
url: url_to_repo,
ssh_url: ssh_url_to_repo,
http_url: http_url_to_repo
}
# Backward compatibility
if backward
attrs.merge!({
homepage: web_url,
url: url_to_repo,
ssh_url: ssh_url_to_repo,
http_url: http_url_to_repo
})
end
attrs
end
# Reset events cache related to this project
......
......@@ -73,6 +73,7 @@ class GitPushService < BaseService
@project.update_merge_requests(params[:oldrev], params[:newrev], params[:ref], current_user)
EventCreateService.new.push(@project, current_user, build_push_data)
SystemHooksService.new.execute_hooks(build_push_data_system_hook.dup, :push_hooks)
@project.execute_hooks(build_push_data.dup, :push_hooks)
@project.execute_services(build_push_data.dup, :push_hooks)
CreateCommitBuildsService.new.execute(@project, current_user, build_push_data)
......@@ -138,6 +139,11 @@ class GitPushService < BaseService
build(@project, current_user, params[:oldrev], params[:newrev], params[:ref], push_commits)
end
def build_push_data_system_hook
@push_data_system ||= Gitlab::PushDataBuilder.
build_system(@project, current_user, params[:oldrev], params[:newrev], params[:ref])
end
def push_to_existing_branch?
# Return if this is not a push to a branch (e.g. new commits)
Gitlab::Git.branch_ref?(params[:ref]) && !Gitlab::Git.blank_ref?(params[:oldrev])
......
......@@ -8,6 +8,7 @@ class GitTagPushService
@push_data = build_push_data(oldrev, newrev, ref)
EventCreateService.new.push(project, user, @push_data)
SystemHooksService.new.execute_hooks(build_system_push_data.dup, :tag_push_hooks)
project.execute_hooks(@push_data.dup, :tag_push_hooks)
project.execute_services(@push_data.dup, :tag_push_hooks)
CreateCommitBuildsService.new.execute(project, @user, @push_data)
......@@ -35,4 +36,9 @@ class GitTagPushService
Gitlab::PushDataBuilder.
build(project, user, oldrev, newrev, ref, commits, message)
end
def build_system_push_data(oldrev, newrev, ref)
Gitlab::PushDataBuilder.
build_system(project, user, oldrev, newrev, ref)
end
end
......@@ -3,17 +3,13 @@ class SystemHooksService
execute_hooks(build_event_data(model, event))
end
private
def execute_hooks(data)
SystemHook.all.each do |sh|
async_execute_hook(sh, data, 'system_hooks')
def execute_hooks(data, hooks_scope = :all)
SystemHook.send(hooks_scope).each do |hook|
hook.async_execute(data, 'system_hooks')
end
end
def async_execute_hook(hook, data, hook_name)
Sidekiq::Client.enqueue(SystemHookWorker, hook.id, data, hook_name)
end
private
def build_event_data(model, event)
data = {
......
......@@ -240,3 +240,80 @@ X-Gitlab-Event: System Hook
"user_id": 41
}
```
## Push events
Triggered when you push to the repository except when pushing tags.
**Request header**:
```
X-Gitlab-Event: System Hook
```
**Request body:**
```json
{
"event_name": "push",
"before": "95790bf891e76fee5e1747ab589903a6a1f80f22",
"after": "da1560886d4f094c3e6c9ef40349f7d38b5d27d7",
"ref": "refs/heads/master",
"checkout_sha": "da1560886d4f094c3e6c9ef40349f7d38b5d27d7",
"user_id": 4,
"user_name": "John Smith",
"user_email": "john@example.com",
"user_avatar": "https://s.gravatar.com/avatar/d4c74594d841139328695756648b6bd6?s=8://s.gravatar.com/avatar/d4c74594d841139328695756648b6bd6?s=80",
"project_id": 15,
"project":{
"name":"Diaspora",
"description":"",
"web_url":"http://example.com/mike/diaspora",
"avatar_url":null,
"git_ssh_url":"git@example.com:mike/diaspora.git",
"git_http_url":"http://example.com/mike/diaspora.git",
"namespace":"Mike",
"visibility_level":0,
"path_with_namespace":"mike/diaspora",
"default_branch":"master",
}
}
```
## Tag events
Triggered when you create (or delete) tags to the repository.
**Request header**:
```
X-Gitlab-Event: System Hook
```
**Request body:**
```json
{
"event_name": "tag_push",
"before": "0000000000000000000000000000000000000000",
"after": "82b3d5ae55f7080f1e6022629cdb57bfae7cccc7",
"ref": "refs/tags/v1.0.0",
"checkout_sha": "5937ac0a7beb003549fc5fd26fc247adbce4a52e",
"user_id": 1,
"user_name": "John Smith",
"user_avatar": "https://s.gravatar.com/avatar/d4c74594d841139328695756648b6bd6?s=8://s.gravatar.com/avatar/d4c74594d841139328695756648b6bd6?s=80",
"project_id": 1,
"project":{
"name":"Example",
"description":"",
"web_url":"http://example.com/jsmith/example",
"avatar_url":null,
"git_ssh_url":"git@example.com:jsmith/example.git",
"git_http_url":"http://example.com/jsmith/example.git",
"namespace":"Jsmith",
"visibility_level":0,
"path_with_namespace":"jsmith/example",
"default_branch":"master",
}
}
```
......@@ -41,6 +41,7 @@ X-Gitlab-Event: Push Hook
"before": "95790bf891e76fee5e1747ab589903a6a1f80f22",
"after": "da1560886d4f094c3e6c9ef40349f7d38b5d27d7",
"ref": "refs/heads/master",
"checkout_sha": "da1560886d4f094c3e6c9ef40349f7d38b5d27d7",
"user_id": 4,
"user_name": "John Smith",
"user_email": "john@example.com",
......@@ -118,9 +119,10 @@ X-Gitlab-Event: Tag Push Hook
```json
{
"object_kind": "tag_push",
"ref": "refs/tags/v1.0.0",
"before": "0000000000000000000000000000000000000000",
"after": "82b3d5ae55f7080f1e6022629cdb57bfae7cccc7",
"ref": "refs/tags/v1.0.0",
"checkout_sha": "82b3d5ae55f7080f1e6022629cdb57bfae7cccc7",
"user_id": 1,
"user_name": "John Smith",
"user_avatar": "https://s.gravatar.com/avatar/d4c74594d841139328695756648b6bd6?s=8://s.gravatar.com/avatar/d4c74594d841139328695756648b6bd6?s=80",
......
......@@ -36,7 +36,7 @@ module Gitlab
commit.hook_attrs(with_changed_files: true)
end
type = Gitlab::Git.tag_ref?(ref) ? "tag_push" : "push"
type = Gitlab::Git.tag_ref?(ref) ? 'tag_push' : 'push'
# Hash to be passed as post_receive_data
data = {
......@@ -62,6 +62,26 @@ module Gitlab
data
end
def build_system(project, user, oldrev, newrev, ref)
type = Gitlab::Git.tag_ref?(ref) ? 'tag_push' : 'push'
data = {
event_name: type,
before: oldrev,
after: newrev,
ref: ref,
checkout_sha: checkout_sha(project.repository, newrev, ref),
user_id: user.id,
user_name: user.name,
user_email: user.email,
user_avatar: user.avatar_url,
project_id: project.id,
project: project.hook_attrs(backward: false)
}
data
end
# This method provide a sample data generated with
# existing project and commits to test webhooks
def build_sample(project, user)
......
......@@ -14,11 +14,11 @@ describe Gitlab::PushDataBuilder, lib: true do
it { expect(data[:ref]).to eq('refs/heads/master') }
it { expect(data[:commits].size).to eq(3) }
it { expect(data[:total_commits_count]).to eq(3) }
it { expect(data[:commits].first[:added]).to eq(["gitlab-grack"]) }
it { expect(data[:commits].first[:modified]).to eq([".gitmodules"]) }
it { expect(data[:commits].first[:added]).to eq(['gitlab-grack']) }
it { expect(data[:commits].first[:modified]).to eq(['.gitmodules']) }
it { expect(data[:commits].first[:removed]).to eq([]) }
include_examples 'project hook data'
include_examples 'project hook data with deprecateds'
include_examples 'deprecated repository hook data'
end
......@@ -37,9 +37,34 @@ describe Gitlab::PushDataBuilder, lib: true do
it { expect(data[:commits]).to be_empty }
it { expect(data[:total_commits_count]).to be_zero }
include_examples 'project hook data with deprecateds'
include_examples 'deprecated repository hook data'
it 'does not raise an error when given nil commits' do
expect { described_class.build(spy, spy, spy, spy, spy, nil) }.
not_to raise_error
end
end
describe '.build_system' do
let(:data) do
described_class.build_system(project, user, Gitlab::Git::BLANK_SHA,
'8a2a6eb295bb170b34c24c76c49ed0e9b2eaf34b',
'refs/tags/v1.1.0')
end
it { expect(data).to be_a(Hash) }
it { expect(data[:before]).to eq(Gitlab::Git::BLANK_SHA) }
it { expect(data[:checkout_sha]).to eq('5937ac0a7beb003549fc5fd26fc247adbce4a52e') }
it { expect(data[:after]).to eq('8a2a6eb295bb170b34c24c76c49ed0e9b2eaf34b') }
it { expect(data[:ref]).to eq('refs/tags/v1.1.0') }
it { expect(data[:user_id]).to eq(user.id) }
it { expect(data[:user_name]).to eq(user.name) }
it { expect(data[:user_email]).to eq(user.email) }
it { expect(data[:user_avatar]).to eq(user.avatar_url) }
it { expect(data[:project_id]).to eq(project.id) }
it { expect(data[:project]).to be_a(Hash) }
include_examples 'project hook data'
end
end
RSpec.shared_examples 'project hook data' do |project_key: :project|
RSpec.shared_examples 'project hook data with deprecateds' do |project_key: :project|
it 'contains project data' do
expect(data[project_key][:name]).to eq(project.name)
expect(data[project_key][:description]).to eq(project.description)
......@@ -17,6 +17,21 @@ RSpec.shared_examples 'project hook data' do |project_key: :project|
end
end
RSpec.shared_examples 'project hook data' do |project_key: :project|
it 'contains project data' do
expect(data[project_key][:name]).to eq(project.name)
expect(data[project_key][:description]).to eq(project.description)
expect(data[project_key][:web_url]).to eq(project.web_url)
expect(data[project_key][:avatar_url]).to eq(project.avatar_url)
expect(data[project_key][:git_http_url]).to eq(project.http_url_to_repo)
expect(data[project_key][:git_ssh_url]).to eq(project.ssh_url_to_repo)
expect(data[project_key][:namespace]).to eq(project.namespace.name)
expect(data[project_key][:visibility_level]).to eq(project.visibility_level)
expect(data[project_key][:path_with_namespace]).to eq(project.path_with_namespace)
expect(data[project_key][:default_branch]).to eq(project.default_branch)
end
end
RSpec.shared_examples 'deprecated repository hook data' do |project_key: :project|
it 'contains deprecated repository data' do
expect(data[:repository][:name]).to eq(project.name)
......
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