[IMP] runbot: improve build_error management

The build error view was unstructured and contains to much information.

This commit organize fields in groups and also validate some
modification on records in order to avoid build error manager to
disable test-tags by mistake.

An error cannot be deactivated if it appeared less than 24 hours ago to
avoid disabling a non forxardported pr that will fail the next nightly
generating another build error.

Test tags can only be added or removed by administrators.

Also adds a menu for easier User managerment

Also fixed the dname search and display.
This commit is contained in:
Xavier-Do 2022-11-08 14:09:26 +01:00 committed by Christophe Monniez
parent ac010405dc
commit e0856b2245
5 changed files with 54 additions and 26 deletions

View File

@ -12,7 +12,7 @@ _logger = logging.getLogger(__name__)
class Hook(http.Controller): class Hook(http.Controller):
@http.route(['/runbot/hook', '/runbot/hook/<int:remote_id>'], type='http', auth="public", website=True, csrf=False) @http.route(['/runbot/hook', '/runbot/hook/<int:remote_id>'], type='http', auth="public", website=True, csrf=False, sitemap=False)
def hook(self, remote_id=None, **_post): def hook(self, remote_id=None, **_post):
event = request.httprequest.headers.get("X-Github-Event") event = request.httprequest.headers.get("X-Github-Event")
payload = json.loads(request.params.get('payload', '{}')) payload = json.loads(request.params.get('payload', '{}'))

View File

@ -12,6 +12,8 @@ class Branch(models.Model):
_name = 'runbot.branch' _name = 'runbot.branch'
_description = "Branch" _description = "Branch"
_order = 'name' _order = 'name'
_rec_name = 'dname'
_sql_constraints = [('branch_repo_uniq', 'unique (name,remote_id)', 'The branch must be unique per repository !')] _sql_constraints = [('branch_repo_uniq', 'unique (name,remote_id)', 'The branch must be unique per repository !')]
name = fields.Char('Name', required=True) name = fields.Char('Name', required=True)
@ -44,7 +46,7 @@ class Branch(models.Model):
def _search_dname(self, operator, value): def _search_dname(self, operator, value):
if ':' not in value: if ':' not in value:
return [('name', operator, 'value')] return [('name', operator, value)]
repo_short_name, branch_name = value.split(':') repo_short_name, branch_name = value.split(':')
owner, repo_name = repo_short_name.split('/') owner, repo_name = repo_short_name.split('/')
return ['&', ('remote_id', '=', self.env['runbot.remote'].search([('owner', '=', owner), ('repo_name', '=', repo_name)]).id), ('name', operator, branch_name)] return ['&', ('remote_id', '=', self.env['runbot.remote'].search([('owner', '=', owner), ('repo_name', '=', repo_name)]).id), ('name', operator, branch_name)]

View File

@ -5,9 +5,10 @@ import logging
import re import re
from collections import defaultdict from collections import defaultdict
from dateutil.relativedelta import relativedelta
from fnmatch import fnmatch from fnmatch import fnmatch
from odoo import models, fields, api from odoo import models, fields, api
from odoo.exceptions import ValidationError from odoo.exceptions import ValidationError, UserError
_logger = logging.getLogger(__name__) _logger = logging.getLogger(__name__)
@ -31,7 +32,7 @@ class BuildError(models.Model):
responsible = fields.Many2one('res.users', 'Assigned fixer', tracking=True) responsible = fields.Many2one('res.users', 'Assigned fixer', tracking=True)
team_id = fields.Many2one('runbot.team', 'Assigned team') team_id = fields.Many2one('runbot.team', 'Assigned team')
fixing_commit = fields.Char('Fixing commit', tracking=True) fixing_commit = fields.Char('Fixing commit', tracking=True)
fixing_pr_id = fields.Many2one('runbot.branch', 'Fixing PR', tracking=True) fixing_pr_id = fields.Many2one('runbot.branch', 'Fixing PR', tracking=True, domain=[('is_pr', '=', True)])
build_ids = fields.Many2many('runbot.build', 'runbot_build_error_ids_runbot_build_rel', string='Affected builds') build_ids = fields.Many2many('runbot.build', 'runbot_build_error_ids_runbot_build_rel', string='Affected builds')
bundle_ids = fields.One2many('runbot.bundle', compute='_compute_bundle_ids') bundle_ids = fields.One2many('runbot.bundle', compute='_compute_bundle_ids')
version_ids = fields.One2many('runbot.version', compute='_compute_version_ids', string='Versions', search='_search_version') version_ids = fields.One2many('runbot.version', compute='_compute_version_ids', string='Versions', search='_search_version')
@ -71,6 +72,15 @@ class BuildError(models.Model):
if 'active' in vals: if 'active' in vals:
for build_error in self: for build_error in self:
(build_error.child_ids - self).write({'active': vals['active']}) (build_error.child_ids - self).write({'active': vals['active']})
if not self.user_has_groups('runbot.group_runbot_admin'):
if build_error.test_tags:
raise UserError(f"This error as a test-tag and can only be (de)activated by admin")
if not vals['active'] and build_error.last_seen_date + relativedelta(days=1) > fields.Datetime.now():
raise UserError(f"This error broke less than one day ago can only be deactivated by admin")
if vals.get('parent_id') and not self.env.su:
for build_error in self:
if build_error.test_tags:
raise UserError(f"Cannot parent an error with test tags: {build_error.test_tags}")
return super(BuildError, self).write(vals) return super(BuildError, self).write(vals)
@api.depends('build_ids', 'child_ids.build_ids') @api.depends('build_ids', 'child_ids.build_ids')

View File

@ -7,27 +7,39 @@
<form> <form>
<header> <header>
</header> </header>
<group name="build_error_group"> <group>
<field name="fingerprint" readonly="1"/> <group name="build_error_group" string="Base info">
<field name="content"/> <field name="content" readonly="1"/>
<field name="module_name"/> <field name="module_name" readonly="1"/>
<field name="function"/> <field name="function" readonly="1"/>
<field name="random"/> </group>
<field name="responsible"/> </group>
<field name="team_id"/> <group col="2">
<field name="fixing_commit"/> <group name="fixer_info" string="Fixing">
<field name="fixing_pr_id"/> <field name="responsible"/>
<field name="active"/> <field name="team_id"/>
<field name="parent_id" /> <field name="fixing_pr_id"/>
<field name="bundle_ids" widget="many2many_tags"/> <field name="active"/>
<field name="version_ids" widget="many2many_tags"/> <field name="test_tags" readonly="1" groups="!runbot.group_runbot_admin"/>
<field name="trigger_ids" widget="many2many_tags"/> <field name="test_tags" readonly="0" groups="runbot.group_runbot_admin"/>
<field name="tag_ids" widget="many2many_tags"/> </group>
<field name="first_seen_date"/> <group name="fixer_info" string="Fixing">
<field name="first_seen_build_id" widget="frontend_url"/> <field name="version_ids" widget="many2many_tags"/>
<field name="last_seen_date"/> <field name="trigger_ids" widget="many2many_tags"/>
<field name="last_seen_build_id" widget="frontend_url"/> <field name="tag_ids" widget="many2many_tags" readonly="1"/>
<field name="test_tags"/> </group>
</group>
<group name="fixer_info" string="More info" col="2">
<group>
<field name="random"/>
<field name="first_seen_date"/>
<field name="first_seen_build_id" widget="frontend_url"/>
</group>
<group>
<field name="parent_id"/>
<field name="last_seen_date"/>
<field name="last_seen_build_id" widget="frontend_url"/>
</group>
</group> </group>
<notebook> <notebook>
<page string="Builds"> <page string="Builds">
@ -76,9 +88,12 @@
</tree> </tree>
</field> </field>
</page> </page>
<page string="Cleaned" groups="base.group_no_one"> <page string="Debug" groups="base.group_no_one">
<group name="build_error_group"> <group name="build_error_group">
<field name="fingerprint" readonly="1"/>
<field name="cleaned_content"/> <field name="cleaned_content"/>
<field name="fixing_commit"/>
<field name="bundle_ids" widget="many2many_tags"/>
</group> </group>
</page> </page>
</notebook> </notebook>

View File

@ -51,6 +51,7 @@
<menuitem id="runbot_menu_ir_cron_act" action="base.ir_cron_act" parent="runbot_menu_technical"/> <menuitem id="runbot_menu_ir_cron_act" action="base.ir_cron_act" parent="runbot_menu_technical"/>
<menuitem id="runbot_menu_base_automation_act" action="base_automation.base_automation_act" parent="runbot_menu_technical"/> <menuitem id="runbot_menu_base_automation_act" action="base_automation.base_automation_act" parent="runbot_menu_technical"/>
<menuitem id="runbot_menu_action_ui_view" action="base.action_ui_view" parent="runbot_menu_technical"/> <menuitem id="runbot_menu_action_ui_view" action="base.action_ui_view" parent="runbot_menu_technical"/>
<menuitem id="runbot_menu_action_res_users" action="base.action_res_users" parent="runbot_menu_technical"/>
<menuitem name="▶" id="runbot_menu_website" parent="runbot_menu_root" sequence="20000" action="website.action_website"/> <menuitem name="▶" id="runbot_menu_website" parent="runbot_menu_root" sequence="20000" action="website.action_website"/>