class Dependabot::Clients::Bitbucket
Attributes
auth_header[R]
credentials[R]
Public Class Methods
for_source(source:, credentials:)
click to toggle source
Constructor methods #
# File lib/dependabot/clients/bitbucket.rb, line 19 def self.for_source(source:, credentials:) credential = credentials. select { |cred| cred["type"] == "git_source" }. find { |cred| cred["host"] == source.hostname } new(credentials: credential) end
new(credentials:)
click to toggle source
Client #
# File lib/dependabot/clients/bitbucket.rb, line 32 def initialize(credentials:) @credentials = credentials @auth_header = auth_header_for(credentials&.fetch("token", nil)) end
Public Instance Methods
branch(repo, branch_name)
click to toggle source
# File lib/dependabot/clients/bitbucket.rb, line 75 def branch(repo, branch_name) branch_path = "#{repo}/refs/branches/#{branch_name}" response = get(base_url + branch_path) JSON.parse(response.body) end
commits(repo, branch_name = nil)
click to toggle source
# File lib/dependabot/clients/bitbucket.rb, line 69 def commits(repo, branch_name = nil) commits_path = "#{repo}/commits/#{branch_name}?pagelen=100" next_page_url = base_url + commits_path paginate({ "next" => next_page_url }) end
compare(repo, previous_tag, new_tag)
click to toggle source
# File lib/dependabot/clients/bitbucket.rb, line 151 def compare(repo, previous_tag, new_tag) path = "#{repo}/commits/?include=#{new_tag}&exclude=#{previous_tag}" response = get(base_url + path) JSON.parse(response.body).fetch("values") end
create_commit(repo, branch_name, base_commit, commit_message, files, author_details)
click to toggle source
rubocop:disable Metrics/ParameterLists
# File lib/dependabot/clients/bitbucket.rb, line 99 def create_commit(repo, branch_name, base_commit, commit_message, files, author_details) parameters = { message: commit_message, # TODO: Format markup in commit message author: "#{author_details.fetch(:name)} <#{author_details.fetch(:email)}>", parents: base_commit, branch: branch_name } files.each do |file| absolute_path = file.name.start_with?("/") ? file.name : "/" + file.name parameters[absolute_path] = file.content end body = encode_form_parameters(parameters) commit_path = "#{repo}/src" post(base_url + commit_path, body, "application/x-www-form-urlencoded") end
create_pull_request(repo, pr_name, source_branch, target_branch, pr_description, _labels, _work_item = nil)
click to toggle source
rubocop:disable Metrics/ParameterLists
# File lib/dependabot/clients/bitbucket.rb, line 121 def create_pull_request(repo, pr_name, source_branch, target_branch, pr_description, _labels, _work_item = nil) content = { title: pr_name, source: { branch: { name: source_branch } }, destination: { branch: { name: target_branch } }, description: pr_description, close_source_branch: true } pr_path = "#{repo}/pullrequests" post(base_url + pr_path, content.to_json) end
fetch_commit(repo, branch)
click to toggle source
# File lib/dependabot/clients/bitbucket.rb, line 37 def fetch_commit(repo, branch) path = "#{repo}/refs/branches/#{branch}" response = get(base_url + path) JSON.parse(response.body).fetch("target").fetch("hash") end
fetch_default_branch(repo)
click to toggle source
# File lib/dependabot/clients/bitbucket.rb, line 44 def fetch_default_branch(repo) response = get(base_url + repo) JSON.parse(response.body).fetch("mainbranch").fetch("name") end
fetch_file_contents(repo, commit, path)
click to toggle source
# File lib/dependabot/clients/bitbucket.rb, line 62 def fetch_file_contents(repo, commit, path) path = "#{repo}/src/#{commit}/#{path.gsub(%r{/+$}, '')}" response = get(base_url + path) response.body end
fetch_repo_contents(repo, commit = nil, path = nil)
click to toggle source
# File lib/dependabot/clients/bitbucket.rb, line 50 def fetch_repo_contents(repo, commit = nil, path = nil) raise "Commit is required if path provided!" if commit.nil? && path api_path = "#{repo}/src" api_path += "/#{commit}" if commit api_path += "/#{path.gsub(%r{/+$}, '')}" if path api_path += "?pagelen=100" response = get(base_url + api_path) JSON.parse(response.body).fetch("values") end
get(url)
click to toggle source
# File lib/dependabot/clients/bitbucket.rb, line 158 def get(url) response = Excon.get( url, user: credentials&.fetch("username", nil), password: credentials&.fetch("password", nil), idempotent: true, **Dependabot::SharedHelpers.excon_defaults( headers: auth_header ) ) raise Unauthorized if response.status == 401 raise Forbidden if response.status == 403 raise NotFound if response.status == 404 if response.status >= 400 raise "Unhandled Bitbucket error!\n"\ "Status: #{response.status}\n"\ "Body: #{response.body}" end response end
post(url, body, content_type = "application/json")
click to toggle source
# File lib/dependabot/clients/bitbucket.rb, line 181 def post(url, body, content_type = "application/json") response = Excon.post( url, body: body, user: credentials&.fetch("username", nil), password: credentials&.fetch("password", nil), idempotent: false, **SharedHelpers.excon_defaults( headers: auth_header.merge( { "Content-Type" => content_type } ) ) ) raise Unauthorized if response.status == 401 raise Forbidden if response.status == 403 raise NotFound if response.status == 404 response end
pull_requests(repo, source_branch, target_branch)
click to toggle source
# File lib/dependabot/clients/bitbucket.rb, line 82 def pull_requests(repo, source_branch, target_branch) pr_path = "#{repo}/pullrequests" # Get pull requests with any status pr_path += "?status=OPEN&status=MERGED&status=DECLINED&status=SUPERSEDED" next_page_url = base_url + pr_path pull_requests = paginate({ "next" => next_page_url }) pull_requests unless source_branch && target_branch pull_requests.select do |pr| pr_source_branch = pr.fetch("source").fetch("branch").fetch("name") pr_target_branch = pr.fetch("destination").fetch("branch").fetch("name") pr_source_branch == source_branch && pr_target_branch == target_branch end end
Private Instance Methods
auth_header_for(token)
click to toggle source
# File lib/dependabot/clients/bitbucket.rb, line 205 def auth_header_for(token) return {} unless token { "Authorization" => "Bearer #{token}" } end
base_url()
click to toggle source
# File lib/dependabot/clients/bitbucket.rb, line 245 def base_url # TODO: Make this configurable when we support enterprise Bitbucket "https://api.bitbucket.org/2.0/repositories/" end
encode_form_parameters(parameters)
click to toggle source
# File lib/dependabot/clients/bitbucket.rb, line 211 def encode_form_parameters(parameters) parameters.map do |key, value| URI.encode_www_form_component(key.to_s) + "=" + URI.encode_www_form_component(value.to_s) end.join("&") end
paginate(page)
click to toggle source
Takes a hash with optional `values` and `next` fields Returns an enumerator.
Can be used a few ways: With GET:
paginate ({"next" => url})
or
paginate(JSON.parse(get(url).body))
With POST (for endpoints that provide POST methods for long query parameters)
response = post(url, body) first_page = JSON.parse(repsonse.body) paginate(first_page)
# File lib/dependabot/clients/bitbucket.rb, line 230 def paginate(page) Enumerator.new do |yielder| loop do page.fetch("values", []).each { |value| yielder << value } break unless page.key?("next") next_page_url = page.fetch("next") page = JSON.parse(get(next_page_url).body) end end end