[IMP] runbot: improve build error frontend page

On the build error web page, a regular assigned error is not shown to
all users.

With this commit, a regular build error (not only random) will be shown
if the error is assigned.
This commit is contained in:
Christophe Monniez 2020-11-12 16:08:25 +01:00
parent c6a1d202a1
commit 9c7cee657d
3 changed files with 115 additions and 17 deletions

View File

@ -351,16 +351,36 @@ class Runbot(Controller):
return request.render(view_id if view_id else "runbot.monitoring", qctx)
@route(['/runbot/errors',
'/runbot/errors/<int:error_id>'], type='http', auth='user', website=True)
def build_errors(self, error_id=None, **kwargs):
build_errors = request.env['runbot.build.error'].search([('random', '=', True), ('parent_id', '=', False), ('responsible', '!=', request.env.user.id)]).filtered(lambda rec: len(rec.children_build_ids) > 1)
assigned_errors = request.env['runbot.build.error'].search([('responsible', '=', request.env.user.id)])
build_errors = build_errors.sorted(lambda rec: (rec.last_seen_date.date(), rec.build_count), reverse=True)
assigned_errors = assigned_errors.sorted(lambda rec: (rec.last_seen_date.date(), rec.build_count), reverse=True)
build_errors = assigned_errors + build_errors
'/runbot/errors/page/<int:page>'], type='http', auth='user', website=True)
def build_errors(self, error_id=None, sort=None, page=1, limit=20, **kwargs):
sort_order_choices = {
'last_seen_date desc': 'Last seen date: Newer First',
'last_seen_date asc': 'Last seen date: Older First',
'build_count desc': 'Number seen: High to Low',
'build_count asc': 'Number seen: Low to High',
'responsible asc': 'Assignee: A - Z',
'responsible desc': 'Assignee: Z - A',
'module_name asc': 'Module name: A - Z',
'module_name desc': 'Module name: Z -A'
}
sort_order = sort if sort in sort_order_choices else 'last_seen_date desc'
current_user_errors = request.env['runbot.build.error'].search([('responsible', '=', request.env.user.id)], order='last_seen_date desc, build_count desc')
domain = [('responsible', '!=', request.env.user.id), ('build_count', '>', 1)]
build_errors_count = request.env['runbot.build.error'].search_count(domain)
url_args = {}
url_args['sort'] = sort
pager = request.website.pager(url='/runbot/errors/', url_args=url_args, total=build_errors_count, page=page, step=limit)
build_errors = request.env['runbot.build.error'].search(domain, order=sort_order, limit=limit, offset=pager.get('offset', 0))
qctx = {
'current_user_errors': current_user_errors,
'build_errors': build_errors,
'title': 'Build Errors'
'title': 'Build Errors',
'sort_order_choices': sort_order_choices,
'pager': pager
}
return request.render('runbot.build_error', qctx)

View File

@ -32,15 +32,15 @@ class BuildError(models.Model):
trigger_ids = fields.Many2many('runbot.trigger', compute='_compute_trigger_ids')
active = fields.Boolean('Error is not fixed', default=True, tracking=True)
tag_ids = fields.Many2many('runbot.build.error.tag', string='Tags')
build_count = fields.Integer(compute='_compute_build_counts', string='Nb seen')
build_count = fields.Integer(compute='_compute_build_counts', string='Nb seen', store=True)
parent_id = fields.Many2one('runbot.build.error', 'Linked to', index=True)
child_ids = fields.One2many('runbot.build.error', 'parent_id', string='Child Errors', context={'active_test': False})
children_build_ids = fields.Many2many('runbot.build', compute='_compute_children_build_ids', string='Children builds')
error_history_ids = fields.Many2many('runbot.build.error', compute='_compute_error_history_ids', string='Old errors', context={'active_test': False})
first_seen_build_id = fields.Many2one('runbot.build', compute='_compute_first_seen_build_id', string='First Seen build')
first_seen_date = fields.Datetime(string='First Seen Date', related='first_seen_build_id.create_date')
last_seen_build_id = fields.Many2one('runbot.build', compute='_compute_last_seen_build_id', string='Last Seen build')
last_seen_date = fields.Datetime(string='Last Seen Date', related='last_seen_build_id.create_date')
last_seen_build_id = fields.Many2one('runbot.build', compute='_compute_last_seen_build_id', string='Last Seen build', store=True)
last_seen_date = fields.Datetime(string='Last Seen Date', related='last_seen_build_id.create_date', store=True)
test_tags = fields.Char(string='Test tags', help="Comma separated list of test_tags to use to reproduce/remove this error")
@api.constrains('test_tags')
@ -65,10 +65,10 @@ class BuildError(models.Model):
(build_error.child_ids - self).write({'active': vals['active']})
return super(BuildError, self).write(vals)
@api.depends('build_ids')
@api.depends('build_ids', 'child_ids.build_ids')
def _compute_build_counts(self):
for build_error in self:
build_error.build_count = len(build_error.children_build_ids)
build_error.build_count = len(build_error.build_ids | build_error.mapped('child_ids.build_ids'))
@api.depends('build_ids')
def _compute_bundle_ids(self):
@ -86,18 +86,18 @@ class BuildError(models.Model):
for build_error in self:
build_error.summary = build_error.content[:50]
@api.depends('child_ids')
@api.depends('build_ids', 'child_ids.build_ids')
def _compute_children_build_ids(self):
for build_error in self:
all_builds = build_error.build_ids | build_error.mapped('child_ids.build_ids')
build_error.children_build_ids = all_builds.sorted(key=lambda rec: rec.id, reverse=True)
@api.depends('build_ids', 'child_ids')
@api.depends('children_build_ids')
def _compute_last_seen_build_id(self):
for build_error in self:
build_error.last_seen_build_id = build_error.children_build_ids and build_error.children_build_ids[0] or False
@api.depends('build_ids', 'child_ids')
@api.depends('children_build_ids')
def _compute_first_seen_build_id(self):
for build_error in self:
build_error.first_seen_build_id = build_error.children_build_ids and build_error.children_build_ids[-1] or False

View File

@ -6,7 +6,81 @@
<div class="container-fluid">
<div class="row">
<div class='col-md-12'>
<h1>Current Random Bugs on Runbot Builds</h1>
<t t-if="current_user_errors">
<h3>Your assigned bugs Bugs on Runbot Builds</h3>
<div class="accordion" id="userErrorAccordion">
<div class="card">
<div class="card-header">
<div class="row">
<div class="col">Last seen date</div>
<div class="col col-md-3">Module</div>
<div class="col col-md-3">Summary</div>
<div class="col">Nb Seen</div>
<div class="col">Random</div>
<div class="col">Assigned to</div>
<div class="col">&amp;nbsp;</div>
</div>
</div>
</div>
<t t-foreach="current_user_errors" t-as="build_error">
<div class="card">
<div class="card-header">
<div class="row">
<div class="col"><t t-esc="build_error.last_seen_date" t-options='{"widget": "datetime"}'/></div>
<div class="col col-md-3"><t t-esc="build_error.module_name"/></div>
<div class="col col-md-3">
<button class="btn btn-link" type="button" data-toggle="collapse" t-attf-data-target="#collapse{{build_error.id}}" aria-expanded="true" aria-controls="collapseOne">
<i class="fa fa-minus"/>
</button>
<code><t t-esc="build_error.summary"/></code>
</div>
<div class="col">
<t t-esc="build_error.build_count"/>
</div>
<div class="col">
<i t-if="build_error.random" class="fa fa-random"/>
</div>
<div class="col"><t t-esc="build_error.responsible.name"/></div>
<div class="col">
<a groups="runbot.group_user" t-attf-href="/web/#id={{build_error.id}}&amp;view_type=form&amp;model=runbot.build.error" target="new" title="View in Backend">
<i class="fa fa-list"/>
</a>
<a t-att-href="build_error.last_seen_build_id.build_url" t-attf-title="View last affected build ({{build_error.last_seen_build_id.id}})"><i class="fa fa-external-link"/></a>
</div>
</div>
</div>
<div t-attf-id="collapse{{build_error.id}}" class="collapse" aria-labelledby="headingOne" data-parent="#userErrorAccordion">
<div class="card-body">
<pre class="pre-scrollable">
<code><t t-esc="build_error.content.strip()" /></code>
</pre>
</div>
</div>
</div>
</t>
</div>
</t>
<h3>Current Bugs on Runbot Builds</h3>
<div class="container">
<nav class="navbar navbar-expand-lg navbar-light bg-light">
<div class="dropdown mr-auto">
<a role="button" href="#" class="dropdown-toggle btn btn-secondary" data-toggle="dropdown">
Sort By: <t t-esc="request.params.get('sort', '')"/>
</a>
<div class="dropdown-menu" aria-labelledby="sortMenuButton" role="menu">
<t t-foreach="sort_order_choices" t-as="sort_choice">
<a role="menuitem" class="dropdown-item" t-attf-href="/runbot/errors?sort={{sort_choice}}"><t t-esc="sort_order_choices[sort_choice]"/></a>
</t>
</div>
</div>
<span class="ml-auto">
<t t-call="website.pager" />
</span>
</nav>
</div>
<div class="accordion" id="errorAccordion">
<div class="card">
<div class="card-header">
@ -15,6 +89,7 @@
<div class="col col-md-3">Module</div>
<div class="col col-md-3">Summary</div>
<div class="col">Nb Seen</div>
<div class="col">Random</div>
<div class="col">Assigned to</div>
<div class="col">&amp;nbsp;</div>
</div>
@ -36,6 +111,9 @@
<div class="col">
<t t-esc="build_error.build_count"/>
</div>
<div class="col">
<i t-if="build_error.random" class="fa fa-random"/>
</div>
<div class="col"><t t-esc="build_error.responsible.name"/></div>
<div class="col">
<a groups="runbot.group_user" t-attf-href="/web/#id={{build_error.id}}&amp;view_type=form&amp;model=runbot.build.error" target="new" title="View in Backend">