class GitReflow::GitServer::GitHub::PullRequest

Public Class Methods

create(options = {}) click to toggle source
# File lib/git_reflow/git_server/git_hub/pull_request.rb, line 17
def self.create(options = {})
  self.new(GitReflow.git_server.connection.pull_requests.create(
    GitReflow.git_server.class.remote_user,
    GitReflow.git_server.class.remote_repo_name,
    title: options[:title],
    body:  options[:body],
    head:  "#{GitReflow.git_server.class.remote_user}:#{GitReflow.git_server.class.current_branch}",
    base:  options[:base]))
end
find_open(options = {}) click to toggle source
# File lib/git_reflow/git_server/git_hub/pull_request.rb, line 27
def self.find_open(options = {})
  options[:to] ||= 'master'
  options[:from] ||= GitReflow.git_server.class.current_branch

  matching_pull = GitReflow.git_server.connection.pull_requests.all(
    GitReflow.remote_user,
    GitReflow.remote_repo_name,
    base: options[:to],
    head: "#{GitReflow.remote_user}:#{options[:from]}",
    state: 'open'
  ).first

  if matching_pull
    self.new matching_pull
  end
end
new(attributes) click to toggle source
# File lib/git_reflow/git_server/git_hub/pull_request.rb, line 7
def initialize(attributes)
  self.number              = attributes.number
  self.description         = attributes[:body]
  self.html_url            = attributes.html_url
  self.feature_branch_name = attributes.head.label[/[^:]+$/]
  self.base_branch_name    = attributes.base.label[/[^:]+$/]
  self.source_object       = attributes
  self.build               = Build.new(state: build.state, description: build.description, url: build.url)
end

Public Instance Methods

approvals() click to toggle source
# File lib/git_reflow/git_server/git_hub/pull_request.rb, line 63
def approvals
  pull_last_committed_at = get_committed_time(self.head.sha)

  approved_reviewers = pull_request_reviews.select { |r| r.state == 'APPROVED' }.map(&:user).map(&:login)

  (
    comment_authors(with: self.class.approval_regex, after: pull_last_committed_at) +
    approved_reviewers
  ).uniq
end
approved?() click to toggle source
# File lib/git_reflow/git_server/git_hub/pull_request.rb, line 89
def approved?
  if self.class.minimum_approvals.to_i == 0
    super
  else
    approvals.size >= self.class.minimum_approvals.to_i and (
      last_comment.empty? ||
      !last_comment.match(self.class.approval_regex).nil?
    )
  end
end
build() click to toggle source
# File lib/git_reflow/git_server/git_hub/pull_request.rb, line 183
def build
  github_build_status = GitReflow.git_server.get_build_status(self.head.sha)
  if github_build_status
    Build.new(
      state:       github_build_status.state,
      description: github_build_status.description,
      url:         github_build_status.target_url
    )
  else
    Build.new
  end
end
build_status() click to toggle source

override attr_reader for auto-updates

# File lib/git_reflow/git_server/git_hub/pull_request.rb, line 45
def build_status
  @build_status ||= build.state
end
comments() click to toggle source
# File lib/git_reflow/git_server/git_hub/pull_request.rb, line 74
def comments
  comments        = GitReflow.git_server.connection.issues.comments.all        GitReflow.remote_user, GitReflow.remote_repo_name, number: self.number
  review_comments = GitReflow.git_server.connection.pull_requests.comments.all GitReflow.remote_user, GitReflow.remote_repo_name, number: self.number

  (review_comments.to_a + comments.to_a).select { |c| c.user.login != user.login }
end
commit_author() click to toggle source
# File lib/git_reflow/git_server/git_hub/pull_request.rb, line 49
def commit_author
  begin
    username, _  = base.label.split(':')
    first_commit = GitReflow.git_server.connection.pull_requests.commits(username, GitReflow.git_server.class.remote_repo_name, number.to_s).first
    "#{first_commit.commit.author.name} <#{first_commit.commit.author.email}>".strip
  rescue Github::Error::NotFound
    nil
  end
end
last_comment() click to toggle source
# File lib/git_reflow/git_server/git_hub/pull_request.rb, line 81
def last_comment
  if comments.last.nil?
    ""
  else
    "#{comments.last.body.inspect}"
  end
end
merge!(options = {}) click to toggle source
# File lib/git_reflow/git_server/git_hub/pull_request.rb, line 100
def merge!(options = {})

  # fallback to default merge process if user "forces" merge
  if(options[:force])
    super options
  else
    if deliver?
      GitReflow.say "Merging pull request ##{self.number}: '#{self.title}', from '#{self.feature_branch_name}' into '#{self.base_branch_name}'", :notice

      merge_method       = options[:merge_method] || GitReflow::Config.get("reflow.merge-method")
      merge_method       = "squash" if "#{merge_method}".length < 1
      merge_message_file = GitReflow.merge_message_path(merge_method: merge_method)

      unless options[:title] || options[:message]
        # prompts user for commit_title and commit_message
        File.open(merge_message_file, 'w') do |file|
          file.write("#{self.title}\n#{self.commit_message_for_merge}\n")
        end

        GitReflow.run("#{GitReflow.git_editor_command} #{merge_message_file}", with_system: true)
        merge_message = File.read(merge_message_file).split(/[\r\n]|\r\n/).map(&:strip)

        title  = merge_message.shift

        File.delete(merge_message_file)

        unless merge_message.empty?
          merge_message.shift if merge_message.first.empty?
        end

        options[:title] = title
        options[:body]  = "#{merge_message.join("\n")}\n"

        GitReflow.say "\nReview your merge commit message:\n"
        GitReflow.say "--------\n"
        GitReflow.say "Title:\n#{options[:title]}\n\n"
        GitReflow.say "Body:\n#{options[:body]}\n"
        GitReflow.say "--------\n"
      end

      options[:body] = "#{options[:message]}\n" if options[:body].nil? and "#{options[:message]}".length > 0

      merge_response = GitReflow::GitServer::GitHub.connection.pull_requests.merge(
        "#{GitReflow.git_server.class.remote_user}",
        "#{GitReflow.git_server.class.remote_repo_name}",
        "#{self.number}",
        {
          "commit_title"   => "#{options[:title]}",
          "commit_message" => "#{options[:body]}",
          "sha"            => "#{self.head.sha}",
          "merge_method"   => merge_method
        }
      )

      if merge_response.success?
        GitReflow.run_command_with_label "git checkout #{self.base_branch_name}"
        # Pulls merged changes from remote base_branch
        GitReflow.run_command_with_label "git pull origin #{self.base_branch_name}"
        GitReflow.say "Pull request ##{self.number} successfully merged.", :success

        if cleanup_remote_feature_branch?
          GitReflow.run_command_with_label "git push origin :#{self.feature_branch_name}", blocking: false
        else
          GitReflow.say "Skipped. Remote feature branch #{self.feature_branch_name} left in tact."
        end

        if cleanup_local_feature_branch?
          GitReflow.run_command_with_label "git branch -D #{self.feature_branch_name}"
        else
          GitReflow.say "Skipped. Local feature branch #{self.feature_branch_name} left in tact."
        end

        GitReflow.say "Nice job buddy."
      else
        GitReflow.say merge_response.to_s, :deliver_halted
        GitReflow.say "There were problems commiting your feature... please check the errors above and try again.", :error
      end
    else
      GitReflow.say "Merge aborted", :deliver_halted
    end
  end
end
reviewers() click to toggle source
# File lib/git_reflow/git_server/git_hub/pull_request.rb, line 59
def reviewers
  (comment_authors + pull_request_reviews.map(&:user).map(&:login)).uniq - [user.login]
end

Private Instance Methods

comment_authors(with: nil, after: nil) click to toggle source
# File lib/git_reflow/git_server/git_hub/pull_request.rb, line 205
def comment_authors(with: nil, after: nil)
  comment_authors = []

  comments.each do |comment|
    next if after and Time.parse(comment.created_at) < after
    if (with.nil? or comment[:body] =~ with)
      comment_authors |= [comment.user.login]
    end
  end

  # remove the current user from the list to check
  comment_authors -= [self.user.login]
  comment_authors.uniq
end
get_committed_time(commit_sha) click to toggle source
# File lib/git_reflow/git_server/git_hub/pull_request.rb, line 220
def get_committed_time(commit_sha)
  last_commit = GitReflow.git_server.connection.repos.commits.find GitReflow.git_server.class.remote_user, GitReflow.git_server.class.remote_repo_name, commit_sha
  Time.parse last_commit.commit.author[:date]
end
pull_request_reviews() click to toggle source
# File lib/git_reflow/git_server/git_hub/pull_request.rb, line 198
def pull_request_reviews
  @pull_request_reviews ||= GitReflow.git_server.connection.pull_requests.reviews.list(
    user: base.label.split(':').first,
    repo: GitReflow.git_server.class.remote_repo_name, number: number
  )
end