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

Side by Side Diff: master/skia_master_scripts/utils.py

Issue 14517004: Change Builder Names, MkIII (Closed) Base URL: http://skia.googlecode.com/svn/buildbot/
Patch Set: Created 7 years, 7 months 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 | Annotate | Revision Log
OLDNEW
1 # Copyright (c) 2013 The Chromium Authors. All rights reserved. 1 # Copyright (c) 2013 The Chromium Authors. All rights reserved.
2 # Use of this source code is governed by a BSD-style license that can be 2 # Use of this source code is governed by a BSD-style license that can be
3 # found in the LICENSE file. 3 # found in the LICENSE file.
4 4
5 5
6 """Miscellaneous utilities needed by the Skia buildbot master.""" 6 """Miscellaneous utilities needed by the Skia buildbot master."""
7 7
8 8
9 import httplib2 9 import httplib2
10 import re 10 import re
11 11
12 # requires Google APIs client library for Python; see 12 # requires Google APIs client library for Python; see
13 # https://code.google.com/p/google-api-python-client/wiki/Installation 13 # https://code.google.com/p/google-api-python-client/wiki/Installation
14 from apiclient.discovery import build 14 from apiclient.discovery import build
15 from buildbot.scheduler import AnyBranchScheduler 15 from buildbot.scheduler import AnyBranchScheduler
16 from buildbot.schedulers import timed 16 from buildbot.schedulers import timed
17 from buildbot.schedulers.filter import ChangeFilter 17 from buildbot.schedulers.filter import ChangeFilter
18 from buildbot.util import NotABranch 18 from buildbot.util import NotABranch
19 from config_private import TRY_SVN_BASEURL 19 from config_private import TRY_SVN_BASEURL
20 from master import master_config 20 from master import master_config
21 from master import try_job_svn 21 from master import try_job_svn
22 from master import try_job_rietveld 22 from master import try_job_rietveld
23 from master.builders_pools import BuildersPools 23 from master.builders_pools import BuildersPools
24 from oauth2client.client import SignedJwtAssertionCredentials 24 from oauth2client.client import SignedJwtAssertionCredentials
25 25
26 import config_private 26 import config_private
27 27
28 28
29 BUILDER_NAME_SEP = '-'
30
31 # Patterns for creating builder names, based on the role of the builder.
32 # TODO(borenet): Extract these into a separate file (JSON?) so that they can be
33 # read by other users.
34 BUILDER_ROLE_COMPILE = 'Build'
35 BUILDER_ROLE_PERF = 'Perf'
36 BUILDER_ROLE_TEST = 'Test'
37 BUILDER_ROLE_HOUSEKEEPER = 'Housekeeper'
38 BUILDER_NAME_DEFAULT_ATTRS = ['os', 'model', 'gpu', 'arch', 'configuration']
39 BUILDER_NAME_SCHEMA = {
40 BUILDER_ROLE_COMPILE: ['os', 'compiler', 'target_arch', 'configuration'],
41 BUILDER_ROLE_TEST: BUILDER_NAME_DEFAULT_ATTRS,
42 BUILDER_ROLE_PERF: BUILDER_NAME_DEFAULT_ATTRS,
43 BUILDER_ROLE_HOUSEKEEPER: ['frequency'],
44 }
45
29 CATEGORY_BUILD = ' Build' 46 CATEGORY_BUILD = ' Build'
30 TRYBOT_NAME_SUFFIX = '_Trybot' 47 TRYBOT_NAME_SUFFIX = 'Trybot'
31 TRY_SCHEDULER_SVN = 'skia_try_svn' 48 TRY_SCHEDULER_SVN = 'skia_try_svn'
32 TRY_SCHEDULER_RIETVELD = 'skia_try_rietveld' 49 TRY_SCHEDULER_RIETVELD = 'skia_try_rietveld'
33 TRY_SCHEDULERS = [TRY_SCHEDULER_SVN, TRY_SCHEDULER_RIETVELD] 50 TRY_SCHEDULERS = [TRY_SCHEDULER_SVN, TRY_SCHEDULER_RIETVELD]
34 TRY_SCHEDULERS_STR = '|'.join(TRY_SCHEDULERS) 51 TRY_SCHEDULERS_STR = '|'.join(TRY_SCHEDULERS)
35 52
36 53
37 def IsTrybot(builder_name): 54 def IsTrybot(builder_name):
38 return builder_name.endswith(TRYBOT_NAME_SUFFIX) 55 return builder_name.endswith(TRYBOT_NAME_SUFFIX)
39 56
40 57
(...skipping 201 matching lines...) Expand 10 before | Expand all | Expand 10 after
242 # Skip buildbot runs of a CL if its commit log message contains the following 259 # Skip buildbot runs of a CL if its commit log message contains the following
243 # substring. 260 # substring.
244 SKIP_BUILDBOT_SUBSTRING = '(SkipBuildbotRuns)' 261 SKIP_BUILDBOT_SUBSTRING = '(SkipBuildbotRuns)'
245 262
246 # If the below regex is found in a CL's commit log message, only run the 263 # If the below regex is found in a CL's commit log message, only run the
247 # builders specified therein. 264 # builders specified therein.
248 RUN_BUILDERS_REGEX = '\(RunBuilders:(.+)\)' 265 RUN_BUILDERS_REGEX = '\(RunBuilders:(.+)\)'
249 RUN_BUILDERS_RE_COMPILED = re.compile(RUN_BUILDERS_REGEX) 266 RUN_BUILDERS_RE_COMPILED = re.compile(RUN_BUILDERS_REGEX)
250 267
251 268
269 def AndroidModelToDevice(android_model):
270 """ Converts Android model names to device names which android_setup.sh will
271 like.
272
273 Examples:
274 'NexusS' becomes 'nexus_s'
275 'Nexus10' becomes 'nexus_10'
276
277 android_model: string; model name for an Android device.
278 """
279 name_parts = []
280 for part in re.split('(\d+)', android_model):
281 if re.match('(\d+)', part):
282 name_parts.append(part)
283 else:
284 name_parts.extend(re.findall('[A-Z][a-z]*', part))
285 return '_'.join([part.lower() for part in name_parts])
286
287
252 # Since we can't modify the existing Helper class, we subclass it here, 288 # Since we can't modify the existing Helper class, we subclass it here,
253 # overriding the necessary parts to get things working as we want. 289 # overriding the necessary parts to get things working as we want.
254 # Specifically, the Helper class hardcodes each registered scheduler to be 290 # Specifically, the Helper class hardcodes each registered scheduler to be
255 # instantiated as a 'Scheduler,' which aliases 'SingleBranchScheduler.' We add 291 # instantiated as a 'Scheduler,' which aliases 'SingleBranchScheduler.' We add
256 # an 'AnyBranchScheduler' method and change the implementation of Update() to 292 # an 'AnyBranchScheduler' method and change the implementation of Update() to
257 # instantiate the proper type. 293 # instantiate the proper type.
258 294
259 # TODO(borenet): modify this code upstream so that we don't need this override. 295 # TODO(borenet): modify this code upstream so that we don't need this override.
260 # BUG: http://code.google.com/p/skia/issues/detail?id=761 296 # BUG: http://code.google.com/p/skia/issues/detail?id=761
261 class SkiaHelper(master_config.Helper): 297 class SkiaHelper(master_config.Helper):
262 298
263 def Builder(self, name, factory, gatekeeper=None, scheduler=None, 299 def Builder(self, name, factory, gatekeeper=None, scheduler=None,
264 builddir=None, auto_reboot=False, notify_on_missing=False, 300 builddir=None, auto_reboot=False, notify_on_missing=False):
265 override_category=None):
266 if override_category:
267 old_category = self._defaults.get('category')
268 self._defaults['category'] = override_category
269 super(SkiaHelper, self).Builder(name=name, factory=factory, 301 super(SkiaHelper, self).Builder(name=name, factory=factory,
270 gatekeeper=gatekeeper, scheduler=scheduler, 302 gatekeeper=gatekeeper, scheduler=scheduler,
271 builddir=builddir, auto_reboot=auto_reboot, 303 builddir=builddir, auto_reboot=auto_reboot,
272 notify_on_missing=notify_on_missing) 304 notify_on_missing=notify_on_missing)
273 if override_category:
274 self._defaults['category'] = old_category
275 305
276 def AnyBranchScheduler(self, name, branches, treeStableTimer=60, 306 def AnyBranchScheduler(self, name, branches, treeStableTimer=60,
277 categories=None): 307 categories=None):
278 if name in self._schedulers: 308 if name in self._schedulers:
279 raise ValueError('Scheduler %s already exist' % name) 309 raise ValueError('Scheduler %s already exist' % name)
280 self._schedulers[name] = {'type': 'AnyBranchScheduler', 310 self._schedulers[name] = {'type': 'AnyBranchScheduler',
281 'branches': branches, 311 'branches': branches,
282 'treeStableTimer': treeStableTimer, 312 'treeStableTimer': treeStableTimer,
283 'builders': [], 313 'builders': [],
284 'categories': categories} 314 'categories': categories}
(...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after
406 # been defined. 436 # been defined.
407 # pylint: disable=W0601 437 # pylint: disable=W0601
408 global skia_all_subdirs 438 global skia_all_subdirs
409 try: 439 try:
410 if skia_all_subdirs: 440 if skia_all_subdirs:
411 raise Exception('skia_all_subdirs has already been defined!') 441 raise Exception('skia_all_subdirs has already been defined!')
412 except NameError: 442 except NameError:
413 skia_all_subdirs = all_subdirs 443 skia_all_subdirs = all_subdirs
414 444
415 445
416 def MakeBuilderName(builder_base_name, config): 446 def MakeBuilderName(role, extra_config=None, is_trybot=False, **kwargs):
417 """ Inserts config into builder_base_name at '%s', or if builder_base_name 447 schema = BUILDER_NAME_SCHEMA.get(role)
418 does not contain '%s', appends config to the end of builder_base_name, 448 if not schema:
419 separated by an underscore. """ 449 raise ValueError('%s is not a recognized role.' % role)
420 try: 450 for k, v in kwargs.iteritems():
421 return builder_base_name % config 451 if BUILDER_NAME_SEP in v:
422 except TypeError: 452 raise ValueError('%s not allowed in %s.' % (v, BUILDER_NAME_SEP))
423 # If builder_base_name does not contain '%s' 453 if not k in schema:
424 return '%s_%s' % (builder_base_name, config) 454 raise ValueError('Schema does not contain "%s": %s' %(k, schema))
455 if extra_config and BUILDER_NAME_SEP in extra_config:
456 raise ValueError('%s not allowed in %s.' % (extra_config,
457 BUILDER_NAME_SEP))
458 name_parts = [role]
459 name_parts.extend([kwargs[attribute] for attribute in schema])
460 if extra_config:
461 name_parts.append(extra_config)
462 if is_trybot:
463 name_parts.append(TRYBOT_NAME_SUFFIX)
464 print BUILDER_NAME_SEP.join(name_parts)
465 return BUILDER_NAME_SEP.join(name_parts)
425 466
426 467
427 def MakeCompileBuilderName(builder_base_name, release=False): 468 def _MakeBuilder(helper, role, os, model, gpu, configuration, arch,
428 if release: 469 gm_image_subdir, factory_type, extra_config=None,
429 compile_name = 'Compile_Release' 470 perf_output_basedir=None, extra_branches=None, is_trybot=False,
430 else: 471 **kwargs):
431 compile_name = 'Compile_Debug' 472 """ Creates a builder and scheduler. """
432 return MakeBuilderName(builder_base_name, compile_name)
433
434
435 def MakeDebugBuilderName(builder_base_name):
436 return MakeBuilderName(builder_base_name, 'Debug')
437
438
439 def MakeReleaseBuilderName(builder_base_name):
440 return MakeBuilderName(builder_base_name, 'Release')
441
442
443 def MakeBenchBuilderName(builder_base_name):
444 return MakeBuilderName(builder_base_name, 'Bench')
445
446
447 def MakeSchedulerName(builder_base_name):
448 return MakeBuilderName(builder_base_name, 'Scheduler')
449
450
451 def _MakeBuilderSet(helper, builder_base_name, gm_image_subdir, factory_type,
452 perf_output_basedir=None, extra_branches=None,
453 do_compile=True, do_debug=True, do_release=True,
454 do_bench=True, try_schedulers=None,
455 compile_bot_warnings_as_errors=True, **kwargs):
456 """ Creates a trio of builders for a given platform:
457 1. Debug mode builder which runs all steps
458 2. Release mode builder which runs all steps EXCEPT benchmarks
459 3. Release mode builder which runs ONLY benchmarks.
460 """
461 B = helper.Builder 473 B = helper.Builder
462 F = helper.Factory 474 F = helper.Factory
463 475
464 if not extra_branches: 476 if not extra_branches:
465 extra_branches = [] 477 extra_branches = []
466 subdirs_to_checkout = set(extra_branches) 478 subdirs_to_checkout = set(extra_branches)
467 if gm_image_subdir: 479 if gm_image_subdir:
468 gm_image_branch = 'gm-expected/%s' % gm_image_subdir 480 gm_image_branch = 'gm-expected/%s' % gm_image_subdir
469 subdirs_to_checkout.add(gm_image_branch) 481 subdirs_to_checkout.add(gm_image_branch)
470 482
471 if try_schedulers: 483 builder_name = MakeBuilderName(
472 scheduler_name = '|'.join(try_schedulers) 484 role=role,
473 builder_base_name = builder_base_name + TRYBOT_NAME_SUFFIX 485 os=os,
486 model=model,
487 gpu=gpu,
488 configuration=configuration,
489 arch=arch,
490 extra_config=extra_config,
491 is_trybot=is_trybot)
492
493 if is_trybot:
494 scheduler_name = TRY_SCHEDULERS_STR
474 else: 495 else:
475 scheduler_name = MakeSchedulerName(builder_base_name) 496 scheduler_name = builder_name + BUILDER_NAME_SEP + 'Scheduler'
476 branches = list(subdirs_to_checkout.union(SKIA_PRIMARY_SUBDIRS)) 497 branches = list(subdirs_to_checkout.union(SKIA_PRIMARY_SUBDIRS))
477 helper.AnyBranchScheduler(scheduler_name, branches=branches) 498 helper.AnyBranchScheduler(scheduler_name, branches=branches)
478 499
479 if do_compile: 500 B(builder_name, 'f_%s' % builder_name, scheduler=scheduler_name)
480 compile_debug_builder_name = MakeCompileBuilderName(builder_base_name, 501 F('f_%s' % builder_name, factory_type(
481 release=False) 502 builder_name=builder_name,
482 B(compile_debug_builder_name, 'f_%s' % compile_debug_builder_name, 503 other_subdirs=subdirs_to_checkout,
483 # Do not add gatekeeper for trybots. 504 configuration=configuration,
484 gatekeeper='GateKeeper' if try_schedulers is None else None, 505 gm_image_subdir=gm_image_subdir,
485 scheduler=scheduler_name, override_category=CATEGORY_BUILD) 506 do_patch_step=is_trybot,
486 F('f_%s' % compile_debug_builder_name, factory_type( 507 perf_output_basedir=perf_output_basedir,
487 builder_name=compile_debug_builder_name, 508 **kwargs
488 other_subdirs=subdirs_to_checkout, 509 ).Build(role=role))
489 configuration='Debug',
490 gm_image_subdir=gm_image_subdir,
491 do_patch_step=(try_schedulers is not None),
492 perf_output_basedir=None,
493 compile_warnings_as_errors=compile_bot_warnings_as_errors,
494 **kwargs
495 ).BuildCompileOnly())
496 compile_release_builder_name = MakeCompileBuilderName(builder_base_name,
497 release=True)
498 B(compile_release_builder_name, 'f_%s' % compile_release_builder_name,
499 # Do not add gatekeeper for trybots.
500 gatekeeper='GateKeeper' if try_schedulers is None else None,
501 scheduler=scheduler_name, override_category=CATEGORY_BUILD)
502 F('f_%s' % compile_release_builder_name, factory_type(
503 builder_name=compile_release_builder_name,
504 other_subdirs=subdirs_to_checkout,
505 configuration='Release',
506 gm_image_subdir=gm_image_subdir,
507 do_patch_step=(try_schedulers is not None),
508 perf_output_basedir=None,
509 compile_warnings_as_errors=compile_bot_warnings_as_errors,
510 **kwargs
511 ).BuildCompileOnly())
512
513 if do_debug:
514 debug_builder_name = MakeDebugBuilderName(builder_base_name)
515 B(debug_builder_name, 'f_%s' % debug_builder_name,
516 scheduler=scheduler_name)
517 F('f_%s' % debug_builder_name, factory_type(
518 builder_name=debug_builder_name,
519 other_subdirs=subdirs_to_checkout,
520 configuration='Debug',
521 gm_image_subdir=gm_image_subdir,
522 do_patch_step=(try_schedulers is not None),
523 perf_output_basedir=None,
524 compile_warnings_as_errors=False,
525 **kwargs
526 ).Build())
527
528 if do_release:
529 no_perf_builder_name = MakeReleaseBuilderName(builder_base_name)
530 B(no_perf_builder_name, 'f_%s' % no_perf_builder_name,
531 scheduler=scheduler_name)
532 F('f_%s' % no_perf_builder_name, factory_type(
533 builder_name=no_perf_builder_name,
534 other_subdirs=subdirs_to_checkout,
535 configuration='Release',
536 gm_image_subdir=gm_image_subdir,
537 do_patch_step=(try_schedulers is not None),
538 perf_output_basedir=None,
539 compile_warnings_as_errors=False,
540 **kwargs
541 ).BuildNoPerf())
542
543 if do_bench:
544 perf_builder_name = MakeBenchBuilderName(builder_base_name)
545 B(perf_builder_name, 'f_%s' % perf_builder_name,
546 scheduler=scheduler_name)
547 F('f_%s' % perf_builder_name, factory_type(
548 builder_name=perf_builder_name,
549 other_subdirs=subdirs_to_checkout,
550 configuration='Release',
551 gm_image_subdir=gm_image_subdir,
552 do_patch_step=(try_schedulers is not None),
553 perf_output_basedir=perf_output_basedir,
554 compile_warnings_as_errors=False,
555 **kwargs
556 ).BuildPerfOnly())
557 510
558 511
559 def _MakeBuilderAndMaybeTrybotSet(do_trybots=True, **kwargs): 512 def _MakeBuilderAndMaybeTrybotSet(do_trybots=True, **kwargs):
560 _MakeBuilderSet(try_schedulers=None, **kwargs) 513 _MakeBuilder(**kwargs)
561 if do_trybots: 514 if do_trybots:
562 _MakeBuilderSet(try_schedulers=TRY_SCHEDULERS, **kwargs) 515 _MakeBuilder(is_trybot=True, **kwargs)
563 516
564 517
565 def MakeBuilderSet(**kwargs): 518 def MakeBuilderSet(**kwargs):
566 _MakeBuilderAndMaybeTrybotSet(**kwargs) 519 _MakeBuilderAndMaybeTrybotSet(**kwargs)
567 520
568 521
569 def MakeHousekeeperBuilderSet(helper, percommit_factory_type, 522 def _MakeCompileBuilder(helper, scheduler, os, compiler, configuration,
570 periodic_factory_type, do_trybots, **kwargs): 523 target_arch, factory_type, is_trybot,
571 B = helper.Builder 524 extra_config=None, **kwargs):
572 F = helper.Factory 525 builder_name = MakeBuilderName(role=BUILDER_ROLE_COMPILE,
526 os=os,
527 compiler=compiler,
528 configuration=configuration,
529 target_arch=target_arch,
530 extra_config=extra_config,
531 is_trybot=is_trybot)
532 helper.Builder(builder_name, 'f_%s' % builder_name,
533 # Do not add gatekeeper for trybots.
534 gatekeeper='GateKeeper' if is_trybot else None,
535 scheduler=scheduler)
536 helper.Factory('f_%s' % builder_name, factory_type(
537 builder_name=builder_name,
538 do_patch_step=is_trybot,
539 configuration=configuration,
540 **kwargs
541 ).Build(role=BUILDER_ROLE_COMPILE))
542 return builder_name
573 543
574 builder_factory_scheduler = [ 544
575 # The Percommit housekeeper 545 def MakeCompileBuilderSet(scheduler, do_trybots=True, **kwargs):
576 ('Skia_PerCommit_House_Keeping',
577 percommit_factory_type,
578 'skia_rel'),
579 # The Periodic housekeeper
580 ('Skia_Periodic_House_Keeping',
581 periodic_factory_type,
582 'skia_periodic'),
583 ]
584 if do_trybots: 546 if do_trybots:
585 # Add the corresponding trybot builders to the above list. 547 _MakeCompileBuilder(scheduler=scheduler, is_trybot=True, **kwargs)
586 builder_factory_scheduler.extend([ 548 _MakeCompileBuilder(scheduler=TRY_SCHEDULERS_STR, is_trybot=False, **kwargs)
587 (builder + TRYBOT_NAME_SUFFIX, factory, TRY_SCHEDULERS_STR)
588 for (builder, factory, _scheduler) in builder_factory_scheduler])
589 549
590 for (builder_name, factory, scheduler) in builder_factory_scheduler:
591 B(builder_name, 'f_%s' % builder_name, scheduler=scheduler)
592 F('f_%s' % builder_name,
593 factory(
594 builder_name=builder_name,
595 do_patch_step=(scheduler == TRY_SCHEDULERS_STR),
596 **kwargs
597 ).Build())
598 550
599 def CanMergeBuildRequests(req1, req2): 551 def CanMergeBuildRequests(req1, req2):
600 """ Determine whether or not two BuildRequests can be merged. Note that the 552 """ Determine whether or not two BuildRequests can be merged. Note that the
601 call to buildbot.sourcestamp.SourceStamp.canBeMergedWith() is conspicuously 553 call to buildbot.sourcestamp.SourceStamp.canBeMergedWith() is conspicuously
602 missing. This is because that method verifies that: 554 missing. This is because that method verifies that:
603 1. req1.source.repository == req2.source.repository 555 1. req1.source.repository == req2.source.repository
604 2. req1.source.project == req2.source.project 556 2. req1.source.project == req2.source.project
605 3. req1.source.branch == req2.source.branch 557 3. req1.source.branch == req2.source.branch
606 4. req1.patch == None and req2.patch = None 558 4. req1.patch == None and req2.patch = None
607 5. (req1.source.changes and req2.source.changes) or \ 559 5. (req1.source.changes and req2.source.changes) or \
(...skipping 28 matching lines...) Expand all
636 # request is associated with a change but the revisions match (#5 above). 588 # request is associated with a change but the revisions match (#5 above).
637 if req1.source.changes and not req2.source.changes: 589 if req1.source.changes and not req2.source.changes:
638 return False 590 return False
639 if not req1.source.changes and req2.source.changes: 591 if not req1.source.changes and req2.source.changes:
640 return False 592 return False
641 if not (req1.source.changes and req2.source.changes): 593 if not (req1.source.changes and req2.source.changes):
642 if req1.source.revision != req2.source.revision: 594 if req1.source.revision != req2.source.revision:
643 return False 595 return False
644 596
645 return True 597 return True
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698