Skip to content

Commit

Permalink
Handle offences found outside of the PR diff
Browse files Browse the repository at this point in the history
  • Loading branch information
dbackeus committed Jul 5, 2023
1 parent 1018879 commit 6c4d197
Showing 1 changed file with 55 additions and 9 deletions.
64 changes: 55 additions & 9 deletions rubocop.rb
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,13 @@ module Github
define_singleton_method(method) do |path, params = nil|
request(klass, path, params)
end

define_singleton_method("#{method}!") do |path, params = nil|
response = request(klass, path, params)
raise HttpError, "status: #{response.code}, body: #{response.body}" unless response.is_a?(Net::HTTPSuccess)

JSON.parse(response.body) if response.body
end
end

def self.request(request_class, path, params = nil)
Expand All @@ -50,11 +57,7 @@ def self.request(request_class, path, params = nil)
request["Authorization"] = "Bearer #{ENV.fetch('GITHUB_TOKEN')}"
request["Accept"] = "application/vnd.github.v3+json"

response = CONNECTION.request(request)

raise HttpError, "status: #{response.code}, body: #{response.body}" unless response.is_a?(Net::HTTPSuccess)

JSON.parse(response.body) if response.body
CONNECTION.request(request)
end
end

Expand All @@ -66,7 +69,7 @@ def self.request(request_class, path, params = nil)

changed_files = []
1.step do |page|
files = Github.get("/repos/#{owner_and_repository}/pulls/#{pr_number}/files?per_page=100&page=#{page}")
files = Github.get!("/repos/#{owner_and_repository}/pulls/#{pr_number}/files?per_page=100&page=#{page}")
changed_files.concat(files)
break if files.length < 100
end
Expand Down Expand Up @@ -94,7 +97,7 @@ def self.request(request_class, path, params = nil)

puts "Fetching comments from https://api.github.com/repos/#{owner_and_repository}/pulls/#{pr_number}/comments"

existing_comments = Github.get("/repos/#{owner_and_repository}/pulls/#{pr_number}/comments")
existing_comments = Github.get!("/repos/#{owner_and_repository}/pulls/#{pr_number}/comments")

comments_made_by_rubocop = existing_comments.select do |comment|
comment.fetch("body").include?("rubocop-comment-id")
Expand All @@ -118,11 +121,13 @@ def self.request(request_class, path, params = nil)

puts "Deleting resolved comment #{comment_id} on #{path} line #{line}"

Github.delete("/repos/#{owner_and_repository}/pulls/comments/#{comment_id}")
Github.delete!("/repos/#{owner_and_repository}/pulls/comments/#{comment_id}")
end

# Comment on the pull request with the offenses found

offences_outside_diff = []

files_with_offenses.each do |file|
path = file.fetch("path")
offenses_by_line = file.fetch("offenses").group_by do |offense|
Expand Down Expand Up @@ -167,17 +172,58 @@ def self.request(request_class, path, params = nil)
# Somehow the commit_id should not be just the HEAD SHA: https://stackoverflow.com/a/71431370/1075108
commit_id = github_event.fetch("pull_request").fetch("head").fetch("sha")

Github.post(
response = Github.post(
"/repos/#{owner_and_repository}/pulls/#{pr_number}/comments",
body: body,
path: path,
commit_id: commit_id,
line: line,
)

# Rubocop might hit errors on lines which are not part of the diff and thus cannot be commented on.
if response.code == "422" && response.body.include?("line must be part of the diff")
puts "Deferring comment on #{path} line #{line} because it isn't part of the diff"

offences_outside_diff << { path: path, line: line, message: message }
end
end
end
end

# If there are any offenses outside the diff, make a separate comment for them

if offences_outside_diff.any?
existing_comment = comments_made_by_rubocop.find do |comment|
comment.fetch("body").include?("rubocop-comment-id: outside-diff")
end

body = <<~BODY
<!-- rubocop-comment-id: outside-diff -->
Rubocop offenses found outside of the diff:
BODY

body += offences_outside_diff.map do |offense|
"**#{offense.fetch(:path)}:#{offense.fetch(:line)}**\n#{offense.fetch(:message)}"
end.join("\n\n")

if existing_comment
existing_comment_id = existing_comment.fetch("id")

# No need to do anything if the offense already exists and hasn't changed
if existing_comment.fetch("body") == body
puts "Skipping unchanged separate comment #{existing_comment_id}"
else
puts "Updating comment #{existing_comment_id} on pull request"
Github.patch!("/repos/#{owner_and_repository}/pulls/comments/#{existing_comment_id}", body: body)
end
else
puts "Commenting on pull request with offenses found outside the diff"

Github.post!("/repos/#{owner_and_repository}/issues/#{pr_number}/comments", body: body)
end
end

# Fail the build if there were any offenses

number_of_offenses = files_with_offenses.sum { |file| file.fetch("offenses").length }
Expand Down

0 comments on commit 6c4d197

Please sign in to comment.