From 840bd196ba0803b9114dd634a2aa8818424e664f Mon Sep 17 00:00:00 2001 From: Nir Izraeli Date: Wed, 1 Jul 2020 12:27:20 +0300 Subject: [PATCH] Option to merge all MRs instead of just the oldest and skip on timeout ci-timeout-skip, skip-pending --- marge/app.py | 12 ++++++++++++ marge/bot.py | 25 +++++++++++++++++-------- marge/job.py | 8 +++++++- 3 files changed, 36 insertions(+), 9 deletions(-) diff --git a/marge/app.py b/marge/app.py index d30092fd..6d9c5a18 100644 --- a/marge/app.py +++ b/marge/app.py @@ -224,6 +224,16 @@ def regexp(str_regex): action='store_true', help='Skip CI when updating individual MRs when using batches' ) + parser.add_argument( + '--ci-timeout-skip', + action='store_true', + help='Skip to next MR if CI timeout expires (otherwise, give up on MR)' + ) + parser.add_argument( + '--skip-pending', + action='store_true', + help='Skip to next MR if oldest MR is not ready (otherwise, wait until it is)' + ) config = parser.parse_args(args) if config.use_merge_strategy and config.batch: @@ -321,12 +331,14 @@ def main(args=None): approval_timeout=options.approval_reset_timeout, embargo=options.embargo, ci_timeout=options.ci_timeout, + ci_timeout_skip=options.ci_timeout_skip, fusion=fusion, use_no_ff_batches=options.use_no_ff_batches, use_merge_commit_batches=options.use_merge_commit_batches, skip_ci_batches=options.skip_ci_batches, ), batch=options.batch, + skip_pending=options.skip_pending, ) marge_bot = bot.Bot(api=api, config=config) diff --git a/marge/bot.py b/marge/bot.py index 9f8acb1a..fb38344f 100644 --- a/marge/bot.py +++ b/marge/bot.py @@ -166,13 +166,22 @@ def _process_merge_requests(self, repo_manager, project, merge_requests): return except git.GitError as err: log.exception('BatchMergeJob failed: %s', err) - log.info('Attempting to merge the oldest MR...') - merge_request = merge_requests[0] - merge_job = self._get_single_job( - project=project, merge_request=merge_request, repo=repo, - options=self._config.merge_opts, - ) - merge_job.execute() + elif not self._config.skip_pending: + log.info('Attempting to merge the oldest MR...') + merge_request = merge_requests[0] + merge_job = self._get_single_job( + project=project, merge_request=merge_request, repo=repo, + options=self._config.merge_opts, + ) + merge_job.execute() + else: + for i, merge_request in enumerate(merge_requests): + log.info('Attempting to merge MR #%d / %d of assigned MRs...', i + 1, len(merge_requests)) + merge_job = self._get_single_job( + project=project, merge_request=merge_request, + repo=repo, options=self._config.merge_opts + ) + merge_job.execute() def _get_single_job(self, project, merge_request, repo, options): return single_merge_job.SingleMergeJob( @@ -187,7 +196,7 @@ def _get_single_job(self, project, merge_request, repo, options): class BotConfig(namedtuple('BotConfig', 'user ssh_key_file project_regexp merge_order merge_opts git_timeout ' + - 'git_reference_repo branch_regexp source_branch_regexp batch')): + 'git_reference_repo branch_regexp source_branch_regexp batch skip_pending')): pass diff --git a/marge/job.py b/marge/job.py index 0646518f..27f2d6e7 100644 --- a/marge/job.py +++ b/marge/job.py @@ -188,7 +188,10 @@ def wait_for_ci_to_pass(self, merge_request, commit_sha=None): log.debug('Waiting for %s secs before polling CI status again', waiting_time_in_secs) time.sleep(waiting_time_in_secs) - raise CannotMerge('CI is taking too long.') + if self._options.ci_timeout_skip: + raise SkipMerge('CI is taking too long.') + else: + raise CannotMerge('CI is taking too long.') def wait_for_merge_status_to_resolve(self, merge_request): """ @@ -452,6 +455,7 @@ class Fusion(enum.Enum): 'use_no_ff_batches', 'use_merge_commit_batches', 'skip_ci_batches', + 'ci_timeout_skip', ] @@ -468,6 +472,7 @@ def default( add_tested=False, add_part_of=False, add_reviewers=False, reapprove=False, approval_timeout=None, embargo=None, ci_timeout=None, fusion=Fusion.rebase, use_no_ff_batches=False, use_merge_commit_batches=False, skip_ci_batches=False, + ci_timeout_skip=False, ): approval_timeout = approval_timeout or timedelta(seconds=0) embargo = embargo or IntervalUnion.empty() @@ -480,6 +485,7 @@ def default( approval_timeout=approval_timeout, embargo=embargo, ci_timeout=ci_timeout, + ci_timeout_skip=ci_timeout_skip, fusion=fusion, use_no_ff_batches=use_no_ff_batches, use_merge_commit_batches=use_merge_commit_batches,