From 5c1caa1a18805e05ea46aa6718224eaec54c3ea9 Mon Sep 17 00:00:00 2001 From: Xavier Morel Date: Fri, 10 Jul 2020 12:55:39 +0200 Subject: [PATCH] [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. --- runbot_merge/models/pull_requests.py | 17 ++++++++++++++--- runbot_merge/tests/test_by_branch.py | 19 ++++++++++++++++++- runbot_merge/views/mergebot.xml | 2 ++ 3 files changed, 34 insertions(+), 4 deletions(-) diff --git a/runbot_merge/models/pull_requests.py b/runbot_merge/models/pull_requests.py index 8d38f047..19a6dbd7 100644 --- a/runbot_merge/models/pull_requests.py +++ b/runbot_merge/models/pull_requests.py @@ -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('^') ] diff --git a/runbot_merge/tests/test_by_branch.py b/runbot_merge/tests/test_by_branch.py index f51098aa..ea688f8b 100644 --- a/runbot_merge/tests/test_by_branch.py +++ b/runbot_merge/tests/test_by_branch.py @@ -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') diff --git a/runbot_merge/views/mergebot.xml b/runbot_merge/views/mergebot.xml index 566d5dbf..b6d27b55 100644 --- a/runbot_merge/views/mergebot.xml +++ b/runbot_merge/views/mergebot.xml @@ -65,6 +65,8 @@ + +