Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[WIP] Commenting feature for issues outside current PR #6

Draft
wants to merge 5 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .github/workflows/brakeman.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@ on:
push:
branches:
- main
pull_request:
types:
- opened
- edited

jobs:
brakeman:
Expand Down
7 changes: 7 additions & 0 deletions .github/workflows/rubocop.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,13 @@ on:
push:
branches:
- main
pull_request:
types:
- opened
- edited

permissions:
contents: read

jobs:
rubocop:
Expand Down
7 changes: 7 additions & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,13 @@ on:
push:
branches:
- main
pull_request:
types:
- opened
- edited

permissions:
contents: read

jobs:
test:
Expand Down
28 changes: 28 additions & 0 deletions lib/github_check_run_service.rb
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,15 @@ def client_post_pull_requests(annotation)
pull_request_endpoint_url.to_s,
create_pull_request_comment_payload(annotation)
)
rescue GithubClient::IssueExistsOutsideOfPullRequestError
client_post_pull_request_for_issue_outside_of_pr(annotation)
end

def client_post_pull_request_for_issue_outside_of_pr(annotation)
@client.post(
pull_request_endpoint_url.to_s,
create_issue_in_repo_but_not_pr_comment_payload(annotation)
)
end

def annotation_endpoint_url
Expand Down Expand Up @@ -88,6 +97,12 @@ def create_pull_request_comment_payload(annotation)
}
end

def create_issue_in_repo_but_not_pr_comment_payload(annotation)
{
body: pr_comment_body_generator(annotation)
}
end

def get_confidence_level(title)
title.split("-")[0].strip
end
Expand All @@ -110,4 +125,17 @@ def comment_body_generator(annotation)
"**More information available at**: #{BRAKEMAN_URL}<br />" +
(@github_data[:custom_message_content]).to_s
end

def pr_comment_body_generator(annotation)
title = annotation["title"]
emoji = confidence_level_map(title)
# rubocop:disable Layout/LineLength
body = "#{emoji} **Potential Vulnerability Detected Outside Of PR** #{emoji}<br /><br />You might not need to deal with this, but be aware that it exists in the codebase.<br />**Confidence level**: #{get_confidence_level(title)}<br />**Type**: #{get_potential_vuln_type(title)}<br />**Description**: #{annotation['message']}<br />**More information available at**: #{BRAKEMAN_URL}<br />**Location**: #{annotation['path']}:#{annotation['start_line']}<br />"
# rubocop:enable Layout/LineLength
if @github_data[:custom_message_content]
body + @github_data[:custom_message_content]
else
body
end
end
end
4 changes: 4 additions & 0 deletions lib/github_client.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
# frozen_string_literal: true

class GithubClient
class IssueExistsOutsideOfPullRequestError < StandardError
end

def initialize(github_token, user_agent: "ruby")
@github_token = github_token
@user_agent = user_agent
Expand Down Expand Up @@ -33,6 +36,7 @@ def request_http
http = Net::HTTP.new("api.github.com", 443)
http.use_ssl = true
response = yield(http)
raise IssueExistsOutsideOfPullRequestError if response.body.include? "pull_request_review_thread.diff_hunk"
raise "#{response.message}: #{response.body}" if response.code.to_i >= 300

JSON.parse(response.body)
Expand Down
36 changes: 36 additions & 0 deletions spec/github_check_run_service_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -60,4 +60,40 @@
service.run
end
end

# Eventually we'll have this comment, but for now, we don't want to fail the build
context "an issue in the codebase but not in the PR" do
it "does not fail the build" do
expected_pr_comment_body = {
body: "⚠️ **Potential Vulnerability Detected Outside Of PR** ⚠️<br /><br />You might not need to deal with this, but be aware that it exists in the codebase.<br />**Confidence level**: Medium<br />**Type**: Deserialize<br />**Description**: `Marshal.load` called with parameter value<br />**More information available at**: https://brakemanscanner.org/docs/warning_types/<br />**Location**: app/controllers/password_resets_controller.rb:6<br />"
}
expected_file_comment_body = {
"annotation_level" => "warning",
"end_line" => 6,
"message" => "`Marshal.load` called with parameter value",
"path" => "app/controllers/password_resets_controller.rb",
"start_line" => 6,
"title" => "Medium - Deserialize"
}

stub_request(:any, "https://api.github.com/repos/owner/repository_name/check-runs").
to_return(status: 200, body: '{"id": "id"}')

stub_request(:any, "https://api.github.com/repos/owner/repository_name/check-runs/id").
to_return(status: 200, body: '{"id": "id"}')

stub_request(:any, "https://api.github.com/repos/owner/repository_name/pulls/10/comments").
to_return(status: 422, body: '{"message":"Validation Failed","errors":[{"resource":"PullRequestReviewComment","code":"invalid","field":"pull_request_review_thread.path"},{"resource":"PullRequestReviewComment","code":"missing_field","field":"pull_request_review_thread.diff_hunk"}],"documentation_url":"https://docs.github.com/rest"}').
times(1)

stub_request(:post, "https://api.github.com/repos/owner/repository_name/pulls/10/comments").
with(expected_pr_comment_body).
to_return(status: 200, body: '{"id": "id"}').
times(1)

expect(service).to receive(:client_post_pull_request_for_issue_outside_of_pr).with(expected_file_comment_body).once.
and_return(expected_pr_comment_body)
expect { service.run }.not_to raise_error
end
end
end