Commit f6619809 authored by Gabriel Mazetto's avatar Gabriel Mazetto

Added repository_update hook

parent 8b17fb61
class SystemHook < WebHook class SystemHook < WebHook
scope :repository_update_hooks, -> { where(repository_update_events: true) }
def async_execute(data, hook_name) def async_execute(data, hook_name)
Sidekiq::Client.enqueue(SystemHookWorker, id, data, hook_name) Sidekiq::Client.enqueue(SystemHookWorker, id, data, hook_name)
end end
......
...@@ -10,6 +10,7 @@ class WebHook < ActiveRecord::Base ...@@ -10,6 +10,7 @@ class WebHook < ActiveRecord::Base
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 :pipeline_events, false
default_value_for :repository_update_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) }
......
...@@ -20,13 +20,32 @@ class PostReceive ...@@ -20,13 +20,32 @@ class PostReceive
# Nothing defined here yet. # Nothing defined here yet.
else else
process_project_changes(post_received) process_project_changes(post_received)
process_repository_update(post_received)
end end
end end
def process_project_changes(post_received) def process_repository_update(post_received)
post_received.changes.each do |change| changes = []
oldrev, newrev, ref = change.strip.split(' ') refs = Set.new
post_received.changes_refs do |oldrev, newrev, ref|
@user ||= post_received.identify(newrev)
unless @user
log("Triggered hook for non-existing user \"#{post_received.identifier}\"")
return false
end
changes << Gitlab::DataBuilder::Repository.single_change(oldrev, newrev, ref)
refs << ref
end
hook_data = Gitlab::DataBuilder::Repository.update(post_received.project, @user, changes, refs.to_a)
SystemHooksService.new.execute_hooks(hook_data, :repository_update_hooks)
end
def process_project_changes(post_received)
post_received.changes_refs do |oldrev, newrev, ref|
@user ||= post_received.identify(newrev) @user ||= post_received.identify(newrev)
unless @user unless @user
......
class AddRepositoryUpdateEventsToWebHooks < ActiveRecord::Migration
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
disable_ddl_transaction!
def up
add_column_with_default :web_hooks, :repository_update_events, :boolean, default: false, allow_null: false
end
def down
remove_column :web_hooks, :repository_update_events
end
end
...@@ -1404,6 +1404,7 @@ ActiveRecord::Schema.define(version: 20170508190732) do ...@@ -1404,6 +1404,7 @@ ActiveRecord::Schema.define(version: 20170508190732) do
t.string "token" t.string "token"
t.boolean "pipeline_events", default: false, null: false t.boolean "pipeline_events", default: false, null: false
t.boolean "confidential_issues_events", default: false, null: false t.boolean "confidential_issues_events", default: false, null: false
t.boolean "repository_update_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
......
module Gitlab
module DataBuilder
module Repository
extend self
# Produce a hash of post-receive data
def update(project, user, changes, refs)
{
event_name: 'repository_update',
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,
changes: changes,
refs: refs
}
end
# Produce a hash of partial data for a single change
def single_change(oldrev, newrev, ref)
{
before: oldrev,
after: newrev,
ref: ref
}
end
end
end
end
...@@ -13,6 +13,16 @@ module Gitlab ...@@ -13,6 +13,16 @@ module Gitlab
super(identifier, project, revision) super(identifier, project, revision)
end end
def changes_refs
return enum_for(:changes_refs) unless block_given?
changes.each do |change|
oldrev, newrev, ref = change.strip.split(' ')
yield oldrev, newrev, ref
end
end
private private
def deserialize_changes(changes) def deserialize_changes(changes)
......
...@@ -317,6 +317,7 @@ ProjectHook: ...@@ -317,6 +317,7 @@ ProjectHook:
- token - token
- group_id - group_id
- confidential_issues_events - confidential_issues_events
- repository_update_events
ProtectedBranch: ProtectedBranch:
- id - id
- project_id - project_id
......
...@@ -105,4 +105,12 @@ describe SystemHook, models: true do ...@@ -105,4 +105,12 @@ describe SystemHook, models: true do
).once ).once
end end
end end
describe '.repository_update_hooks' do
it 'returns hooks for repository update events only' do
hook = create(:system_hook, repository_update_events: true)
create(:system_hook, repository_update_events: false)
expect(SystemHook.repository_update_hooks).to eq([hook])
end
end
end end
...@@ -9,7 +9,7 @@ describe PostReceive do ...@@ -9,7 +9,7 @@ describe PostReceive do
let(:key) { create(:key, user: project.owner) } let(:key) { create(:key, user: project.owner) }
let(:key_id) { key.shell_id } let(:key_id) { key.shell_id }
context "as a resque worker" do context "as a sidekiq worker" do
it "reponds to #perform" do it "reponds to #perform" do
expect(described_class.new).to respond_to(:perform) expect(described_class.new).to respond_to(:perform)
end end
...@@ -93,6 +93,27 @@ describe PostReceive do ...@@ -93,6 +93,27 @@ describe PostReceive do
end end
end end
describe '#process_repository_update' do
let(:changes) {'123456 789012 refs/heads/tést'}
let(:fake_hook_data) do
{ event_name: 'repository_update' }
end
before do
allow_any_instance_of(Gitlab::GitPostReceive).to receive(:identify).and_return(project.owner)
allow_any_instance_of(Gitlab::DataBuilder::Repository).to receive(:update).and_return(fake_hook_data)
# silence hooks so we can isolate
allow_any_instance_of(Key).to receive(:post_create_hook).and_return(true)
allow(subject).to receive(:process_project_changes).and_return(true)
end
it 'calls SystemHooksService' do
expect_any_instance_of(SystemHooksService).to receive(:execute_hooks).with(fake_hook_data, :repository_update_hooks).and_return(true)
subject.perform(pwd(project), key_id, base64_changes)
end
end
context "webhook" do context "webhook" do
it "fetches the correct project" do it "fetches the correct project" do
expect(Project).to receive(:find_by).with(id: project.id.to_s) expect(Project).to receive(:find_by).with(id: project.id.to_s)
......
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