class Geet::Github::PR
def self.create(title, description, head, api_interface, base, draft: false)
def self.create(title, description, head, api_interface, base, draft: false) api_path = 'pulls' if api_interface.upstream? authenticated_user = Geet::Github::User.authenticated(api_interface).username head = "#{authenticated_user}:#{head}" end request_data = {title:, body: description, head:, base:, draft:} response = T.cast(api_interface.send_request(api_path, data: request_data), T::Hash[String, T.untyped]) number = T.cast(response.fetch('number'), Integer) title = T.cast(response.fetch('title'), String) link = T.cast(response.fetch('html_url'), String) node_id = T.cast(response['node_id'], T.nilable(String)) new(number, api_interface, title, link, node_id:) end
def self.list(api_interface, milestone: nil, assignee: nil, owner: nil, head: nil, &type_filter)
def self.list(api_interface, milestone: nil, assignee: nil, owner: nil, head: nil, &type_filter) check_list_params!(milestone, assignee, head) if head api_path = 'pulls' # Technically, the upstream approach could be used for both, but it's actually good to have # both of them as reference. # # For upstream pulls, the owner is the authenticated user, otherwise, the repository owner. # response = if api_interface.upstream? unfiltered_response = T.cast( api_interface.send_request(api_path, multipage: true), T::Array[T::Hash[String, T.untyped]] ) # VERY weird. From the docs, it's not clear if the user/org is required in the `head` parameter, # but: # # - if it isn't included (eg. `anything`), the parameter is ignored # - if it's included (eg. `saveriomiroddi:local_branch_name`), an empty resultset is returned. # # For this reason, we can't use that param, and have to filter manually. # unfiltered_response.select do |pr_data| pr_head = T.cast(pr_data.fetch('head'), T::Hash[String, T.untyped]) label = T.cast(pr_head.fetch('label'), String) label == "#{owner}:#{head}" end else request_params = {head: "#{owner}:#{head}"} T.cast( api_interface.send_request(api_path, params: request_params, multipage: true), T::Array[T::Hash[String, T.untyped]] ) end response.map do |pr_data| number = T.cast(pr_data.fetch('number'), Integer) title = T.cast(pr_data.fetch('title'), String) link = T.cast(pr_data.fetch('html_url'), String) new(number, api_interface, title, link) end else result = super(api_interface, milestone:, assignee:) do |issue_data| issue_data.key?('pull_request') end T.cast(result, T::Array[Geet::Github::PR]) end end
def check_list_params!(milestone, assignee, head)
def check_list_params!(milestone, assignee, head) if (milestone || assignee) && head raise "Head can't be specified with milestone or assignee!" end end
def enable_automerge
def enable_automerge merge_method = fetch_available_merge_method query = <<~GRAPHQL mutation($pullRequestId: ID!, $mergeMethod: PullRequestMergeMethod!) { enablePullRequestAutoMerge(input: {pullRequestId: $pullRequestId, mergeMethod: $mergeMethod}) { pullRequest { id autoMergeRequest { enabledAt mergeMethod } } } } GRAPHQL variables = {pullRequestId: @node_id, mergeMethod: merge_method} @api_interface.send_graphql_request(query, variables:) merge_method end
def fetch_available_merge_method
def fetch_available_merge_method query = <<~GRAPHQL query($owner: String!, $name: String!, $number: Int!) { repository(owner: $owner, name: $name) { mergeCommitAllowed squashMergeAllowed rebaseMergeAllowed pullRequest(number: $number) { commits { totalCount } } } } GRAPHQL owner, name = T.must(@api_interface.repository_path).split('/') response = @api_interface.send_graphql_request(query, variables: {owner:, name:, number:}) repo_data = response['repository'].transform_keys(&:to_sym) commit_count = repo_data[:pullRequest]['commits']['totalCount'] if commit_count == 1 && repo_data[:squashMergeAllowed] 'SQUASH' elsif repo_data[:mergeCommitAllowed] 'MERGE' elsif repo_data[:squashMergeAllowed] 'SQUASH' elsif repo_data[:rebaseMergeAllowed] 'REBASE' else raise 'No merge methods are allowed on this repository' end end
def initialize(number, api_interface, title, link, node_id: nil)
def initialize(number, api_interface, title, link, node_id: nil) super(number, api_interface, title, link) @node_id = node_id end
def merge(merge_method: nil)
def merge(merge_method: nil) api_path = "pulls/#{number}/merge" request_data = {merge_method:} if merge_method @api_interface.send_request(api_path, http_method: :put, data: request_data) end
def request_review(reviewers)
def request_review(reviewers) api_path = "pulls/#{number}/requested_reviewers" request_data = {reviewers:} @api_interface.send_request(api_path, data: request_data) end