Commit 85007434645c817e7674003bbdda0674287dd106

Authored by Dmitriy Zaporozhets
1 parent 95c23b2f

Post Receive Refactored. Service hooks also triggered now

app/roles/push_observer.rb
@@ -2,45 +2,83 @@ @@ -2,45 +2,83 @@
2 # 2 #
3 # Triggered by PostReceive job 3 # Triggered by PostReceive job
4 module PushObserver 4 module PushObserver
5 - def observe_push(oldrev, newrev, ref, user) 5 + # This method will be called after each post receive and only if the provided
  6 + # user is present in GitLab.
  7 + #
  8 + # All callbacks for post receive should be placed here.
  9 + def trigger_post_receive(oldrev, newrev, ref, user)
6 data = post_receive_data(oldrev, newrev, ref, user) 10 data = post_receive_data(oldrev, newrev, ref, user)
7 11
8 - Event.create(  
9 - project: self,  
10 - action: Event::Pushed,  
11 - data: data,  
12 - author_id: data[:user_id]  
13 - )  
14 - end 12 + # Create push event
  13 + self.observe_push(data)
15 14
16 - def update_merge_requests(oldrev, newrev, ref, user)  
17 - return true unless ref =~ /heads/  
18 - branch_name = ref.gsub("refs/heads/", "")  
19 - c_ids = self.commits_between(oldrev, newrev).map(&:id) 15 + if push_to_branch? ref, oldrev
  16 + # Close merged MR
  17 + self.update_merge_requests(oldrev, newrev, ref, user)
20 18
21 - # Update code for merge requests  
22 - mrs = self.merge_requests.opened.find_all_by_branch(branch_name).all  
23 - mrs.each { |merge_request| merge_request.reload_code; merge_request.mark_as_unchecked } 19 + # Execute web hooks
  20 + self.execute_hooks(data.dup)
24 21
25 - # Close merge requests  
26 - mrs = self.merge_requests.opened.where(target_branch: branch_name).all  
27 - mrs = mrs.select(&:last_commit).select { |mr| c_ids.include?(mr.last_commit.id) }  
28 - mrs.each { |merge_request| merge_request.merge!(user.id) } 22 + # Execute project services
  23 + self.execute_services(data.dup)
  24 + end
29 25
30 - true 26 + # Create satellite
  27 + self.satellite.create unless self.satellite.exists?
  28 +
  29 + # Discover the default branch, but only if it hasn't already been set to
  30 + # something else
  31 + if default_branch.nil?
  32 + update_attributes(default_branch: discover_default_branch)
  33 + end
31 end 34 end
32 35
33 - def execute_hooks(oldrev, newrev, ref, user) 36 + def push_to_branch? ref, oldrev
34 ref_parts = ref.split('/') 37 ref_parts = ref.split('/')
35 38
36 # Return if this is not a push to a branch (e.g. new commits) 39 # Return if this is not a push to a branch (e.g. new commits)
37 - return if ref_parts[1] !~ /heads/ || oldrev == "00000000000000000000000000000000" 40 + !(ref_parts[1] !~ /heads/ || oldrev == "00000000000000000000000000000000")
  41 + end
38 42
39 - data = post_receive_data(oldrev, newrev, ref, user) 43 + def observe_push(data)
  44 + Event.create(
  45 + project: self,
  46 + action: Event::Pushed,
  47 + data: data,
  48 + author_id: data[:user_id]
  49 + )
  50 + end
40 51
  52 + def execute_hooks(data)
41 hooks.each { |hook| hook.execute(data) } 53 hooks.each { |hook| hook.execute(data) }
42 end 54 end
43 55
  56 + def execute_services(data)
  57 + services.each do |service|
  58 +
  59 + # Call service hook for service if it has one
  60 + service.service_hook.execute if service.service_hook
  61 + end
  62 + end
  63 +
  64 + # Produce a hash of post-receive data
  65 + #
  66 + # data = {
  67 + # before: String,
  68 + # after: String,
  69 + # ref: String,
  70 + # user_id: String,
  71 + # user_name: String,
  72 + # repository: {
  73 + # name: String,
  74 + # url: String,
  75 + # description: String,
  76 + # homepage: String,
  77 + # },
  78 + # commits: Array,
  79 + # total_commits_count: Fixnum
  80 + # }
  81 + #
44 def post_receive_data(oldrev, newrev, ref, user) 82 def post_receive_data(oldrev, newrev, ref, user)
45 83
46 push_commits = commits_between(oldrev, newrev) 84 push_commits = commits_between(oldrev, newrev)
@@ -87,27 +125,20 @@ module PushObserver @@ -87,27 +125,20 @@ module PushObserver
87 data 125 data
88 end 126 end
89 127
90 - # This method will be called after each post receive and only if the provided  
91 - # user is present in GitLab.  
92 - #  
93 - # All callbacks for post receive should be placed here.  
94 - def trigger_post_receive(oldrev, newrev, ref, user)  
95 - # Create push event  
96 - self.observe_push(oldrev, newrev, ref, user)  
97 -  
98 - # Close merged MR  
99 - self.update_merge_requests(oldrev, newrev, ref, user) 128 + def update_merge_requests(oldrev, newrev, ref, user)
  129 + return true unless ref =~ /heads/
  130 + branch_name = ref.gsub("refs/heads/", "")
  131 + c_ids = self.commits_between(oldrev, newrev).map(&:id)
100 132
101 - # Execute web hooks  
102 - self.execute_hooks(oldrev, newrev, ref, user) 133 + # Update code for merge requests
  134 + mrs = self.merge_requests.opened.find_all_by_branch(branch_name).all
  135 + mrs.each { |merge_request| merge_request.reload_code; merge_request.mark_as_unchecked }
103 136
104 - # Create satellite  
105 - self.satellite.create unless self.satellite.exists? 137 + # Close merge requests
  138 + mrs = self.merge_requests.opened.where(target_branch: branch_name).all
  139 + mrs = mrs.select(&:last_commit).select { |mr| c_ids.include?(mr.last_commit.id) }
  140 + mrs.each { |merge_request| merge_request.merge!(user.id) }
106 141
107 - # Discover the default branch, but only if it hasn't already been set to  
108 - # something else  
109 - if default_branch.nil?  
110 - update_attributes(default_branch: discover_default_branch)  
111 - end 142 + true
112 end 143 end
113 end 144 end
spec/models/project_hooks_spec.rb
@@ -11,13 +11,15 @@ describe Project, "Hooks" do @@ -11,13 +11,15 @@ describe Project, "Hooks" do
11 describe "Post Receive Event" do 11 describe "Post Receive Event" do
12 it "should create push event" do 12 it "should create push event" do
13 oldrev, newrev, ref = '00000000000000000000000000000000', 'newrev', 'refs/heads/master' 13 oldrev, newrev, ref = '00000000000000000000000000000000', 'newrev', 'refs/heads/master'
14 - project.observe_push(oldrev, newrev, ref, @user) 14 + data = project.post_receive_data(oldrev, newrev, ref, @user)
  15 +
  16 + project.observe_push(data)
15 event = Event.last 17 event = Event.last
16 18
17 event.should_not be_nil 19 event.should_not be_nil
18 event.project.should == project 20 event.project.should == project
19 event.action.should == Event::Pushed 21 event.action.should == Event::Pushed
20 - event.data == project.post_receive_data(oldrev, newrev, ref, @user) 22 + event.data.should == data
21 end 23 end
22 end 24 end
23 25
@@ -25,7 +27,7 @@ describe Project, "Hooks" do @@ -25,7 +27,7 @@ describe Project, "Hooks" do
25 context "with no web hooks" do 27 context "with no web hooks" do
26 it "raises no errors" do 28 it "raises no errors" do
27 lambda { 29 lambda {
28 - project.execute_hooks('oldrev', 'newrev', 'ref', @user) 30 + project.execute_hooks({})
29 }.should_not raise_error 31 }.should_not raise_error
30 end 32 end
31 end 33 end
@@ -41,7 +43,7 @@ describe Project, "Hooks" do @@ -41,7 +43,7 @@ describe Project, "Hooks" do
41 @project_hook.should_receive(:execute).once 43 @project_hook.should_receive(:execute).once
42 @project_hook_2.should_receive(:execute).once 44 @project_hook_2.should_receive(:execute).once
43 45
44 - project.execute_hooks('oldrev', 'newrev', 'refs/heads/master', @user) 46 + project.trigger_post_receive('oldrev', 'newrev', 'refs/heads/master', @user)
45 end 47 end
46 end 48 end
47 49
@@ -53,12 +55,12 @@ describe Project, "Hooks" do @@ -53,12 +55,12 @@ describe Project, "Hooks" do
53 55
54 it "when pushing a branch for the first time" do 56 it "when pushing a branch for the first time" do
55 @project_hook.should_not_receive(:execute) 57 @project_hook.should_not_receive(:execute)
56 - project.execute_hooks('00000000000000000000000000000000', 'newrev', 'refs/heads/master', @user) 58 + project.trigger_post_receive('00000000000000000000000000000000', 'newrev', 'refs/heads/master', @user)
57 end 59 end
58 60
59 it "when pushing tags" do 61 it "when pushing tags" do
60 @project_hook.should_not_receive(:execute) 62 @project_hook.should_not_receive(:execute)
61 - project.execute_hooks('oldrev', 'newrev', 'refs/tags/v1.0.0', @user) 63 + project.trigger_post_receive('oldrev', 'newrev', 'refs/tags/v1.0.0', @user)
62 end 64 end
63 end 65 end
64 66
spec/workers/post_receive_spec.rb
@@ -27,16 +27,12 @@ describe PostReceive do @@ -27,16 +27,12 @@ describe PostReceive do
27 PostReceive.perform(project.path, 'sha-old', 'sha-new', 'refs/heads/master', key_id).should be_false 27 PostReceive.perform(project.path, 'sha-old', 'sha-new', 'refs/heads/master', key_id).should be_false
28 end 28 end
29 29
30 - it "asks the project to execute web hooks" do 30 + it "asks the project to trigger all hooks" do
31 Project.stub(find_by_path: project) 31 Project.stub(find_by_path: project)
32 - project.should_receive(:execute_hooks).with('sha-old', 'sha-new', 'refs/heads/master', project.owner)  
33 -  
34 - PostReceive.perform(project.path, 'sha-old', 'sha-new', 'refs/heads/master', key_id)  
35 - end  
36 -  
37 - it "asks the project to observe push/create event data" do  
38 - Project.stub(find_by_path: project)  
39 - project.should_receive(:observe_push).with('sha-old', 'sha-new', 'refs/heads/master', project.owner) 32 + project.should_receive(:execute_hooks)
  33 + project.should_receive(:execute_services)
  34 + project.should_receive(:update_merge_requests)
  35 + project.should_receive(:observe_push)
40 36
41 PostReceive.perform(project.path, 'sha-old', 'sha-new', 'refs/heads/master', key_id) 37 PostReceive.perform(project.path, 'sha-old', 'sha-new', 'refs/heads/master', key_id)
42 end 38 end