[IMP] runbot: force a rebuild when commit in reverse dependency

When a build fails in a repo that depends on another repo, it's difficult
to figure out from which commit it comes in the depending repo.

If this commit is applied, when a new commit is found in a repo's sticky
branch, the latest build from the same branch name, in the depending
repo will be forced to rebuild.
This commit is contained in:
Christophe Monniez 2018-03-28 13:18:50 +02:00
parent 5d23d0957a
commit 46c4c54337
5 changed files with 40 additions and 7 deletions

View File

@ -6,7 +6,7 @@
'author': "Odoo SA",
'website': "http://runbot.odoo.com",
'category': 'Website',
'version': '2.0',
'version': '2.1',
'depends': ['website', 'base'],
'data': [
'security/runbot_security.xml',

View File

@ -34,6 +34,7 @@ class Runbot(http.Controller):
'server_match': real_build.server_match,
'duplicate_of': build.duplicate_id if build.state == 'duplicate' else False,
'coverage': build.branch_id.coverage,
'revdep_build_ids': build.revdep_build_ids,
}
@http.route(['/runbot', '/runbot/repo/<model("runbot.repo"):repo>'], website=True, auth='public', type='http')

View File

@ -59,6 +59,9 @@ class runbot_build(models.Model):
('fuzzy', 'Fuzzy - common ancestor found'),
('default', 'No match found - defaults to master')],
string='Server branch matching')
revdep_build_ids = fields.Many2many('runbot.build', 'runbot_rev_dep_builds',
column1='rev_dep_id', column2='dependent_id',
string='Builds that depends on this build')
def copy(self, values=None):
raise UserError("Cannot duplicate build!")
@ -253,8 +256,9 @@ class runbot_build(models.Model):
if build.job_start:
build.job_age = int(time.time() - dt2time(build.job_start))
def _force(self):
"""Force a rebuild"""
def _force(self, message=None):
"""Force a rebuild and return a recordset of forced builds"""
forced_builds = self.env['runbot.build']
for build in self:
pending_ids = self.search([('state', '=', 'pending')], order='id', limit=1)
if pending_ids:
@ -282,11 +286,17 @@ class runbot_build(models.Model):
else:
rebuild = False
if rebuild:
forced_builds |= build
user = request.env.user if request else self.env.user
build._log('rebuild', 'Rebuild initiated by %s' % user.name)
if message:
build._log('rebuild', message)
return forced_builds
def _skip(self):
def _skip(self, reason=None):
"""Mark builds ids as skipped"""
if reason:
self._logger('skip', reason)
self.write({'state': 'done', 'result': 'skipped'})
to_unduplicate = self.search([('id', 'in', self.ids), ('duplicate_id', '!=', False)])
to_unduplicate._force()

View File

@ -201,10 +201,18 @@ class runbot_repo(models.Model):
builds_to_skip = Build.search(
[('branch_id', '=', branch.id), ('state', '=', 'pending')],
order='sequence asc')
builds_to_skip._skip()
builds_to_skip._skip(reason='New ref found')
if builds_to_skip:
build_info['sequence'] = builds_to_skip[0].sequence
Build.create(build_info)
new_build = Build.create(build_info)
# create a reverse dependency build if needed
if branch.sticky:
for rev_repo in self.search([('dependency_ids', 'in', self.id)]):
# find the latest build with the same branch name
latest_rev_build = Build.search([('repo_id.id', '=', rev_repo.id), ('branch_id.branch_name', '=', branch.branch_name)], order='id desc', limit=1)
if latest_rev_build:
_logger.debug('Reverse dependency build %s forced in repo %s by commit %s', latest_rev_build.dest, rev_repo.name, sha[:6])
new_build.revdep_build_ids += latest_rev_build._force(message='Rebuild from dependency %s commit %s' % (repo.name, sha[:6]))
# skip old builds (if their sequence number is too low, they will not ever be built)
skippable_domain = [('repo_id', '=', repo.id), ('state', '=', 'pending')]

View File

@ -17,7 +17,21 @@
<t t-if="bu['server_match'] in ('default', 'fuzzy')">
<i class="text-warning fa fa-question-circle fa-fw"
title="Server branch cannot be determined exactly. Please use naming convention '9.0-my-branch' to build with '9.0' server branch."/>
title="Server branch cannot be determined exactly. Please use naming convention '9.0-my-branch' to build with '9.0' server branch."/>
</t>
<t t-if="bu['revdep_build_ids']">
<small class="pull-right">Dep builds:
<t t-foreach="bu['revdep_build_ids']" t-as="rbu">
<a t-attf-href="/runbot/build/{{rbu['id']}}" aria-label="Build details" data-toggle="tooltip" t-attf-title="{{rbu['repo_id']['name']}}">
<t t-if="rbu['result']=='ok'"><i class="text-success fa fa-thumbs-up"/></t>
<t t-if="rbu['result']=='ko'"><i class="text-danger fa fa-thumbs-down"/></t>
<t t-if="rbu['result']=='warn'"><i class="text-warning fa fa-warning"/></t>
<t t-if="rbu['result']=='skipped'"><i class="text-danger fa fa-ban"/></t>
<t t-if="rbu['result']=='killed'"><i class="text-danger fa fa-times"/>&#x1f480;</t>
<t t-if="rbu['result']=='manually_killed'"><i class="text-danger fa fa-times"/>&#x1f52b;</t>
</a>
</t>
</small>
</t>
</template>
<template id="runbot.build_button">