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

Improve PR search when gitarro is running with cron-like tools to avoid exceeding GitHub API limits #47

Merged
merged 1 commit into from
Oct 3, 2017

Conversation

juliogonzalez
Copy link
Member

@juliogonzalez juliogonzalez commented Sep 28, 2017

Since some people (including us) is using a cron-like pull instead of GitHub Webhooks, knowing which PRs were updated since the last time the cron ran a pull can avoid some request to the API (otherwise it is easy to hit the request limit easily -as we do now- and get failed tests just because we can't contact GitHub).

New parameter is --changed_since <SECONDS>

If present it will consider only PRs with changes newer than X seconds.

So for example, if we look for PRs requiring tests each 5 minutes, and we set here --changed_since=60 it will ignore open PRs unless there were changes in the last 60 seconss.

A change is considered a commit or a comment, and it will update the field updated_at at GitHub API (if the PR was just opened then updated_at has the same value as created_at.

If the parameter is NOT present, gitarro will work as usual.

If SECONDS is 0 then it will ignore all PRs. And negative values is the same as not using the parameters. These last two options are useful for testing, including unit tests.

@juliogonzalez juliogonzalez changed the title Improve PR search when gitarro is running with cron-like tools to avoidid exceeding GitHub API limits Improve PR search when gitarro is running with cron-like tools to avoid exceeding GitHub API limits Sep 28, 2017
@juliogonzalez
Copy link
Member Author

In the future we can also consider using Conditional Requests. At this moment I didn't find how to use them with octokit.

@juliogonzalez
Copy link
Member Author

juliogonzalez commented Sep 28, 2017

And just as an example of a test hitting the limit: https://travis-ci.org/openSUSE/gitarro/builds/280934686?utm_source=github_status&utm_medium=notification :-)

We now need to wait so the test can pass.

@MalloZup
Copy link
Contributor

@juliogonzalez lthx ooks really cool. i will review it with calm tomorrow

@@ -84,8 +90,7 @@ def retrigger_check(pr)

# public always rerun tests against the pr number if this exists
def trigger_by_pr_number(pr)
return false if @pr_number.nil?
return false if @pr_number != pr.number
return false if @pr_number.nil? || @pr_number != pr.number
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Small refactor to avoid rubocop complains.

@@ -117,8 +122,7 @@ def reviewed_pr_test(comm_st, pr)
pr_all_files_type(@repo, pr.number, @file_type)
return true if changelog_active(pr, comm_st)
return false unless @pr_files.any?
exit 1 if @check
launch_test_and_setup_status(@repo, pr)
@check ? exit(1) : launch_test_and_setup_status(@repo, pr)
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Small refactor to avoid rubocop complains.

# a pr contain always a comments, cannot be nil
pr_comment.each do |com|
@client.issue_comments(repo, pr_number).each do |com|
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Small refactor to avoid rubocop complains.

@@ -160,8 +163,7 @@ def magicword(repo, pr_number, context)
# check all files of a Prs Number if they are a specific type
# EX: Pr 56, we check if files are '.rb'
def pr_all_files_type(repo, pr_number, type)
files = @client.pull_request_files(repo, pr_number)
files.each do |file|
@client.pull_request_files(repo, pr_number).each do |file|
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Small refactor to avoid rubocop complains.

@@ -259,8 +261,7 @@ def do_changelog_test(repo, pr)
def changelog_changed(repo, pr, comm_st)
return false unless @changelog_test
# only execute 1 time, don"t run if test is failed, or ok
return false if failed_status?(comm_st)
return false if success_status?(comm_st)
return false if failed_status?(comm_st) || success_status?(comm_st)
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Small refactor to avoid rubocop complains.

end

def test_get_no_prs
@full_hash[:repo] = 'openSUSE/gitbot'
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

typo gitbot --> gitarro

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

@@ -48,4 +49,19 @@ def assert_file_non_ex(gbex, test_file)
assert_equal("'#{test_file}\' doesn't exists.Enter valid file, -t option",
ex.message)
end

def test_get_all_prs
@full_hash[:repo] = 'openSUSE/gitbot'
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

gitarro

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

gitarro.rb Outdated
prs = b.open_newer_prs

# Exit without errors if no PRs were found
if prs.empty?
Copy link
Contributor

@MalloZup MalloZup Sep 29, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

even if rubocop will complain, is good to move this function to a class to backend.rb.
I would put it in the general class, or we could create a module which is included by the main class of backend.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, maybe we should call it inside Backend.open_newer_prs() and exit if the array is empty?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yo

def open_newer_prs
prs = []
@client.pull_requests(@repo, state: 'open').each do |pr|
if Time.now.utc - pr.updated_at < @options[:change_newer] * 60 ||
Copy link
Contributor

@MalloZup MalloZup Sep 29, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i think we need here a private method for 2 reasons:
something like: ( naming could be improved)

def pr_comment_commit_changed_less_then(pr, min)
 return true  if Time.now.utc - pr.updated_at < @options[:change_newer] * 60 || ..
end
  • for making the code more abstract from the algorithm itself, and more maintenable.
  • it will remove the the if and end block, making a inline if (more compact)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, but maybe pr_changed_less_than(pr, min) will be a easier name. What do you think?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yop, but if so i would make a comment above the function saying what trigger tje change

change_newer_desc = 'If present, will only check PRs with a change in ' \
'the last X minutes'
opt.on("--change_newer 'MINUTES'", change_newer_desc) do |change_newer|
@options[:change_newer] = Integer(change_newer)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

as the first glance i was wondering why there is an Integer and not a boolean here.

I think that the name change_newer_since can remove all doubts, and we can accept the integer.
Otherwise, as an option i would expect a boolean for activating something.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sounds good. I will change it.

Copy link
Contributor

@MalloZup MalloZup left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

great pr part of the inline comments,

i think we need also 2 things:

  • update the documentation with example and more verbose about this ( sd oemthing what you wrote in the pr)

  • we should have a spec test for this

@MalloZup
Copy link
Contributor

#51

@juliogonzalez juliogonzalez force-pushed the FIX/limit-rate-new branch 3 times, most recently from 7b99a0a to d8621fc Compare October 2, 2017 14:01
it 'gitarro should see at least PR #30 changed in the last 60 seconds' do
context = 'changed-since'
desc = 'changed-since'
@comment = @rgit.create_comment(@pr, "gitarro rerun #{context} !!!")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you need here to target explicetly the PR number 30, you will write on the first pr open which is not the 30.
i

@juliogonzalez juliogonzalez force-pushed the FIX/limit-rate-new branch 5 times, most recently from 9bd3b20 to 660bec5 Compare October 2, 2017 15:53
context = 'changed-since'
desc = 'changed-since'
@pr = @rgit.pr_by_number(PR_NUMBER)
@comment = @rgit.create_comment(@pr, "gitarro rerun #{context} !!!")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

here i would write instead of @comment comment, since we don't need a class var

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done, pending test and push.

it 'gitarro should see at least PR #30 changed in the last 60 seconds' do
context = 'changed-since'
desc = 'changed-since'
@pr = @rgit.pr_by_number(PR_NUMBER)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same for pr

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done, pending test and push.

@juliogonzalez
Copy link
Member Author

About the refactor: I can't do nothing but fully agree with you. I always say the same thing and this time I even broke my own rules. My mistake :-)

That said, I think we should open an issue to refactor Backend class as a priority.

It's growing and most probably we can simplify some stuff and move other stuff to a new class. In the end most of the refactors we are adding are to prevent rubocop from complaining about methods or classes being bigger than the rules allow.

About all other changes: I will have a look and will fix.

Copy link
Contributor

@MalloZup MalloZup left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

some inline comments

gitarro.rb Outdated
@@ -8,7 +8,9 @@
require_relative 'lib/gitarro/backend'

b = Backend.new
prs = b.open_prs
prs = b.open_newer_prs
exit 0 if b.check_pr_list_empty(prs)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

following issue #64 we can rename this as
prs_list_empty?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done, pending test and push.

# Check if a PR list is empty
# If it is and we do want to consider the update time, return true
# Otherwise return false
def check_pr_list_empty(prs)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

renaming

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done, pending test and push.

def open_newer_prs
prs = []
@client.pull_requests(@repo, state: 'open').each do |pr|
prs << pr if pr_last_update_less_than(pr, @options[:changed_since])
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

cosmetical :

https://stackoverflow.com/questions/10569529/ruby-difference-between-array-and-arraypush
I tend to prefer prs.push(pr) (since it is more verbose) but << it is ok

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done, pending test and push.

client.create_status(@repo, pr.head.sha, status, context: @context,
description: @description,
target_url: @target_url)
true
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i think this true should go on the respectives public method

retrigger_pr_number etc

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think I placed this at the wrong place (create_status)

Shouldn't we place it a launch_test_and_setup_status since it's in use by all the public methods? In the end it's being used by all of them (with the exception of changelog) that are being used at /gitarro.rb

@juliogonzalez
Copy link
Member Author

Done. Unit and acceptance tests passed locally.

return false
end
pr_all_files_type(@repo, pr.number, @file_type)
return false unless @pr_files.any?
return false unless pr_all_files_type(pr.number, @file_type).any?
Copy link
Contributor

@MalloZup MalloZup Oct 3, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nitpick: imho we can refactor this;

return pr_all_files_type(pr.number, @file_type).any?

Which will return false if there is no file and true if any
and we can remove line 294 true

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we can just refactor as:

pr_all_files_type(pr.number, @file_type).any?

Can't we?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

@openSUSE openSUSE deleted a comment from juliogonzalez Oct 3, 2017
@openSUSE openSUSE deleted a comment from juliogonzalez Oct 3, 2017
@openSUSE openSUSE deleted a comment from juliogonzalez Oct 3, 2017
@openSUSE openSUSE deleted a comment from juliogonzalez Oct 3, 2017
@openSUSE openSUSE deleted a comment from juliogonzalez Oct 3, 2017
@openSUSE openSUSE deleted a comment from juliogonzalez Oct 3, 2017
@openSUSE openSUSE deleted a comment from juliogonzalez Oct 3, 2017
Copy link
Contributor

@MalloZup MalloZup left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

last nitpick

# public method for get prs opened and matching the changed_since
# condition
def open_newer_prs
prs = []
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ntipick: we can refactor this with a beatiful ruby enumerable class.

prs = @client.pull_requests(@repo, state: 'open').select do 
  pr_last_update_less_than(pr, @options[:changed_since])
end

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

$ irb
irb(main):001:0> [1,2,3].select {|n| n > 4 }
=> []

http://ruby-doc.org/core-2.2.2/Enumerable.html#method-i-select

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

@MalloZup
Copy link
Contributor

MalloZup commented Oct 3, 2017

gif
gatt
danza
piscina

@MalloZup MalloZup merged commit 80a7abe into openSUSE:master Oct 3, 2017
@MalloZup
Copy link
Contributor

MalloZup commented Oct 3, 2017

@juliogonzalez i think we can upload the new version in production with this.

@juliogonzalez
Copy link
Member Author

Sure, can you update the gem while I update the docker image?

@juliogonzalez
Copy link
Member Author

Maybe we should also create a release for each time we update the Gem

@MalloZup
Copy link
Contributor

MalloZup commented Oct 3, 2017

yop, imho i would wait to create the gem until a week/3-4 days of running in production. ( in case there is a bug that we overlooked and so on that we need to fix) so in this way we prevent to publish buggy gems and releases.

@juliogonzalez
Copy link
Member Author

Ok, sounds fine.

Updating Docker image and changing jobs.

@MalloZup
Copy link
Contributor

MalloZup commented Oct 3, 2017

danza

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants