-
Notifications
You must be signed in to change notification settings - Fork 37
GitHub Status API Integration #412
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
base: master
Are you sure you want to change the base?
Conversation
0f24fbc to
cfe0348
Compare
skateman
left a comment
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.
Looks good, but some things can be simplified and logically reorganized. Also please add some tests.
| def rubocop_comments | ||
| MessageBuilder.new(results, branch).comments | ||
| message_builder = MessageBuilder.new(results, branch) | ||
| @status = message_builder.commit_status |
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.
I don't think this is The Right Way™ to pass the information, the rubocop_comments method is being used just in the replace_rubocop_comments method, so it's safe to move its content there. This way you don't need the instance variable at all. Then you can refactor or even rename the method and maybe break it into small(er) chunk.
| def replace_rubocop_comments | ||
| logger.info("Updating PR #{pr_number} with rubocop comment.") | ||
| GithubService.replace_comments(fq_repo_name, pr_number, rubocop_comments) do |old_comment| | ||
| GithubService.replace_comments(fq_repo_name, pr_number, rubocop_comments, @status) do |old_comment| |
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.
See my comment above...
lib/github_service.rb
Outdated
|
|
||
| unless commit_status.nil? | ||
| commit_status["options"]["target_url"] = retval["html_url"] | ||
| add_status(commit_status) |
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.
Adding the status is depending on the comment's ID, however, it is an operation on the same level so this method call doesn't belong here, but AFTER the add_comments is called.
lib/github_service.rb
Outdated
| to_delete = issue_comments(fq_repo_name, issue_number).select { |c| yield c } | ||
| delete_comments(fq_repo_name, to_delete.map(&:id)) | ||
| add_comments(fq_repo_name, issue_number, new_comments) | ||
| add_comments(fq_repo_name, issue_number, new_comments, commit_status) |
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.
I think you should put the add_status call after this line, see above...
Gemfile.lock
Outdated
|
|
||
| BUNDLED WITH | ||
| 1.15.4 | ||
| 1.16.1 |
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.
Don't forget to change this back please...
ef1f877 to
bb0aee2
Compare
| GithubService.replace_comments(fq_repo_name, pr_number, rubocop_comments) do |old_comment| | ||
| msg_builder_result = rubocop_comments | ||
|
|
||
| GithubService.replace_comments(fq_repo_name, pr_number, msg_builder_result[:comments], msg_builder_result[:status]) do |old_comment| |
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.
Do you really need the 2 arguments if you're taking them from the same hash? Send the whole hash instead!
| end | ||
|
|
||
| # requirements to "create_status(repo, sha, state, options)" | ||
| def commit_status |
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.
Why is this method under the MessageBuilder? Maybe this can be moved to a better place.
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.
Agreed. This feels like it should live somewhere else.
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.
lib/github_service.rb
Outdated
| first_comment = add_comments(fq_repo_name, issue_number, new_comments) | ||
|
|
||
| # add_status creates a commit status pointing to the first comment URL | ||
| add_status(commit_status, first_comment) |
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.
add_status(commit_status, first_comment) unless first_comment.nil?Then you don't need the condition in the add_status.
lib/github_service.rb
Outdated
| def add_status(comstat, comment) | ||
| unless comstat.nil? | ||
| comstat["options"]["target_url"] = comment["html_url"] | ||
| create_status(comstat["repo"], comstat["sha"], comstat["state"], comstat["options"]) |
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.
Again, you're sending arguments from a single hash, these things can be simplified.
4395636 to
d59d903
Compare
lib/github_service.rb
Outdated
| Array(comments).map do |comment| | ||
| add_comment(fq_repo_name, issue_number, comment) | ||
| end | ||
| end.first |
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.
I like the idea of returning the comments, but from a clean standpoint, this method should just return all of the comments. If the caller only needs the first one, they should be the one to call .first. This way you also don't need the comment describing why you need the .first.
9f39949 to
85b2f5a
Compare
| "state" => state ? "success" : "error", | ||
| "options" => { | ||
| "context" => "miq-bot", # TODO: it should be user name variable | ||
| "target_url" => nil, |
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.
Why is this nil? Can't be this parametrized as state?
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.
@skateman The key is required and the value is added when the URL of the comment is obtained.
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.
OK, what about the 2nd part of the question? 😉
42e8f34 to
9699f2d
Compare
56fc858 to
20a574f
Compare
|
@miq-bot remove_label wip |
caad3ad to
b0e6911
Compare
| logger.info("Updating PR #{pr_number} with rubocop comment.") | ||
| GithubService.replace_comments(fq_repo_name, pr_number, rubocop_comments) do |old_comment| | ||
|
|
||
| status = results["files"].select { |f| f["offenses"].any? }.empty? |
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.
Can you just do status = results["files"].any? { |f| f["offenses"].any? } ?
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.
It works exactly the opposite. I will have to negate it as
status = !results["files"].any? { |f| f["offenses"].any? }otherwise I will have to remake the rest of the code. Do you agree with the negation?
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.
if you're looking for the negation, then you can also do
results["files"].none? { |f| f["offenses"].any? }
lib/github_service.rb
Outdated
| first_comment = add_comments(fq_repo_name, issue_number, new_comments).first | ||
|
|
||
| # add_status creates a commit status pointing to the first comment URL | ||
| unless first_comment.nil? && status.nil? |
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.
unless nil && nil is melting my head with triple-negatives. This would be much easier to read in the positive. I think it's
if first_comment && status
add_status(...)
endThere 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.
@Fryguy Can it be like this?
if first_comment && !status.nil?
add_status(...)
endThe status variable contain a boolean value so your example will not work in case of status has False value.
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.
Ah ok, then yes, first_comment && !status.nil? is good.
spec/lib/github_service_spec.rb
Outdated
|
|
||
| RSpec.describe GithubService do | ||
| let(:repo) { "owner/repository" } | ||
| let(:sha) { "cd16q9z48b3b0xbb91wb311" } |
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.
Pretty sure a SHA only has hexidecimal digits ;)
|
high level I like the ability to use the github api status, but I'm not sure I want to block the PR expect in specific cases (like 💣 💥 🔥 🚒) |
|
@Fryguy by block do you mean red status? AFAIK we don't block PRs based on any status... |
|
Sorry, yes, red status. If too many PRs go "red" then it's harder for reviewers to differentiate between actual failed PRs (i.e. travis didn't pass) vs not actually failed PRs (like how when code climate goes red on 1 new issue). |
|
@Fryguy this makes sense, so let's add a green status when all is good and a red when 💣 💥 🔥 🚒 happens. For other cases I would just simply not set the status...what do you think? |
|
@europ I'm thinking the third case
should still show the status API entry, but it should be a) green and b) say something like "Changes requested" |
|
@Fryguy There is a possibility to use "yellow" status - the pending status. There are 4 available statuses:
Would you like to use the "yellow" one (pending status) for this case with a message "detected offenses required to fix"? |
|
The problem there is that when PR reviewers see "yellow" they think "the CI for this PR is still running", which is not what we want. I'm thinking just use green. |
Commits are marked with [success/error] state depending on offence detection. If there are any offences in the code, the commit is marked with error state otherwise with success state. It is reflected at the end of PR in the check conclusion part.
|
@Fryguy The commits are from now marked every time depending of the detected offences as you requested. There are 3 types of commit marking:
|
|
Checked commit europ@1354dd8 with ruby 2.3.3, rubocop 0.52.1, haml-lint 0.20.0, and yamllint 1.10.0 |
|
This pull request is not mergeable. Please rebase and repush. |



This feature will allow miq-bot to mark the latest commit with a status which depends from the offence(s).
Commits are marked with
successorerrorstate based on offence(s) detection viacreate_status. If there are any offences in the code, the latest commit is marked witherrorstate, otherwise withsuccessstate. It is reflected at the end of pull request in thecheckssection. The status also involves a reference (URL) to the comment which has the description about the offences.Detailed description about the creation of a commit status.
The commit state is stated in
rubocop_checker.rbwhich will be used as a marking state for the last commit. This state is passed to thereplace_commentsmethod ingithub_service.rbas an optional parameter also with the hash (sha) of the last commit which is going to be marked with this state. Inreplace_commentsthe comment(s) writing is firstly proceed as it was originally. After writing the comment(s) about the offence(s) the id of each comment is preserved due to the missing URL which will be used in the commit status as a reference to the comment including the commit status description including the offence(s). The first comment id is selected and a payload is created which is required for thecreate_status. Obtaining these information, the last commit is marked with the adequate state, a little state description and link to the comment including detailed description.\cc
@skateman
@romanblanco
Preview
success
error
NOTE: The
Detailsrefers to the comment shown above.