[IMP] runbot_merge: avoid unnecessary fetches

* avoid fetching PRs for un-managed branches if we know up-front
* avoid processing comments with no commands (avoids fetching the
  corresponding PR which we know nothing about yet and which may or
  may not be for a managed branch)
This commit is contained in:
Xavier Morel 2018-06-22 10:55:44 +02:00 committed by xmo-odoo
parent cab683ae0f
commit 0afe8797f4
2 changed files with 51 additions and 26 deletions

View File

@ -205,26 +205,26 @@ def handle_comment(env, event):
if 'pull_request' not in event['issue']: if 'pull_request' not in event['issue']:
return "issue comment, ignoring" return "issue comment, ignoring"
_logger.info( repo = event['repository']['full_name']
'comment: %s %s:%s "%s"', issue = event['issue']['number']
event['sender']['login'], author = event['sender']['login']
event['repository']['full_name'], comment = event['comment']['body']
event['issue']['number'], _logger.info('comment: %s %s:%s "%s"', author, repo, issue, comment)
event['comment']['body'],
)
partner = env['res.partner'].search([('github_login', '=', event['sender']['login']),]) partner = env['res.partner'].search([('github_login', '=', author), ])
if not partner: if not partner:
_logger.info("ignoring comment from %s: not in system", event['sender']['login']) _logger.info("ignoring comment from %s: not in system", author)
return 'ignored' return 'ignored'
pr = env['runbot_merge.pull_requests']._get_or_schedule( repository = env['runbot_merge.repository'].search([('name', '=', repo)])
event['repository']['full_name'], if not repository.project_id._find_commands(comment):
event['issue']['number'], return "No commands, ignoring"
)
pr = env['runbot_merge.pull_requests']._get_or_schedule(repo, issue)
if not pr: if not pr:
return "Unknown PR, scheduling fetch" return "Unknown PR, scheduling fetch"
return pr._parse_commands(partner, event['comment']['body'])
return pr._parse_commands(partner, comment)
def handle_review(env, event): def handle_review(env, event):
partner = env['res.partner'].search([('github_login', '=', event['review']['user']['login'])]) partner = env['res.partner'].search([('github_login', '=', event['review']['user']['login'])])
@ -235,6 +235,7 @@ def handle_review(env, event):
pr = env['runbot_merge.pull_requests']._get_or_schedule( pr = env['runbot_merge.pull_requests']._get_or_schedule(
event['repository']['full_name'], event['repository']['full_name'],
event['pull_request']['number'], event['pull_request']['number'],
event['pull_request']['base']['ref']
) )
if not pr: if not pr:
return "Unknown PR, scheduling fetch" return "Unknown PR, scheduling fetch"

View File

@ -243,17 +243,26 @@ class Project(models.Model):
if not f: if not f:
return return
repo = self.env['runbot_merge.repository'].search([('name', '=', f.repository)]) f.repository._load_pr(f.number)
if repo:
repo._load_pr(f.number)
else:
_logger.warn("Fetch job for unknown repository %s, disabling & skipping", f.repository)
# commit after each fetched PR # commit after each fetched PR
f.active = False f.active = False
if commit: if commit:
self.env.cr.commit() self.env.cr.commit()
def _find_commands(self, comment):
return re.findall(
'^{}:? (.*)$'.format(self.github_prefix),
comment, re.MULTILINE)
def _has_branch(self, name):
self.env.cr.execute("""
SELECT 1 FROM runbot_merge_branch
WHERE project_id = %s AND name = %s
LIMIT 1
""", (self.id, name))
return bool(self.env.cr.rowcount)
class Repository(models.Model): class Repository(models.Model):
_name = 'runbot_merge.repository' _name = 'runbot_merge.repository'
@ -274,6 +283,11 @@ class Repository(models.Model):
# fetch PR object and handle as *opened* # fetch PR object and handle as *opened*
issue, pr = gh.pr(number) issue, pr = gh.pr(number)
if not self.project_id._has_branch(pr['base']['ref']):
_logger.info("Tasked with loading PR %d for un-managed branch %s, ignoring", pr['number'], pr['base']['ref'])
return
controllers.handle_pr(self.env, { controllers.handle_pr(self.env, {
'action': 'opened', 'action': 'opened',
'pull_request': pr, 'pull_request': pr,
@ -382,18 +396,28 @@ class PullRequests(models.Model):
for r in self: for r in self:
r.batch_id = r.batch_ids.filtered(lambda b: b.active)[:1] r.batch_id = r.batch_ids.filtered(lambda b: b.active)[:1]
def _get_or_schedule(self, repo_name, number): def _get_or_schedule(self, repo_name, number, target=None):
repo = self.env['runbot_merge.repository'].search([('name', '=', repo_name)])
if not repo:
return
if target and not repo.project_id._has_branch(target):
return
pr = self.search([ pr = self.search([
('repository.name', '=', repo_name), ('repository', '=', repo.id),
('number', '=', number,) ('number', '=', number,)
]) ])
if pr: if pr:
return pr return pr
Fetch = self.env['runbot_merge.fetch_job'] Fetch = self.env['runbot_merge.fetch_job']
if Fetch.search([('repository', '=', repo_name), ('number', '=', number)]): if Fetch.search([('repository', '=', repo.id), ('number', '=', number)]):
return return
Fetch.create({'repository': repo_name, 'number': number}) Fetch.create({
'repository': repo.id,
'number': number,
})
def _parse_command(self, commandstring): def _parse_command(self, commandstring):
m = re.match(r'(\w+)(?:([+-])|=(.*))?', commandstring) m = re.match(r'(\w+)(?:([+-])|=(.*))?', commandstring)
@ -452,7 +476,7 @@ class PullRequests(models.Model):
commands = dict( commands = dict(
ps ps
for m in re.findall('^{}:? (.*)$'.format(self.repository.project_id.github_prefix), comment, re.MULTILINE) for m in self.repository.project_id._find_commands(comment)
for c in m.strip().split() for c in m.strip().split()
for ps in [self._parse_command(c)] for ps in [self._parse_command(c)]
if ps is not None if ps is not None
@ -901,5 +925,5 @@ class FetchJob(models.Model):
_name = 'runbot_merge.fetch_job' _name = 'runbot_merge.fetch_job'
active = fields.Boolean(default=True) active = fields.Boolean(default=True)
repository = fields.Char(index=True) repository = fields.Many2one('runbot_merge.repository', index=True, required=True)
number = fields.Integer(index=True) number = fields.Integer(index=True, required=True)