Skip to content

Commit 6c3e359

Browse files
committed
[IMP] runbot: use batch date for first seen date
The log date can be useful to identify a pattern in apparition (alway arround midnight, ...) but it is usually less relevant for apparition when when usually focus on the "commit" so the batch date Moreover the log date can be misleading when the build ran in faketime. Even if it is not always the case, it is possible to have log_dates in the future.
1 parent 21683fc commit 6c3e359

File tree

5 files changed

+52
-37
lines changed

5 files changed

+52
-37
lines changed

runbot/__manifest__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
'author': "Odoo SA",
77
'website': "http://runbot.odoo.com",
88
'category': 'Website',
9-
'version': '5.12',
9+
'version': '5.13',
1010
'application': True,
1111
'depends': ['base', 'base_automation', 'website'],
1212
'data': [
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
def migrate(cr, version):
2+
cr.execute('ALTER TABLE runbot_build_error_link ADD COLUMN batch_id INT')
3+
cr.execute('ALTER TABLE runbot_build_error_link ADD COLUMN batch_date TIMESTAMP WITHOUT TIME ZONE')
4+
cr.execute('''
5+
UPDATE runbot_build_error_link SET batch_id = batch.id, batch_date = batch.create_date
6+
FROM runbot_batch as batch
7+
JOIN runbot_build build on build.create_batch_id = batch.id
8+
JOIN runbot_build_error_link as link on link.build_id = build.id
9+
''')

runbot/models/build_error.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,8 @@ class BuildErrorLink(models.Model):
3939
build_id = fields.Many2one('runbot.build', required=True, index=True)
4040
error_content_id = fields.Many2one('runbot.build.error.content', required=True, index=True, ondelete='cascade')
4141
log_date = fields.Datetime(string='Log date')
42+
batch_id = fields.Many2one('runbot.batch', related='build_id.create_batch_id', string='Batch', store=True, readonly=True)
43+
batch_date = fields.Datetime(related='batch_id.create_date', string='Batch date', store=True, readonly=True)
4244
host = fields.Char(related='build_id.host')
4345
dest = fields.Char(related='build_id.dest')
4446
version_id = fields.Many2one(related='build_id.version_id')
@@ -75,8 +77,8 @@ def _compute_seen(self):
7577
if error_link_ids:
7678
first_error_link = error_link_ids[0]
7779
last_error_link = error_link_ids[-1]
78-
record.first_seen_date = first_error_link.log_date
79-
record.last_seen_date = last_error_link.log_date
80+
record.first_seen_date = first_error_link.batch_date
81+
record.last_seen_date = last_error_link.batch_date
8082
record.first_seen_build_id = first_error_link.build_id
8183
record.last_seen_build_id = last_error_link.build_id
8284
record.build_count = len(error_link_ids.build_id)

runbot/tests/test_build_error.py

Lines changed: 37 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -39,9 +39,10 @@ def setUpClass(cls):
3939
cls.x_test_class = cls.env['ir.model.fields'].search([('name', '=', 'x_test_class'), ('model_id', '=', model)], limit=1)
4040
cls.x_test_method = cls.env['ir.model.fields'].search([('name', '=', 'x_test_method'), ('model_id', '=', model)], limit=1)
4141

42-
def create_test_build(self, vals):
42+
def create_test_build(self, vals, params_vals=None):
43+
params = self.create_params(params_vals or {})
4344
create_vals = {
44-
'params_id': self.base_params.id,
45+
'params_id': params.id,
4546
'port': '1234',
4647
'local_result': 'ok'
4748
}
@@ -380,48 +381,51 @@ def test_build_scan(self):
380381

381382
def test_seen_date(self):
382383
# create all the records before the tests to evaluate compute dependencies
383-
build_a = self.create_test_build({'local_result': 'ok', 'local_state': 'testing'})
384-
first_seen_date = fields.Datetime.from_string('2023-08-29 00:46:21')
385-
self.create_log({'create_date': first_seen_date, 'message': RTE_ERROR, 'build_id': build_a.id})
386-
387-
build_b = self.create_test_build({'local_result': 'ok', 'local_state': 'testing'})
388-
new_seen_date = fields.Datetime.from_string('2023-08-29 02:46:21')
389-
self.create_log({'create_date': new_seen_date, 'message': RTE_ERROR, 'build_id': build_b.id})
390-
391-
build_c = self.create_test_build({'local_result': 'ok', 'local_state': 'testing'})
392-
child_seen_date = fields.Datetime.from_string('2023-09-01 12:00:00')
393-
self.create_log({'create_date': child_seen_date, 'message': 'Fail: foo bar error', 'build_id': build_c.id})
384+
trigger = self.Trigger.create({
385+
'name': 'test-trigger',
386+
'batch_dependent': True,
387+
'project_id': self.project.id,
388+
'config_id': self.default_config.id,
389+
})
390+
batch_date = fields.Datetime.from_string('2023-08-28 19:00:01')
391+
log_date = fields.Datetime.from_string('2023-08-29 00:46:21')
392+
self.fist_batch = self.Batch.create({
393+
'bundle_id': self.dev_bundle.id,
394+
})
395+
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
396+
self.fist_batch.invalidate_recordset()
397+
self.assertEqual(self.fist_batch.create_date, batch_date, 'Batch create date should be set')
394398

395-
build_d = self.create_test_build({'local_result': 'ok', 'local_state': 'testing'})
396-
new_child_seen_date = fields.Datetime.from_string('2023-09-02 12:00:00')
397-
self.create_log({'create_date': new_child_seen_date, 'message': 'Fail: foo bar error', 'build_id': build_d.id})
399+
build_a = self.create_test_build({'local_result': 'ok', 'local_state': 'testing'}, {'create_batch_id': self.fist_batch.id, 'trigger_id': trigger.id})
400+
self.assertEqual(build_a.create_batch_id, self.fist_batch, 'Build should be linked to the batch')
401+
self.create_log({'create_date': log_date, 'message': RTE_ERROR, 'build_id': build_a.id})
398402

399403
build_a._parse_logs()
400404
build_error_a = build_a.build_error_ids
401-
self.assertEqual(build_error_a.first_seen_date, first_seen_date)
402405
self.assertEqual(build_error_a.first_seen_build_id, build_a)
403-
self.assertEqual(build_error_a.last_seen_date, first_seen_date)
406+
self.assertEqual(build_error_a.first_seen_build_id.create_batch_id, self.fist_batch)
407+
self.assertEqual(build_error_a.first_seen_date, batch_date)
404408
self.assertEqual(build_error_a.last_seen_build_id, build_a)
409+
self.assertEqual(build_error_a.last_seen_build_id.create_batch_id, self.fist_batch)
410+
self.assertEqual(build_error_a.last_seen_date, batch_date)
411+
412+
new_batch_date = fields.Datetime.from_string('2023-08-29 19:00:01')
413+
new_log_date = fields.Datetime.from_string('2023-08-30 00:48:21')
414+
self.new_batch = self.Batch.create({
415+
'bundle_id': self.dev_bundle.id,
416+
})
417+
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
418+
self.new_batch.invalidate_recordset()
419+
self.assertEqual(self.new_batch.create_date, new_batch_date, 'New batch create date should be set')
420+
421+
build_b = self.create_test_build({'local_result': 'ok', 'local_state': 'testing'}, {'create_batch_id': self.new_batch.id, 'trigger_id': trigger.id})
422+
self.create_log({'create_date': new_log_date, 'message': RTE_ERROR, 'build_id': build_b.id})
405423

406424
# a new build with the same error should be the last seen
407425
build_b._parse_logs()
408-
self.assertEqual(build_error_a.last_seen_date, new_seen_date)
426+
self.assertEqual(build_error_a.last_seen_date, new_batch_date)
409427
self.assertEqual(build_error_a.last_seen_build_id, build_b)
410428

411-
# a new build error is linked to the current one
412-
build_c._parse_logs()
413-
build_error_c = build_c.build_error_ids
414-
self.assertNotIn(build_c, build_error_a.build_ids)
415-
build_error_a._merge(build_error_c)
416-
self.assertIn(build_c, build_error_a.build_ids)
417-
self.assertEqual(build_error_a.last_seen_date, child_seen_date)
418-
self.assertEqual(build_error_a.last_seen_build_id, build_c)
419-
420-
# a new build appears in the linked error
421-
build_d._parse_logs()
422-
self.assertEqual(build_error_a.last_seen_date, new_child_seen_date)
423-
self.assertEqual(build_error_a.last_seen_build_id, build_d)
424-
425429
def test_build_error_links(self):
426430
build_a = self.create_test_build({'local_result': 'ko'})
427431
build_b = self.create_test_build({'local_result': 'ko'})

runbot/views/build_error_views.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,6 @@
3434
</group>
3535
<group>
3636
<group name="fixer_info" string="Fixing" col="2">
37-
<field name="breaking_bundle_url" invisible="not breaking_pr_id"/>
3837
<field name="responsible"/>
3938
<field name="customer"/>
4039
<field name="team_id"/>
@@ -50,6 +49,7 @@
5049
<field name="random"/>
5150
<field name="breaking_pr_id"/>
5251
<field name="breaking_pr_url" widget="pull_request_url" invisible="not breaking_pr_id"/>
52+
<field name="breaking_bundle_url" invisible="not breaking_pr_id"/>
5353
<field name="first_seen_date" widget="frontend_url" options="{'link_field': 'first_seen_build_id'}"/>
5454
<field name="last_seen_date" widget="frontend_url" options="{'link_field': 'last_seen_build_id'}"/>
5555
<field name="first_seen_build_id" invisible="True"/>

0 commit comments

Comments
 (0)