[IMP] runbot_merge, forwardport: unify tagging

Genericise runbot_merge's tagging (move states to the "UI" but only
store / manage actual tags), and remove forwardport.tagging as it's
now redundant.

Closes #232
This commit is contained in:
Xavier Morel 2020-03-10 13:36:46 +01:00
parent 3918d266fa
commit e82de3136b
4 changed files with 26 additions and 87 deletions

View File

@ -17,15 +17,6 @@
<field name="perm_write">1</field>
<field name="perm_unlink">1</field>
</record>
<record id="access_forwardport_tagging_admin" model="ir.model.access">
<field name="name">Admin access to tagging</field>
<field name="model_id" ref="model_forwardport_tagging"/>
<field name="group_id" ref="runbot_merge.group_admin"/>
<field name="perm_read">1</field>
<field name="perm_create">1</field>
<field name="perm_write">1</field>
<field name="perm_unlink">1</field>
</record>
<record id="access_forwardport_branch_remover_admin" model="ir.model.access">
<field name="name">Admin access to branch remover</field>
<field name="model_id" ref="model_forwardport_branch_remover"/>
@ -36,14 +27,6 @@
<field name="perm_unlink">1</field>
</record>
<record id="access_forwardport_tagging" model="ir.model.access">
<field name="name">No normal access to tagging</field>
<field name="model_id" ref="model_forwardport_tagging"/>
<field name="perm_read">1</field>
<field name="perm_create">0</field>
<field name="perm_write">0</field>
<field name="perm_unlink">0</field>
</record>
<record id="access_forwardport_batches" model="ir.model.access">
<field name="name">No normal access to batches</field>
<field name="model_id" ref="model_forwardport_batches"/>

View File

@ -83,30 +83,6 @@ class Project(models.Model):
if not project.fp_github_email:
raise UserError(_("The forward-port bot needs a primary email set up."))
def _send_feedback(self):
super()._send_feedback()
ghs = {}
to_remove = []
for f in self.env['forwardport.tagging'].search([]):
repo = f.repository
gh = ghs.get(repo)
if not gh:
gh = ghs[repo] = repo.github()
try:
gh('POST', 'issues/{}/labels'.format(f.pull_request), json={
'labels': json.loads(f.to_add)
})
except Exception:
_logger.exception(
"Error while trying to add the tags %s to %s#%s",
f.to_add, repo.name, f.pull_request
)
else:
to_remove.append(f.id)
if to_remove:
self.env['forwardport.tagging'].browse(to_remove).unlink()
def write(self, vals):
Branches = self.env['runbot_merge.branch']
# check on branches both active and inactive so disabling branches doesn't
@ -722,11 +698,10 @@ This PR targets %s and is part of the forward-port chain. Further PRs will be cr
labels = ['forwardport']
if has_conflicts:
labels.append('conflict')
self.env['forwardport.tagging'].create({
self.env['runbot_merge.pull_requests.tagging'].create({
'repository': new_pr.repository.id,
'pull_request': new_pr.number,
'to_add': json.dumps(labels),
'token_field': 'fp_github_token',
'tags_add': labels,
})
# batch the PRs so _validate can perform the followup FP properly
@ -1016,18 +991,6 @@ class Feedback(models.Model):
token_field = fields.Selection(selection_add=[('fp_github_token', 'Forwardport Bot')])
class Tagging(models.Model):
_name = 'forwardport.tagging'
_description = "ad-hoc forwardport tagging commands"
token_field = fields.Selection([
('github_token', 'Mergebot'),
('fp_github_token', 'Forwardport Bot'),
], required=True)
repository = fields.Many2one('runbot_merge.repository', required=True)
pull_request = fields.Integer(string="PR number")
to_add = fields.Char(string="JSON-encoded array of labels to add")
def git(directory): return Repo(directory, check=True)
class Repo:
def __init__(self, directory, **config):

View File

@ -166,13 +166,10 @@ class GH(object):
def close(self, pr):
self('PATCH', 'pulls/{}'.format(pr), json={'state': 'closed'})
def change_tags(self, pr, to_):
def change_tags(self, pr, remove, add):
labels_endpoint = 'issues/{}/labels'.format(pr)
from .models.pull_requests import _TAGS
mergebot_tags = set.union(*_TAGS.values())
tags_before = {label['name'] for label in self('GET', labels_endpoint).json()}
# remove all mergebot tags from the PR, then add just the ones which should be set
tags_after = (tags_before - mergebot_tags) | to_
tags_after = (tags_before - remove) | add
# replace labels entirely
self('PUT', labels_endpoint, json={'labels': list(tags_after)})

View File

@ -89,26 +89,27 @@ class Project(models.Model):
t.repository as repo_id,
t.pull_request as pr_number,
array_agg(t.id) as ids,
(array_agg(t.state_from ORDER BY t.id))[1] as state_from,
(array_agg(t.state_to ORDER BY t.id DESC))[1] as state_to
array_agg(t.tags_remove::json) as to_remove,
array_agg(t.tags_add::json) as to_add
FROM runbot_merge_pull_requests_tagging t
GROUP BY t.repository, t.pull_request
""")
to_remove = []
for repo_id, pr, ids, from_, to_ in self.env.cr.fetchall():
for repo_id, pr, ids, remove, add in self.env.cr.fetchall():
repo = Repos.browse(repo_id)
to_tags = _TAGS[to_ or False]
gh = ghs.get(repo)
if not gh:
gh = ghs[repo] = repo.github()
remove = set().union(*remove)
add = set().union(*add)
try:
gh.change_tags(pr, to_tags)
gh.change_tags(pr, remove, add)
except Exception:
_logger.exception(
"Error while trying to change the tags of %s#%s from %s to %s",
repo.name, pr, _TAGS[from_ or False], to_tags,
repo.name, pr.display_name, remove, add,
)
else:
to_remove.extend(ids)
@ -1324,6 +1325,7 @@ _TAGS['staged'] = _TAGS['ready'] | {'merging 👷'}
_TAGS['merged'] = _TAGS['ready'] | {'merged 🎉'}
_TAGS['error'] = _TAGS['opened'] | {'error 🙅'}
_TAGS['closed'] = _TAGS['opened'] | {'closed 💔'}
ALL_TAGS = set.union(*_TAGS.values())
class Tagging(models.Model):
"""
@ -1341,26 +1343,20 @@ class Tagging(models.Model):
# being deleted (retargeted to non-managed branches)
pull_request = fields.Integer()
state_from = fields.Selection([
('opened', 'Opened'),
('closed', 'Closed'),
('validated', 'Validated'),
('approved', 'Approved'),
('ready', 'Ready'),
('staged', 'Staged'),
('merged', 'Merged'),
('error', 'Error'),
])
state_to = fields.Selection([
('opened', 'Opened'),
('closed', 'Closed'),
('validated', 'Validated'),
('approved', 'Approved'),
('ready', 'Ready'),
('staged', 'Staged'),
('merged', 'Merged'),
('error', 'Error'),
])
tags_remove = fields.Char(required=True, default='[]')
tags_add = fields.Char(required=True, defualt='[]')
def create(self, values):
values.pop('state_from', None)
state_to = values.pop('state_to', None)
if state_to:
values['tags_remove'] = ALL_TAGS
values['tags_add'] = _TAGS[state_to]
if not isinstance(values.get('tags_remove', ''), str):
values['tags_remove'] = json.dumps(list(values['tags_remove']))
if not isinstance(values.get('tags_add', ''), str):
values['tags_add'] = json.dumps(list(values['tags_add']))
return super().create(values)
class Feedback(models.Model):
""" Queue of feedback comments to send to PR users