require 'rest-client' module Codestatus module Repositories class BitbucketRepository < Base BITBUCKET_API_ENDPOINT = 'https://api.bitbucket.org/2.0/' #repositories/atlassian/aui # This combined status is generated by the rule of GitHub's # https://developer.github.com/v3/repos/statuses/#get-the-combined-status-for-a-specific-ref def status(ref = main_branch) statuses = statuses(ref) sha = statuses['values'].map {|x| x.dig('commit', 'hash') }.compact.first states = statuses['values'].map { |status| status['state'] } state = if states.any? { |x| ['STOPPED', 'FAILED'].include?(x) } BuildStatus::FAILURE elsif states.empty? || states.all? { |x| x == 'INPROGRESS' } BuildStatus::PENDING elsif states.all? { |x| x == 'SUCCESSFUL' } BuildStatus::SUCCESS else BuildStatus::UNDEFINED end BuildStatus.new(sha: sha, status: state) end # https://bitbucket.org/atlassian/aui def html_url repository.dig('links', 'html', 'href') end private def main_branch repository.dig('mainbranch', 'name') end def repository @repository ||= JSON.parse(client.get(repository_uri)) end def repository_uri File.join(BITBUCKET_API_ENDPOINT, 'repositories', slug) end def client RestClient end # https://developer.atlassian.com/bitbucket/api/2/reference/resource/repositories/%7Busername%7D/%7Brepo_slug%7D/commit/%7Bnode%7D/statuses # example: https://api.bitbucket.org/2.0/repositories/atlassian/aui/commit/master/statuses def statuses(ref) @statuses ||= JSON.parse(client.get(statuses_uri(ref))) end def statuses_uri(ref) File.join(BITBUCKET_API_ENDPOINT, 'repositories', slug, 'commit', ref, 'statuses') end end end end