[IMP] runbot: various improvements

- Add a keep running flag on the build to allow a build to stay in
  running state until the flag is switched off ( or the build killed)
- Do not update configs and config_steps data
- Add a first/last_seen_build and first/last_seen_date on build.error
- Children error builds now include the parent builds too
- Use a notebook on build.error form view to display builds and linked
  errors
- Update result when a build triggers a change from 'warn' to 'ko' too
- Add the sticky flag on the error logs stored sql view
This commit is contained in:
Christophe Monniez 2019-09-05 12:01:40 +02:00
parent b7df8566e4
commit 56999ecfb4
8 changed files with 86 additions and 41 deletions

View File

@ -1,5 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<data noupdate="1">
<record id="runbot_build_config_step_test_base" model="runbot.build.config.step">
<field name="name">base</field>
<field name="install_modules">base</field>
@ -117,4 +118,5 @@
<field name="step_order_ids" eval="[(5,0,0), (0, 0, {'step_id': ref('runbot_build_config_step_test_click_all')})]"/>
<field name="protected" eval="True"/>
</record>
</data>
</odoo>

View File

@ -107,6 +107,7 @@ class runbot_build(models.Model):
string='Source export path mode')
build_url = fields.Char('Build url', compute='_compute_build_url', store=False)
build_error_ids = fields.Many2many('runbot.build.error', 'runbot_build_error_ids_runbot_build_rel', string='Errors')
keep_running = fields.Boolean('Keep running', help='Keep running')
@api.depends('config_id')
def _compute_log_list(self): # storing this field because it will be access trhoug repo viewn and keep track of the list at create
@ -607,9 +608,11 @@ class runbot_build(models.Model):
else: # testing/running build
if build.local_state == 'testing':
# failfast in case of docker error (triggered in database)
if (not build.local_result or build.local_result == 'ok') and build.triggered_result:
build.local_result = build.triggered_result
build._github_status() # failfast
if build.triggered_result:
worst_result = self._get_worst_result([build.triggered_result, build.local_result])
if worst_result != build.local_result:
build.local_result = build.triggered_result
build._github_status() # failfast
# check if current job is finished
if docker_is_running(build._get_docker_name()):
timeout = min(build.active_step.cpu_limit, int(icp.get_param('runbot.runbot_timeout', default=10000)))

View File

@ -34,6 +34,10 @@ class RunbotBuildError(models.Model):
child_ids = fields.One2many('runbot.build.error', 'parent_id', string='Child Errors')
children_build_ids = fields.Many2many('runbot.build', compute='_compute_children_build_ids', string='Children builds')
error_history_ids = fields.One2many('runbot.build.error', compute='_compute_error_history_ids', string='Old errors')
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')
@api.model
def create(self, vals):
@ -48,7 +52,7 @@ class RunbotBuildError(models.Model):
@api.depends('build_ids')
def _compute_build_counts(self):
for build_error in self:
build_error.build_count = len(build_error.build_ids) + len(build_error.children_build_ids)
build_error.build_count = len(build_error.children_build_ids)
@api.depends('build_ids')
def _compute_branch_ids(self):
@ -68,7 +72,18 @@ class RunbotBuildError(models.Model):
@api.depends('child_ids')
def _compute_children_build_ids(self):
for build_error in self:
build_error.children_build_ids = build_error.mapped('child_ids.build_ids')
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')
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')
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
@api.depends('fingerprint')
def _compute_error_history_ids(self):

View File

@ -79,6 +79,7 @@ class RunbotErrorLog(models.Model):
hidden = fields.Boolean(string='Hidden', readonly=True)
branch_id = fields.Many2one('runbot.branch', string='Branch', readonly=True)
branch_name = fields.Char(string='Branch name', readonly=True)
branch_sticky = fields.Boolean(string='Sticky', readonly=True)
repo_id = fields.Many2one('runbot.repo', string='Repo', readonly=True)
repo_name = fields.Char(string='Repo name', readonly=True)
repo_short_name = fields.Char(compute='_compute_repo_short_name', readonly=True)
@ -136,6 +137,7 @@ class RunbotErrorLog(models.Model):
bu.hidden AS hidden,
br.id AS branch_id,
br.branch_name AS branch_name,
br.sticky AS branch_sticky,
re.id AS repo_id,
re.name AS repo_name
FROM

View File

@ -475,7 +475,7 @@ class runbot_repo(models.Model):
pending_build._schedule()
# terminate and reap doomed build
build_ids = Build.search(domain_host + [('local_state', '=', 'running')], order='job_start desc').ids
build_ids = Build.search(domain_host + [('local_state', '=', 'running'), ('keep_running', '!=', True)], order='job_start desc').ids
# sort builds: the last build of each sticky branch then the rest
sticky = {}
non_sticky = []

View File

@ -22,40 +22,60 @@
<field name="branch_ids" widget="many2many_tags"/>
<field name="repo_ids" widget="many2many_tags"/>
<field name="tag_ids" widget="many2many_tags"/>
<field name="first_seen_date"/>
<field name="first_seen_build_id"/>
<field name="last_seen_date"/>
<field name="last_seen_build_id"/>
</group>
<field name="build_ids" nolabel="1" widget="many2many" options="{'not_delete': True, 'no_create': True}">
<tree>
<field name="create_date"/>
<field name="id"/>
<field name="repo_id"/>
<field name="branch_id"/>
<field name="dest"/>
<field name="build_url" widget="url" readonly="1" text="View build"/>
</tree>
</field>
<label for="children_build_ids" string="Linked errors builds"/>
<field name="children_build_ids" widget="many2many" options="{'not_delete': True, 'no_create': True}">
<tree>
<field name="create_date"/>
<field name="id"/>
<field name="repo_id"/>
<field name="branch_id"/>
<field name="dest"/>
<field name="build_url" widget="url" readonly="1" text="View build"/>
</tree>
</field>
<label for="error_history_ids" string="Error history"/>
<field name="error_history_ids" widget="one2many" options="{'not_delete': True, 'no_create': True}">
<tree>
<field name="create_date"/>
<field name="module_name"/>
<field name="summary"/>
<field name="random"/>
<field name="build_count"/>
<field name="responsible"/>
<field name="fixing_commit"/>
</tree>
</field>
<notebook>
<page string="Builds">
<field name="build_ids" nolabel="1" widget="many2many" options="{'not_delete': True, 'no_create': True}">
<tree>
<field name="create_date"/>
<field name="id"/>
<field name="repo_id"/>
<field name="branch_id"/>
<field name="dest"/>
<field name="build_url" widget="url" readonly="1" text="View build"/>
</tree>
</field>
</page>
<page string="All Errors Builds">
<field name="children_build_ids" widget="many2many" options="{'not_delete': True, 'no_create': True}">
<tree>
<field name="create_date"/>
<field name="id"/>
<field name="repo_id"/>
<field name="branch_id"/>
<field name="dest"/>
<field name="build_url" widget="url" readonly="1" text="View build"/>
</tree>
</field>
</page>
<page string="Linked Errors">
<field name="child_ids" widget="many2many" options="{'not_delete': True, 'no_create': True}">
<tree>
<field name="create_date"/>
<field name="module_name"/>
<field name="summary"/>
<field name="build_count"/>
</tree>
</field>
</page>
<page string="Error history">
<field name="error_history_ids" widget="one2many" options="{'not_delete': True, 'no_create': True}">
<tree>
<field name="create_date"/>
<field name="module_name"/>
<field name="summary"/>
<field name="random"/>
<field name="build_count"/>
<field name="responsible"/>
<field name="fixing_commit"/>
</tree>
</field>
</page>
</notebook>
</sheet>
<div class="oe_chatter">
<field name="message_follower_ids" widget="mail_followers"/>
@ -72,7 +92,8 @@
<tree string="Errors">
<field name="module_name"/>
<field name="summary"/>
<field name="random"/>
<field name="random" string="Random"/>
<field name="last_seen_date" string="Last Seen"/>
<field name="build_count"/>
<field name="responsible"/>
<field name="fixing_commit"/>

View File

@ -38,6 +38,7 @@
<field name="orphan_result" readonly="1"/>
<field name="hidden" groups="base.group_no_one"/>
<field name="build_url" widget="url" readonly="1"/>
<field name="keep_running"/>
</group>
</sheet>
</form>

View File

@ -74,6 +74,7 @@
<filter string="Failed builds" name="failed_builds" domain="[('global_state', '=', 'done'), ('global_result', '=', 'ko')]"/>
<separator/>
<filter string="Master branches" name="master_branches" domain="[('branch_name', '=', 'master')]"/>
<filter string="Sticky branches" name="sticky_branches" domain="[('branch_sticky', '=', True)]"/>
</search>
</field>
</record>
@ -82,7 +83,7 @@
<field name="name">Error Logs</field>
<field name="res_model">runbot.error.log</field>
<field name="view_mode">tree,form</field>
<field name="context">{'search_default_master_branches': True, 'search_default_failed_builds': True}</field>
<field name="context">{'search_default_sticky_branches': True, 'search_default_failed_builds': True}</field>
</record>
<menuitem