mirror of
https://github.com/odoo/runbot.git
synced 2025-03-15 23:45:44 +07:00
[ADD] runbot_merge: option to disable staging without cron
Because the mergebot crons are on such a tight scheduling, and just them finding out they have nothing to do can take a while, disabling them can be a chore. Disabling staging via the project is much less likely to cause issues as the projects don't normally (or ever?) get exclusively locked, so they can generally be written to at any moment. Furthermore, if we ever get in a situation where we have multiple active projects (not really the case currently, we have multiple projects but only one is really active) it's less disruptive to disable stagings on a single specific project. Fixes #860
This commit is contained in:
parent
d4fa1fd353
commit
9f54e6f209
14
runbot_merge/changelog/2023-12/staging-shutdown.md
Normal file
14
runbot_merge/changelog/2023-12/staging-shutdown.md
Normal file
@ -0,0 +1,14 @@
|
||||
ADD: stagings can now be disabled on a per-project basis
|
||||
|
||||
Currently stopping stagings requires stopping the staging cron(s), which causes
|
||||
several issues:
|
||||
|
||||
- the staging cron runs very often, so it can be difficult to find a window to
|
||||
deactivate it (as the cron runner acquires an exclusive lock on the cron)
|
||||
- the staging cron is global, so it does not disable staging only on the
|
||||
problematic project (to say nothing of branch) but on all of them
|
||||
|
||||
The latter is not currently a huge issue as only one of the mergebot-tracked
|
||||
projects is ultra active (spreadsheet activity is on the order of a few
|
||||
single-PR stagings a day), but the former is really annoying when trying to
|
||||
stop runaway broken stagings.
|
@ -24,6 +24,7 @@ class Project(models.Model):
|
||||
help="Branches of all project's repos which are managed by the merge bot. Also "\
|
||||
"target branches of PR this project handles."
|
||||
)
|
||||
staging_enabled = fields.Boolean(default=True)
|
||||
|
||||
ci_timeout = fields.Integer(
|
||||
default=60, required=True, group_operator=None,
|
||||
@ -141,6 +142,7 @@ class Project(models.Model):
|
||||
('active_staging_id', '=', False),
|
||||
('active', '=', True),
|
||||
('staging_enabled', '=', True),
|
||||
('project_id.staging_enabled', '=', True),
|
||||
]):
|
||||
try:
|
||||
with self.env.cr.savepoint(), \
|
||||
|
@ -1716,7 +1716,7 @@ class Stagings(models.Model):
|
||||
def cancel(self, reason, *args):
|
||||
self = self.filtered('active')
|
||||
if not self:
|
||||
return
|
||||
return False
|
||||
|
||||
_logger.info("Cancelling staging %s: " + reason, self, *args)
|
||||
self.mapped('batch_ids').write({'active': False})
|
||||
@ -1725,6 +1725,7 @@ class Stagings(models.Model):
|
||||
'state': 'cancelled',
|
||||
'reason': reason % args,
|
||||
})
|
||||
return True
|
||||
|
||||
def fail(self, message, prs=None):
|
||||
_logger.info("Staging %s failed: %s", self, message)
|
||||
@ -1745,6 +1746,7 @@ class Stagings(models.Model):
|
||||
'state': 'failure',
|
||||
'reason': message,
|
||||
})
|
||||
return True
|
||||
|
||||
def try_splitting(self):
|
||||
batches = len(self.batch_ids)
|
||||
|
@ -0,0 +1,42 @@
|
||||
import pytest
|
||||
|
||||
from utils import Commit, to_pr
|
||||
|
||||
@pytest.fixture
|
||||
def repo(env, project, make_repo, users, setreviewers):
|
||||
r = make_repo('repo')
|
||||
project.write({'repo_ids': [(0, 0, {
|
||||
'name': r.name,
|
||||
'group_id': False,
|
||||
'required_statuses': 'default',
|
||||
})]})
|
||||
setreviewers(*project.repo_ids)
|
||||
return r
|
||||
|
||||
def test_disable_staging(env, project, repo, config):
|
||||
"""In order to avoid issues of cron locking, as well as not disable staging
|
||||
for every project when trying to freeze just one of them (cough cough), a
|
||||
toggle is available on the project to skip staging for it.
|
||||
"""
|
||||
with repo:
|
||||
[m] = repo.make_commits(None, Commit("m", tree={"a": "1"}), ref="heads/master")
|
||||
|
||||
[c] = repo.make_commits(m, Commit("c", tree={"a": "2"}), ref="heads/other")
|
||||
pr = repo.make_pr(title="whatever", target="master", head="other")
|
||||
pr.post_comment("hansen r+", config["role_reviewer"]['token'])
|
||||
repo.post_status(c, "success")
|
||||
env.run_crons()
|
||||
|
||||
pr_id = to_pr(env, pr)
|
||||
staging_1 = pr_id.staging_id
|
||||
assert staging_1.active
|
||||
|
||||
project.staging_enabled = False
|
||||
staging_1.cancel("because")
|
||||
|
||||
env.run_crons()
|
||||
|
||||
assert staging_1.active is False
|
||||
assert staging_1.state == "cancelled"
|
||||
assert not pr_id.staging_id.active,\
|
||||
"should not be re-staged, because staging has been disabled"
|
@ -9,7 +9,7 @@ def repo(env, project, make_repo, users, setreviewers):
|
||||
project.write({'repo_ids': [(0, 0, {
|
||||
'name': r.name,
|
||||
'group_id': False,
|
||||
'required_statuses': 'ci'
|
||||
'required_statuses': 'default'
|
||||
})]})
|
||||
setreviewers(*project.repo_ids)
|
||||
return r
|
||||
@ -26,13 +26,13 @@ def test_staging_disabled_branch(env, project, repo, config):
|
||||
[c1] = repo.make_commits(master_commit, Commit("thing", tree={'a': '2'}), ref='heads/master-thing')
|
||||
master_pr = repo.make_pr(title="whatever", target="master", head="master-thing")
|
||||
master_pr.post_comment("hansen r+", config['role_reviewer']['token'])
|
||||
repo.post_status(c1, 'success', 'ci')
|
||||
repo.post_status(c1, 'success')
|
||||
|
||||
[other_commit] = repo.make_commits(None, Commit("other", tree={'b': '1'}), ref='heads/other')
|
||||
[c2] = repo.make_commits(other_commit, Commit("thing", tree={'b': '2'}), ref='heads/other-thing')
|
||||
other_pr = repo.make_pr(title="whatever", target="other", head="other-thing")
|
||||
other_pr.post_comment("hansen r+", config['role_reviewer']['token'])
|
||||
repo.post_status(c2, 'success', 'ci')
|
||||
repo.post_status(c2, 'success')
|
||||
env.run_crons()
|
||||
|
||||
assert to_pr(env, master_pr).staging_id, \
|
||||
|
@ -32,6 +32,7 @@
|
||||
<field name="secret"/>
|
||||
</group>
|
||||
<group>
|
||||
<field name="staging_enabled" widget="boolean_toggle"/>
|
||||
<field name="uniquifier"/>
|
||||
<field name="ci_timeout"/>
|
||||
<field name="batch_limit"/>
|
||||
|
Loading…
Reference in New Issue
Block a user