Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(161)

Side by Side Diff: git_cl.py

Issue 2448193006: git cl try: Simplify _get_bucket_map. (Closed)
Patch Set: Respond to comments Created 4 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 323 matching lines...) Expand 10 before | Expand all | Expand 10 after
334 raise httplib2.HttpLib2Error(content) 334 raise httplib2.HttpLib2Error(content)
335 335
336 # status >= 500 means transient failures. 336 # status >= 500 means transient failures.
337 logging.debug('Transient errors when %s. Will retry.', operation_name) 337 logging.debug('Transient errors when %s. Will retry.', operation_name)
338 time_sleep(0.5 + 1.5*try_count) 338 time_sleep(0.5 + 1.5*try_count)
339 try_count += 1 339 try_count += 1
340 assert False, 'unreachable' 340 assert False, 'unreachable'
341 341
342 342
343 def _get_bucket_map(changelist, options, option_parser): 343 def _get_bucket_map(changelist, options, option_parser):
344 """Returns a dict mapping bucket names (or master names) to 344 """Returns a dict mapping bucket names to builders and tests,
345 builders and tests, for triggering try jobs. 345 for triggering try jobs.
346 """ 346 """
347 # If no bots are listed, we try to get a set of builders and tests based
348 # on GetPreferredTryMasters functions in PRESUBMIT.py files.
347 if not options.bot: 349 if not options.bot:
348 change = changelist.GetChange( 350 change = changelist.GetChange(
349 changelist.GetCommonAncestorWithUpstream(), None) 351 changelist.GetCommonAncestorWithUpstream(), None)
350 352
351 # Get try masters from PRESUBMIT.py files.
352 masters = presubmit_support.DoGetTryMasters( 353 masters = presubmit_support.DoGetTryMasters(
353 change=change, 354 change=change,
354 changed_files=change.LocalPaths(), 355 changed_files=change.LocalPaths(),
355 repository_root=settings.GetRoot(), 356 repository_root=settings.GetRoot(),
356 default_presubmit=None, 357 default_presubmit=None,
357 project=None, 358 project=None,
358 verbose=options.verbose, 359 verbose=options.verbose,
359 output_stream=sys.stdout) 360 output_stream=sys.stdout)
360 361
361 if masters: 362 if masters:
362 return masters 363 return masters
363 364
364 # Fall back to deprecated method: get try slaves from PRESUBMIT.py 365 # Fall back to deprecated method: get try slaves from PRESUBMIT.py
365 # files. 366 # files.
366 # TODO(qyearsley): Remove this. 367 # TODO(qyearsley): Remove this.
367 options.bot = presubmit_support.DoGetTrySlaves( 368 options.bot = presubmit_support.DoGetTrySlaves(
368 change=change, 369 change=change,
369 changed_files=change.LocalPaths(), 370 changed_files=change.LocalPaths(),
370 repository_root=settings.GetRoot(), 371 repository_root=settings.GetRoot(),
371 default_presubmit=None, 372 default_presubmit=None,
372 project=None, 373 project=None,
373 verbose=options.verbose, 374 verbose=options.verbose,
374 output_stream=sys.stdout) 375 output_stream=sys.stdout)
375 376
376 if not options.bot: 377 if not options.bot:
377 return {} 378 return {}
378 379
380 # If a bucket or master is passed, then we assume all bots are under
381 # that one master.
379 if options.bucket: 382 if options.bucket:
380 return {options.bucket: {b: [] for b in options.bot}} 383 return {options.bucket: {b: [] for b in options.bot}}
384 if options.master:
385 return {_prefix_master(options.master): {b: [] for b in options.bot}}
381 386
382 if not options.master: 387 # If bots are listed but no master or bucket, then we need to find out
383 bucket_map, error_message = _get_bucket_map_for_builders(options.bot) 388 # the corresponding master for each bot.
384 if error_message: 389 bucket_map, error_message = _get_bucket_map_for_builders(options.bot)
385 option_parser.error( 390 if error_message:
386 'Tryserver master cannot be found because: %s\n' 391 option_parser.error(
387 'Please manually specify the tryserver master, e.g. ' 392 'Tryserver master cannot be found because: %s\n'
388 '"-m tryserver.chromium.linux".' % error_message) 393 'Please manually specify the tryserver master, e.g. '
389 return bucket_map 394 '"-m tryserver.chromium.linux".' % error_message)
390 395 return bucket_map
391 builders_and_tests = {}
392
393 # TODO(machenbach): The old style command-line options don't support
394 # multiple try masters yet.
395 # TODO(qyearsley): If options.bot is always a list of strings, then
396 # "new_style" never applies, and so we should remove support for Specifying
397 # test filters completely.
398 old_style = filter(lambda x: isinstance(x, basestring), options.bot)
399 new_style = filter(lambda x: isinstance(x, tuple), options.bot)
400
401 for bot in old_style:
402 if ':' in bot:
403 option_parser.error('Specifying testfilter is no longer supported')
404 elif ',' in bot:
405 option_parser.error('Specify one bot per --bot flag')
406 else:
407 builders_and_tests.setdefault(bot, [])
408
409 for bot, tests in new_style:
410 builders_and_tests.setdefault(bot, []).extend(tests)
411
412 # Add the "master." prefix to the master name to obtain the bucket name.
413 bucket = _prefix_master(options.master)
414 return {bucket: builders_and_tests}
415 396
416 397
417 def _get_bucket_map_for_builders(builders): 398 def _get_bucket_map_for_builders(builders):
418 """Returns a map of buckets to builders for the given builders.""" 399 """Returns a map of buckets to builders for the given builders."""
419 map_url = 'https://builders-map.appspot.com/' 400 map_url = 'https://builders-map.appspot.com/'
420 try: 401 try:
421 builders_map = json.load(urllib2.urlopen(map_url)) 402 builders_map = json.load(urllib2.urlopen(map_url))
422 except urllib2.URLError as e: 403 except urllib2.URLError as e:
423 return None, ('Failed to fetch builder-to-master map from %s. Error: %s.' % 404 return None, ('Failed to fetch builder-to-master map from %s. Error: %s.' %
424 (map_url, e)) 405 (map_url, e))
425 except ValueError as e: 406 except ValueError as e:
426 return None, ('Invalid json string from %s. Error: %s.' % (map_url, e)) 407 return None, ('Invalid json string from %s. Error: %s.' % (map_url, e))
427 if not builders_map: 408 if not builders_map:
428 return None, 'Failed to build master map.' 409 return None, 'Failed to build master map.'
429 410
430 bucket_map = {} 411 bucket_map = {}
431 for builder in builders: 412 for builder in builders:
432 builder = builder.split(':', 1)[0]
433 masters = builders_map.get(builder, []) 413 masters = builders_map.get(builder, [])
434 if not masters: 414 if not masters:
435 return None, ('No matching master for builder %s.' % builder) 415 return None, ('No matching master for builder %s.' % builder)
436 if len(masters) > 1: 416 if len(masters) > 1:
437 return None, ('The builder name %s exists in multiple masters %s.' % 417 return None, ('The builder name %s exists in multiple masters %s.' %
438 (builder, masters)) 418 (builder, masters))
439 bucket = _prefix_master(masters[0]) 419 bucket = _prefix_master(masters[0])
440 bucket_map.setdefault(bucket, {})[builder] = [] 420 bucket_map.setdefault(bucket, {})[builder] = []
441 421
442 return bucket_map, None 422 return bucket_map, None
(...skipping 4420 matching lines...) Expand 10 before | Expand all | Expand 10 after
4863 4843
4864 error_message = cl.CannotTriggerTryJobReason() 4844 error_message = cl.CannotTriggerTryJobReason()
4865 if error_message: 4845 if error_message:
4866 parser.error('Can\'t trigger try jobs: %s' % error_message) 4846 parser.error('Can\'t trigger try jobs: %s' % error_message)
4867 4847
4868 if options.bucket and options.master: 4848 if options.bucket and options.master:
4869 parser.error('Only one of --bucket and --master may be used.') 4849 parser.error('Only one of --bucket and --master may be used.')
4870 4850
4871 buckets = _get_bucket_map(cl, options, parser) 4851 buckets = _get_bucket_map(cl, options, parser)
4872 4852
4853 # If no bots are listed and we couldn't get a list based on PRESUBMIT files,
4854 # then we default to triggering a CQ dry run (see http://crbug.com/625697).
4873 if not buckets: 4855 if not buckets:
4874 # Default to triggering Dry Run (see http://crbug.com/625697).
4875 if options.verbose: 4856 if options.verbose:
4876 print('git cl try with no bots now defaults to CQ Dry Run.') 4857 print('git cl try with no bots now defaults to CQ Dry Run.')
4877 return cl.TriggerDryRun() 4858 return cl.TriggerDryRun()
4878 4859
4879 for builders in buckets.itervalues(): 4860 for builders in buckets.itervalues():
4880 if any('triggered' in b for b in builders): 4861 if any('triggered' in b for b in builders):
4881 print('ERROR You are trying to send a job to a triggered bot. This type ' 4862 print('ERROR You are trying to send a job to a triggered bot. This type '
4882 'of bot requires an initial job from a parent (usually a builder). ' 4863 'of bot requires an initial job from a parent (usually a builder). '
4883 'Instead send your job to the parent.\n' 4864 'Instead send your job to the parent.\n'
4884 'Bot list: %s' % builders, file=sys.stderr) 4865 'Bot list: %s' % builders, file=sys.stderr)
(...skipping 510 matching lines...) Expand 10 before | Expand all | Expand 10 after
5395 if __name__ == '__main__': 5376 if __name__ == '__main__':
5396 # These affect sys.stdout so do it outside of main() to simplify mocks in 5377 # These affect sys.stdout so do it outside of main() to simplify mocks in
5397 # unit testing. 5378 # unit testing.
5398 fix_encoding.fix_encoding() 5379 fix_encoding.fix_encoding()
5399 setup_color.init() 5380 setup_color.init()
5400 try: 5381 try:
5401 sys.exit(main(sys.argv[1:])) 5382 sys.exit(main(sys.argv[1:]))
5402 except KeyboardInterrupt: 5383 except KeyboardInterrupt:
5403 sys.stderr.write('interrupted\n') 5384 sys.stderr.write('interrupted\n')
5404 sys.exit(1) 5385 sys.exit(1)
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698