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
GitHub pull request review #702
Merged
orta
merged 22 commits into
danger:master
from
Antondomashnev:antondomashnev/github_review
Jan 25, 2017
Merged
Changes from all commits
Commits
Show all changes
22 commits
Select commit
Hold shift + click to select a range
2ac42ef
Working on github review integration;
Antondomashnev 38465ee
Playing around with github_review integration;
Antondomashnev 528494b
Working on Octokit PullRequestReviews extension;
Antondomashnev c3b362d
Create basic methods for PullRequestReivews for Octokit;
Antondomashnev a3c089d
Fixes in sytax and logic in github & github_review classes;
Antondomashnev 3cf1015
Working on github review transitions resolver;
Antondomashnev 9c3165a
Add tests for review method for github request_source;
Antondomashnev fbb4027
Add tests for review method for github request_source;
Antondomashnev cb6e0c4
Add tests for github_review_resolver;
Antondomashnev f427bee
Update review resolver with new logic;
Antondomashnev 8f6daa9
Do not submit pull request review with the same body;
Antondomashnev 8ec776a
Cleanup GitHubReview;
Antondomashnev 6e612c6
Create ReviewResolver tests;
Antondomashnev b0149e0
Working on review spec;
Antondomashnev 898e6a9
Fix GitHubReview specs;
Antondomashnev b5bd8f6
Finalize spec for github review;
Antondomashnev b07ef94
Small cleanup in review object;
Antondomashnev d4a20ab
Fix testd and offenses;
Antondomashnev 5730d68
PR feedback; Test fixes;
Antondomashnev c60b63f
Do not show pull request review summary message;
Antondomashnev 68474f0
Update changelog and documentation;
Antondomashnev 4500e98
Downgrade rubocop to 0.46;
Antondomashnev File filter
Filter by extension
Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,126 @@ | ||
# coding: utf-8 | ||
require "octokit" | ||
require "danger/ci_source/ci_source" | ||
require "danger/request_sources/github/octokit_pr_review" | ||
require "danger/request_sources/github/github_review_resolver" | ||
require "danger/danger_core/messages/violation" | ||
require "danger/danger_core/messages/markdown" | ||
require "danger/helpers/comments_helper" | ||
require "danger/helpers/comment" | ||
|
||
module Danger | ||
module RequestSources | ||
module GitHubSource | ||
class Review | ||
include Danger::Helpers::CommentsHelper | ||
|
||
# @see https://developer.github.com/v3/pulls/reviews/ for all possible events | ||
EVENT_APPROVE = "APPROVE".freeze | ||
EVENT_REQUEST_CHANGES = "REQUEST_CHANGES".freeze | ||
EVENT_COMMENT = "COMMENT".freeze | ||
|
||
# Current review status, if the review has not been submitted yet -> STATUS_PENDING | ||
STATUS_APPROVED = "APPROVED".freeze | ||
STATUS_REQUESTED_CHANGES = "CHANGES_REQUESTED".freeze | ||
STATUS_COMMENTED = "COMMENTED".freeze | ||
STATUS_PENDING = "PENDING".freeze | ||
|
||
attr_reader :id, :body, :status, :review_json | ||
|
||
def initialize(client, ci_source, review_json = nil) | ||
@ci_source = ci_source | ||
@client = client | ||
@review_json = review_json | ||
end | ||
|
||
def id | ||
return nil unless self.review_json | ||
self.review_json["id"] | ||
end | ||
|
||
def body | ||
return "" unless self.review_json | ||
self.review_json["body"] | ||
end | ||
|
||
def status | ||
return STATUS_PENDING if self.review_json.nil? | ||
return self.review_json["state"] | ||
end | ||
|
||
# Starts the new review process | ||
def start | ||
@warnings = [] | ||
@errors = [] | ||
@messages = [] | ||
@markdowns = [] | ||
end | ||
|
||
# Submits the prepared review | ||
def submit | ||
general_violations = generate_general_violations | ||
submission_body = generate_body | ||
|
||
# If the review resolver says that there is nothing to submit we skip submission | ||
return unless ReviewResolver.should_submit?(self, submission_body) | ||
|
||
@review_json = @client.create_pull_request_review(@ci_source.repo_slug, @ci_source.pull_request_id, generate_event(general_violations), submission_body) | ||
end | ||
|
||
def generated_by_danger?(danger_id = "danger") | ||
self.review_json["body"].include?("generated_by_#{danger_id}") | ||
end | ||
|
||
def message(message, sticky = true, file = nil, line = nil) | ||
@messages << Violation.new(message, sticky, file, line) | ||
end | ||
|
||
def warn(message, sticky = true, file = nil, line = nil) | ||
@warnings << Violation.new(message, sticky, file, line) | ||
end | ||
|
||
def fail(message, sticky = true, file = nil, line = nil) | ||
@errors << Violation.new(message, sticky, file, line) | ||
end | ||
|
||
def markdown(message, file = nil, line = nil) | ||
@markdowns << Markdown.new(message, file, line) | ||
end | ||
|
||
private | ||
|
||
# The only reason to request changes for the PR is to have errors from Danger | ||
# otherwise let's just notify user and we're done | ||
def generate_event(violations) | ||
violations[:errors].empty? ? EVENT_APPROVE : EVENT_REQUEST_CHANGES | ||
end | ||
|
||
def generate_body(danger_id: "danger") | ||
previous_violations = parse_comment(body) | ||
general_violations = generate_general_violations | ||
new_body = generate_comment(warnings: general_violations[:warnings], | ||
errors: general_violations[:errors], | ||
messages: general_violations[:messages], | ||
markdowns: general_violations[:markdowns], | ||
previous_violations: previous_violations, | ||
danger_id: danger_id, | ||
template: "github") | ||
return new_body | ||
end | ||
|
||
def generate_general_violations | ||
general_warnings = @warnings.reject(&:inline?) | ||
general_errors = @errors.reject(&:inline?) | ||
general_messages = @messages.reject(&:inline?) | ||
general_markdowns = @markdowns.reject(&:inline?) | ||
{ | ||
warnings: general_warnings, | ||
markdowns: general_markdowns, | ||
errors: general_errors, | ||
messages: general_messages | ||
} | ||
end | ||
end | ||
end | ||
end | ||
end |
18 changes: 18 additions & 0 deletions
18
lib/danger/request_sources/github/github_review_resolver.rb
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
# coding: utf-8 | ||
require "danger/request_sources/github/github_review" | ||
|
||
module Danger | ||
module RequestSources | ||
module GitHubSource | ||
class ReviewResolver | ||
def self.should_submit?(review, body) | ||
return !same_body?(body, review.body) | ||
end | ||
|
||
def self.same_body?(body1, body2) | ||
return !body1.nil? && !body2.nil? && body1 == body2 | ||
end | ||
end | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,83 @@ | ||
# coding: utf-8 | ||
require "octokit" | ||
|
||
module Octokit | ||
class Client | ||
# The Pull Request Review API is currently available for developers to preview. | ||
# During the preview period, the API may change without advance notice. | ||
# please see the blog post for full details. | ||
# To access the API during the preview period, you must provide | ||
# a custom media type in the Accept header: | ||
CUSTOM_ACCEPT_HEADER = "application/vnd.github.black-cat-preview+json".freeze | ||
|
||
# Approve pull request event | ||
PULL_REQUEST_REVIEW_EVENT_APPROVE = "APPROVE".freeze | ||
|
||
# Request changes on the pull request event | ||
PULL_REQUEST_REVIEW_EVENT_REQUEST_CHANGES = "REQUEST_CHANGES".freeze | ||
|
||
# Left a gemeneral comment on the pull request event | ||
PULL_REQUEST_REVIEW_EVENT_COMMENT = "COMMENT".freeze | ||
|
||
# List pull request reviews for a pull request | ||
# | ||
# @see https://developer.github.com/v3/pulls/reviews/#list-reviews-on-a-pull-request | ||
# @param repo [Integer, String, Hash, Repository] A GitHub repository | ||
# @param pull_request_number [Integer] Number of the pull request to fetch reviews for | ||
# @return [Array<Sawyer::Resource>] Array of reviews | ||
# @example | ||
# Octokit.pull_request_reviews('rails/rails', :state => 'closed') | ||
def pull_request_reviews(repo, pull_request_number, options = {}) | ||
accept = { | ||
accept: CUSTOM_ACCEPT_HEADER | ||
} | ||
paginate "#{Repository.path repo}/pulls/#{pull_request_number}/reviews", options.merge(accept) | ||
end | ||
|
||
# Create a pull request review | ||
# | ||
# @see https://developer.github.com/v3/pulls/reviews/#create-a-pull-request-review | ||
# @param repo [Integer, String, Hash, Repository] A GitHub repository | ||
# @param pull_request_number [Integer] Number of the pull request to create review for | ||
# @param event [String] The review action (event) to perform. Can be one of | ||
# PULL_REQUEST_REVIEW_EVENT_APPROVE | ||
# PULL_REQUEST_REVIEW_EVENT_REQUEST_CHANGES | ||
# PULL_REQUEST_REVIEW_EVENT_COMMENT | ||
# @param body [String] The body for the pull request review (optional). Supports GFM. | ||
# @return [Sawyer::Resource] The newly created pull request | ||
# @example | ||
# @client.create_pull_request_review("octokit/octokit.rb", "APPROVE", "Thanks for your contribution") | ||
def create_pull_request_review(repo, pull_request_number, event, body = nil, options = {}) | ||
review = { | ||
event: event, | ||
accept: CUSTOM_ACCEPT_HEADER | ||
} | ||
review[:body] = body unless body.nil? | ||
post "#{Repository.path repo}/pulls/#{pull_request_number}/reviews", options.merge(review) | ||
end | ||
|
||
# Submit a pull request review | ||
# | ||
# @see https://developer.github.com/v3/pulls/reviews/#create-a-pull-request-review | ||
# @param repo [Integer, String, Hash, Repository] A GitHub repository | ||
# @param pull_request_number [Integer] Number of the pull request to create review for | ||
# @param review_id [Integer] ID of the pull request review to submit | ||
# @param event [String] The review action (event) to perform. Can be one of | ||
# PULL_REQUEST_REVIEW_EVENT_APPROVE | ||
# PULL_REQUEST_REVIEW_EVENT_REQUEST_CHANGES | ||
# PULL_REQUEST_REVIEW_EVENT_COMMENT | ||
# @param body [String] The body for the pull request review (optional). Supports GFM. | ||
# @return [Sawyer::Resource] The newly created pull request | ||
# @example | ||
# @client.submit_pull_request_review("octokit/octokit.rb", "REQUEST_CHANGES", | ||
# "Nice changes, but please make couple of imrovements") | ||
def submit_pull_request_review(repo, pull_request_number, review_id, event, body = nil, options = {}) | ||
review = { | ||
event: event, | ||
accept: CUSTOM_ACCEPT_HEADER | ||
} | ||
review[:body] = body unless body.nil? | ||
post "#{Repository.path repo}/pulls/#{pull_request_number}/reviews/#{review_id}/events", options.merge(review) | ||
end | ||
end | ||
end | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nice one |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This will need considerable documentation before we ship ( as this is what an end user would see on the website ) - I'm happy to do this once you're ready though 👍
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sure, do you think we should provide an example here or what are your thoughts? 😄
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sure thing, something like this
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
People don't see the inline documentation for the
review
object, so it needs to be attached to this DSL attribute to end up on the reference - http://danger.systems/reference.htmlThere was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@orta looks cool 👍
The small feedback:
@return [GitHubReview]
->@return [GitHubSource::Review]
or we can just leaveReview
.github.review.markdown(...)
?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
IMO
@return Review
is fine, maybe even@return ReviewDSL
as these docs are for end-users who don't care about our internal semanticsYep :D - please make it a real-ish example like the ones above