diff --git a/git_cl.py b/git_cl.py index 0ae2cd37c..4a054be41 100755 --- a/git_cl.py +++ b/git_cl.py @@ -836,10 +836,11 @@ class Settings(object): class _CQState(object): """Enum for states of CL with respect to CQ.""" NONE = 'none' + QUICK_RUN = 'quick_run' DRY_RUN = 'dry_run' COMMIT = 'commit' - ALL_STATES = [NONE, DRY_RUN, COMMIT] + ALL_STATES = [NONE, QUICK_RUN, DRY_RUN, COMMIT] class _ParsedIssueNumberArgument(object): @@ -1527,17 +1528,25 @@ class Changelist(object): def SetCQState(self, new_state): """Updates the CQ state for the latest patchset. - Issue must have been already uploaded and known. + Issue must have been already uploaded and known. Optionally allows for + updating Quick-Run (QR) state. """ assert new_state in _CQState.ALL_STATES assert self.GetIssue() try: vote_map = { _CQState.NONE: 0, + _CQState.QUICK_RUN: 1, _CQState.DRY_RUN: 1, _CQState.COMMIT: 2, } - labels = {'Commit-Queue': vote_map[new_state]} + if new_state == _CQState.QUICK_RUN: + labels = { + 'Commit-Queue': vote_map[_CQState.DRY_RUN], + 'Quick-Run': vote_map[_CQState.QUICK_RUN], + } + else: + labels = {'Commit-Queue': vote_map[new_state]} notify = False if new_state == _CQState.DRY_RUN else None gerrit_util.SetReview( self.GetGerritHost(), self._GerritChangeIdentifier(), @@ -2460,6 +2469,9 @@ class Changelist(object): refspec_opts.append('l=Commit-Queue+2') elif options.cq_dry_run: refspec_opts.append('l=Commit-Queue+1') + elif options.cq_quick_run: + refspec_opts.append('l=Commit-Queue+1') + refspec_opts.append('l=Quick-Run+1') if change_desc.get_reviewers(tbr_only=True): score = gerrit_util.GetCodeReviewTbrScore( @@ -4216,6 +4228,14 @@ def CMDupload(parser, args): action='store_true', default=False, help='Send the patchset to do a CQ dry run right after ' 'upload.') + parser.add_option( + '-q', + '--cq-quick-run', + action='store_true', + default=False, + help='Send the patchset to do a CQ quick run right after ' + 'upload (https://source.chromium.org/chromium/chromium/src/+/main:do' + 'cs/cq_quick_run.md) (chromium only).') parser.add_option('--set-bot-commit', action='store_true', help=optparse.SUPPRESS_HELP) parser.add_option('--preserve-tryjobs', action='store_true', @@ -4293,10 +4313,11 @@ def CMDupload(parser, args): options.message = gclient_utils.FileRead(options.message_file) if ([options.cq_dry_run, + options.cq_quick_run, options.use_commit_queue, options.retry_failed].count(True) > 1): - parser.error('Only one of --use-commit-queue, --cq-dry-run, or ' - '--retry-failed is allowed.') + parser.error('Only one of --use-commit-queue, --cq-dry-run, --cq-quick-run ' + 'or --retry-failed is allowed.') if options.skip_title and options.title: parser.error('Only one of --title and --skip-title allowed.') @@ -4571,6 +4592,14 @@ def CMDtry(parser, args): '-c', '--clobber', action='store_true', default=False, help='Force a clobber before building; that is don\'t do an ' 'incremental build') + group.add_option( + '-q', + '--quick-run', + action='store_true', + default=False, + help='trigger in quick run mode ' + '(https://source.chromium.org/chromium/chromium/src/+/main:docs/cq_q' + 'uick_run.md) (chromium only).') group.add_option( '--category', default='git_cl_try', help='Specify custom build category.') group.add_option( @@ -4652,6 +4681,9 @@ def CMDtry(parser, args): if num_builders > 10: confirm_or_exit('There are %d builders with failed builds.' % num_builders, action='continue') + elif options.quick_run: + print('Scheduling CQ quick run on: %s' % cl.GetIssueURL()) + return cl.SetCQState(_CQState.QUICK_RUN) else: if options.verbose: print('git cl try with no bots now defaults to CQ dry run.') @@ -4774,6 +4806,13 @@ def CMDset_commit(parser, args): """Sets the commit bit to trigger the CQ.""" parser.add_option('-d', '--dry-run', action='store_true', help='trigger in dry run mode') + parser.add_option( + '-q', + '--quick-run', + action='store_true', + help='trigger in quick run mode ' + '(https://source.chromium.org/chromium/chromium/src/+/main:docs/cq_qu' + 'ick_run.md) (chromium only).') parser.add_option('-c', '--clear', action='store_true', help='stop CQ run, if any') parser.add_option( @@ -4783,18 +4822,21 @@ def CMDset_commit(parser, args): options, args = parser.parse_args(args) if args: parser.error('Unrecognized args: %s' % ' '.join(args)) - if options.dry_run and options.clear: - parser.error('Only one of --dry-run and --clear are allowed.') + if [options.dry_run, options.quick_run, options.clear].count(True) > 1: + parser.error('Only one of --dry-run, --quick-run, and --clear are allowed.') cl = Changelist(issue=options.issue) + if not cl.GetIssue(): + parser.error('Must upload the issue first.') + if options.clear: state = _CQState.NONE + elif options.quick_run: + state = _CQState.QUICK_RUN elif options.dry_run: state = _CQState.DRY_RUN else: state = _CQState.COMMIT - if not cl.GetIssue(): - parser.error('Must upload the issue first.') cl.SetCQState(state) return 0 diff --git a/tests/git_cl_test.py b/tests/git_cl_test.py index d743095c7..a1499c40f 100755 --- a/tests/git_cl_test.py +++ b/tests/git_cl_test.py @@ -2116,6 +2116,18 @@ class TestGitCl(unittest.TestCase): {'Commit-Queue': vote}, notify, None), ''), ] + def _cmd_set_quick_run_gerrit(self): + self.mockGit.config['branch.master.gerritissue'] = '123' + self.mockGit.config['branch.master.gerritserver'] = ( + 'https://chromium-review.googlesource.com') + self.mockGit.config['remote.origin.url'] = ( + 'https://chromium.googlesource.com/infra/infra') + self.calls = [ + (('SetReview', 'chromium-review.googlesource.com', + 'infra%2Finfra~123', None, + {'Commit-Queue': 1, 'Quick-Run': 1}, None, None), ''), + ] + def test_cmd_set_commit_gerrit_clear(self): self._cmd_set_commit_gerrit_common(0) self.assertEqual(0, git_cl.main(['set-commit', '-c'])) @@ -2128,6 +2140,10 @@ class TestGitCl(unittest.TestCase): self._cmd_set_commit_gerrit_common(2) self.assertEqual(0, git_cl.main(['set-commit'])) + def test_cmd_set_quick_run_gerrit(self): + self._cmd_set_quick_run_gerrit() + self.assertEqual(0, git_cl.main(['set-commit', '-q'])) + def test_description_display(self): mock.patch('git_cl.Changelist', ChangelistMock).start() ChangelistMock.desc = 'foo\n' @@ -3578,6 +3594,16 @@ class CMDTryTestCase(CMDTestCaseBase): 'Scheduling CQ dry run on: ' 'https://chromium-review.googlesource.com/123456\n') + @mock.patch('git_cl.Changelist.SetCQState') + def testSetCQQuickRunByDefault(self, mockSetCQState): + mockSetCQState.return_value = 0 + self.assertEqual(0, git_cl.main(['try', '-q'])) + git_cl.Changelist.SetCQState.assert_called_with(git_cl._CQState.QUICK_RUN) + self.assertEqual( + sys.stdout.getvalue(), + 'Scheduling CQ quick run on: ' + 'https://chromium-review.googlesource.com/123456\n') + @mock.patch('git_cl._call_buildbucket') def testScheduleOnBuildbucket(self, mockCallBuildbucket): mockCallBuildbucket.return_value = {}