diff --git a/runbot/__manifest__.py b/runbot/__manifest__.py index a5ba3408e..173a849df 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.12', + 'version': '5.13', 'application': True, 'depends': ['base', 'base_automation', 'website'], 'data': [ diff --git a/runbot/migrations/18.0.5.13/pre-migration.py b/runbot/migrations/18.0.5.13/pre-migration.py new file mode 100644 index 000000000..bbdc1b9d2 --- /dev/null +++ b/runbot/migrations/18.0.5.13/pre-migration.py @@ -0,0 +1,9 @@ +def migrate(cr, version): + cr.execute('ALTER TABLE runbot_build_error_link ADD COLUMN batch_id INT') + cr.execute('ALTER TABLE runbot_build_error_link ADD COLUMN batch_date TIMESTAMP WITHOUT TIME ZONE') + cr.execute(''' + UPDATE runbot_build_error_link SET batch_id = batch.id, batch_date = batch.create_date + FROM runbot_batch as batch + JOIN runbot_build build on build.create_batch_id = batch.id + JOIN runbot_build_error_link as link on link.build_id = build.id + ''') \ No newline at end of file diff --git a/runbot/models/build_error.py b/runbot/models/build_error.py index 03aec74c5..3efdffec6 100644 --- a/runbot/models/build_error.py +++ b/runbot/models/build_error.py @@ -39,6 +39,8 @@ class BuildErrorLink(models.Model): build_id = fields.Many2one('runbot.build', required=True, index=True) error_content_id = fields.Many2one('runbot.build.error.content', required=True, index=True, ondelete='cascade') log_date = fields.Datetime(string='Log date') + batch_id = fields.Many2one('runbot.batch', related='build_id.create_batch_id', string='Batch', store=True, readonly=True) + batch_date = fields.Datetime(related='batch_id.create_date', string='Batch date', store=True, readonly=True) host = fields.Char(related='build_id.host') dest = fields.Char(related='build_id.dest') version_id = fields.Many2one(related='build_id.version_id') @@ -75,8 +77,8 @@ def _compute_seen(self): if error_link_ids: first_error_link = error_link_ids[0] last_error_link = error_link_ids[-1] - record.first_seen_date = first_error_link.log_date - record.last_seen_date = last_error_link.log_date + record.first_seen_date = first_error_link.batch_date + record.last_seen_date = last_error_link.batch_date record.first_seen_build_id = first_error_link.build_id record.last_seen_build_id = last_error_link.build_id record.build_count = len(error_link_ids.build_id) diff --git a/runbot/tests/test_build_error.py b/runbot/tests/test_build_error.py index 941dc6521..9a8054581 100644 --- a/runbot/tests/test_build_error.py +++ b/runbot/tests/test_build_error.py @@ -39,9 +39,10 @@ def setUpClass(cls): cls.x_test_class = cls.env['ir.model.fields'].search([('name', '=', 'x_test_class'), ('model_id', '=', model)], limit=1) cls.x_test_method = cls.env['ir.model.fields'].search([('name', '=', 'x_test_method'), ('model_id', '=', model)], limit=1) - def create_test_build(self, vals): + def create_test_build(self, vals, params_vals=None): + params = self.create_params(params_vals or {}) create_vals = { - 'params_id': self.base_params.id, + 'params_id': params.id, 'port': '1234', 'local_result': 'ok' } @@ -380,48 +381,51 @@ def test_build_scan(self): def test_seen_date(self): # create all the records before the tests to evaluate compute dependencies - build_a = self.create_test_build({'local_result': 'ok', 'local_state': 'testing'}) - first_seen_date = fields.Datetime.from_string('2023-08-29 00:46:21') - self.create_log({'create_date': first_seen_date, 'message': RTE_ERROR, 'build_id': build_a.id}) - - build_b = self.create_test_build({'local_result': 'ok', 'local_state': 'testing'}) - new_seen_date = fields.Datetime.from_string('2023-08-29 02:46:21') - self.create_log({'create_date': new_seen_date, 'message': RTE_ERROR, 'build_id': build_b.id}) - - build_c = self.create_test_build({'local_result': 'ok', 'local_state': 'testing'}) - child_seen_date = fields.Datetime.from_string('2023-09-01 12:00:00') - self.create_log({'create_date': child_seen_date, 'message': 'Fail: foo bar error', 'build_id': build_c.id}) + trigger = self.Trigger.create({ + 'name': 'test-trigger', + 'batch_dependent': True, + 'project_id': self.project.id, + 'config_id': self.default_config.id, + }) + batch_date = fields.Datetime.from_string('2023-08-28 19:00:01') + log_date = fields.Datetime.from_string('2023-08-29 00:46:21') + self.fist_batch = self.Batch.create({ + 'bundle_id': self.dev_bundle.id, + }) + self.env.cr.execute('UPDATE runbot_batch SET create_date = %s WHERE id = %s', (batch_date, self.fist_batch.id)) # Update in sql to avoid getting removed + self.fist_batch.invalidate_recordset() + self.assertEqual(self.fist_batch.create_date, batch_date, 'Batch create date should be set') - build_d = self.create_test_build({'local_result': 'ok', 'local_state': 'testing'}) - new_child_seen_date = fields.Datetime.from_string('2023-09-02 12:00:00') - self.create_log({'create_date': new_child_seen_date, 'message': 'Fail: foo bar error', 'build_id': build_d.id}) + build_a = self.create_test_build({'local_result': 'ok', 'local_state': 'testing'}, {'create_batch_id': self.fist_batch.id, 'trigger_id': trigger.id}) + self.assertEqual(build_a.create_batch_id, self.fist_batch, 'Build should be linked to the batch') + self.create_log({'create_date': log_date, 'message': RTE_ERROR, 'build_id': build_a.id}) build_a._parse_logs() build_error_a = build_a.build_error_ids - self.assertEqual(build_error_a.first_seen_date, first_seen_date) self.assertEqual(build_error_a.first_seen_build_id, build_a) - self.assertEqual(build_error_a.last_seen_date, first_seen_date) + self.assertEqual(build_error_a.first_seen_build_id.create_batch_id, self.fist_batch) + self.assertEqual(build_error_a.first_seen_date, batch_date) self.assertEqual(build_error_a.last_seen_build_id, build_a) + self.assertEqual(build_error_a.last_seen_build_id.create_batch_id, self.fist_batch) + self.assertEqual(build_error_a.last_seen_date, batch_date) + + new_batch_date = fields.Datetime.from_string('2023-08-29 19:00:01') + new_log_date = fields.Datetime.from_string('2023-08-30 00:48:21') + self.new_batch = self.Batch.create({ + 'bundle_id': self.dev_bundle.id, + }) + self.env.cr.execute('UPDATE runbot_batch SET create_date = %s WHERE id = %s', (new_batch_date, self.new_batch.id)) # Update in sql to avoid getting removed + self.new_batch.invalidate_recordset() + self.assertEqual(self.new_batch.create_date, new_batch_date, 'New batch create date should be set') + + build_b = self.create_test_build({'local_result': 'ok', 'local_state': 'testing'}, {'create_batch_id': self.new_batch.id, 'trigger_id': trigger.id}) + self.create_log({'create_date': new_log_date, 'message': RTE_ERROR, 'build_id': build_b.id}) # a new build with the same error should be the last seen build_b._parse_logs() - self.assertEqual(build_error_a.last_seen_date, new_seen_date) + self.assertEqual(build_error_a.last_seen_date, new_batch_date) self.assertEqual(build_error_a.last_seen_build_id, build_b) - # a new build error is linked to the current one - build_c._parse_logs() - build_error_c = build_c.build_error_ids - self.assertNotIn(build_c, build_error_a.build_ids) - build_error_a._merge(build_error_c) - self.assertIn(build_c, build_error_a.build_ids) - self.assertEqual(build_error_a.last_seen_date, child_seen_date) - self.assertEqual(build_error_a.last_seen_build_id, build_c) - - # a new build appears in the linked error - build_d._parse_logs() - self.assertEqual(build_error_a.last_seen_date, new_child_seen_date) - self.assertEqual(build_error_a.last_seen_build_id, build_d) - def test_build_error_links(self): build_a = self.create_test_build({'local_result': 'ko'}) build_b = self.create_test_build({'local_result': 'ko'}) diff --git a/runbot/views/build_error_views.xml b/runbot/views/build_error_views.xml index 7f5646211..b382b3651 100644 --- a/runbot/views/build_error_views.xml +++ b/runbot/views/build_error_views.xml @@ -34,7 +34,6 @@ - @@ -50,6 +49,7 @@ +