diff --git a/runbot/__manifest__.py b/runbot/__manifest__.py index 5085df56..e6ea8832 100644 --- a/runbot/__manifest__.py +++ b/runbot/__manifest__.py @@ -6,7 +6,7 @@ 'author': "Odoo SA", 'website': "http://runbot.odoo.com", 'category': 'Website', - 'version': '5.9', + 'version': '5.10', 'application': True, 'depends': ['base', 'base_automation', 'website'], 'data': [ @@ -18,6 +18,7 @@ 'data/runbot_data.xml', 'data/runbot_error_regex_data.xml', 'data/website_data.xml', + 'data/ir_cron_data.xml', 'security/runbot_security.xml', 'security/ir.model.access.csv', diff --git a/runbot/data/ir_cron_data.xml b/runbot/data/ir_cron_data.xml new file mode 100644 index 00000000..f55bf3f9 --- /dev/null +++ b/runbot/data/ir_cron_data.xml @@ -0,0 +1,10 @@ + + + Runbot: Update Build Errors Stage + + code + model._update_stage() + 1 + days + + diff --git a/runbot/migrations/18.0.5.10/post-migration.py b/runbot/migrations/18.0.5.10/post-migration.py new file mode 100644 index 00000000..79184822 --- /dev/null +++ b/runbot/migrations/18.0.5.10/post-migration.py @@ -0,0 +1,11 @@ + +from odoo import api, SUPERUSER_ID + + +def migrate(cr, version): + env = api.Environment(cr, SUPERUSER_ID, {}) + + # Archived build errors are set are considered Done + env['runbot.build.error'].search([['active', "=", False]]).write({'state': 'done'}) + # Build errors with test_tags are set to Ignored + env['runbot.build.error'].search([['test_tags', '!=', False]]).write({'state': 'ignored'}) diff --git a/runbot/models/build_error.py b/runbot/models/build_error.py index c2eccda4..c690ec86 100644 --- a/runbot/models/build_error.py +++ b/runbot/models/build_error.py @@ -105,6 +105,17 @@ class BuildError(models.Model): error_count = fields.Integer("Error count", store=True, compute='_compute_count') previous_error_id = fields.Many2one('runbot.build.error', string="Already seen error") + state = fields.Selection([ + ('new', 'New/Unsolved'), + ('solved', 'Solved'), + ('ignored', 'Ignored'), + ('done', 'Done'), + ], default='new', tracking=True, group_expand=True, + help="New: Error is new and not yet solved. Build error not happening for a long time in this state will automatically move to Done\n" + "Solved: Error should be solved. Build error not happening for a small time in this state will automatically move to Done\n" + "Ignored: Error is ignored. No change of state will apply\n" + "Done: Error is done. No change of state will apply except if issue re-appear, then it will go back to New" + ) responsible = fields.Many2one('res.users', 'Assigned fixer', tracking=True) customer = fields.Many2one('res.users', 'Customer', tracking=True) team_id = fields.Many2one('runbot.team', 'Assigned team', tracking=True) @@ -586,6 +597,37 @@ class BuildError(models.Model): base_error = self_sorted[0] base_error._merge(self_sorted - base_error) + def _update_state(self, nbr_day_solved_to_done=7, nbr_day_new_to_done=15): + """Called automatically by scheduled action to update the state of the error if necessary""" + now = fields.Datetime.now() + + # Done errors that did happen again recently are moved back to new + self.search([ + ('state', '=', 'done'), + ('last_seen_date', '>=', now - relativedelta(days=nbr_day_new_to_done)), + ]).write({'state': 'new'}) + + # New error that did not appear after a long time are marked as done + # Solved error that did not appear after a short time are marked as done + self.search([ + '|', + '&', + ('state', '=', 'new'), + ('last_seen_date', '<', now - relativedelta(days=nbr_day_new_to_done)), + '&', + ('state', '=', 'solved'), + ('last_seen_date', '<', now - relativedelta(days=nbr_day_solved_to_done)), + ]).write({'state': 'done'}) + + @api.model + def _read_group_fill_results(self, domain, groupby, annoted_aggregates, read_group_result, read_group_order=None): + # Override to fold ignored and done state + read_groups = super()._read_group_fill_results(domain, groupby, annoted_aggregates, read_group_result, read_group_order) + for read_group in read_groups: + if read_group.get('state', False) in ('ignored', 'done'): + read_group['__fold'] = True + return read_groups + class BuildErrorContent(models.Model): diff --git a/runbot/views/build_error_views.xml b/runbot/views/build_error_views.xml index b1c30c92..7e041a1d 100644 --- a/runbot/views/build_error_views.xml +++ b/runbot/views/build_error_views.xml @@ -5,6 +5,9 @@ runbot.build.error
+
+ +