From 328a25a31f83eee6a411d9d75ad2c576ccca9c24 Mon Sep 17 00:00:00 2001 From: Julien Legros Date: Wed, 14 Mar 2018 13:33:51 +0100 Subject: [PATCH] [FIX] runbot: do not rely on copy behavior for rebuilds Instead of marking most fields as `copy=False` to be able to use the copy method for rebuilds, we create the build explicitly. We also forbid to copy builds as it doesn't make much sense to begin with. As for duplicates, it wasn't always possible to rebuild them. The rebuild now injects a specific context key (force_rebuild). This allows duplicates to undergo a rebuild. The side-effect of writing on previous builds is also removed[1]. [1]: it's not obvious from the diff but the porting to the V8 API should have yielded duplicate.write({'duplicate_id': build_id.id}) instead of build_id.write({'duplicate_id': build_id.id}) --- runbot/models/build.py | 32 +++++++++++++++++++++++--------- 1 file changed, 23 insertions(+), 9 deletions(-) diff --git a/runbot/models/build.py b/runbot/models/build.py index 63e4c180..16cc2bef 100644 --- a/runbot/models/build.py +++ b/runbot/models/build.py @@ -12,6 +12,7 @@ import time from subprocess import CalledProcessError from ..common import dt2time, fqdn, now, locked, grep, time2str, rfind, uniq_list, local_pgadmin_cursor, lock from odoo import models, fields, api +from odoo.exceptions import UserError from odoo.tools import config, appdirs _re_error = r'^(?:\d{4}-\d\d-\d\d \d\d:\d\d:\d\d,\d{3} \d+ (?:ERROR|CRITICAL) )|(?:Traceback \(most recent call last\):)$' @@ -41,15 +42,15 @@ class runbot_build(models.Model): subject = fields.Text('Subject') sequence = fields.Integer('Sequence') modules = fields.Char("Modules to Install") - result = fields.Char('Result', default='', copy=False) # ok, ko, warn, skipped, killed, manually_killed + result = fields.Char('Result', default='') # ok, ko, warn, skipped, killed, manually_killed guess_result = fields.Char(compute='_guess_result') pid = fields.Integer('Pid') state = fields.Char('Status', default='pending') # pending, testing, running, done, duplicate, deathrow job = fields.Char('Job') # job_* - job_start = fields.Datetime('Job start', copy=False) - job_end = fields.Datetime('Job end', copy=False) - job_time = fields.Integer(compute='_get_time', string='Job time', copy=False) - job_age = fields.Integer(compute='_get_age', string='Job age', copy=False) + job_start = fields.Datetime('Job start') + job_end = fields.Datetime('Job end') + job_time = fields.Integer(compute='_get_time', string='Job time') + job_age = fields.Integer(compute='_get_age', string='Job age') duplicate_id = fields.Many2one('runbot.build', 'Corresponding Build') server_match = fields.Selection([('builtin', 'This branch includes Odoo server'), ('exact', 'branch/PR exact name'), @@ -58,9 +59,13 @@ class runbot_build(models.Model): ('default', 'No match found - defaults to master')], string='Server branch matching') + def copy(self, values=None): + raise UserError("Cannot duplicate build!") + def create(self, vals): build_id = super(runbot_build, self).create(vals) extra_info = {'sequence': build_id.id} + context = self.env.context # detect duplicate duplicate_id = None @@ -79,9 +84,8 @@ class runbot_build(models.Model): duplicate_closest_name = duplicate._get_closest_branch_name(extra_repo.id)[1] if build_closest_name != duplicate_closest_name: duplicate_id = None - if duplicate_id: + if duplicate_id and not context.get('force_rebuild'): extra_info.update({'state': 'duplicate', 'duplicate_id': duplicate_id}) - build_id.write({'duplicate_id': build_id.id}) build_id.write(extra_info) return build_id @@ -257,7 +261,17 @@ class runbot_build(models.Model): build.write({'state': 'pending', 'sequence': sequence, 'result': ''}) # or duplicate it elif build.state in ['running', 'done', 'duplicate', 'deathrow']: - new_build = build.copy({'sequence': sequence}) + new_build = build.with_context(force_rebuild=True).create({ + 'sequence': sequence, + 'branch_id': build.branch_id.id, + 'name': build.name, + 'author': build.author, + 'author_email': build.author_email, + 'committer': build.committer, + 'committer_email': build.committer_email, + 'subject': build.subject, + 'modules': build.modules, + }) build = new_build else: rebuild = False @@ -783,4 +797,4 @@ class runbot_build(models.Model): cmd += ['--db-filter', '%d.*$'] else: cmd += ['--db-filter', '%s.*$' % build.dest] - return self._spawn(cmd, lock_path, log_path, cpu_limit=None) \ No newline at end of file + return self._spawn(cmd, lock_path, log_path, cpu_limit=None)