Commit 897da534fa7ab3b2280bfea05c5da4b57e3b8612

Authored by randx
1 parent eb2c1cd2

Fix issues with push 600+ commits. refactored, improved push events

app/models/event/push_trait.rb
@@ -49,11 +49,14 @@ module Event::PushTrait @@ -49,11 +49,14 @@ module Event::PushTrait
49 def tag_name 49 def tag_name
50 @tag_name ||= data[:ref].gsub("refs/tags/", "") 50 @tag_name ||= data[:ref].gsub("refs/tags/", "")
51 end 51 end
52 - 52 +
  53 + # Max 20 commits from push DESC
53 def commits 54 def commits
54 - @commits ||= data[:commits].map do |commit|  
55 - project.commit(commit["id"])  
56 - end 55 + @commits ||= data[:commits].map { |commit| project.commit(commit[:id]) }.reverse
  56 + end
  57 +
  58 + def commits_count
  59 + data[:total_commits_count] || commits.count || 0
57 end 60 end
58 61
59 def ref_type 62 def ref_type
@@ -71,13 +74,15 @@ module Event::PushTrait @@ -71,13 +74,15 @@ module Event::PushTrait
71 end 74 end
72 75
73 def parent_commit 76 def parent_commit
74 - commits.first.prev_commit 77 + project.commit(commit_from)
75 rescue => ex 78 rescue => ex
76 nil 79 nil
77 end 80 end
78 81
79 def last_commit 82 def last_commit
80 - commits.last 83 + project.commit(commit_to)
  84 + rescue => ex
  85 + nil
81 end 86 end
82 87
83 def push_with_commits? 88 def push_with_commits?
app/models/project/hooks_trait.rb
1 module Project::HooksTrait 1 module Project::HooksTrait
2 as_trait do 2 as_trait do
3 - def observe_push(oldrev, newrev, ref, author_key_id)  
4 - data = web_hook_data(oldrev, newrev, ref, author_key_id) 3 + def observe_push(oldrev, newrev, ref, user)
  4 + data = post_receive_data(oldrev, newrev, ref, user)
5 5
6 Event.create( 6 Event.create(
7 :project => self, 7 :project => self,
@@ -11,10 +11,9 @@ module Project::HooksTrait @@ -11,10 +11,9 @@ module Project::HooksTrait
11 ) 11 )
12 end 12 end
13 13
14 - def update_merge_requests(oldrev, newrev, ref, author_key_id) 14 + def update_merge_requests(oldrev, newrev, ref, user)
15 return true unless ref =~ /heads/ 15 return true unless ref =~ /heads/
16 branch_name = ref.gsub("refs/heads/", "") 16 branch_name = ref.gsub("refs/heads/", "")
17 - user = Key.find_by_identifier(author_key_id).user  
18 c_ids = self.commits_between(oldrev, newrev).map(&:id) 17 c_ids = self.commits_between(oldrev, newrev).map(&:id)
19 18
20 # Update code for merge requests 19 # Update code for merge requests
@@ -29,36 +28,48 @@ module Project::HooksTrait @@ -29,36 +28,48 @@ module Project::HooksTrait
29 true 28 true
30 end 29 end
31 30
32 - def execute_web_hooks(oldrev, newrev, ref, author_key_id) 31 + def execute_web_hooks(oldrev, newrev, ref, user)
33 ref_parts = ref.split('/') 32 ref_parts = ref.split('/')
34 33
35 # Return if this is not a push to a branch (e.g. new commits) 34 # Return if this is not a push to a branch (e.g. new commits)
36 return if ref_parts[1] !~ /heads/ || oldrev == "00000000000000000000000000000000" 35 return if ref_parts[1] !~ /heads/ || oldrev == "00000000000000000000000000000000"
37 36
38 - data = web_hook_data(oldrev, newrev, ref, author_key_id) 37 + data = post_receive_data(oldrev, newrev, ref, user)
39 38
40 web_hooks.each { |web_hook| web_hook.execute(data) } 39 web_hooks.each { |web_hook| web_hook.execute(data) }
41 end 40 end
42 41
43 - def web_hook_data(oldrev, newrev, ref, author_key_id)  
44 - key = Key.find_by_identifier(author_key_id) 42 + def post_receive_data(oldrev, newrev, ref, user)
  43 +
  44 + push_commits = commits_between(oldrev, newrev)
  45 +
  46 + # Total commits count
  47 + push_commits_count = push_commits.size
  48 +
  49 + # Get latest 20 commits ASC
  50 + push_commits_limited = push_commits.last(20)
  51 +
  52 + # Hash to be passed as post_receive_data
45 data = { 53 data = {
46 before: oldrev, 54 before: oldrev,
47 after: newrev, 55 after: newrev,
48 ref: ref, 56 ref: ref,
49 - user_id: key.user.id,  
50 - user_name: key.user_name, 57 + user_id: user.id,
  58 + user_name: user.name,
51 repository: { 59 repository: {
52 name: name, 60 name: name,
53 url: web_url, 61 url: web_url,
54 description: description, 62 description: description,
55 homepage: web_url, 63 homepage: web_url,
56 - private: private?  
57 }, 64 },
58 - commits: [] 65 + commits: [],
  66 + total_commits_count: push_commits_count
59 } 67 }
60 68
61 - commits_between(oldrev, newrev).each do |commit| 69 + # For perfomance purposes maximum 20 latest commits
  70 + # will be passed as post receive hook data.
  71 + #
  72 + push_commits_limited.each do |commit|
62 data[:commits] << { 73 data[:commits] << {
63 id: commit.id, 74 id: commit.id,
64 message: commit.safe_message, 75 message: commit.safe_message,
@@ -73,5 +84,23 @@ module Project::HooksTrait @@ -73,5 +84,23 @@ module Project::HooksTrait
73 84
74 data 85 data
75 end 86 end
  87 +
  88 +
  89 + # This method will be called after each post receive
  90 + # and only if autor_key_id present in gitlab.
  91 + # All callbacks for post receive should be placed here
  92 + #
  93 + def trigger_post_receive(oldrev, newrev, ref, author_key_id)
  94 + user = Key.find_by_identifier(author_key_id).user
  95 +
  96 + # Create push event
  97 + self.observe_push(oldrev, newrev, ref, user)
  98 +
  99 + # Close merged MR
  100 + self.update_merge_requests(oldrev, newrev, ref, user)
  101 +
  102 + # Execute web hooks
  103 + self.execute_web_hooks(oldrev, newrev, ref, user)
  104 + end
76 end 105 end
77 end 106 end
app/views/commits/compare.html.haml
@@ -24,7 +24,7 @@ @@ -24,7 +24,7 @@
24 24
25 25
26 - unless @commits.empty? 26 - unless @commits.empty?
27 - %h4 Commits 27 + %h4 Commits (#{@commits.count})
28 %ul.unstyled= render @commits 28 %ul.unstyled= render @commits
29 29
30 - unless @diffs.empty? 30 - unless @diffs.empty?
app/views/dashboard/index.html.haml
@@ -47,7 +47,7 @@ @@ -47,7 +47,7 @@
47 - if @last_push && @last_push.valid_push? 47 - if @last_push && @last_push.valid_push?
48 .padded.prepend-top-20 48 .padded.prepend-top-20
49 %h5 49 %h5
50 - %small Latest push was to the #{@last_push.branch_name} branch of #{@last_push.project.name}: 50 + %small Latest push was to the #{@last_push.ref_name} #{@last_push.ref_type} of #{@last_push.project.name}:
51 %ul.unstyled= render @last_push 51 %ul.unstyled= render @last_push
52 52
53 - if @merge_requests.any? 53 - if @merge_requests.any?
app/views/events/_event_push.html.haml
@@ -11,17 +11,17 @@ @@ -11,17 +11,17 @@
11 ago. 11 ago.
12 12
13 - if event.push_with_commits? 13 - if event.push_with_commits?
14 - - if event.commits.count > 1 14 + - if event.commits_count > 1
15 = link_to compare_project_commits_path(event.project, :from => event.parent_commit.id, :to => event.last_commit.id) do 15 = link_to compare_project_commits_path(event.project, :from => event.parent_commit.id, :to => event.last_commit.id) do
16 - %strong #{event.commits.first.id[0..7]}...#{event.last_commit.id[0..7]} 16 + %strong #{event.parent_commit.id[0..7]}...#{event.last_commit.id[0..7]}
17 - project = event.project 17 - project = event.project
18 %ul.unstyled.event_commits 18 %ul.unstyled.event_commits
19 - - if event.commits.size > 3 19 + - if event.commits_count > 3
20 - event.commits[0...2].each do |commit| 20 - event.commits[0...2].each do |commit|
21 = render "events/commit", :commit => commit, :project => project 21 = render "events/commit", :commit => commit, :project => project
22 %li 22 %li
23 %br 23 %br
24 - \... and #{event.commits.size - 2} more commits 24 + \... and #{event.commits_count - 2} more commits
25 - else 25 - else
26 - event.commits.each do |commit| 26 - event.commits.each do |commit|
27 = render "events/commit", :commit => commit, :project => project 27 = render "events/commit", :commit => commit, :project => project
app/workers/post_receive.rb
@@ -8,13 +8,6 @@ class PostReceive @@ -8,13 +8,6 @@ class PostReceive
8 # Ignore push from non-gitlab users 8 # Ignore push from non-gitlab users
9 return false unless Key.find_by_identifier(author_key_id) 9 return false unless Key.find_by_identifier(author_key_id)
10 10
11 - # Create push event  
12 - project.observe_push(oldrev, newrev, ref, author_key_id)  
13 -  
14 - # Close merged MR  
15 - project.update_merge_requests(oldrev, newrev, ref, author_key_id)  
16 -  
17 - # Execute web hooks  
18 - project.execute_web_hooks(oldrev, newrev, ref, author_key_id) 11 + project.trigger_post_receive(oldrev, newrev, ref, author_key_id)
19 end 12 end
20 end 13 end
spec/models/project_hooks_spec.rb
@@ -4,19 +4,20 @@ describe Project, &quot;Hooks&quot; do @@ -4,19 +4,20 @@ describe Project, &quot;Hooks&quot; do
4 let(:project) { Factory :project } 4 let(:project) { Factory :project }
5 before do 5 before do
6 @key = Factory :key, :user => project.owner 6 @key = Factory :key, :user => project.owner
  7 + @user = @key.user
7 @key_id = @key.identifier 8 @key_id = @key.identifier
8 end 9 end
9 10
10 describe "Post Receive Event" do 11 describe "Post Receive Event" do
11 it "should create push event" do 12 it "should create push event" do
12 oldrev, newrev, ref = '00000000000000000000000000000000', 'newrev', 'refs/heads/master' 13 oldrev, newrev, ref = '00000000000000000000000000000000', 'newrev', 'refs/heads/master'
13 - project.observe_push(oldrev, newrev, ref, @key_id) 14 + project.observe_push(oldrev, newrev, ref, @user)
14 event = Event.last 15 event = Event.last
15 16
16 event.should_not be_nil 17 event.should_not be_nil
17 event.project.should == project 18 event.project.should == project
18 event.action.should == Event::Pushed 19 event.action.should == Event::Pushed
19 - event.data == project.web_hook_data(oldrev, newrev, ref, @key_id) 20 + event.data == project.post_receive_data(oldrev, newrev, ref, @user)
20 end 21 end
21 end 22 end
22 23
@@ -24,7 +25,7 @@ describe Project, &quot;Hooks&quot; do @@ -24,7 +25,7 @@ describe Project, &quot;Hooks&quot; do
24 context "with no web hooks" do 25 context "with no web hooks" do
25 it "raises no errors" do 26 it "raises no errors" do
26 lambda { 27 lambda {
27 - project.execute_web_hooks('oldrev', 'newrev', 'ref', @key_id) 28 + project.execute_web_hooks('oldrev', 'newrev', 'ref', @user)
28 }.should_not raise_error 29 }.should_not raise_error
29 end 30 end
30 end 31 end
@@ -40,7 +41,7 @@ describe Project, &quot;Hooks&quot; do @@ -40,7 +41,7 @@ describe Project, &quot;Hooks&quot; do
40 @webhook.should_receive(:execute).once 41 @webhook.should_receive(:execute).once
41 @webhook_2.should_receive(:execute).once 42 @webhook_2.should_receive(:execute).once
42 43
43 - project.execute_web_hooks('oldrev', 'newrev', 'refs/heads/master', @key_id) 44 + project.execute_web_hooks('oldrev', 'newrev', 'refs/heads/master', @user)
44 end 45 end
45 end 46 end
46 47
@@ -52,12 +53,12 @@ describe Project, &quot;Hooks&quot; do @@ -52,12 +53,12 @@ describe Project, &quot;Hooks&quot; do
52 53
53 it "when pushing a branch for the first time" do 54 it "when pushing a branch for the first time" do
54 @webhook.should_not_receive(:execute) 55 @webhook.should_not_receive(:execute)
55 - project.execute_web_hooks('00000000000000000000000000000000', 'newrev', 'refs/heads/master', @key_id) 56 + project.execute_web_hooks('00000000000000000000000000000000', 'newrev', 'refs/heads/master', @user)
56 end 57 end
57 58
58 it "when pushing tags" do 59 it "when pushing tags" do
59 @webhook.should_not_receive(:execute) 60 @webhook.should_not_receive(:execute)
60 - project.execute_web_hooks('oldrev', 'newrev', 'refs/tags/v1.0.0', @key_id) 61 + project.execute_web_hooks('oldrev', 'newrev', 'refs/tags/v1.0.0', @user)
61 end 62 end
62 end 63 end
63 64
@@ -73,7 +74,7 @@ describe Project, &quot;Hooks&quot; do @@ -73,7 +74,7 @@ describe Project, &quot;Hooks&quot; do
73 # Fill nil/empty attributes 74 # Fill nil/empty attributes
74 project.description = "This is a description" 75 project.description = "This is a description"
75 76
76 - @data = project.web_hook_data(@oldrev, @newrev, @ref, @key_id) 77 + @data = project.post_receive_data(@oldrev, @newrev, @ref, @user)
77 end 78 end
78 79
79 subject { @data } 80 subject { @data }
@@ -91,7 +92,6 @@ describe Project, &quot;Hooks&quot; do @@ -91,7 +92,6 @@ describe Project, &quot;Hooks&quot; do
91 it { should include(url: project.web_url) } 92 it { should include(url: project.web_url) }
92 it { should include(description: project.description) } 93 it { should include(description: project.description) }
93 it { should include(homepage: project.web_url) } 94 it { should include(homepage: project.web_url) }
94 - it { should include(private: project.private?) }  
95 end 95 end
96 96
97 context "with commits" do 97 context "with commits" do
spec/models/project_spec.rb
@@ -175,7 +175,7 @@ describe Project do @@ -175,7 +175,7 @@ describe Project do
175 it "should close merge request if last commit from source branch was pushed to target branch" do 175 it "should close merge request if last commit from source branch was pushed to target branch" do
176 @merge_request.reloaded_commits 176 @merge_request.reloaded_commits
177 @merge_request.last_commit.id.should == "bcf03b5de6c33f3869ef70d68cf06e679d1d7f9a" 177 @merge_request.last_commit.id.should == "bcf03b5de6c33f3869ef70d68cf06e679d1d7f9a"
178 - project.update_merge_requests("8716fc78f3c65bbf7bcf7b574febd583bc5d2812", "bcf03b5de6c33f3869ef70d68cf06e679d1d7f9a", "refs/heads/stable", @key.identifier) 178 + project.update_merge_requests("8716fc78f3c65bbf7bcf7b574febd583bc5d2812", "bcf03b5de6c33f3869ef70d68cf06e679d1d7f9a", "refs/heads/stable", @key.user)
179 @merge_request.reload 179 @merge_request.reload
180 @merge_request.merged.should be_true 180 @merge_request.merged.should be_true
181 @merge_request.closed.should be_true 181 @merge_request.closed.should be_true
@@ -183,7 +183,7 @@ describe Project do @@ -183,7 +183,7 @@ describe Project do
183 183
184 it "should update merge request commits with new one if pushed to source branch" do 184 it "should update merge request commits with new one if pushed to source branch" do
185 @merge_request.last_commit.should == nil 185 @merge_request.last_commit.should == nil
186 - project.update_merge_requests("8716fc78f3c65bbf7bcf7b574febd583bc5d2812", "bcf03b5de6c33f3869ef70d68cf06e679d1d7f9a", "refs/heads/master", @key.identifier) 186 + project.update_merge_requests("8716fc78f3c65bbf7bcf7b574febd583bc5d2812", "bcf03b5de6c33f3869ef70d68cf06e679d1d7f9a", "refs/heads/master", @key.user)
187 @merge_request.reload 187 @merge_request.reload
188 @merge_request.last_commit.id.should == "bcf03b5de6c33f3869ef70d68cf06e679d1d7f9a" 188 @merge_request.last_commit.id.should == "bcf03b5de6c33f3869ef70d68cf06e679d1d7f9a"
189 end 189 end
spec/workers/post_receive_spec.rb
@@ -29,14 +29,14 @@ describe PostReceive do @@ -29,14 +29,14 @@ describe PostReceive do
29 29
30 it "asks the project to execute web hooks" do 30 it "asks the project to execute web hooks" do
31 Project.stub(find_by_path: project) 31 Project.stub(find_by_path: project)
32 - project.should_receive(:execute_web_hooks).with('sha-old', 'sha-new', 'refs/heads/master', key_id) 32 + project.should_receive(:execute_web_hooks).with('sha-old', 'sha-new', 'refs/heads/master', project.owner)
33 33
34 PostReceive.perform(project.path, 'sha-old', 'sha-new', 'refs/heads/master', key_id) 34 PostReceive.perform(project.path, 'sha-old', 'sha-new', 'refs/heads/master', key_id)
35 end 35 end
36 36
37 it "asks the project to observe push/create event data" do 37 it "asks the project to observe push/create event data" do
38 Project.stub(find_by_path: project) 38 Project.stub(find_by_path: project)
39 - project.should_receive(:observe_push).with('sha-old', 'sha-new', 'refs/heads/master', key_id) 39 + project.should_receive(:observe_push).with('sha-old', 'sha-new', 'refs/heads/master', project.owner)
40 40
41 PostReceive.perform(project.path, 'sha-old', 'sha-new', 'refs/heads/master', key_id) 41 PostReceive.perform(project.path, 'sha-old', 'sha-new', 'refs/heads/master', key_id)
42 end 42 end