[IMP] runbot_merge: provide for statuses being only on PRs or stagings

Requirement for odoo/runbot#376: one can't expect there being someone
to override CI checks on stagings, so it only makes sense for checks
on PRs, which in turns requires that there could be checks only
required on PRs.

Could also be useful for features like incremental linting /
formatting, we may want to apply checks on PRs which filter on the
lines modified, but not require the entire software be reformatted at
once.
This commit is contained in:
Xavier Morel 2020-07-10 12:55:39 +02:00 committed by xmo-odoo
parent be228a5681
commit 5c1caa1a18
3 changed files with 34 additions and 4 deletions

View File

@ -223,11 +223,22 @@ class StatusConfiguration(models.Model):
context = fields.Char(required=True)
repo_id = fields.Many2one('runbot_merge.repository', required=True, ondelete='cascade')
branch_ids = fields.Many2many('runbot_merge.branch', 'runbot_merge_repository_status_branch', 'status_id', 'branch_id')
prs = fields.Boolean(string="Applies to pull requests", default=True)
stagings = fields.Boolean(string="Applies to stagings", default=True)
def _for_branch(self, branch):
assert branch._name == 'runbot_merge.branch', \
f'Expected branch, got {branch}'
return self.filtered(lambda st: not st.branch_ids or branch in st.branch_ids)
def _for_pr(self, pr):
assert pr._name == 'runbot_merge.pull_requests', \
f'Expected pull request, got {pr}'
return self._for_branch(pr.target).filtered('prs')
def _for_staging(self, staging):
assert staging._name == 'runbot_merge.stagings', \
f'Expected staging, got {staging}'
return self._for_branch(staging.target).filtered('stagings')
class Repository(models.Model):
_name = _description = 'runbot_merge.repository'
_order = 'sequence, id'
@ -699,7 +710,7 @@ class PullRequests(models.Model):
pr.statuses = pprint.pformat(statuses)
st = 'success'
for ci in pr.repository.status_ids._for_branch(pr.target):
for ci in pr.repository.status_ids._for_pr(pr):
v = state_(statuses, ci.context) or 'pending'
if v in ('error', 'failure'):
st = 'failure'
@ -968,7 +979,7 @@ class PullRequests(models.Model):
# targets
failed = self.browse(())
for pr in self:
required = pr.repository.status_ids._for_branch(pr.target).mapped('context')
required = pr.repository.status_ids._for_pr(pr).mapped('context')
success = True
for ci in required:
@ -1547,7 +1558,7 @@ class Stagings(models.Model):
}
# maps commits to the statuses they need
required_statuses = [
(head, repos[repo].status_ids._for_branch(s.target).mapped('context'))
(head, repos[repo].status_ids._for_staging(s).mapped('context'))
for repo, head in json.loads(s.heads).items()
if not repo.endswith('^')
]

View File

@ -16,6 +16,8 @@ def repo(env, project, make_repo, users, setreviewers):
'context': 'lint',
'branch_ids': [(4, project.branch_ids.id, False)]
}),
(0, 0, {'context': 'pr', 'stagings': False}),
(0, 0, {'context': 'staging', 'prs': False}),
]
})],
})
@ -41,7 +43,10 @@ def test_status_applies(env, repo, config):
repo.post_status(c, 'success', 'ci')
env.run_crons('runbot_merge.process_updated_commits')
assert pr_id.state == 'opened'
with repo:
repo.post_status(c, 'success', 'pr')
env.run_crons('runbot_merge.process_updated_commits')
assert pr_id.state == 'opened'
with repo:
repo.post_status(c, 'success', 'lint')
env.run_crons('runbot_merge.process_updated_commits')
@ -60,6 +65,10 @@ def test_status_applies(env, repo, config):
with repo:
repo.post_status('staging.master', 'success', 'lint')
env.run_crons('runbot_merge.process_updated_commits')
assert st.state == 'pending'
with repo:
repo.post_status('staging.master', 'success', 'staging')
env.run_crons('runbot_merge.process_updated_commits')
assert st.state == 'success'
def test_status_skipped(env, project, repo, config):
@ -82,6 +91,10 @@ def test_status_skipped(env, project, repo, config):
with repo:
repo.post_status(c, 'success', 'ci')
env.run_crons('runbot_merge.process_updated_commits')
assert pr_id.state == 'opened'
with repo:
repo.post_status(c, 'success', 'pr')
env.run_crons('runbot_merge.process_updated_commits')
assert pr_id.state == 'validated'
with repo:
@ -90,6 +103,10 @@ def test_status_skipped(env, project, repo, config):
st = env['runbot_merge.stagings'].search([])
assert st.state == 'pending'
with repo:
repo.post_status('staging.maintenance', 'success', 'staging')
env.run_crons('runbot_merge.process_updated_commits')
assert st.state == 'pending'
with repo:
repo.post_status('staging.maintenance', 'success', 'ci')
env.run_crons('runbot_merge.process_updated_commits')

View File

@ -65,6 +65,8 @@
<tree editable="bottom">
<field name="context"/>
<field name="branch_ids" widget="many2many_tags"/>
<field name="prs"/>
<field name="stagings"/>
</tree>
</field>
</sheet>