lib/pronto/github.rb
require 'pronto/github_pull'
module Pronto
class Github < Client
def initialize(repo)
super(repo)
@github_pull = Pronto::GithubPull.new(client, slug)
end
def pull_comments(sha)
@comment_cache["#{pull_id}/#{sha}"] ||= begin
client.pull_comments(slug, pull_id).map do |comment|
Comment.new(
sha, comment.body, comment.path, comment.line || comment.original_line
)
end
end
rescue Octokit::NotFound => e
@config.logger.log("Error raised and rescued: #{e}")
msg = "Pull request for sha #{sha} with id #{pull_id} was not found."
raise Pronto::Error, msg
end
def commit_comments(sha)
@comment_cache[sha.to_s] ||= begin
client.commit_comments(slug, sha).map do |comment|
Comment.new(sha, comment.body, comment.path, comment.line)
end
end
end
def create_commit_comment(comment)
@config.logger.log("Creating commit comment on #{comment.sha}")
client.create_commit_comment(slug, comment.sha, comment.body,
comment.path, nil, comment.position)
end
def create_pull_comment(comment)
if comment.path && comment.position
@config.logger.log("Creating pull request comment on #{pull_id}")
client.create_pull_comment(
# Depending on the Octokit version the 6th argument can be either postion or line. We'll
# provide the `line` as this argument and also provide the line in the options argument.
# The API uses `line` and ignores position when `line` is provided.
slug, pull_id, comment.body, pull_sha || comment.sha,
comment.path, comment.position, { line: comment.position }
)
else
create_commit_comment(comment)
end
end
def publish_pull_request_comments(comments)
comments_left = comments.clone
while comments_left.any?
comments_to_publish = comments_left.slice!(0, warnings_per_review)
create_pull_request_review(comments_to_publish)
end
end
def create_commit_status(status)
sha = pull_sha || status.sha
@config.logger.log("Creating comment status on #{sha}")
client.create_status(slug, sha, status.state,
context: status.context,
description: status.description)
end
private
def create_pull_request_review(comments)
options = {
event: @config.github_review_type,
comments: comments.map do |comment|
{
path: comment.path,
line: comment.position,
body: comment.body
}
end
}
client.create_pull_request_review(slug, pull_id, options)
end
def slug
return @config.github_slug if @config.github_slug
@slug ||= begin
@repo.remote_urls.map do |url|
hostname = Regexp.escape(@config.github_hostname)
match = %r{.*#{hostname}(:|\/)(?<slug>.*?)(?:\.git)?\z}.match(url)
match[:slug] if match
end.compact.first
end
end
def client
@client ||= Octokit::Client.new(api_endpoint: @config.github_api_endpoint,
web_endpoint: @config.github_web_endpoint,
access_token: @config.github_access_token,
auto_paginate: true)
end
def pull_id
env_pull_id || pull[:number].to_i
end
def pull_sha
pull[:head][:sha] if pull
end
def pull
@pull ||= if env_pull_id
@github_pull.pull_by_id(env_pull_id)
elsif @repo.branch
@github_pull.pull_by_branch(@repo.branch)
elsif @repo.head_detached?
@github_pull.pull_by_commit(@repo.head_commit_sha)
end
end
def warnings_per_review
@warnings_per_review ||= @config.warnings_per_review
end
end
end