From 833b4e29d0308793ea76781b5af80a328172b4c2 Mon Sep 17 00:00:00 2001 From: William Braeckman Date: Wed, 27 Nov 2024 11:04:19 +0100 Subject: [PATCH] [IMP] runbot: add configurable process delay Adds a configurable process delay on projects. It can be used to reduce or otherwise increase the time between a push and a batch starting. --- runbot/models/batch.py | 6 +++++- runbot/models/project.py | 7 +++++++ runbot/tests/__init__.py | 1 + runbot/tests/common.py | 3 +-- runbot/tests/test_batch.py | 20 ++++++++++++++++++++ runbot/tests/test_build.py | 6 ------ runbot/tests/test_build_config_step.py | 2 -- runbot/tests/test_repo.py | 1 - runbot/tests/test_upgrade.py | 8 -------- runbot/views/bundle_views.xml | 1 + 10 files changed, 35 insertions(+), 20 deletions(-) create mode 100644 runbot/tests/test_batch.py diff --git a/runbot/models/batch.py b/runbot/models/batch.py index 5df699d5..3b9b019a 100644 --- a/runbot/models/batch.py +++ b/runbot/models/batch.py @@ -109,7 +109,11 @@ class Batch(models.Model): def _process(self): processed = self.browse() for batch in self: - if batch.state == 'preparing' and batch.last_update <= fields.Datetime.now() - datetime.timedelta(seconds=60): + process_delay = batch.bundle_id.project_id.process_delay + if batch.state == 'preparing' and ( + process_delay == 0 or + batch.last_update <= fields.Datetime.now() - datetime.timedelta(seconds=process_delay) + ): batch._prepare() processed |= batch if batch.state == 'ready': diff --git a/runbot/models/project.py b/runbot/models/project.py index eba0bd8e..0235dcf9 100644 --- a/runbot/models/project.py +++ b/runbot/models/project.py @@ -1,4 +1,5 @@ from odoo import models, fields, api +from odoo.exceptions import ValidationError class Project(models.Model): @@ -22,6 +23,12 @@ class Project(models.Model): staging_prefix = fields.Char('staging branches prefix', default="staging.") hidden = fields.Boolean('Hidden', help='Hide this project from the main page') active = fields.Boolean("Active", default=True) + process_delay = fields.Integer('Process delay', default=60, required=True, help="Delay between a push and a batch starting its process.") + + @api.constrains('process_delay') + def _constraint_process_delay(self): + if any(project.process_delay < 0 for project in self): + raise ValidationError("Process delay should be positive.") @api.model_create_multi def create(self, vals_list): diff --git a/runbot/tests/__init__.py b/runbot/tests/__init__.py index 188387ca..e4410f29 100644 --- a/runbot/tests/__init__.py +++ b/runbot/tests/__init__.py @@ -1,4 +1,5 @@ from . import common +from . import test_batch from . import test_repo from . import test_build_error from . import test_branch diff --git a/runbot/tests/common.py b/runbot/tests/common.py index fbb6ceea..140304c5 100644 --- a/runbot/tests/common.py +++ b/runbot/tests/common.py @@ -64,7 +64,7 @@ class RunbotCase(TransactionCase): self.Step = self.env['runbot.build.config.step'].with_context(mail_create_nolog=True, mail_notrack=True) self.Commit = self.env['runbot.commit'] self.Runbot = self.env['runbot.runbot'] - self.project = self.env['runbot.project'].create({'name': 'Tests'}) + self.project = self.env['runbot.project'].create({'name': 'Tests', 'process_delay': 0}) self.repo_server = self.Repo.create({ 'name': 'server', 'project_id': self.project.id, @@ -251,7 +251,6 @@ class RunbotCase(TransactionCase): self.assertEqual(triggers.repo_ids + triggers.dependency_ids, self.remote_addons.repo_id + self.remote_server.repo_id) batch = self.branch_addons.bundle_id._force() - batch.last_update = fields.Datetime.now() - datetime.timedelta(seconds=60) batch._process() diff --git a/runbot/tests/test_batch.py b/runbot/tests/test_batch.py new file mode 100644 index 00000000..7cc980b4 --- /dev/null +++ b/runbot/tests/test_batch.py @@ -0,0 +1,20 @@ +from datetime import timedelta + +from odoo import fields + +from .common import RunbotCase + + +class TestBatch(RunbotCase): + + def test_process_delay(self): + self.project.process_delay = 120 + self.additionnal_setup() + + batch = self.branch_addons.bundle_id.last_batch + batch._process() + self.assertEqual(batch.state, 'preparing') + + batch.last_update = fields.Datetime.now() - timedelta(seconds=120) + batch._process() + self.assertEqual(batch.state, 'ready') diff --git a/runbot/tests/test_build.py b/runbot/tests/test_build.py index 73c2c2c5..d05a45a5 100644 --- a/runbot/tests/test_build.py +++ b/runbot/tests/test_build.py @@ -90,7 +90,6 @@ class TestBuildParams(RunbotCaseMinimalSetup): # prepare last_batch bundle = self.env['runbot.bundle'].search([('name', '=', branch_a_name), ('project_id', '=', self.project.id)]) - bundle.last_batch.last_update = fields.Datetime.now() - datetime.timedelta(seconds=60) bundle.last_batch._process() build_slot = bundle.last_batch.slot_ids.filtered(lambda rec: rec.trigger_id == self.trigger_server) self.assertEqual(build_slot.build_id.params_id.config_id, self.trigger_server.config_id) @@ -119,7 +118,6 @@ class TestBuildParams(RunbotCaseMinimalSetup): 'bundle_id': bundle.id, 'config_id': custom_config.id }) - bundle.last_batch.last_update = fields.Datetime.now() - datetime.timedelta(seconds=60) bundle.last_batch._process() build_slot = bundle.last_batch.slot_ids.filtered(lambda rec: rec.trigger_id == self.trigger_server) self.assertEqual(build_slot.build_id.params_id.config_id, custom_config) @@ -147,7 +145,6 @@ class TestBuildParams(RunbotCaseMinimalSetup): self.repo_server._update_batches() bundle = self.Bundle.search([('name', '=', branch_a_name), ('project_id', '=', self.project.id)]) batch = bundle.last_batch - batch.last_update = fields.Datetime.now() - datetime.timedelta(seconds=60) batch._process() self.assertEqual(batch.slot_ids.mapped('trigger_id.name'), ['minimal_check', 'Server trigger', 'Addons trigger'], 'All three slot should have been created') minimal_check_build = batch.slot_ids.build_id @@ -616,7 +613,6 @@ class TestGc(RunbotCaseMinimalSetup): # prepare last_batch bundle_a = self.env['runbot.bundle'].search([('name', '=', branch_a_name)]) - bundle_a.last_batch.last_update = fields.Datetime.now() - datetime.timedelta(seconds=60) bundle_a.last_batch._process() # now we should have a build in pending state in the bundle @@ -631,7 +627,6 @@ class TestGc(RunbotCaseMinimalSetup): self.push_commit(self.remote_server_dev, branch_b_name, 'other subject', sha='cacad0d0') self.repo_server._update_batches() bundle_b = self.env['runbot.bundle'].search([('name', '=', branch_b_name)]) - bundle_b.last_batch.last_update = fields.Datetime.now() - datetime.timedelta(seconds=60) bundle_b.last_batch._process() @@ -651,7 +646,6 @@ class TestGc(RunbotCaseMinimalSetup): self.push_commit(self.remote_server_dev, branch_a_name, 'new subject', sha='d0cad0ca') self.repo_server._update_batches() bundle_a = self.env['runbot.bundle'].search([('name', '=', branch_a_name)]) - bundle_a.last_batch.last_update = fields.Datetime.now() - datetime.timedelta(seconds=60) bundle_a.last_batch._process() build_a_last = bundle_a.last_batch.slot_ids[0].build_id self.assertEqual(build_a_last.local_state, 'pending') diff --git a/runbot/tests/test_build_config_step.py b/runbot/tests/test_build_config_step.py index d66568af..ac96e1e8 100644 --- a/runbot/tests/test_build_config_step.py +++ b/runbot/tests/test_build_config_step.py @@ -236,7 +236,6 @@ class TestBuildConfigStepRestore(TestBuildConfigStepCommon): # setup master branch master_batch = self.master_bundle._force() with mute_logger('odoo.addons.runbot.models.batch'): - master_batch.last_update = fields.Datetime.now() - datetime.timedelta(seconds=60) master_batch._process() reference_slot = master_batch.slot_ids trigger = reference_slot.trigger_id @@ -264,7 +263,6 @@ class TestBuildConfigStepRestore(TestBuildConfigStepCommon): # create dev build dev_batch = self.dev_bundle._force() with mute_logger('odoo.addons.runbot.models.batch'): - dev_batch.last_update = fields.Datetime.now() - datetime.timedelta(seconds=60) dev_batch._process() dev_batch.base_reference_batch_id = master_batch # not tested, this is not the purpose of this test dev_build = dev_batch.slot_ids.build_id diff --git a/runbot/tests/test_repo.py b/runbot/tests/test_repo.py index 9965b44d..56dccccb 100644 --- a/runbot/tests/test_repo.py +++ b/runbot/tests/test_repo.py @@ -252,7 +252,6 @@ class TestRepo(RunbotCaseMinimalSetup): return {} self.patchers['github_patcher'].side_effect = github2 - bundle.last_batch.last_update = fields.Datetime.now() - datetime.timedelta(seconds=60) bundle.last_batch._process() self.assertEqual(last_batch.commit_link_ids.commit_id.mapped('subject'), ['Server subject', 'Addons subject']) diff --git a/runbot/tests/test_upgrade.py b/runbot/tests/test_upgrade.py index 67e8e49f..2f19536c 100644 --- a/runbot/tests/test_upgrade.py +++ b/runbot/tests/test_upgrade.py @@ -208,7 +208,6 @@ class TestUpgradeFlow(RunbotCase): # create nightly batch_nigthly = bundle._force(self.nightly_category.id) - batch_nigthly.last_update = fields.Datetime.now() - datetime.timedelta(seconds=60) batch_nigthly._process() self.assertEqual(batch_nigthly.category_id, self.nightly_category) builds_nigthly = {} @@ -235,7 +234,6 @@ class TestUpgradeFlow(RunbotCase): batch_nigthly.state = 'done' batch_weekly = bundle._force(self.weekly_category.id) - batch_weekly.last_update = fields.Datetime.now() - datetime.timedelta(seconds=60) batch_weekly._process() self.assertEqual(batch_weekly.category_id, self.weekly_category) builds_weekly = {} @@ -253,7 +251,6 @@ class TestUpgradeFlow(RunbotCase): batch_weekly.state = 'done' batch_default = bundle._force() - batch_default.last_update = fields.Datetime.now() - datetime.timedelta(seconds=60) batch_default._process() build = batch_default.slot_ids.filtered(lambda s: s.trigger_id == self.trigger_server).build_id build.local_state = 'done' @@ -273,7 +270,6 @@ class TestUpgradeFlow(RunbotCase): self.trigger_upgrade_server.flush_recordset(['upgrade_step_id']) batch = self.master_bundle._force() - batch.last_update = fields.Datetime.now() - datetime.timedelta(seconds=60) batch._process() upgrade_current_build = batch.slot_ids.filtered(lambda slot: slot.trigger_id == self.trigger_upgrade_server).build_id #host = self.env['runbot.host']._get_current() @@ -340,7 +336,6 @@ class TestUpgradeFlow(RunbotCase): }) batch = self.master_bundle._force(self.nightly_category.id) - batch.last_update = fields.Datetime.now() - datetime.timedelta(seconds=60) batch._process() upgrade_nightly = batch.slot_ids.filtered(lambda slot: slot.trigger_id == trigger_upgrade_addons_nightly).build_id #upgrade_nightly.host = host.name @@ -491,7 +486,6 @@ class TestUpgradeFlow(RunbotCase): # test_build_references batch = self.master_bundle._force() - batch.last_update = fields.Datetime.now() - datetime.timedelta(seconds=60) batch._process() upgrade_slot = batch.slot_ids.filtered(lambda slot: slot.trigger_id == self.trigger_upgrade_server) self.assertTrue(upgrade_slot) @@ -509,7 +503,6 @@ class TestUpgradeFlow(RunbotCase): self.trigger_upgrade_server.upgrade_step_id.upgrade_from_all_intermediate_version = True batch = self.master_bundle._force() - batch.last_update = fields.Datetime.now() - datetime.timedelta(seconds=60) batch._process() upgrade_build = batch.slot_ids.filtered(lambda slot: slot.trigger_id == self.trigger_upgrade_server).build_id self.assertEqual( @@ -548,7 +541,6 @@ class TestUpgradeFlow(RunbotCase): self.assertEqual(bundle_133.name, 'saas-13.3') batch13 = bundle_13._force() - batch13.last_update = fields.Datetime.now() - datetime.timedelta(seconds=60) batch13._process() upgrade_complement_build_13 = batch13.slot_ids.filtered(lambda slot: slot.trigger_id == trigger_upgrade_complement).build_id # upgrade_complement_build_13.host = host.name diff --git a/runbot/views/bundle_views.xml b/runbot/views/bundle_views.xml index 9d9f4a5b..0562a0e5 100644 --- a/runbot/views/bundle_views.xml +++ b/runbot/views/bundle_views.xml @@ -16,6 +16,7 @@ +