module PushObserver

Includes methods for handling Git Push events

Triggered by PostReceive job

Public Instance Methods

execute_hooks(oldrev, newrev, ref, user) click to toggle source
# File app/roles/push_observer.rb, line 33
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] !~ %rheads/ || oldrev == "00000000000000000000000000000000"

  data = post_receive_data(oldrev, newrev, ref, user)

  hooks.each { |hook| hook.execute(data) }
end
observe_push(oldrev, newrev, ref, user) click to toggle source
# File app/roles/push_observer.rb, line 5
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
post_receive_data(oldrev, newrev, ref, user) click to toggle source
# File app/roles/push_observer.rb, line 44
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
trigger_post_receive(oldrev, newrev, ref, user) click to toggle source

This method will be called after each post receive and only if the provided user is present in GitLab.

All callbacks for post receive should be placed here.

# File app/roles/push_observer.rb, line 94
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?

  # Discover the default branch, but only if it hasn't already been set to
  # something else
  if default_branch.nil?
    update_attributes(default_branch: discover_default_branch)
  end
end
update_merge_requests(oldrev, newrev, ref, user) click to toggle source
# File app/roles/push_observer.rb, line 16
def update_merge_requests(oldrev, newrev, ref, user)
  return true unless ref =~ %rheads/
  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