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 49 def tag_name
50 50 @tag_name ||= data[:ref].gsub("refs/tags/", "")
51 51 end
52   -
  52 +
  53 + # Max 20 commits from push DESC
53 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 60 end
58 61  
59 62 def ref_type
... ... @@ -71,13 +74,15 @@ module Event::PushTrait
71 74 end
72 75  
73 76 def parent_commit
74   - commits.first.prev_commit
  77 + project.commit(commit_from)
75 78 rescue => ex
76 79 nil
77 80 end
78 81  
79 82 def last_commit
80   - commits.last
  83 + project.commit(commit_to)
  84 + rescue => ex
  85 + nil
81 86 end
82 87  
83 88 def push_with_commits?
... ...
app/models/project/hooks_trait.rb
1 1 module Project::HooksTrait
2 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 6 Event.create(
7 7 :project => self,
... ... @@ -11,10 +11,9 @@ module Project::HooksTrait
11 11 )
12 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 15 return true unless ref =~ /heads/
16 16 branch_name = ref.gsub("refs/heads/", "")
17   - user = Key.find_by_identifier(author_key_id).user
18 17 c_ids = self.commits_between(oldrev, newrev).map(&:id)
19 18  
20 19 # Update code for merge requests
... ... @@ -29,36 +28,48 @@ module Project::HooksTrait
29 28 true
30 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 32 ref_parts = ref.split('/')
34 33  
35 34 # Return if this is not a push to a branch (e.g. new commits)
36 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 39 web_hooks.each { |web_hook| web_hook.execute(data) }
41 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 53 data = {
46 54 before: oldrev,
47 55 after: newrev,
48 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 59 repository: {
52 60 name: name,
53 61 url: web_url,
54 62 description: description,
55 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 73 data[:commits] << {
63 74 id: commit.id,
64 75 message: commit.safe_message,
... ... @@ -73,5 +84,23 @@ module Project::HooksTrait
73 84  
74 85 data
75 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 105 end
77 106 end
... ...
app/views/commits/compare.html.haml
... ... @@ -24,7 +24,7 @@
24 24  
25 25  
26 26 - unless @commits.empty?
27   - %h4 Commits
  27 + %h4 Commits (#{@commits.count})
28 28 %ul.unstyled= render @commits
29 29  
30 30 - unless @diffs.empty?
... ...
app/views/dashboard/index.html.haml
... ... @@ -47,7 +47,7 @@
47 47 - if @last_push && @last_push.valid_push?
48 48 .padded.prepend-top-20
49 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 51 %ul.unstyled= render @last_push
52 52  
53 53 - if @merge_requests.any?
... ...
app/views/events/_event_push.html.haml
... ... @@ -11,17 +11,17 @@
11 11 ago.
12 12  
13 13 - if event.push_with_commits?
14   - - if event.commits.count > 1
  14 + - if event.commits_count > 1
15 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 17 - project = event.project
18 18 %ul.unstyled.event_commits
19   - - if event.commits.size > 3
  19 + - if event.commits_count > 3
20 20 - event.commits[0...2].each do |commit|
21 21 = render "events/commit", :commit => commit, :project => project
22 22 %li
23 23 %br
24   - \... and #{event.commits.size - 2} more commits
  24 + \... and #{event.commits_count - 2} more commits
25 25 - else
26 26 - event.commits.each do |commit|
27 27 = render "events/commit", :commit => commit, :project => project
... ...
app/workers/post_receive.rb
... ... @@ -8,13 +8,6 @@ class PostReceive
8 8 # Ignore push from non-gitlab users
9 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 12 end
20 13 end
... ...
spec/models/project_hooks_spec.rb
... ... @@ -4,19 +4,20 @@ describe Project, &quot;Hooks&quot; do
4 4 let(:project) { Factory :project }
5 5 before do
6 6 @key = Factory :key, :user => project.owner
  7 + @user = @key.user
7 8 @key_id = @key.identifier
8 9 end
9 10  
10 11 describe "Post Receive Event" do
11 12 it "should create push event" do
12 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 15 event = Event.last
15 16  
16 17 event.should_not be_nil
17 18 event.project.should == project
18 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 21 end
21 22 end
22 23  
... ... @@ -24,7 +25,7 @@ describe Project, &quot;Hooks&quot; do
24 25 context "with no web hooks" do
25 26 it "raises no errors" do
26 27 lambda {
27   - project.execute_web_hooks('oldrev', 'newrev', 'ref', @key_id)
  28 + project.execute_web_hooks('oldrev', 'newrev', 'ref', @user)
28 29 }.should_not raise_error
29 30 end
30 31 end
... ... @@ -40,7 +41,7 @@ describe Project, &quot;Hooks&quot; do
40 41 @webhook.should_receive(:execute).once
41 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 45 end
45 46 end
46 47  
... ... @@ -52,12 +53,12 @@ describe Project, &quot;Hooks&quot; do
52 53  
53 54 it "when pushing a branch for the first time" do
54 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 57 end
57 58  
58 59 it "when pushing tags" do
59 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 62 end
62 63 end
63 64  
... ... @@ -73,7 +74,7 @@ describe Project, &quot;Hooks&quot; do
73 74 # Fill nil/empty attributes
74 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 78 end
78 79  
79 80 subject { @data }
... ... @@ -91,7 +92,6 @@ describe Project, &quot;Hooks&quot; do
91 92 it { should include(url: project.web_url) }
92 93 it { should include(description: project.description) }
93 94 it { should include(homepage: project.web_url) }
94   - it { should include(private: project.private?) }
95 95 end
96 96  
97 97 context "with commits" do
... ...
spec/models/project_spec.rb
... ... @@ -175,7 +175,7 @@ describe Project do
175 175 it "should close merge request if last commit from source branch was pushed to target branch" do
176 176 @merge_request.reloaded_commits
177 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 179 @merge_request.reload
180 180 @merge_request.merged.should be_true
181 181 @merge_request.closed.should be_true
... ... @@ -183,7 +183,7 @@ describe Project do
183 183  
184 184 it "should update merge request commits with new one if pushed to source branch" do
185 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 187 @merge_request.reload
188 188 @merge_request.last_commit.id.should == "bcf03b5de6c33f3869ef70d68cf06e679d1d7f9a"
189 189 end
... ...
spec/workers/post_receive_spec.rb
... ... @@ -29,14 +29,14 @@ describe PostReceive do
29 29  
30 30 it "asks the project to execute web hooks" do
31 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 34 PostReceive.perform(project.path, 'sha-old', 'sha-new', 'refs/heads/master', key_id)
35 35 end
36 36  
37 37 it "asks the project to observe push/create event data" do
38 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 41 PostReceive.perform(project.path, 'sha-old', 'sha-new', 'refs/heads/master', key_id)
42 42 end
... ...