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 345 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 356 default_presubmit=None, | 356 default_presubmit=None, |
| 357 project=None, | 357 project=None, |
| 358 verbose=options.verbose, | 358 verbose=options.verbose, |
| 359 output_stream=sys.stdout) | 359 output_stream=sys.stdout) |
| 360 | 360 |
| 361 if masters: | 361 if masters: |
| 362 return masters | 362 return masters |
| 363 | 363 |
| 364 # Fall back to deprecated method: get try slaves from PRESUBMIT.py | 364 # Fall back to deprecated method: get try slaves from PRESUBMIT.py |
| 365 # files. | 365 # files. |
| 366 # TODO(qyearsley): Remove this. | |
| 366 options.bot = presubmit_support.DoGetTrySlaves( | 367 options.bot = presubmit_support.DoGetTrySlaves( |
| 367 change=change, | 368 change=change, |
| 368 changed_files=change.LocalPaths(), | 369 changed_files=change.LocalPaths(), |
| 369 repository_root=settings.GetRoot(), | 370 repository_root=settings.GetRoot(), |
| 370 default_presubmit=None, | 371 default_presubmit=None, |
| 371 project=None, | 372 project=None, |
| 372 verbose=options.verbose, | 373 verbose=options.verbose, |
| 373 output_stream=sys.stdout) | 374 output_stream=sys.stdout) |
| 374 | 375 |
| 375 if not options.bot: | 376 if not options.bot: |
| 376 return {} | 377 return {} |
| 377 | 378 |
| 378 if options.bucket: | 379 if options.bucket: |
| 379 return {options.bucket: {b: [] for b in options.bot}} | 380 return {options.bucket: {b: [] for b in options.bot}} |
| 380 | 381 |
| 382 if not options.master: | |
| 383 master_map, error_message = _get_master_map_for_builders(options.bot) | |
| 384 if error_message: | |
| 385 option_parser.error( | |
| 386 'Tryserver master cannot be found because: %s\n' | |
| 387 'Please manually specify the tryserver master, e.g. ' | |
| 388 '"-m tryserver.chromium.linux".' % error_message) | |
| 389 buckets = {} | |
| 390 for master, builders in master_map.iteritems(): | |
| 391 buckets[_prefix_master(master)] = {b: [] for b in builders} | |
| 392 return buckets | |
| 393 | |
| 381 builders_and_tests = {} | 394 builders_and_tests = {} |
| 382 | 395 |
| 383 # TODO(machenbach): The old style command-line options don't support | 396 # TODO(machenbach): The old style command-line options don't support |
| 384 # multiple try masters yet. | 397 # multiple try masters yet. |
| 385 old_style = filter(lambda x: isinstance(x, basestring), options.bot) | 398 old_style = filter(lambda x: isinstance(x, basestring), options.bot) |
| 386 new_style = filter(lambda x: isinstance(x, tuple), options.bot) | 399 new_style = filter(lambda x: isinstance(x, tuple), options.bot) |
|
qyearsley
2016/10/24 21:33:39
One thing I'm not sure about -- are the elements i
tandrii(chromium)
2016/10/25 17:59:12
Very good question. I don't see how either.
+mache
Michael Achenbach
2016/10/26 10:17:47
I have no idea. I just got involved here at some p
| |
| 387 | 400 |
| 388 for bot in old_style: | 401 for bot in old_style: |
| 389 if ':' in bot: | 402 if ':' in bot: |
| 390 option_parser.error('Specifying testfilter is no longer supported') | 403 option_parser.error('Specifying testfilter is no longer supported') |
| 391 elif ',' in bot: | 404 elif ',' in bot: |
| 392 option_parser.error('Specify one bot per --bot flag') | 405 option_parser.error('Specify one bot per --bot flag') |
| 393 else: | 406 else: |
| 394 builders_and_tests.setdefault(bot, []) | 407 builders_and_tests.setdefault(bot, []) |
| 395 | 408 |
| 396 for bot, tests in new_style: | 409 for bot, tests in new_style: |
| 397 builders_and_tests.setdefault(bot, []).extend(tests) | 410 builders_and_tests.setdefault(bot, []).extend(tests) |
| 398 | 411 |
| 399 if not options.master: | 412 # Add the "master." prefix to the master name to obtain the bucket name. |
| 400 # TODO(qyearsley): crbug.com/640740 | 413 bucket = _prefix_master(options.master) |
| 401 options.master, error_message = _get_builder_master(options.bot) | |
| 402 if error_message: | |
| 403 option_parser.error( | |
| 404 'Tryserver master cannot be found because: %s\n' | |
| 405 'Please manually specify the tryserver master, e.g. ' | |
| 406 '"-m tryserver.chromium.linux".' % error_message) | |
| 407 | |
| 408 # Return a master map with one master to be backwards compatible. The | |
| 409 # master name defaults to an empty string, which will cause the master | |
| 410 # not to be set on rietveld (deprecated). | |
| 411 bucket = '' | |
| 412 if options.master: | |
| 413 # Add the "master." prefix to the master name to obtain the bucket name. | |
| 414 bucket = _prefix_master(options.master) | |
| 415 return {bucket: builders_and_tests} | 414 return {bucket: builders_and_tests} |
| 416 | 415 |
| 417 | 416 |
| 418 def _get_builder_master(bot_list): | 417 def _get_master_map_for_builders(builders): |
| 419 """Fetches a master for the given list of builders. | 418 """Returns a map of masters to builders for the given builders.""" |
| 420 | |
| 421 Returns a pair (master, error_message), where either master or | |
| 422 error_message is None. | |
| 423 """ | |
| 424 map_url = 'https://builders-map.appspot.com/' | 419 map_url = 'https://builders-map.appspot.com/' |
| 425 try: | 420 try: |
| 426 master_map = json.load(urllib2.urlopen(map_url)) | 421 builders_map = json.load(urllib2.urlopen(map_url)) |
| 427 except urllib2.URLError as e: | 422 except urllib2.URLError as e: |
| 428 return None, ('Failed to fetch builder-to-master map from %s. Error: %s.' % | 423 return None, ('Failed to fetch builder-to-master map from %s. Error: %s.' % |
| 429 (map_url, e)) | 424 (map_url, e)) |
| 430 except ValueError as e: | 425 except ValueError as e: |
| 431 return None, ('Invalid json string from %s. Error: %s.' % (map_url, e)) | 426 return None, ('Invalid json string from %s. Error: %s.' % (map_url, e)) |
| 432 if not master_map: | 427 if not builders_map: |
| 433 return None, 'Failed to build master map.' | 428 return None, 'Failed to build master map.' |
| 434 | 429 |
| 435 result_master = '' | 430 master_map = {} |
| 436 for bot in bot_list: | 431 for builder in builders: |
| 437 builder = bot.split(':', 1)[0] | 432 builder = builder.split(':', 1)[0] |
| 438 master_list = master_map.get(builder, []) | 433 masters = builders_map.get(builder, []) |
| 439 if not master_list: | 434 if not masters: |
| 440 return None, ('No matching master for builder %s.' % builder) | 435 return None, ('No matching master for builder %s.' % builder) |
| 441 elif len(master_list) > 1: | 436 elif len(masters) > 1: |
| 442 return None, ('The builder name %s exists in multiple masters %s.' % | 437 return None, ('The builder name %s exists in multiple masters %s.' % |
| 443 (builder, master_list)) | 438 (builder, masters)) |
| 444 else: | 439 else: |
| 445 cur_master = master_list[0] | 440 master = masters[0] |
| 446 if not result_master: | 441 master_map.setdefault(master, []) |
| 447 result_master = cur_master | 442 master_map[master].append(builder) |
| 448 elif result_master != cur_master: | 443 |
| 449 return None, 'The builders do not belong to the same master.' | 444 return master_map, None |
| 450 return result_master, None | |
| 451 | 445 |
| 452 | 446 |
| 453 def _trigger_try_jobs(auth_config, changelist, buckets, options, | 447 def _trigger_try_jobs(auth_config, changelist, buckets, options, |
| 454 category='git_cl_try', patchset=None): | 448 category='git_cl_try', patchset=None): |
| 455 """Sends a request to Buildbucket to trigger try jobs for a changelist. | 449 """Sends a request to Buildbucket to trigger try jobs for a changelist. |
| 456 | 450 |
| 457 Args: | 451 Args: |
| 458 auth_config: AuthConfig for Rietveld. | 452 auth_config: AuthConfig for Rietveld. |
| 459 changelist: Changelist that the try jobs are associated with. | 453 changelist: Changelist that the try jobs are associated with. |
| 460 buckets: A nested dict mapping bucket names to builders to tests. | 454 buckets: A nested dict mapping bucket names to builders to tests. |
| (...skipping 4949 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 5410 if __name__ == '__main__': | 5404 if __name__ == '__main__': |
| 5411 # These affect sys.stdout so do it outside of main() to simplify mocks in | 5405 # These affect sys.stdout so do it outside of main() to simplify mocks in |
| 5412 # unit testing. | 5406 # unit testing. |
| 5413 fix_encoding.fix_encoding() | 5407 fix_encoding.fix_encoding() |
| 5414 setup_color.init() | 5408 setup_color.init() |
| 5415 try: | 5409 try: |
| 5416 sys.exit(main(sys.argv[1:])) | 5410 sys.exit(main(sys.argv[1:])) |
| 5417 except KeyboardInterrupt: | 5411 except KeyboardInterrupt: |
| 5418 sys.stderr.write('interrupted\n') | 5412 sys.stderr.write('interrupted\n') |
| 5419 sys.exit(1) | 5413 sys.exit(1) |
| OLD | NEW |