diff options
Diffstat (limited to 'app/roles/push_observer.rb')
-rw-r--r-- | app/roles/push_observer.rb | 105 |
1 files changed, 105 insertions, 0 deletions
diff --git a/app/roles/push_observer.rb b/app/roles/push_observer.rb new file mode 100644 index 00000000000..1067404d5af --- /dev/null +++ b/app/roles/push_observer.rb @@ -0,0 +1,105 @@ +module PushObserver + def observe_push(oldrev, newrev, ref, user) + data = post_receive_data(oldrev, newrev, ref, user) + + Event.create( + project: self, + action: Event::Pushed, + data: data, + author_id: data[:user_id] + ) + end + + def update_merge_requests(oldrev, newrev, ref, user) + return true unless ref =~ /heads/ + branch_name = ref.gsub("refs/heads/", "") + c_ids = self.commits_between(oldrev, newrev).map(&:id) + + # Update code for merge requests + mrs = self.merge_requests.opened.find_all_by_branch(branch_name).all + mrs.each { |merge_request| merge_request.reload_code; merge_request.mark_as_unchecked } + + # Close merge requests + mrs = self.merge_requests.opened.where(target_branch: branch_name).all + mrs = mrs.select(&:last_commit).select { |mr| c_ids.include?(mr.last_commit.id) } + mrs.each { |merge_request| merge_request.merge!(user.id) } + + true + end + + def execute_hooks(oldrev, newrev, ref, user) + ref_parts = ref.split('/') + + # Return if this is not a push to a branch (e.g. new commits) + return if ref_parts[1] !~ /heads/ || oldrev == "00000000000000000000000000000000" + + data = post_receive_data(oldrev, newrev, ref, user) + + hooks.each { |hook| hook.execute(data) } + end + + def post_receive_data(oldrev, newrev, ref, user) + + push_commits = commits_between(oldrev, newrev) + + # Total commits count + push_commits_count = push_commits.size + + # Get latest 20 commits ASC + push_commits_limited = push_commits.last(20) + + # Hash to be passed as post_receive_data + data = { + before: oldrev, + after: newrev, + ref: ref, + user_id: user.id, + user_name: user.name, + repository: { + name: name, + url: web_url, + description: description, + homepage: web_url, + }, + commits: [], + total_commits_count: push_commits_count + } + + # For perfomance purposes maximum 20 latest commits + # will be passed as post receive hook data. + # + push_commits_limited.each do |commit| + data[:commits] << { + id: commit.id, + message: commit.safe_message, + timestamp: commit.date.xmlschema, + url: "#{Gitlab.config.url}/#{code}/commits/#{commit.id}", + author: { + name: commit.author_name, + email: commit.author_email + } + } + end + + data + end + + + # This method will be called after each post receive + # and only if user present in gitlab. + # All callbacks for post receive should be placed here + # + def trigger_post_receive(oldrev, newrev, ref, user) + # Create push event + self.observe_push(oldrev, newrev, ref, user) + + # Close merged MR + self.update_merge_requests(oldrev, newrev, ref, user) + + # Execute web hooks + self.execute_hooks(oldrev, newrev, ref, user) + + # Create satellite + self.satellite.create unless self.satellite.exists? + end +end |