[IMP] runbot_merge: allow only freezing a subset of a project

- add flag to not select repos for freezing
- allow removing more repositories from the wizard
- when performing the freeze, only create branches for the selected
  repos
This commit is contained in:
Xavier Morel 2022-02-07 15:15:13 +01:00
parent 1add3d4854
commit e2887a7473
6 changed files with 101 additions and 8 deletions

View File

@ -9,9 +9,9 @@
'data/merge_cron.xml',
'views/res_partner.xml',
'views/runbot_merge_project.xml',
'models/project_freeze/views.xml',
'views/mergebot.xml',
'views/templates.xml',
'models/project_freeze/views.xml',
],
'post_load': 'enable_sentry',
'pre_init_hook': '_check_citext',

View File

@ -115,6 +115,10 @@ class Project(models.Model):
w = Freeze.search([('project_id', '=', self.id)]) or Freeze.create({
'project_id': self.id,
'branch_name': self._next_freeze(),
'release_pr_ids': [(0, 0, {'repository_id': repo.id}) for repo in self.repo_ids]
'release_pr_ids': [
(0, 0, {'repository_id': repo.id})
for repo in self.repo_ids
if repo.freeze
]
})
return w.action_open()

View File

@ -97,7 +97,8 @@ class FreezeWizard(models.Model):
# create new branch on every repository
errors = []
repository = None
for repository in project_id.repo_ids:
for rel in self.release_pr_ids:
repository = rel.repository_id
gh = repository.github()
# annoyance: can't directly alias a ref to an other ref, need to
# resolve the "old" branch explicitely
@ -117,11 +118,11 @@ class FreezeWizard(models.Model):
# if an error occurred during creation, try to clean up then raise error
if errors:
for r in project_id.repo_ids:
if r == repository:
for r in self.release_pr_ids:
if r.repository_id == repository:
break
deletion = r.github().delete(f'git/refs/heads/{self.branch_name}')
deletion = r.repository_id.github().delete(f'git/refs/heads/{self.branch_name}')
if not deletion.ok:
errors.append(f"Consequently unable to delete branch {self.branch_name} of repository {r.name}.")
time.sleep(1)
@ -166,6 +167,11 @@ class ReleasePullRequest(models.Model):
return super().write(vals)
class RepositoryFreeze(models.Model):
_inherit = 'runbot_merge.repository'
freeze = fields.Boolean(required=True, default=True,
help="Freeze this repository by default")
@enum.unique
class Colors(enum.IntEnum):
No = 0

View File

@ -25,7 +25,7 @@
<group>
<group colspan="2">
<field name="release_pr_ids" nolabel="1">
<tree editable="bottom" create="false" unlink="false">
<tree editable="bottom" create="false">
<field name="repository_id" readonly="1"/>
<field name="pr_id" options="{'no_create': True}"/>
</tree>
@ -49,4 +49,15 @@
</form>
</field>
</record>
<record id="runbot_merge_repository_freeze" model="ir.ui.view">
<field name="name">Add freeze field to repo form</field>
<field name="model">runbot_merge.repository</field>
<field name="inherit_id" ref="form_repository"/>
<field name="arch" type="xml">
<field name="branch_filter" position="after">
<field name="freeze"/>
</field>
</field>
</record>
</odoo>

View File

@ -1,7 +1,7 @@
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
access_runbot_merge_project_admin,Admin access to project,model_runbot_merge_project,runbot_merge.group_admin,1,1,1,1
access_runbot_merge_project_freeze,Admin access to freeze wizard,model_runbot_merge_project_freeze,runbot_merge.group_admin,1,1,0,0
access_runbot_merge_project_freeze_prs,Admin access to freeze wizard prs,model_runbot_merge_project_freeze_prs,runbot_merge.group_admin,1,1,0,0
access_runbot_merge_project_freeze_prs,Admin access to freeze wizard prs,model_runbot_merge_project_freeze_prs,runbot_merge.group_admin,1,1,0,1
access_runbot_merge_repository_admin,Admin access to repo,model_runbot_merge_repository,runbot_merge.group_admin,1,1,1,1
access_runbot_merge_repository_status_admin,Admin access to repo statuses,model_runbot_merge_repository_status,runbot_merge.group_admin,1,1,1,1
access_runbot_merge_branch_admin,Admin access to branches,model_runbot_merge_branch,runbot_merge.group_admin,1,1,1,1

1 id name model_id:id group_id:id perm_read perm_write perm_create perm_unlink
2 access_runbot_merge_project_admin Admin access to project model_runbot_merge_project runbot_merge.group_admin 1 1 1 1
3 access_runbot_merge_project_freeze Admin access to freeze wizard model_runbot_merge_project_freeze runbot_merge.group_admin 1 1 0 0
4 access_runbot_merge_project_freeze_prs Admin access to freeze wizard prs model_runbot_merge_project_freeze_prs runbot_merge.group_admin 1 1 0 0 1
5 access_runbot_merge_repository_admin Admin access to repo model_runbot_merge_repository runbot_merge.group_admin 1 1 1 1
6 access_runbot_merge_repository_status_admin Admin access to repo statuses model_runbot_merge_repository_status runbot_merge.group_admin 1 1 1 1
7 access_runbot_merge_branch_admin Admin access to branches model_runbot_merge_branch runbot_merge.group_admin 1 1 1 1

View File

@ -1234,3 +1234,75 @@ def test_freeze_complete(env, project, repo_a, repo_b, repo_c, users, config):
assert c_c.message.startswith('Release 1.1 (C)')
assert repo_c.read_tree(c_c) == {'f': '2', 'version': ''}
assert repo_c.commit(c_c.parents[0]).parents[0] == masters[2]
def test_freeze_subset(env, project, repo_a, repo_b, repo_c, users, config):
"""It should be possible to only freeze a subset of a project when e.g. one
of the repository is managed differently than the rest and has
non-synchronous releases.
- it should be possible to mark repositories as non-freezed (just opted out
of the entire thing), in which case no freeze PRs should be asked of them
- it should be possible to remove repositories from the freeze wizard
- repositories which are not in the freeze wizard should just not be frozen
To do things correctly that should probably match with the branch filters
and stuff, but that's a configuration concern.
"""
# have a project with 3 repos, and two branches (1.0 and master)
project.branch_ids = [
(1, project.branch_ids.id, {'sequence': 1}),
(0, 0, {'name': '1.0', 'sequence': 2}),
]
masters = []
for r in [repo_a, repo_b, repo_c]:
with r:
[root, _] = r.make_commits(
None,
Commit('base', tree={'version': '', 'f': '0'}),
Commit('release 1.0', tree={'version': '1.0'} if r is repo_a else None),
ref='heads/1.0'
)
masters.extend(r.make_commits(root, Commit('other', tree={'f': '1'}), ref='heads/master'))
with repo_a:
repo_a.make_commits(
masters[0],
Commit('Release 1.1', tree={'version': '1.1'}),
ref='heads/release-1.1'
)
pr_rel_a = repo_a.make_pr(target='master', head='release-1.1')
# the third repository we opt out of freezing
project.repo_ids.filtered(lambda r: r.name == repo_c.name).freeze = False
env.run_crons() # process the PRs
# open the freeze wizard
w = project.action_prepare_freeze()
w_id = env[w['res_model']].browse([w['res_id']])
# check that there are only rels for repos A and B
assert w_id.mapped('release_pr_ids.repository_id.name') == [repo_a.name, repo_b.name]
# remove B from the set
b_id = w_id.release_pr_ids.filtered(lambda r: r.repository_id.name == repo_b.name)
w_id.write({'release_pr_ids': [(3, b_id.id, 0)]})
assert len(w_id.release_pr_ids) == 1
# set lone release PR
w_id.release_pr_ids.pr_id = to_pr(env, pr_rel_a).id
assert not w_id.errors
w_id.action_freeze()
assert not w_id.exists()
assert repo_a.commit('1.1'), "should have created branch in repo A"
try:
repo_b.commit('1.1')
pytest.fail("should *not* have created branch in repo B")
except AssertionError:
...
try:
repo_c.commit('1.1')
pytest.fail("should *not* have created branch in repo C")
except AssertionError:
...
# can't stage because we (wilfully) don't have branches 1.1 in repos B and C