Skip to content

Commit a68549c

Browse files
committed
feat: enable multiple target branches for batching MRs (smarkets#267)
In order to support batch jobs in parallel, the batch branches need to be tied to the target branch name. Signed-off-by: Sascha Binckly <[email protected]>
1 parent 70ab3c8 commit a68549c

File tree

2 files changed

+28
-26
lines changed

2 files changed

+28
-26
lines changed

marge/batch_job.py

Lines changed: 24 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -15,24 +15,24 @@ class CannotBatch(Exception):
1515

1616

1717
class BatchMergeJob(MergeJob):
18-
BATCH_BRANCH_NAME = 'marge_bot_batch_merge_job'
18+
BATCH_BRANCH_NAME = 'marge_bot_batch_merge_job_'
1919

2020
def __init__(self, *, api, user, project, repo, options, merge_requests):
2121
super().__init__(api=api, user=user, project=project, repo=repo, options=options)
2222
self._merge_requests = merge_requests
2323

24-
def remove_batch_branch(self):
24+
def remove_batch_branch(self, batch_branch_name):
2525
log.info('Removing local batch branch')
2626
try:
27-
self._repo.remove_branch(BatchMergeJob.BATCH_BRANCH_NAME)
27+
self._repo.remove_branch(batch_branch_name)
2828
except git.GitError:
2929
pass
3030

31-
def close_batch_mr(self):
31+
def close_batch_mr(self, batch_branch_name):
3232
log.info('Closing batch MRs')
3333
params = {
3434
'author_id': self._user.id,
35-
'labels': BatchMergeJob.BATCH_BRANCH_NAME,
35+
'labels': batch_branch_name,
3636
'state': 'opened',
3737
'order_by': 'created_at',
3838
'sort': 'desc',
@@ -46,14 +46,14 @@ def close_batch_mr(self):
4646
log.info('Closing batch MR !%s', batch_mr.iid)
4747
batch_mr.close()
4848

49-
def create_batch_mr(self, target_branch):
50-
self.push_batch()
49+
def create_batch_mr(self, target_branch, batch_branch_name):
50+
self.push_batch(batch_branch_name)
5151
log.info('Creating batch MR')
5252
params = {
53-
'source_branch': BatchMergeJob.BATCH_BRANCH_NAME,
53+
'source_branch': batch_branch_name,
5454
'target_branch': target_branch,
5555
'title': 'Marge Bot Batch MR - DO NOT TOUCH',
56-
'labels': BatchMergeJob.BATCH_BRANCH_NAME,
56+
'labels': batch_branch_name,
5757
}
5858
batch_mr = MergeRequest.create(
5959
api=self._api,
@@ -94,9 +94,9 @@ def get_mergeable_mrs(self, merge_requests):
9494
mergeable_mrs.append(merge_request)
9595
return mergeable_mrs
9696

97-
def push_batch(self):
97+
def push_batch(self, batch_branch_name):
9898
log.info('Pushing batch branch')
99-
self._repo.push(BatchMergeJob.BATCH_BRANCH_NAME, force=True)
99+
self._repo.push(batch_branch_name, force=True)
100100

101101
def ensure_mr_not_changed(self, merge_request):
102102
log.info('Ensuring MR !%s did not change', merge_request.iid)
@@ -198,11 +198,15 @@ def accept_mr(
198198
return final_sha
199199

200200
def execute(self):
201+
# name of batch branch based on the name of target branch to allow parallel merges #267
202+
target_branch = self._merge_requests[0].target_branch
203+
batch_branch_name = (BatchMergeJob.BATCH_BRANCH_NAME + target_branch)
204+
log.debug("batch: execute: batch_branch_name: %s", batch_branch_name)
205+
201206
# Cleanup previous batch work
202-
self.remove_batch_branch()
203-
self.close_batch_mr()
207+
self.remove_batch_branch(batch_branch_name)
208+
self.close_batch_mr(batch_branch_name)
204209

205-
target_branch = self._merge_requests[0].target_branch
206210
merge_requests = self.get_mrs_with_common_target_branch(target_branch)
207211
merge_requests = self.get_mergeable_mrs(merge_requests)
208212

@@ -218,11 +222,9 @@ def execute(self):
218222
remote_target_branch_sha = self._repo.get_commit_hash('origin/%s' % target_branch)
219223

220224
self._repo.checkout_branch(target_branch, 'origin/%s' % target_branch)
221-
self._repo.checkout_branch(BatchMergeJob.BATCH_BRANCH_NAME, 'origin/%s' % target_branch)
225+
self._repo.checkout_branch(batch_branch_name, 'origin/%s' % target_branch)
222226

223-
batch_mr = self.create_batch_mr(
224-
target_branch=target_branch,
225-
)
227+
batch_mr = self.create_batch_mr(target_branch, batch_branch_name)
226228
batch_mr_sha = batch_mr.sha
227229

228230
working_merge_requests = []
@@ -243,7 +245,7 @@ def execute(self):
243245
)
244246
# Update <batch> branch with MR changes
245247
batch_mr_sha = self._repo.merge(
246-
BatchMergeJob.BATCH_BRANCH_NAME,
248+
batch_branch_name,
247249
merge_request.source_branch,
248250
'-m',
249251
'Batch merge !%s into %s (!%s)' % (
@@ -257,13 +259,13 @@ def execute(self):
257259
# Update <source_branch> on latest <batch> branch so it contains previous MRs
258260
self.fuse(
259261
merge_request.source_branch,
260-
BatchMergeJob.BATCH_BRANCH_NAME,
262+
batch_branch_name,
261263
source_repo_url=source_repo_url,
262264
local=True,
263265
)
264266
# Update <batch> branch with MR changes
265267
batch_mr_sha = self._repo.fast_forward(
266-
BatchMergeJob.BATCH_BRANCH_NAME,
268+
batch_branch_name,
267269
merge_request.source_branch,
268270
local=True,
269271
)
@@ -286,7 +288,7 @@ def execute(self):
286288
raise CannotBatch('not enough ready merge requests')
287289

288290
# This switches git to <batch> branch
289-
self.push_batch()
291+
self.push_batch(batch_branch_name)
290292
for merge_request in working_merge_requests:
291293
merge_request.comment('I will attempt to batch this MR (!{})...'.format(batch_mr.iid))
292294

tests/test_batch_job.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ def get_batch_merge_job(self, api, mocklab, **batch_merge_kwargs):
4949
def test_remove_batch_branch(self, api, mocklab):
5050
repo = create_autospec(marge.git.Repo, spec_set=True)
5151
batch_merge_job = self.get_batch_merge_job(api, mocklab, repo=repo)
52-
batch_merge_job.remove_batch_branch()
52+
batch_merge_job.remove_batch_branch(BatchMergeJob.BATCH_BRANCH_NAME)
5353
repo.remove_branch.assert_called_once_with(
5454
BatchMergeJob.BATCH_BRANCH_NAME,
5555
)
@@ -60,7 +60,7 @@ def test_close_batch_mr(self, api, mocklab):
6060
mr_class.search.return_value = [batch_mr]
6161

6262
batch_merge_job = self.get_batch_merge_job(api, mocklab)
63-
batch_merge_job.close_batch_mr()
63+
batch_merge_job.close_batch_mr(BatchMergeJob.BATCH_BRANCH_NAME)
6464

6565
params = {
6666
'author_id': batch_merge_job._user.id,
@@ -83,7 +83,7 @@ def test_create_batch_mr(self, api, mocklab):
8383

8484
batch_merge_job = self.get_batch_merge_job(api, mocklab)
8585
target_branch = 'master'
86-
r_batch_mr = batch_merge_job.create_batch_mr(target_branch)
86+
r_batch_mr = batch_merge_job.create_batch_mr(target_branch, BatchMergeJob.BATCH_BRANCH_NAME)
8787

8888
params = {
8989
'source_branch': BatchMergeJob.BATCH_BRANCH_NAME,
@@ -132,7 +132,7 @@ def test_ensure_mergeable_mr_ci_not_ok(self, bmj_get_mr_ci_status, api, mocklab)
132132

133133
def test_push_batch(self, api, mocklab):
134134
batch_merge_job = self.get_batch_merge_job(api, mocklab)
135-
batch_merge_job.push_batch()
135+
batch_merge_job.push_batch(BatchMergeJob.BATCH_BRANCH_NAME)
136136
batch_merge_job._repo.push.assert_called_once_with(
137137
BatchMergeJob.BATCH_BRANCH_NAME,
138138
force=True,

0 commit comments

Comments
 (0)