diff --git a/runbot_merge/models/project.py b/runbot_merge/models/project.py index e828d29b..57fc1a33 100644 --- a/runbot_merge/models/project.py +++ b/runbot_merge/models/project.py @@ -51,6 +51,15 @@ class Project(models.Model): freeze_id = fields.Many2one('runbot_merge.project.freeze', compute='_compute_freeze') freeze_reminder = fields.Text() + uniquifier = fields.Boolean( + default=True, + help="Whether to add a uniquifier commit on repositories without PRs" + " during staging. The lack of uniquifier can lead to CI conflicts" + " as github works off of commits, so it's possible for an" + " unrelated build to trigger a failure if somebody is a dummy and" + " includes repos they have no commit for." + ) + @api.depends('github_token') def _compute_identity(self): s = requests.Session() diff --git a/runbot_merge/models/stagings_create.py b/runbot_merge/models/stagings_create.py index 42b1aad5..7e083e0e 100644 --- a/runbot_merge/models/stagings_create.py +++ b/runbot_merge/models/stagings_create.py @@ -90,23 +90,11 @@ def try_staging(branch: Branch) -> Optional[Stagings]: heads = [] commits = [] for repo, it in staging_state.items(): - if it.head != original_heads[repo]: - # if we staged something for that repo, just create a record for - # that commit, or flag existing one as to-recheck in case there are - # already statuses we want to propagate to the staging or something - env.cr.execute( - "INSERT INTO runbot_merge_commit (sha, to_check, statuses) " - "VALUES (%s, true, '{}') " - "ON CONFLICT (sha) DO UPDATE SET to_check=true " - "RETURNING id", - [it.head] - ) - [commit] = [head] = env.cr.fetchone() - else: - # if we didn't stage anything for that repo, create a dummy commit - # (with a uniquifier to ensure we don't hit a previous version of - # the same) to ensure the staging head is new and we're building - # everything + if it.head == original_heads[repo] and branch.project_id.uniquifier: + # if we didn't stage anything for that repo and uniquification is + # enabled, create a dummy commit with a uniquifier to ensure we + # don't hit a previous version of the same to ensure the staging + # head is new and we're building everything project = branch.project_id uniquifier = base64.b64encode(os.urandom(12)).decode('ascii') dummy_head = it.repo.with_config(check=True).commit_tree( @@ -135,6 +123,18 @@ For-Commit-Id: {it.head} ) ([commit], [head]) = env.cr.fetchall() it.head = dummy_head + else: + # otherwise just create a record for that commit, or flag existing + # one as to-recheck in case there are already statuses we want to + # propagate to the staging or something + env.cr.execute( + "INSERT INTO runbot_merge_commit (sha, to_check, statuses) " + "VALUES (%s, true, '{}') " + "ON CONFLICT (sha) DO UPDATE SET to_check=true " + "RETURNING id", + [it.head] + ) + [commit] = [head] = env.cr.fetchone() heads.append(fields.Command.create({ 'repository_id': repo.id, diff --git a/runbot_merge/tests/test_multirepo.py b/runbot_merge/tests/test_multirepo.py index 3ba105ca..dbae165c 100644 --- a/runbot_merge/tests/test_multirepo.py +++ b/runbot_merge/tests/test_multirepo.py @@ -87,9 +87,11 @@ def make_branch(repo, name, message, tree, protect=True): repo.protect(name) return c -def test_stage_one(env, project, repo_a, repo_b, config): +@pytest.mark.parametrize('uniquifier', [False, True]) +def test_stage_one(env, project, repo_a, repo_b, config, uniquifier): """ First PR is non-matched from A => should not select PR from B """ + project.uniquifier = uniquifier project.batch_limit = 1 with repo_a: @@ -112,7 +114,10 @@ def test_stage_one(env, project, repo_a, repo_b, config): assert pra_id.state == 'ready' assert pra_id.staging_id assert repo_a.commit('staging.master').message.startswith('commit_A_00') - assert repo_b.commit('staging.master').message.startswith('force rebuild') + if uniquifier: + assert repo_b.commit('staging.master').message.startswith('force rebuild') + else: + assert repo_b.commit('staging.master').message == 'initial' prb_id = to_pr(env, pr_b) assert prb_id.state == 'ready' diff --git a/runbot_merge/views/runbot_merge_project.xml b/runbot_merge/views/runbot_merge_project.xml index 4795b502..5aa49d47 100644 --- a/runbot_merge/views/runbot_merge_project.xml +++ b/runbot_merge/views/runbot_merge_project.xml @@ -32,6 +32,7 @@ +