Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 #!/usr/bin/env python | 1 #!/usr/bin/env python |
| 2 # Copyright (c) 2012 The Chromium Authors. All rights reserved. | 2 # Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 3 # Use of this source code is governed by a BSD-style license that can be | 3 # Use of this source code is governed by a BSD-style license that can be |
| 4 # found in the LICENSE file. | 4 # found in the LICENSE file. |
| 5 | 5 |
| 6 # Copyright (C) 2008 Evan Martin <martine@danga.com> | 6 # Copyright (C) 2008 Evan Martin <martine@danga.com> |
| 7 | 7 |
| 8 """A git-command for integrating reviews on Rietveld and Gerrit.""" | 8 """A git-command for integrating reviews on Rietveld and Gerrit.""" |
| 9 | 9 |
| 10 from __future__ import print_function | 10 from __future__ import print_function |
| (...skipping 380 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 391 headers={'Content-Type': 'application/json'} | 391 headers={'Content-Type': 'application/json'} |
| 392 ) | 392 ) |
| 393 print_text.append('To see results here, run: git cl try-results') | 393 print_text.append('To see results here, run: git cl try-results') |
| 394 print_text.append('To see results in browser, run: git cl web') | 394 print_text.append('To see results in browser, run: git cl web') |
| 395 print('\n'.join(print_text)) | 395 print('\n'.join(print_text)) |
| 396 | 396 |
| 397 | 397 |
| 398 def fetch_try_jobs(auth_config, changelist, options): | 398 def fetch_try_jobs(auth_config, changelist, options): |
| 399 """Fetches try jobs from buildbucket. | 399 """Fetches try jobs from buildbucket. |
| 400 | 400 |
| 401 Returns a map from build id to build info as json dictionary. | 401 Returns a map from build id to build info as a dictionary. |
| 402 """ | 402 """ |
| 403 rietveld_url = settings.GetDefaultServerUrl() | 403 rietveld_url = settings.GetDefaultServerUrl() |
| 404 rietveld_host = urlparse.urlparse(rietveld_url).hostname | 404 rietveld_host = urlparse.urlparse(rietveld_url).hostname |
| 405 authenticator = auth.get_authenticator_for_host(rietveld_host, auth_config) | 405 authenticator = auth.get_authenticator_for_host(rietveld_host, auth_config) |
| 406 if authenticator.has_cached_credentials(): | 406 if authenticator.has_cached_credentials(): |
| 407 http = authenticator.authorize(httplib2.Http()) | 407 http = authenticator.authorize(httplib2.Http()) |
| 408 else: | 408 else: |
| 409 print('Warning: Some results might be missing because %s' % | 409 print('Warning: Some results might be missing because %s' % |
| 410 # Get the message on how to login. | 410 # Get the message on how to login. |
| 411 (auth.LoginRequiredError(rietveld_host).message,)) | 411 (auth.LoginRequiredError(rietveld_host).message,)) |
| (...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 526 pop(status='SCHEDULED', | 526 pop(status='SCHEDULED', |
| 527 title='Scheduled:', | 527 title='Scheduled:', |
| 528 f=lambda b: (get_name(b), 'id=%s' % b['id'])) | 528 f=lambda b: (get_name(b), 'id=%s' % b['id'])) |
| 529 # The last section is just in case buildbucket API changes OR there is a bug. | 529 # The last section is just in case buildbucket API changes OR there is a bug. |
| 530 pop(title='Other:', | 530 pop(title='Other:', |
| 531 f=lambda b: (get_name(b), 'id=%s' % b['id'])) | 531 f=lambda b: (get_name(b), 'id=%s' % b['id'])) |
| 532 assert len(builds) == 0 | 532 assert len(builds) == 0 |
| 533 print('Total: %d try jobs' % total) | 533 print('Total: %d try jobs' % total) |
| 534 | 534 |
| 535 | 535 |
| 536 def write_try_results_json(output_file, builds): | |
| 537 """Writes a subset of the data from fetch_try_jobs to a file as JSON. | |
| 538 | |
| 539 The input |builds| dict is assumed to be generated by Buildbucket. | |
| 540 Buildbucket documentation: http://goo.gl/G0s101 | |
| 541 """ | |
| 542 | |
| 543 def convert_build_dict(build): | |
| 544 return { | |
| 545 'buildbucket_id': build.get('id'), | |
| 546 'status': build.get('status'), | |
| 547 'result': build.get('result'), | |
| 548 'builder_name': json.loads( | |
| 549 build.get('parameters_json', '{}')).get('builder_name'), | |
|
tandrii(chromium)
2016/08/30 22:22:45
what about bucket_name? (that's where you can get
qyearsley
2016/08/30 23:41:24
Added bucket and url.
By category, do you mean so
tandrii(chromium)
2016/08/30 23:47:35
no, i meant parameters_json.category. It's usually
| |
| 550 'failure_reason': build.get('failure_reason'), | |
|
qyearsley
2016/08/30 22:13:22
Does it seem like a good idea to use build['key']
tandrii(chromium)
2016/08/30 22:22:45
What's build['key']? I don't see it in buildbucket
qyearsley
2016/08/30 23:41:25
Ah, that's not a real thing, what I meant was "doe
tandrii(chromium)
2016/08/30 23:47:35
ah, dict.get() is the right way.
| |
| 551 } | |
| 552 | |
| 553 converted = [] | |
| 554 for _, build in sorted(builds.items()): | |
| 555 converted.append(convert_build_dict(build)) | |
| 556 write_json(output_file, converted) | |
| 557 | |
| 558 | |
| 536 def MatchSvnGlob(url, base_url, glob_spec, allow_wildcards): | 559 def MatchSvnGlob(url, base_url, glob_spec, allow_wildcards): |
| 537 """Return the corresponding git ref if |base_url| together with |glob_spec| | 560 """Return the corresponding git ref if |base_url| together with |glob_spec| |
| 538 matches the full |url|. | 561 matches the full |url|. |
| 539 | 562 |
| 540 If |allow_wildcards| is true, |glob_spec| can contain wildcards (see below). | 563 If |allow_wildcards| is true, |glob_spec| can contain wildcards (see below). |
| 541 """ | 564 """ |
| 542 fetch_suburl, as_ref = glob_spec.split(':') | 565 fetch_suburl, as_ref = glob_spec.split(':') |
| 543 if allow_wildcards: | 566 if allow_wildcards: |
| 544 glob_match = re.match('(.+/)?(\*|{[^/]*})(/.+)?', fetch_suburl) | 567 glob_match = re.match('(.+/)?(\*|{[^/]*})(/.+)?', fetch_suburl) |
| 545 if glob_match: | 568 if glob_match: |
| (...skipping 4202 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 4748 group.add_option( | 4771 group.add_option( |
| 4749 "-p", "--patchset", type=int, help="patchset number if not current.") | 4772 "-p", "--patchset", type=int, help="patchset number if not current.") |
| 4750 group.add_option( | 4773 group.add_option( |
| 4751 "--print-master", action='store_true', help="print master name as well.") | 4774 "--print-master", action='store_true', help="print master name as well.") |
| 4752 group.add_option( | 4775 group.add_option( |
| 4753 "--color", action='store_true', default=setup_color.IS_TTY, | 4776 "--color", action='store_true', default=setup_color.IS_TTY, |
| 4754 help="force color output, useful when piping output.") | 4777 help="force color output, useful when piping output.") |
| 4755 group.add_option( | 4778 group.add_option( |
| 4756 "--buildbucket-host", default='cr-buildbucket.appspot.com', | 4779 "--buildbucket-host", default='cr-buildbucket.appspot.com', |
| 4757 help="Host of buildbucket. The default host is %default.") | 4780 help="Host of buildbucket. The default host is %default.") |
| 4781 group.add_option( | |
| 4782 '--json', help='Path of JSON output file to write try job results to.') | |
| 4758 parser.add_option_group(group) | 4783 parser.add_option_group(group) |
| 4759 auth.add_auth_options(parser) | 4784 auth.add_auth_options(parser) |
| 4760 options, args = parser.parse_args(args) | 4785 options, args = parser.parse_args(args) |
| 4761 if args: | 4786 if args: |
| 4762 parser.error('Unrecognized args: %s' % ' '.join(args)) | 4787 parser.error('Unrecognized args: %s' % ' '.join(args)) |
| 4763 | 4788 |
| 4764 auth_config = auth.extract_auth_config_from_options(options) | 4789 auth_config = auth.extract_auth_config_from_options(options) |
| 4765 cl = Changelist(auth_config=auth_config) | 4790 cl = Changelist(auth_config=auth_config) |
| 4766 if not cl.GetIssue(): | 4791 if not cl.GetIssue(): |
| 4767 parser.error('Need to upload first') | 4792 parser.error('Need to upload first') |
| 4768 | 4793 |
| 4769 if not options.patchset: | 4794 if not options.patchset: |
| 4770 options.patchset = cl.GetMostRecentPatchset() | 4795 options.patchset = cl.GetMostRecentPatchset() |
| 4771 if options.patchset and options.patchset != cl.GetPatchset(): | 4796 if options.patchset and options.patchset != cl.GetPatchset(): |
| 4772 print( | 4797 print( |
| 4773 '\nWARNING Mismatch between local config and server. Did a previous ' | 4798 '\nWARNING Mismatch between local config and server. Did a previous ' |
| 4774 'upload fail?\ngit-cl try always uses latest patchset from rietveld. ' | 4799 'upload fail?\ngit-cl try always uses latest patchset from rietveld. ' |
| 4775 'Continuing using\npatchset %s.\n' % options.patchset) | 4800 'Continuing using\npatchset %s.\n' % options.patchset) |
| 4776 try: | 4801 try: |
| 4777 jobs = fetch_try_jobs(auth_config, cl, options) | 4802 jobs = fetch_try_jobs(auth_config, cl, options) |
| 4778 except BuildbucketResponseException as ex: | 4803 except BuildbucketResponseException as ex: |
| 4779 print('Buildbucket error: %s' % ex) | 4804 print('Buildbucket error: %s' % ex) |
| 4780 return 1 | 4805 return 1 |
| 4781 except Exception as e: | 4806 except Exception as e: |
| 4782 stacktrace = (''.join(traceback.format_stack()) + traceback.format_exc()) | 4807 stacktrace = (''.join(traceback.format_stack()) + traceback.format_exc()) |
| 4783 print('ERROR: Exception when trying to fetch try jobs: %s\n%s' % | 4808 print('ERROR: Exception when trying to fetch try jobs: %s\n%s' % |
| 4784 (e, stacktrace)) | 4809 (e, stacktrace)) |
| 4785 return 1 | 4810 return 1 |
| 4786 print_try_jobs(options, jobs) | 4811 if options.json: |
| 4812 write_try_results_json(options.json, jobs) | |
| 4813 else: | |
| 4814 print_try_jobs(options, jobs) | |
| 4787 return 0 | 4815 return 0 |
| 4788 | 4816 |
| 4789 | 4817 |
| 4790 @subcommand.usage('[new upstream branch]') | 4818 @subcommand.usage('[new upstream branch]') |
| 4791 def CMDupstream(parser, args): | 4819 def CMDupstream(parser, args): |
| 4792 """Prints or sets the name of the upstream branch, if any.""" | 4820 """Prints or sets the name of the upstream branch, if any.""" |
| 4793 _, args = parser.parse_args(args) | 4821 _, args = parser.parse_args(args) |
| 4794 if len(args) > 1: | 4822 if len(args) > 1: |
| 4795 parser.error('Unrecognized args: %s' % ' '.join(args)) | 4823 parser.error('Unrecognized args: %s' % ' '.join(args)) |
| 4796 | 4824 |
| (...skipping 428 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 5225 if __name__ == '__main__': | 5253 if __name__ == '__main__': |
| 5226 # These affect sys.stdout so do it outside of main() to simplify mocks in | 5254 # These affect sys.stdout so do it outside of main() to simplify mocks in |
| 5227 # unit testing. | 5255 # unit testing. |
| 5228 fix_encoding.fix_encoding() | 5256 fix_encoding.fix_encoding() |
| 5229 setup_color.init() | 5257 setup_color.init() |
| 5230 try: | 5258 try: |
| 5231 sys.exit(main(sys.argv[1:])) | 5259 sys.exit(main(sys.argv[1:])) |
| 5232 except KeyboardInterrupt: | 5260 except KeyboardInterrupt: |
| 5233 sys.stderr.write('interrupted\n') | 5261 sys.stderr.write('interrupted\n') |
| 5234 sys.exit(1) | 5262 sys.exit(1) |
| OLD | NEW |