class Danger::PullRequestFinder

Attributes

git_logs[R]
remote[R]
remote_url[R]
repo_slug[R]
specific_pull_request_id[R]

Public Class Methods

new(specific_pull_request_id, repo_slug = nil, remote: false, git_logs: "", remote_url: "") click to toggle source
# File lib/danger/ci_source/support/pull_request_finder.rb, line 9
def initialize(specific_pull_request_id, repo_slug = nil, remote: false, git_logs: "", remote_url: "")
  @specific_pull_request_id = specific_pull_request_id
  @git_logs = git_logs
  @repo_slug = repo_slug
  @remote = to_boolean(remote)
  @remote_url = remote_url
end

Public Instance Methods

call(env: nil) click to toggle source
# File lib/danger/ci_source/support/pull_request_finder.rb, line 17
def call(env: nil)
  find_pull_request(env).tap do |pull_request|
    raise_pull_request_not_found!(pull_request) unless pull_request.valid?
  end
end

Private Instance Methods

api_url() click to toggle source
# File lib/danger/ci_source/support/pull_request_finder.rb, line 170
def api_url
  ENV.fetch("DANGER_GITHUB_API_HOST") do
    ENV.fetch("DANGER_GITHUB_API_BASE_URL") do
      "https://api.github.com/"
    end
  end
end
both_present?() click to toggle source
# File lib/danger/ci_source/support/pull_request_finder.rb, line 99
def both_present?
  most_recent_merged_pull_request && most_recent_squash_and_merged_pull_request
end
client(env) click to toggle source
# File lib/danger/ci_source/support/pull_request_finder.rb, line 136
def client(env)
  scm_provider = find_scm_provider(remote_url)

  case scm_provider
  when :bitbucket_cloud
    require "danger/request_sources/bitbucket_cloud_api"
    branch_name = ENV["DANGER_BITBUCKET_TARGET_BRANCH"] # Optional env variable (specifying the target branch) to help find the PR.
    RequestSources::BitbucketCloudAPI.new(repo_slug, specific_pull_request_id, branch_name, env)

  when :bitbucket_server
    require "danger/request_sources/bitbucket_server_api"
    project, slug = repo_slug.split("/")
    RequestSources::BitbucketServerAPI.new(project, slug, specific_pull_request_id, env)

  when :vsts
    require "danger/request_sources/vsts_api"
    RequestSources::VSTSAPI.new(repo_slug, specific_pull_request_id, env)

  when :github
    require "octokit"
    access_token = ENV["DANGER_GITHUB_API_TOKEN"]
    bearer_token = ENV["DANGER_GITHUB_BEARER_TOKEN"]
    if bearer_token && !bearer_token.empty?
      Octokit::Client.new(bearer_token: bearer_token, api_endpoint: api_url)
    elsif access_token && !access_token.empty?
      Octokit::Client.new(access_token: access_token, api_endpoint: api_url)
    else
      raise "No API token given, please provide one using `DANGER_GITHUB_API_TOKEN` or `DANGER_GITHUB_BEARER_TOKEN`"
    end
  else
    raise "SCM provider not supported: #{scm_provider}"
  end
end
find_pull_request(env) click to toggle source

@return [String] Log line of most recent merged Pull Request

# File lib/danger/ci_source/support/pull_request_finder.rb, line 40
def find_pull_request(env)
  return if pull_request_ref.empty?

  if both_present?
    LocalPullRequest.new(pick_the_most_recent_one_from_two_matches)
  elsif only_merged_pull_request_present?
    LocalPullRequest.new(most_recent_merged_pull_request)
  elsif only_squash_and_merged_pull_request_present?
    LocalPullRequest.new(most_recent_squash_and_merged_pull_request)
  elsif remote
    remote_pull_request = find_remote_pull_request(env)
    remote_pull_request ? generate_remote_pull_request(remote_pull_request) : NoPullRequest.new
  else
    NoPullRequest.new
  end
end
find_remote_pull_request(env) click to toggle source
# File lib/danger/ci_source/support/pull_request_finder.rb, line 95
def find_remote_pull_request(env)
  client(env).pull_request(repo_slug, specific_pull_request_id)
end
find_scm_provider(remote_url) click to toggle source
# File lib/danger/ci_source/support/pull_request_finder.rb, line 178
def find_scm_provider(remote_url)
  if remote_url =~ %r{/bitbucket.org/}
    :bitbucket_cloud
  elsif remote_url =~ %r{/pull-requests/}
    :bitbucket_server
  elsif remote_url =~ /\.visualstudio\.com/i || remote_url =~ /dev\.azure\.com/i
    :vsts
  else
    :github
  end
end
generate_remote_pull_request(remote_pull_request) click to toggle source
# File lib/danger/ci_source/support/pull_request_finder.rb, line 62
def generate_remote_pull_request(remote_pull_request)
  scm_provider = find_scm_provider(remote_url)

  case scm_provider
  when :bitbucket_cloud
    RemotePullRequest.new(
      remote_pull_request[:id].to_s,
      remote_pull_request[:source][:commit][:hash],
      remote_pull_request[:destination][:commit][:hash]
    )
  when :bitbucket_server
    RemotePullRequest.new(
      remote_pull_request[:id].to_s,
      remote_pull_request[:fromRef][:latestCommit],
      remote_pull_request[:toRef][:latestCommit]
    )
  when :github
    RemotePullRequest.new(
      remote_pull_request.number.to_s,
      remote_pull_request.head.sha,
      remote_pull_request.base.sha
    )
  when :vsts
    RemotePullRequest.new(
      remote_pull_request[:pullRequestId].to_s,
      remote_pull_request[:lastMergeSourceCommit][:commitId],
      remote_pull_request[:lastMergeTargetCommit][:commitId]
    )
  else
    raise "SCM provider not supported: #{scm_provider}"
  end
end
most_recent_merged_pull_request() click to toggle source

@return [String] Log line of format: “Merge pull request #42”

# File lib/danger/ci_source/support/pull_request_finder.rb, line 104
def most_recent_merged_pull_request
  @most_recent_merged_pull_request ||= git_logs.lines.grep(/Merge pull request #{pull_request_ref} from/)[0]
end
most_recent_squash_and_merged_pull_request() click to toggle source

@return [String] Log line of format: “description (#42)”

# File lib/danger/ci_source/support/pull_request_finder.rb, line 109
def most_recent_squash_and_merged_pull_request
  @most_recent_squash_and_merged_pull_request ||= git_logs.lines.grep(/\(#{pull_request_ref}\)/)[0]
end
only_merged_pull_request_present?() click to toggle source
# File lib/danger/ci_source/support/pull_request_finder.rb, line 124
def only_merged_pull_request_present?
  return false if most_recent_squash_and_merged_pull_request

  !most_recent_merged_pull_request.nil? && !most_recent_merged_pull_request.empty?
end
only_squash_and_merged_pull_request_present?() click to toggle source
# File lib/danger/ci_source/support/pull_request_finder.rb, line 130
def only_squash_and_merged_pull_request_present?
  return false if most_recent_merged_pull_request

  !most_recent_squash_and_merged_pull_request.nil? && !most_recent_squash_and_merged_pull_request.empty?
end
pick_the_most_recent_one_from_two_matches() click to toggle source
# File lib/danger/ci_source/support/pull_request_finder.rb, line 113
def pick_the_most_recent_one_from_two_matches
  merged_index = git_logs.lines.index(most_recent_merged_pull_request)
  squash_and_merged_index = git_logs.lines.index(most_recent_squash_and_merged_pull_request)

  if merged_index > squash_and_merged_index # smaller index is more recent
    most_recent_squash_and_merged_pull_request
  else
    most_recent_merged_pull_request
  end
end
pull_request_ref() click to toggle source

@return [String] “#42”

# File lib/danger/ci_source/support/pull_request_finder.rb, line 58
def pull_request_ref
  !specific_pull_request_id.empty? ? "##{specific_pull_request_id}" : "#\\d+"
end
raise_pull_request_not_found!(_pull_request) click to toggle source
# File lib/danger/ci_source/support/pull_request_finder.rb, line 31
def raise_pull_request_not_found!(_pull_request)
  if specific_pull_request_id.empty?
    raise "No recent Pull Requests found for this repo, danger requires at least one Pull Request for the local mode."
  else
    raise "Could not find the Pull Request (#{specific_pull_request_id}) inside the git history for this repo."
  end
end
to_boolean(maybe_string) click to toggle source
# File lib/danger/ci_source/support/pull_request_finder.rb, line 27
def to_boolean(maybe_string)
  ["true", "1", "yes", "y", true].include?(maybe_string)
end