diff --git a/git_cl.py b/git_cl.py index ed3f10ff1..0b1d91507 100755 --- a/git_cl.py +++ b/git_cl.py @@ -460,12 +460,44 @@ def _trigger_try_jobs(auth_config, changelist, buckets, options, patchset): print('To see results here, run: git cl try-results') print('To see results in browser, run: git cl web') + requests = _make_try_job_schedule_requests( + changelist, buckets, options, patchset) + if not requests: + return + + codereview_url = changelist.GetCodereviewServer() + codereview_host = urlparse.urlparse(codereview_url).hostname + + authenticator = auth.get_authenticator_for_host(codereview_host, auth_config) + http = authenticator.authorize(httplib2.Http()) + http.force_exception_to_status_code = True + + batch_request = {'requests': requests} + batch_response = _call_buildbucket( + http, options.buildbucket_host, 'Batch', batch_request) + + errors = [ + ' ' + response['error']['message'] + for response in batch_response.get('responses', []) + if 'error' in response + ] + if errors: + raise BuildbucketResponseException( + 'Failed to schedule builds for some bots:\n%s' % '\n'.join(errors)) + + +def _make_try_job_schedule_requests(changelist, buckets, options, patchset): gerrit_changes = [changelist.GetGerritChange(patchset)] shared_properties = {'category': getattr(options, 'category', 'git_cl_try')} if getattr(options, 'clobber', False): shared_properties['clobber'] = True shared_properties.update(_get_properties_from_options(options) or {}) + shared_tags = [{'key': 'user_agent', 'value': 'git_cl_try'}] + if options.retry_failed: + shared_tags.append({'key': 'retry_failed', + 'value': '1'}) + requests = [] for raw_bucket, builders_and_tests in sorted(buckets.iteritems()): project, bucket = _parse_bucket(raw_bucket) @@ -492,33 +524,10 @@ def _trigger_try_jobs(auth_config, changelist, buckets, options, patchset): 'properties': properties, 'tags': [ {'key': 'builder', 'value': builder}, - {'key': 'user_agent', 'value': 'git_cl_try'}, - ], + ] + shared_tags, } }) - - if not requests: - return - - codereview_url = changelist.GetCodereviewServer() - codereview_host = urlparse.urlparse(codereview_url).hostname - - authenticator = auth.get_authenticator_for_host(codereview_host, auth_config) - http = authenticator.authorize(httplib2.Http()) - http.force_exception_to_status_code = True - - batch_request = {'requests': requests} - batch_response = _call_buildbucket( - http, options.buildbucket_host, 'Batch', batch_request) - - errors = [ - ' ' + response['error']['message'] - for response in batch_response.get('responses', []) - if 'error' in response - ] - if errors: - raise BuildbucketResponseException( - 'Failed to schedule builds for some bots:\n%s' % '\n'.join(errors)) + return requests def fetch_try_jobs(auth_config, changelist, buildbucket_host, @@ -1870,7 +1879,7 @@ class Changelist(object): self._GetGerritHost(), self._GerritChangeIdentifier()) # Add the robot comments onto the list of comments, but only - # keep those that are from the latest pachset. + # keep those that are from the latest patchset. latest_patch_set = self.GetMostRecentPatchset() for path, robot_comments in robot_file_comments.iteritems(): line_comments = file_comments.setdefault(path, []) diff --git a/tests/git_cl_test.py b/tests/git_cl_test.py index 963972619..1a2612f77 100755 --- a/tests/git_cl_test.py +++ b/tests/git_cl_test.py @@ -3176,6 +3176,59 @@ class CMDTryTestCase(CMDTestCaseBase): 'WARNING Could not parse bucket "not-a-bucket". Skipping.', git_cl.sys.stdout.getvalue()) + @mock.patch('git_cl._call_buildbucket') + @mock.patch('git_cl.fetch_try_jobs') + def testScheduleOnBuildbucketRetryFailed( + self, mockFetchTryJobs, mockCallBuildbucket): + + git_cl.fetch_try_jobs.side_effect = lambda *_, **kw: { + 7: [], + 6: [{ + 'id': 112112, + 'builder': { + 'project': 'chromium', + 'bucket': 'try', + 'builder': 'linux', + }, + 'status': 'FAILURE', + }], + }[kw['patchset']] + mockCallBuildbucket.return_value = {} + + self.assertEqual(0, git_cl.main(['try', '--retry-failed'])) + self.assertIn( + 'Scheduling jobs on:\nBucket: chromium/try', + git_cl.sys.stdout.getvalue()) + + expected_request = { + "requests": [{ + "scheduleBuild": { + "requestId": "uuid4", + "builder": { + "project": "chromium", + "bucket": "try", + "builder": "linux", + }, + "gerritChanges": [{ + "project": "depot_tools", + "host": "chromium-review.googlesource.com", + "patchset": 7, + "change": 123456, + }], + "properties": { + "category": "git_cl_try", + }, + "tags": [ + {"value": "linux", "key": "builder"}, + {"value": "git_cl_try", "key": "user_agent"}, + {"value": "1", "key": "retry_failed"}, + ], + }, + }], + } + mockCallBuildbucket.assert_called_with( + mock.ANY, 'cr-buildbucket.appspot.com', 'Batch', expected_request) + def test_parse_bucket(self): test_cases = [ {