cf3ae0167157a783734025e0b755db12e04168b4
[chromiumos/chromite.git] / buildbot / cbuildbot_config.py
1 #!/usr/bin/python
2 # Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
3 # Use of this source code is governed by a BSD-style license that can be
4 # found in the LICENSE file.
5
6
7 # Disable relative import warning from pylint.
8 # pylint: disable=W0403
9 import constants
10 import copy
11 import json
12 import optparse
13 import sys
14 import urllib
15
16 GS_PATH_DEFAULT = 'default' # Means gs://chromeos-archive/ + bot_id
17
18 # Contains the valid build config suffixes in the order that they are dumped.
19 CONFIG_TYPE_RELEASE = 'release'
20 CONFIG_TYPE_FULL = 'full'
21 CONFIG_TYPE_FIRMWARE = 'firmware'
22
23 CONFIG_TYPE_DUMP_ORDER = (
24     'paladin',
25     constants.PRE_CQ_BUILDER_NAME,
26     'pre-cq',
27     'pre-cq-launcher',
28     'incremental',
29     'telemetry',
30     CONFIG_TYPE_FULL,
31     CONFIG_TYPE_RELEASE,
32     'release-group',
33     'release-pgo',
34     'release-pgo-generate',
35     'release-pgo-use',
36     'sdk',
37     'chromium-pfq',
38     'chromium-pfq-informational',
39     'chrome-perf',
40     'chrome-pgo',
41     'chrome-pfq',
42     'chrome-pfq-informational',
43     'pre-flight-branch',
44     'factory',
45     CONFIG_TYPE_FIRMWARE,
46     'toolchain-major',
47     'toolchain-minor',
48     'asan',
49     'asan-informational',
50     'refresh-packages',
51     'platform2',
52     'stumpy_test_ap',
53     constants.BRANCH_UTIL_CONFIG,
54 )
55
56 def OverrideConfigForTrybot(build_config, options):
57   """Apply trybot-specific configuration settings.
58
59   Args:
60     build_config:  The build configuration dictionary to override.
61       The dictionary is not modified.
62     options: The options passed on the commandline.
63   Returns:
64     A build configuration dictionary with the overrides applied.
65   """
66   copy_config = copy.deepcopy(build_config)
67   for my_config in [copy_config] + copy_config['child_configs']:
68     my_config['uprev'] = True
69     if my_config['internal']:
70       my_config['overlays'] = constants.BOTH_OVERLAYS
71
72     # Most users don't have access to the pdf repository so disable pdf along
73     # with all other official_chrome useflags, so that we use the external
74     # chromium prebuilts.
75     useflags = my_config['useflags']
76     if not options.remote_trybot and useflags:
77       for chrome_use in official_chrome['useflags']:
78         if chrome_use in useflags:
79           useflags.remove(chrome_use)
80
81     # Use the local manifest which only requires elevated access if it's really
82     # needed to build.
83     if not options.remote_trybot:
84       my_config['manifest'] = my_config['dev_manifest']
85
86     my_config['push_image'] = False
87     if options.hwtest:
88       my_config['upload_hw_test_artifacts'] = True
89       if not my_config['hw_tests']:
90         my_config['hw_tests'] = HWTestConfig.DefaultList(
91             num=constants.HWTEST_TRYBOT_NUM, pool=constants.HWTEST_TRYBOT_POOL,
92             fatal_timeouts=True, file_bugs=False)
93       else:
94         for hw_config in my_config['hw_tests']:
95           hw_config.num = constants.HWTEST_TRYBOT_NUM
96           hw_config.pool = constants.HWTEST_TRYBOT_POOL
97           hw_config.fatal_timeouts = True
98           hw_config.file_bugs = False
99
100     # Default to starting with a fresh chroot on remote trybot runs.
101     if options.remote_trybot:
102       my_config['chroot_replace'] = True
103
104     # In trybots, we want to always run VM tests and all unit tests, so that
105     # developers will get better testing for their changes.
106     if (my_config['build_type'] == constants.PALADIN_TYPE
107         and not my_config['arm']):
108       my_config['vm_tests'] = constants.SIMPLE_AU_TEST_TYPE
109       my_config['quick_unit'] = False
110
111   return copy_config
112
113
114 def GetManifestVersionsRepoUrl(internal_build, read_only=False, test=False):
115   """Returns the url to the manifest versions repository.
116
117   Args:
118     internal_build: Whether to use the internal repo.
119     read_only: Whether the URL may be read only.  If read_only is True,
120       pushing changes (even with dryrun option) may not work.
121     test: Whether we should use the corresponding test repositories. These
122       should be used when staging experimental features.
123   """
124   if internal_build:
125     url = (constants.GERRIT_INT_SSH_URL +
126             constants.MANIFEST_VERSIONS_INT_SUFFIX)
127   elif read_only:
128     url = constants.GIT_HTTP_URL + constants.MANIFEST_VERSIONS_SUFFIX
129   else:
130     url = constants.GERRIT_SSH_URL + constants.MANIFEST_VERSIONS_SUFFIX
131
132   if test:
133     url += '-test'
134
135   return url
136
137
138 def IsPFQType(b_type):
139   """Returns True if this build type is a PFQ."""
140   return b_type in (constants.PFQ_TYPE, constants.PALADIN_TYPE,
141                     constants.CHROME_PFQ_TYPE)
142
143
144 def IsCQType(b_type):
145   """Returns True if this build type is a Commit Queue."""
146   return b_type in (constants.COMMIT_QUEUE_TYPE, constants.PALADIN_TYPE)
147
148
149 # List of usable cbuildbot configs; see add_config method.
150 config = {}
151
152
153 # pylint: disable=W0102
154 def GetCanariesForChromeLKGM(configs=config):
155   """Grabs a list of builders that are important for the Chrome LKGM."""
156   builders = []
157   for build_name, conf in configs.iteritems():
158     if (conf['build_type'] == constants.CANARY_TYPE and
159         conf['critical_for_chrome']):
160       builders.append(build_name)
161
162   return builders
163
164
165 def FindFullConfigsForBoard(board):
166   """Returns full builder configs for a board.
167
168   Returns:
169     A tuple containing a list of matching external configs and a list of
170     matching internal configs for a board.
171   """
172   ext_cfgs = []
173   int_cfgs = []
174
175   for name, c in config.iteritems():
176     if c['boards'] and board in c['boards']:
177       if name.endswith('-%s' % CONFIG_TYPE_RELEASE) and c['internal']:
178         int_cfgs.append(copy.deepcopy(c))
179       elif name.endswith('-%s' % CONFIG_TYPE_FULL) and not c['internal']:
180         ext_cfgs.append(copy.deepcopy(c))
181
182   return ext_cfgs, int_cfgs
183
184
185 def FindCanonicalConfigForBoard(board):
186   """Get the canonical cbuildbot builder config for a board."""
187   ext_cfgs, int_cfgs = FindFullConfigsForBoard(board)
188   # If both external and internal builds exist for this board, prefer the
189   # internal one.
190   both = int_cfgs + ext_cfgs
191   if not both:
192     raise ValueError('Invalid board specified: %s.' % board)
193   return both[0]
194
195
196 # Enumeration of valid settings; any/all config settings must be in this.
197 # All settings must be documented.
198
199 _settings = dict(
200
201 # name -- The name of the config.
202   name=None,
203
204 # boards -- A list of boards to build.
205   boards=None,
206
207 # paladin_builder_name -- Used by paladin logic. The name of the builder on the
208 #                         buildbot waterfall if it differs from the config name.
209 #                         If None is used, defaults to config name.
210   paladin_builder_name=None,
211
212 # profile -- The profile of the variant to set up and build.
213   profile=None,
214
215 # master -- This bot pushes changes to the overlays.
216   master=False,
217
218 # important -- Master bot uses important bots to determine overall status.
219 #              i.e. if master bot succeeds and other important slaves succeed
220 #              then the master will uprev packages.  This should align
221 #              with info vs. closer except for the master and options.tests.
222   important=False,
223
224 # internal -- Whether this is an internal build config.
225   internal=False,
226
227 # branch -- Whether this is a branched build config. Used for pfq logic.
228   branch=False,
229
230 # manifest -- The name of the manifest to use. E.g., to use the buildtools
231 #             manifest, specify 'buildtools'.
232   manifest=constants.DEFAULT_MANIFEST,
233
234 # dev_manifest -- The name of the manifest to use if we're building on a local
235 #                 trybot. This should only require elevated access if it's
236 #                 really needed to build this config.
237   dev_manifest=constants.DEFAULT_MANIFEST,
238
239 # useflags -- emerge use flags to use while setting up the board, building
240 #             packages, making images, etc.
241   useflags=None,
242
243 # chromeos_official -- Set the variable CHROMEOS_OFFICIAL for the build.
244 #                      Known to affect parallel_emerge, cros_set_lsb_release,
245 #                      and chromeos_version.sh. See bug chromium-os:14649
246   chromeos_official=False,
247
248 # usepkg_setup_board -- Use binary packages for setup_board. (emerge --usepkg)
249   usepkg_setup_board=True,
250
251 # usepkg_build_packages -- Use binary packages for build_packages.
252   usepkg_build_packages=True,
253
254 # chrome_binhost_only -- Only use binaries in build_packages for Chrome itself.
255   chrome_binhost_only=False,
256
257 # sync_chrome -- Does this profile need to sync chrome?  If None, we guess based
258 #                on other factors.  If True/False, we always do that.
259   sync_chrome=None,
260
261 # latest_toolchain -- Use the newest ebuilds for all the toolchain packages.
262   latest_toolchain=False,
263
264 # gcc_githash -- This is only valid when latest_toolchain is True.
265 # If you set this to a commit-ish, the gcc ebuild will use it to build the
266 # toolchain compiler.
267   gcc_githash=None,
268
269 # board_replace -- wipe and replace the board inside the chroot.
270   board_replace=False,
271
272 # chroot_replace -- wipe and replace chroot, but not source.
273   chroot_replace=False,
274
275 # uprev -- Uprevs the local ebuilds to build new changes since last stable.
276 #          build.  If master then also pushes these changes on success.
277 #          Note that we uprev on just about every bot config because it gives us
278 #          a more deterministic build system (the tradeoff being that some bots
279 #          build from source more frequently than if they never did an uprev).
280 #          This way the release/factory/etc... builders will pick up changes
281 #          that devs pushed before it runs, but after the correspoding PFQ bot
282 #          ran (which is what creates+uploads binpkgs).  The incremental bots
283 #          are about the only ones that don't uprev because they mimic the flow
284 #          a developer goes through on their own local systems.
285   uprev=True,
286
287 # overlays -- Select what overlays to look at for revving and prebuilts. This
288 #             can be any constants.VALID_OVERLAYS.
289   overlays=constants.PUBLIC_OVERLAYS,
290
291 # push_overlays -- Select what overlays to push at. This should be a subset of
292 #                  overlays for the particular builder.  Must be None if
293 #                  not a master.  There should only be one master bot pushing
294 #                  changes to each overlay per branch.
295   push_overlays=None,
296
297 # chrome_rev -- Uprev Chrome, values of 'tot', 'stable_release', or None.
298   chrome_rev=None,
299
300 # compilecheck -- Exit the builder right after checking compilation.
301   compilecheck=False,
302
303 # pre_cq -- Test CLs to verify they're ready for the commit queue.
304   pre_cq=False,
305
306 # signer_tests -- Runs the tests that the signer would run.
307   signer_tests=False,
308
309 # unittests -- Runs unittests for packages.
310   unittests=True,
311
312 # quick_unit -- If unittests is true, only run the unit tests for packages which
313 #               have changed since the previous build.
314   quick_unit=True,
315
316 # unittest_blacklist -- A list of the packages to blacklist from unittests.
317   unittest_blacklist=[],
318
319 # build_tests -- Builds autotest tests.  Must be True if vm_tests is set.
320   build_tests=True,
321
322 # pgo_generate -- Generates PGO data.
323   pgo_generate=False,
324
325 # pgo_use -- Uses PGO data.
326   pgo_use=False,
327
328 # vm_tests -- Run vm test type defined in constants.
329   vm_tests=constants.SIMPLE_AU_TEST_TYPE,
330
331 # A list of HWTestConfig objects to run.
332   hw_tests=[],
333
334 # upload_hw_test_artifacts -- If true, uploads artifacts for hw testing.
335   upload_hw_test_artifacts=False,
336
337 # upload_standalone_images -- If true, uploads individual image tarballs.
338   upload_standalone_images=True,
339
340 # gs_path -- Google Storage path to offload files to.
341 #            None - No upload
342 #            GS_PATH_DEFAULT - 'gs://chromeos-image-archive/' + bot_id
343 #            value - Upload to explicit path
344   gs_path=GS_PATH_DEFAULT,
345
346 # TODO(sosa): Deprecate binary.
347 # build_type -- Type of builder.  Check constants.VALID_BUILD_TYPES.
348   build_type=constants.PFQ_TYPE,
349
350 # arm -- Whether the board we are building is arm-based.
351   arm=False,
352
353   archive_build_debug=False,
354
355 # images -- List of images we want to build -- see build_image for more details.
356   images=['test'],
357   factory_install_netboot=True,
358
359 # packages -- Tuple of specific packages we want to build.  Most configs won't
360 #             specify anything here and instead let build_packages calculate.
361   packages=(),
362
363 # push_image -- Do we push a final release image to chromeos-images.
364   push_image=False,
365
366 # upload_symbols -- Do we upload debug symbols.
367   upload_symbols=False,
368
369 # hwqual -- Whether we upload a hwqual tarball.
370   hwqual=False,
371
372 # manifest_repo_url -- git repository URL for our manifests.
373 #   External: https://git.chromium.org/git/chromiumos/manifest
374 #   Internal: ssh://gerrit-int.chromium.org:29419/chromeos/manifest-internal
375   manifest_repo_url=constants.MANIFEST_URL,
376
377 # manifest_version -- Whether we are using the manifest_version repo that stores
378 #                     per-build manifests.
379   manifest_version=False,
380
381 # use_lkgm -- Use the Last Known Good Manifest blessed by Paladin.
382   use_lkgm=False,
383
384 # use_chrome_lkgm -- LKGM for Chrome OS generated for Chrome builds that are
385 # blessed from canary runs.
386   use_chrome_lkgm=False,
387
388 # True if this build config is critical for the chrome_lkgm decision.
389   critical_for_chrome=False,
390
391 # prebuilts -- Upload prebuilts for this build. Valid values are PUBLIC,
392 #              PRIVATE, or False.
393   prebuilts=False,
394
395 # use_sdk -- Use SDK as opposed to building the chroot from source.
396   use_sdk=True,
397
398 # trybot_list -- List this config when user runs cbuildbot with --list option
399 #                without the --all flag.
400   trybot_list=False,
401
402 # description -- The description string to print out for config when user runs
403 #                --list.
404   description=None,
405
406 # git_sync -- Boolean that enables parameter --git-sync for upload_prebuilts.
407   git_sync=False,
408
409 # child_configs -- A list of the child config groups, if applicable. See the
410 #                  add_group method.
411   child_configs=[],
412
413 # shared_user_password -- Set shared user password for "chronos" user in built
414 #                         images. Use "None" (default) to remove the shared
415 #                         user password. Note that test images will always set
416 #                         the password to "test0000".
417   shared_user_password=None,
418
419 # grouped -- Whether this config belongs to a config group.
420   grouped=False,
421
422 # disk_layout -- layout of build_image resulting image.
423 #                See scripts/build_library/legacy_disk_layout.json or
424 #                overlay-<board>/scripts/disk_layout.json for possible values.
425   disk_layout=None,
426
427 # disk_vm_layout -- layout of image_to_vm.sh resulting image. See
428 #                   disk_layout for more info.
429   disk_vm_layout='2gb-rootfs-updatable',
430
431 # postsync_patch -- If enabled, run the PatchChanges stage.  Enabled by default.
432 #                   Can be overridden by the --nopatch flag.
433   postsync_patch=True,
434
435 # postsync_rexec -- Reexec into the buildroot after syncing.  Enabled by
436 #                   default.
437   postsync_reexec=True,
438
439 # create_delta_sysroot -- Create delta sysroot during ArchiveStage. Disabled by
440 #                          default.
441   create_delta_sysroot=False,
442
443 # TODO(sosa): Collapse to one option.
444 # ====================== Dev installer prebuilts options =======================
445
446 # binhost_bucket -- Upload prebuilts for this build to this bucket. If it equals
447 #                   None the default buckets are used.
448   binhost_bucket=None,
449
450 # binhost_key -- Parameter --key for upload_prebuilts. If it equals None, the
451 #                default values are used, which depend on the build type.
452   binhost_key=None,
453
454 # binhost_base_url -- Parameter --binhost-base-url for upload_prebuilts. If it
455 #                     equals None, the default value is used.
456   binhost_base_url=None,
457
458 # Upload dev installer prebuilts.
459   dev_installer_prebuilts=False,
460
461 # Enable rootfs verification on the image.
462   rootfs_verification=True,
463
464 # Runs through the chrome-sdk workflow.
465   chrome_sdk=False,
466
467 # If chrome_sdk is set to True, this determines whether we use goma to build
468 # chrome.
469   chrome_sdk_goma=False,
470
471 # =============================================================================
472 )
473
474
475 class _JSONEncoder(json.JSONEncoder):
476   """Json Encoder that encodes objects as their dictionaries."""
477   # pylint: disable=E0202
478   def default(self, obj):
479     return self.encode(obj.__dict__)
480
481
482 class HWTestConfig(object):
483   """Config object for test suites.
484
485   Members:
486     copy_perf_results: If set to True, copy test results back from GS and send
487                        them to the perf dashboard.
488     timeout: How long to wait before timing out waiting for results. Usually,
489              2 hours and ten minutes. This must be less than
490              lib.parallel._BackgroundTask.MINIMUM_SILENT_TIMEOUT.
491     pool: Pool to use for hw testing.
492     async: Fire-and-forget suite.
493     critical: Usually we consider structural failures here as OK.
494     num: Maximum number of devices to use when scheduling tests in the hw lab.
495     file_bugs: Should we file bugs if a test fails in a suite run.
496   """
497
498   DEFAULT_HW_TEST = 'bvt'
499   DEFAULT_HW_TEST_TIMEOUT = 60 * 130
500   # Number of tests running in parallel in the AU suite.
501   AU_TESTS_NUM = 2
502
503   @classmethod
504   def DefaultList(cls, **dargs):
505     """Returns the default list of tests with overrides for optional args."""
506     # Set the number of machines for the au suite. If we are confined with the
507     # number of duts in the lab, only give 1 dut to the AU suite.
508     if (dargs.get('num', constants.HWTEST_DEFAULT_NUM) >=
509         constants.HWTEST_DEFAULT_NUM):
510       au_dict = dict(num=cls.AU_TESTS_NUM)
511     else:
512       au_dict = dict(num=1)
513
514     au_dargs = dargs.copy()
515     au_dargs.update(au_dict)
516     # BVT + AU suite.
517     return [cls(cls.DEFAULT_HW_TEST, **dargs),
518             cls(constants.HWTEST_AU_SUITE, **au_dargs)]
519
520   @classmethod
521   def PGOList(cls, **dargs):
522     """Returns a list of tests to be run on the PGO'd image."""
523     pgo_dict = dict(pool=constants.HWTEST_CHROME_PERF_POOL,
524                     timeout=90 * 60, num=1, async=True)
525     pgo_dict.update(dargs)
526     return [cls('pyauto_perf', **pgo_dict),
527             cls('perf_v2', **pgo_dict)]
528
529   @classmethod
530   def DefaultListCQ(cls, **dargs):
531     """Returns the default list for cq tests with overrides."""
532     default_dict = dict(pool=constants.HWTEST_PALADIN_POOL, timeout=50 * 60,
533                         fatal_timeouts=True, file_bugs=False)
534     # Allows dargs overrides to default_dict for cq.
535     default_dict.update(dargs)
536     return [cls(cls.DEFAULT_HW_TEST, **default_dict)]
537
538   def __init__(self, suite, num=constants.HWTEST_DEFAULT_NUM,
539                pool=constants.HWTEST_MACH_POOL, copy_perf_results=False,
540                timeout=DEFAULT_HW_TEST_TIMEOUT, async=False, critical=False,
541                fatal_timeouts=False, file_bugs=False):
542     """Constructor -- see members above."""
543     self.suite = suite
544     self.num = num
545     self.pool = pool
546     self.copy_perf_results = copy_perf_results
547     self.timeout = timeout
548     self.async = async
549     self.critical = critical
550     self.fatal_timeouts = fatal_timeouts
551     self.file_bugs = file_bugs
552
553
554 def PGORecordTest(**dargs):
555   default_dict = dict(pool=constants.HWTEST_CHROME_PFQ_POOL,
556                       critical=True, num=1, file_bugs=False)
557   # Allows dargs overrides to default_dict for cq.
558   default_dict.update(dargs)
559   return HWTestConfig('PGO_record', **default_dict)
560
561
562 class _config(dict):
563   """Dictionary of explicit configuration settings for a cbuildbot config
564
565   Each dictionary entry is in turn a dictionary of config_param->value.
566
567   See _settings for details on known configurations, and their documentation.
568   """
569
570   _URLQUOTED_PARAMS = ('paladin_builder_name',)
571
572   def derive(self, *inherits, **overrides):
573     """Create a new config derived from this one.
574
575     Args:
576       inherits: Mapping instances to mixin.
577       overrides: Settings to inject; see _settings for valid values.
578     Returns:
579       A new _config instance.
580     """
581     new_config = copy.deepcopy(self)
582     for update_config in inherits:
583       new_config.update(update_config)
584
585     new_config.update(overrides)
586
587     return copy.deepcopy(new_config)
588
589   def add_config(self, name, *inherits, **overrides):
590     """Derive and add the config to cbuildbots usable config targets
591
592     Args:
593       name: The name to label this configuration; this is what cbuildbot
594             would see.
595       inherits: See the docstring of derive.
596       overrides: See the docstring of derive.
597     Returns:
598       See the docstring of derive.
599     """
600     overrides['name'] = name
601     new_config = self.derive(*inherits, **overrides)
602
603     # Derive directly from defaults so missing values are added.
604     # Store a dictionary, rather than our derivative- this is
605     # to ensure any far flung consumers of the config dictionary
606     # aren't affected by recent refactorings.
607
608     config_dict = _default.derive(self, *inherits, **overrides)
609     config_dict.update((key, urllib.quote(config_dict[key]))
610       for key in self._URLQUOTED_PARAMS if config_dict.get(key))
611
612     config[name] = config_dict
613
614     return new_config
615
616   @classmethod
617   def add_raw_config(cls, name, *inherits, **overrides):
618     return cls().add_config(name, *inherits, **overrides)
619
620   @classmethod
621   def add_group(cls, name, *configs, **group_overrides):
622     """Create a new group of build configurations.
623
624     Args:
625       name: The name to label this configuration; this is what cbuildbot
626             would see.
627       configs: Configurations to build in this group. The first config in
628                the group is considered the primary configuration and is used
629                for syncing and creating the chroot.
630       group_overrides: See the docstring of derive. Applies to entire group.
631     """
632     child_configs = [_default.derive(x, grouped=True) for x in configs]
633     group_overrides['child_configs'] = child_configs
634     return configs[0].add_config(name, **group_overrides)
635
636 _default = _config(**_settings)
637
638
639 # It is only safe to inherit prebuilts from generic boards, or from the
640 # same board without the variant. This rule helps keep inheritance trees
641 # sane.
642 generic_boards = set([
643   'x86-generic', 'amd64-generic', 'daisy'
644 ])
645
646
647 # Arch-specific mixins.
648
649 arm = _config(
650   arm=True,
651   # VM/tests are broken on arm.
652   unittests=False,
653   vm_tests=None,
654 )
655
656 amd64 = _config()
657
658
659 # Builder-specific mixins
660
661 binary = _config(
662   # Full builds that build fully from binaries.
663   quick_unit=False,
664
665   build_type=constants.BUILD_FROM_SOURCE_TYPE,
666   archive_build_debug=True,
667   images=['test', 'factory_test', 'factory_install'],
668   git_sync=True,
669 )
670
671 full = _config(
672   # Full builds are test builds to show that we can build from scratch,
673   # so use settings to build from scratch, and archive the results.
674
675   usepkg_setup_board=False,
676   usepkg_build_packages=False,
677   chroot_replace=True,
678
679   quick_unit=False,
680
681   build_type=constants.BUILD_FROM_SOURCE_TYPE,
682   archive_build_debug=True,
683   images=['base', 'test', 'factory_test', 'factory_install'],
684   git_sync=True,
685   trybot_list=True,
686   description='Full Builds',
687 )
688
689 # Full builders with prebuilts.
690 full_prebuilts = full.derive(
691   prebuilts=constants.PUBLIC,
692 )
693
694 pfq = _config(
695   build_type=constants.PFQ_TYPE,
696   important=True,
697   uprev=True,
698   overlays=constants.PUBLIC_OVERLAYS,
699   manifest_version=True,
700   trybot_list=True,
701 )
702
703 paladin = _config(
704   important=True,
705   build_type=constants.PALADIN_TYPE,
706   overlays=constants.PUBLIC_OVERLAYS,
707   prebuilts=constants.PUBLIC,
708   manifest_version=True,
709   trybot_list=True,
710   description='Commit Queue',
711 )
712
713 # Used for paladin builders that build from source.
714 full_paladin = _config(
715   board_replace=True,
716   chrome_binhost_only=True,
717 )
718
719 # Incremental builders are intended to test the developer workflow.
720 # For that reason, they don't uprev.
721 incremental = _config(
722   build_type=constants.INCREMENTAL_TYPE,
723   uprev=False,
724   overlays=constants.PUBLIC_OVERLAYS,
725   description='Incremental Builds',
726 )
727
728 # This builds with more source available.
729 internal = _config(
730   internal=True,
731   overlays=constants.BOTH_OVERLAYS,
732   manifest_repo_url=constants.MANIFEST_INT_URL,
733 )
734
735 # This adds Chrome branding.
736 official_chrome = _config(
737   useflags=[constants.USE_CHROME_INTERNAL, constants.USE_CHROME_PDF],
738 )
739
740 # This sets chromeos_official.
741 official = official_chrome.derive(
742   chromeos_official=True,
743 )
744
745 _cros_sdk = full_prebuilts.add_config('chromiumos-sdk',
746   # The amd64-host has to be last as that is when the toolchains
747   # are bundled up for inclusion in the sdk.
748   boards=('x86-generic', 'arm-generic', 'amd64-generic'),
749   build_type=constants.CHROOT_BUILDER_TYPE,
750   use_sdk=False,
751   trybot_list=True,
752   description='Build the SDK and all the cross-compilers',
753 )
754
755 asan = _config(
756   chroot_replace=True,
757   profile='asan',
758   useflags=['asan'], # see profile for more
759   disk_layout='2gb-rootfs',
760   disk_vm_layout='2gb-rootfs-updatable',
761 )
762
763 _config.add_raw_config('refresh-packages',
764   boards=['x86-generic', 'arm-generic'],
765   build_type=constants.REFRESH_PACKAGES_TYPE,
766   description='Check upstream Gentoo for package updates',
767 )
768
769 incremental.add_config('x86-generic-incremental',
770   boards=['x86-generic'],
771 )
772
773 incremental.add_config('daisy-incremental',
774   arm,
775   boards=['daisy'],
776 )
777
778 incremental.add_config('amd64-generic-incremental',
779   amd64,
780   boards=['amd64-generic'],
781   # This builder runs on a VM, so it can't run VM tests.
782   vm_tests=None,
783 )
784
785 incremental.add_config('x32-generic-incremental',
786   amd64,
787   boards=['x32-generic'],
788   # This builder runs on a VM, so it can't run VM tests.
789   vm_tests=None,
790 )
791
792 paladin.add_config('x86-generic-paladin',
793   boards=['x86-generic'],
794   paladin_builder_name='x86 generic paladin',
795 )
796
797 paladin.add_config('amd64-generic-paladin',
798   amd64,
799   boards=['amd64-generic'],
800   paladin_builder_name='amd64 generic paladin',
801 )
802
803 paladin.add_config('x32-generic-paladin',
804   amd64,
805   boards=['x32-generic'],
806   paladin_builder_name='x32 generic paladin',
807   important=False,
808 )
809
810 telemetry = _config(
811   build_type=constants.INCREMENTAL_TYPE,
812   uprev=False,
813   overlays=constants.PUBLIC_OVERLAYS,
814   vm_tests=constants.TELEMETRY_SUITE_TEST_TYPE,
815   description='Telemetry Builds',
816 )
817
818 telemetry.add_config('amd64-generic-telemetry',
819   amd64,
820   boards=['amd64-generic'],
821 )
822
823 telemetry.add_config('arm-generic-telemetry',
824   arm,
825   boards=['arm-generic'],
826 )
827
828 telemetry.add_config('x86-generic-telemetry',
829   boards=['x86-generic'],
830 )
831
832 chromium_pfq = _config(
833   build_type=constants.CHROME_PFQ_TYPE,
834   important=True,
835   uprev=False,
836   overlays=constants.PUBLIC_OVERLAYS,
837   manifest_version=True,
838   chrome_rev=constants.CHROME_REV_LATEST,
839   upload_hw_test_artifacts=True,
840 )
841
842 # TODO(davidjames): Convert this to an external config once the unified master
843 # logic is ready.
844 internal_chromium_pfq = internal.derive(
845   chromium_pfq,
846   description='Preflight Chromium Build (internal)',
847   overlays=constants.BOTH_OVERLAYS,
848   prebuilts=constants.PUBLIC,
849 )
850
851 internal_chromium_pfq.add_config('x86-generic-chromium-pfq',
852   boards=['x86-generic'],
853   master=True,
854   push_overlays=constants.BOTH_OVERLAYS,
855 )
856
857 internal_chromium_pfq.add_config('daisy-chromium-pfq',
858   arm,
859   boards=['daisy'],
860 )
861
862 internal_chromium_pfq.add_config('amd64-generic-chromium-pfq',
863   amd64,
864   boards=['amd64-generic'],
865 )
866
867 chrome_pfq = internal_chromium_pfq.derive(
868   official,
869   important=True,
870   overlays=constants.BOTH_OVERLAYS,
871   description='Preflight Chrome build (internal)',
872   upload_hw_test_artifacts=True,
873   prebuilts=constants.PRIVATE,
874 )
875
876 chrome_pfq.add_config('alex-chrome-pfq',
877   boards=['x86-alex'],
878 )
879
880 chrome_pfq.add_config('lumpy-chrome-pfq',
881   boards=['lumpy'],
882 )
883
884 chrome_pfq.add_config('daisy_spring-chrome-pfq',
885   arm,
886   boards=['daisy_spring'],
887 )
888
889 chromium_info = chromium_pfq.derive(
890   chrome_rev=constants.CHROME_REV_TOT,
891   use_lkgm=True,
892   important=False,
893   manifest_version=False,
894   vm_tests=constants.SMOKE_SUITE_TEST_TYPE,
895   disk_vm_layout='usb',
896 )
897
898 chrome_info = chromium_info.derive(
899   internal, official,
900 )
901
902 # Config with the official flags except pdf.
903 chrome_info_no_pdf = chrome_info.derive(
904   useflags=[y for y in official['useflags'] if y != constants.USE_CHROME_PDF],
905 )
906
907 chrome_perf = chrome_info.derive(
908   vm_tests=None,
909   upload_hw_test_artifacts=True,
910
911   hw_tests=[HWTestConfig('perf_v2', pool=constants.HWTEST_CHROME_PERF_POOL,
912                          timeout=90 * 60, critical=True, num=1,
913                          copy_perf_results=True)],
914   use_chrome_lkgm=True,
915   use_lkgm=False,
916   useflags=official['useflags'] + ['-cros-debug'],
917 )
918
919 chrome_perf.add_config('daisy-chrome-perf',
920   boards=['daisy'],
921   trybot_list=True,
922 )
923
924 chrome_perf.add_config('lumpy-chrome-perf',
925   boards=['lumpy'],
926   trybot_list=True,
927 )
928
929 chrome_perf.add_config('parrot-chrome-perf',
930   boards=['parrot'],
931   trybot_list=True,
932 )
933
934 chromium_info_x86 = \
935 chromium_info.add_config('x86-generic-tot-chrome-pfq-informational',
936   boards=['x86-generic'],
937 )
938
939 chromium_info_daisy = \
940 chromium_info.add_config('daisy-tot-chrome-pfq-informational',
941   arm,
942   boards=['daisy'],
943 )
944
945 chromium_info_amd64 = \
946 chromium_info.add_config('amd64-generic-tot-chrome-pfq-informational',
947   amd64,
948   boards=['amd64-generic'],
949 )
950
951 chromium_info.add_config('x32-generic-tot-chrome-pfq-informational',
952   amd64,
953   boards=['x32-generic'],
954 )
955
956 chrome_info.add_config('alex-tot-chrome-pfq-informational',
957   boards=['x86-alex'],
958 )
959
960 chrome_info.add_config('lumpy-tot-chrome-pfq-informational',
961   boards=['lumpy'],
962 )
963
964 # WebRTC configurations.
965 chrome_info_no_pdf.add_config('alex-webrtc-chrome-pfq-informational',
966   boards=['x86-alex'],
967 )
968 chrome_info_no_pdf.add_config('lumpy-webrtc-chrome-pfq-informational',
969   boards=['lumpy'],
970 )
971 chrome_info_no_pdf.add_config('daisy-webrtc-chrome-pfq-informational',
972   arm,
973   boards=['daisy'],
974 )
975 chromium_info_x86.add_config('x86-webrtc-chromium-pfq-informational',
976   archive_build_debug=True,
977 )
978 chromium_info_amd64.add_config('amd64-webrtc-chromium-pfq-informational',
979   archive_build_debug=True,
980 )
981 chromium_info_daisy.add_config('daisy-webrtc-chromium-pfq-informational',
982   archive_build_debug=True,
983 )
984
985 _arm_full_boards = frozenset([
986   'arm-generic',
987   'daisy',
988   'daisy_spring',
989 ])
990
991 _x86_full_boards = frozenset([
992   'amd64-generic',
993   'butterfly',
994   'parrot',
995   'parrot32',
996   'parrot64',
997   'link',
998   'lumpy',
999   'stout',
1000   'stout32',
1001   'stumpy',
1002   'x32-generic',
1003   'x86-alex',
1004   'x86-generic',
1005   'x86-mario',
1006   'x86-pineview',
1007   'x86-zgb',
1008 ])
1009
1010 def _AddFullConfigs():
1011   """Add x86 and arm full configs."""
1012   for board in _x86_full_boards:
1013     full_prebuilts.add_config('%s-%s' % (board, CONFIG_TYPE_FULL),
1014       boards=[board],
1015       upload_hw_test_artifacts=True,
1016     )
1017
1018   for board in _arm_full_boards:
1019     full_prebuilts.add_config('%s-%s' % (board, CONFIG_TYPE_FULL),
1020       arm,
1021       boards=[board],
1022       upload_hw_test_artifacts=True,
1023     )
1024
1025 _AddFullConfigs()
1026
1027 _toolchain_major = _cros_sdk.add_config('toolchain-major',
1028   latest_toolchain=True,
1029   prebuilts=False,
1030   gcc_githash='gcc.gnu.org/branches/google/main',
1031   description='Test next major toolchain revision',
1032 )
1033
1034 _toolchain_minor = _cros_sdk.add_config('toolchain-minor',
1035   latest_toolchain=True,
1036   prebuilts=False,
1037   gcc_githash='gcc.gnu.org/branches/google/gcc-4_8-mobile',
1038   description='Test next minor toolchain revision',
1039 )
1040
1041 incremental.add_config('x86-generic-asan',
1042   asan,
1043   boards=['x86-generic'],
1044   description='Build with Address Sanitizer (Clang)',
1045 )
1046
1047 chromium_info.add_config('x86-generic-tot-asan-informational',
1048   asan,
1049   boards=['x86-generic'],
1050   description='Build with Address Sanitizer (Clang) on TOT',
1051 )
1052
1053 incremental.add_config('amd64-generic-asan',
1054   amd64,
1055   asan,
1056   boards=['amd64-generic'],
1057   description='Build with Address Sanitizer (Clang)',
1058 )
1059
1060 chromium_info.add_config('amd64-generic-tot-asan-informational',
1061   amd64,
1062   asan,
1063   boards=['amd64-generic'],
1064   description='Build with Address Sanitizer (Clang) on TOT',
1065 )
1066
1067 incremental_arm = incremental.derive(arm)
1068 incremental_arm.add_config('beaglebone-incremental',
1069   boards=['beaglebone'],
1070   images=['dev'],
1071   trybot_list=True,
1072   build_tests=False,
1073   rootfs_verification=False,
1074   description='Incremental Beaglebone Builder',
1075 )
1076
1077 platform2 = _config(
1078   useflags=['platform2'],
1079   trybot_list=True,
1080   description='Platform2 Builder',
1081 )
1082
1083 platform2_incremental = platform2.derive(
1084   incremental,
1085   description='Incremental Platform2 Builder',
1086 )
1087
1088 platform2_incremental.add_config('x86-incremental-platform2',
1089   boards=['x86-generic'],
1090 )
1091
1092 platform2_incremental.add_config('daisy-incremental-platform2',
1093   arm,
1094   boards=['daisy'],
1095 )
1096
1097 #
1098 # Internal Builds
1099 #
1100
1101 internal_pfq = internal.derive(official_chrome, pfq,
1102   overlays=constants.BOTH_OVERLAYS,
1103   prebuilts=constants.PRIVATE,
1104 )
1105
1106 # Because branch directories may be shared amongst builders on multiple
1107 # branches, they must delete the chroot every time they run.
1108 internal_pfq_branch = internal_pfq.derive(branch=True, chroot_replace=True,
1109                                           trybot_list=False)
1110
1111 internal_paladin = internal.derive(official_chrome, paladin,
1112   overlays=constants.BOTH_OVERLAYS,
1113   prebuilts=constants.PRIVATE,
1114   vm_tests=None,
1115   description=paladin['description'] + ' (internal)',
1116 )
1117
1118 internal_pre_cq = internal_paladin.derive(
1119   build_type=constants.INCREMENTAL_TYPE,
1120   compilecheck=True,
1121   pre_cq=True,
1122   description='Verifies compilation and unit tests',
1123 )
1124
1125 internal_pre_cq.add_group(constants.PRE_CQ_BUILDER_NAME,
1126   internal_pre_cq.add_config(
1127     'parrot-pre-cq',
1128     boards=['parrot'],
1129     # update_engine tests are disabled temporarily since they don't pass when
1130     # run in parallel. TODO(sosa): Re-enable when crbug.com/236465 is fixed.
1131     unittest_blacklist=['chromeos-base/update_engine'],
1132   ),
1133   internal_pre_cq.add_config('lumpy-pre-cq', boards=['lumpy']),
1134   internal_pre_cq.add_config('daisy_spring-pre-cq',
1135                              arm, boards=['daisy_spring']),
1136   internal_pre_cq.add_config('peach_pit-pre-cq',
1137                              arm, boards=['peach_pit']),
1138 )
1139
1140 internal_paladin.add_config('pre-cq-launcher',
1141   boards=[],
1142   build_type=constants.PRE_CQ_LAUNCHER_TYPE,
1143   description='Launcher for Pre-CQ builders.',
1144 )
1145
1146 internal_paladin.add_config(constants.BRANCH_UTIL_CONFIG,
1147   boards=[],
1148   # Disable postsync_patch to prevent conflicting patches from being applied -
1149   # e.g., patches from 'master' branch being applied to a branch.
1150   postsync_patch=False,
1151   # Disable postsync_reexec to continue running the 'master' branch chromite
1152   # for all stages, rather than the chromite in the branch buildroot.
1153   postsync_reexec=False,
1154   build_type=constants.CREATE_BRANCH_TYPE,
1155   description='Used for creating/deleting branches.',
1156 )
1157
1158 # Internal incremental builders don't use official chrome because we want
1159 # to test the developer workflow.
1160 internal_incremental = internal.derive(
1161   incremental,
1162   overlays=constants.BOTH_OVERLAYS,
1163   description='Incremental Builds (internal)',
1164 )
1165
1166 sonic = _config(
1167   manifest='sonic.xml',
1168   boards=['sonic'],
1169   # Until these are configured and ready, disable them.
1170   images=['base', 'dev',],
1171   unittests=False,
1172   upload_hw_test_artifacts=False,
1173   build_tests=False,
1174   vm_tests=None,
1175   signer_tests=False,
1176   hw_tests=[],
1177 )
1178
1179 internal_pfq_branch.add_config('x86-alex-pre-flight-branch',
1180   master=True,
1181   push_overlays=constants.BOTH_OVERLAYS,
1182   boards=['x86-alex'],
1183 )
1184
1185 stumpy_test_ap = internal.derive(
1186   vm_tests=None,
1187   description='stumpy image used for WiFi testing',
1188   boards=['stumpy'],
1189   images=['test'],  # We need Python and utilities found only in test.
1190   profile='testbed-ap',
1191 )
1192
1193 ### Master paladin (CQ builder).
1194
1195 internal_paladin.add_config('mario-paladin',
1196   master=True,
1197   push_overlays=constants.BOTH_OVERLAYS,
1198   boards=['x86-mario'],
1199   gs_path='gs://chromeos-x86-mario/pre-flight-master',
1200   paladin_builder_name='mario paladin',
1201   vm_tests=constants.SIMPLE_AU_TEST_TYPE,
1202 )
1203
1204 ### Other paladins (CQ builders).
1205
1206 internal_paladin.add_config('alex-paladin',
1207   boards=['x86-alex'],
1208   paladin_builder_name='alex paladin',
1209   hw_tests=HWTestConfig.DefaultListCQ(timeout=60 * 60, num=8),
1210   upload_hw_test_artifacts=True,
1211 )
1212
1213 # x86 full compile
1214 internal_paladin.add_config('butterfly-paladin',
1215   full_paladin,
1216   boards=['butterfly'],
1217   paladin_builder_name='butterfly paladin',
1218 )
1219
1220 # amd64 full compile
1221 internal_paladin.add_config('falco-paladin',
1222   full_paladin,
1223   boards=['falco'],
1224   paladin_builder_name='falco paladin',
1225 )
1226
1227 internal_paladin.add_config('fox-wtm2-paladin',
1228   boards=['fox_wtm2'],
1229   paladin_builder_name='fox paladin',
1230   vm_tests=None,
1231 )
1232
1233 internal_paladin.add_config('link-paladin',
1234   boards=['link'],
1235   paladin_builder_name='link paladin',
1236   upload_hw_test_artifacts=True,
1237 )
1238
1239 internal_paladin.add_config('lumpy-paladin',
1240   boards=['lumpy'],
1241   paladin_builder_name='lumpy paladin',
1242   hw_tests=HWTestConfig.DefaultListCQ(),
1243   upload_hw_test_artifacts=True,
1244 )
1245
1246 internal_paladin.add_config('parrot-paladin',
1247   boards=['parrot'],
1248   paladin_builder_name='parrot paladin',
1249   hw_tests=HWTestConfig.DefaultListCQ(),
1250   upload_hw_test_artifacts=True,
1251 )
1252
1253 # x86 full unit tests
1254 internal_paladin.add_config('parrot32-paladin',
1255   boards=['parrot32'],
1256   paladin_builder_name='parrot32 paladin',
1257   quick_unit=False,
1258 )
1259
1260 internal_paladin.add_config('parrot64-paladin',
1261   boards=['parrot64'],
1262   paladin_builder_name='parrot64 paladin',
1263 )
1264
1265 internal_paladin.add_config('peppy-paladin',
1266   boards=['peppy'],
1267   paladin_builder_name='peppy paladin',
1268 )
1269
1270 internal_paladin.add_config('slippy-paladin',
1271   boards=['slippy'],
1272   paladin_builder_name='slippy paladin',
1273 )
1274
1275 internal_paladin.add_config('sonic-paladin',
1276   sonic,
1277   paladin_builder_name='sonic paladin',
1278   important=False,
1279 )
1280
1281 # amd64 full unit tests
1282 internal_paladin.add_config('stout-paladin',
1283   boards=['stout'],
1284   quick_unit=False,
1285   paladin_builder_name='stout paladin',
1286 )
1287
1288 internal_paladin.add_config('stout32-paladin',
1289   boards=['stout32'],
1290   paladin_builder_name='stout32 paladin',
1291 )
1292
1293 internal_paladin.add_config('stumpy-paladin',
1294   boards=['stumpy'],
1295   paladin_builder_name='stumpy paladin',
1296   hw_tests=HWTestConfig.DefaultListCQ(),
1297   upload_hw_test_artifacts=True,
1298 )
1299
1300 internal_paladin.add_config('wolf-paladin',
1301   boards=['wolf'],
1302   paladin_builder_name='wolf paladin',
1303 )
1304
1305 internal_paladin.add_config('zgb-paladin',
1306   boards=['x86-zgb'],
1307   important=False,
1308   paladin_builder_name='zgb paladin',
1309 )
1310
1311 ### Arm paladins (CQ builders).
1312
1313 internal_arm_paladin = internal_paladin.derive(arm)
1314
1315 internal_arm_paladin.add_config('daisy-paladin',
1316   boards=['daisy'],
1317   paladin_builder_name='daisy paladin',
1318   upload_hw_test_artifacts=True,
1319 )
1320
1321 # arm full compile
1322 internal_arm_paladin.add_config('daisy_spring-paladin',
1323   full_paladin,
1324   boards=['daisy_spring'],
1325   paladin_builder_name='daisy_spring paladin',
1326 )
1327
1328 internal_arm_paladin.add_config('peach_pit-paladin',
1329   boards=['peach_pit'],
1330   paladin_builder_name='peach_pit paladin',
1331 )
1332
1333
1334 internal_incremental.add_config('mario-incremental',
1335   boards=['x86-mario'],
1336 )
1337
1338 _toolchain_major.add_config('internal-toolchain-major', internal, official,
1339   boards=('x86-alex', 'stumpy', 'daisy'),
1340   use_lkgm=True,
1341   useflags=[constants.USE_CHROME_INTERNAL],
1342   build_tests=True,
1343   description=_toolchain_major['description'] + ' (internal)',
1344 )
1345
1346 _toolchain_minor.add_config('internal-toolchain-minor', internal, official,
1347   boards=('x86-alex', 'stumpy', 'daisy'),
1348   use_lkgm=True,
1349   useflags=[constants.USE_CHROME_INTERNAL],
1350   build_tests=True,
1351   description=_toolchain_minor['description'] + ' (internal)',
1352 )
1353
1354 _release = full.derive(official, internal,
1355   build_type=constants.CANARY_TYPE,
1356   useflags=official['useflags'] + ['-cros-debug', '-highdpi'],
1357   build_tests=True,
1358   manifest_version=True,
1359   images=['base', 'test', 'factory_test', 'factory_install'],
1360   push_image=True,
1361   upload_symbols=True,
1362   binhost_bucket='gs://chromeos-dev-installer',
1363   binhost_key='RELEASE_BINHOST',
1364   binhost_base_url=
1365     'https://commondatastorage.googleapis.com/chromeos-dev-installer',
1366   dev_installer_prebuilts=True,
1367   git_sync=False,
1368   vm_tests=constants.SMOKE_SUITE_TEST_TYPE,
1369   disk_vm_layout='usb',
1370   hw_tests=HWTestConfig.DefaultList(file_bugs=True),
1371   upload_hw_test_artifacts=True,
1372   signer_tests=True,
1373   trybot_list=True,
1374   hwqual=True,
1375   description="Release Builds (canary) (internal)",
1376   chrome_sdk=True,
1377 )
1378
1379 ### Master release config.
1380
1381 _release.add_config('x86-mario-release',
1382   boards=['x86-mario'],
1383   master=True,
1384 )
1385
1386 ### Release config groups.
1387
1388 _config.add_group('x86-alex-release-group',
1389   _release.add_config('x86-alex-release',
1390     boards=['x86-alex'],
1391   ),
1392   _release.add_config('x86-alex_he-release',
1393     boards=['x86-alex_he'],
1394     vm_tests=None,
1395     unittests=None,
1396     hw_tests=[],
1397     upload_hw_test_artifacts=False,
1398   ),
1399   critical_for_chrome=True,
1400 )
1401
1402 _config.add_group('x86-zgb-release-group',
1403   _release.add_config('x86-zgb-release',
1404     boards=['x86-zgb'],
1405   ),
1406   _release.add_config('x86-zgb_he-release',
1407     boards=['x86-zgb_he'],
1408     vm_tests=None,
1409     unittests=None,
1410     hw_tests=[],
1411     upload_hw_test_artifacts=False,
1412   ),
1413 )
1414
1415 ### Release PGO configs.
1416
1417 release_pgo = _release.derive(
1418   hw_tests=HWTestConfig.DefaultList(pool=constants.HWTEST_CHROME_PERF_POOL,
1419                                     num=4) +
1420            HWTestConfig.PGOList(),
1421   push_image=False,
1422   dev_installer_prebuilts=False,
1423 )
1424
1425 release_pgo.add_group('x86-alex-release-pgo',
1426   release_pgo.add_config('x86-alex-release-pgo-generate',
1427     boards=['x86-alex'],
1428     pgo_generate=True,
1429   ),
1430   release_pgo.add_config('x86-alex-release-pgo-use',
1431     boards=['x86-alex'],
1432     pgo_use=True,
1433   ),
1434 )
1435
1436 release_pgo.add_group('lumpy-release-pgo',
1437   release_pgo.add_config('lumpy-release-pgo-generate',
1438     boards=['lumpy'],
1439     pgo_generate=True,
1440   ),
1441   release_pgo.add_config('lumpy-release-pgo-use',
1442     boards=['lumpy'],
1443     pgo_use=True,
1444   ),
1445 )
1446
1447 release_pgo.add_group('parrot-release-pgo',
1448   release_pgo.add_config('parrot-release-pgo-generate',
1449     boards=['parrot'],
1450     pgo_generate=True,
1451   ),
1452   release_pgo.add_config('parrot-release-pgo-use',
1453     boards=['parrot'],
1454     pgo_use=True,
1455   ),
1456 )
1457
1458 release_pgo.add_group('daisy-release-pgo',
1459   release_pgo.add_config('daisy-release-pgo-generate',
1460     boards=['daisy'],
1461     pgo_generate=True,
1462   ),
1463   release_pgo.add_config('daisy-release-pgo-use',
1464     boards=['daisy'],
1465     pgo_use=True,
1466   ),
1467 )
1468
1469 ### Release configs.
1470
1471 _release.add_config('butterfly-release',
1472   boards=['butterfly'],
1473 )
1474
1475 _release.add_config('falco-release',
1476   boards=['falco'],
1477   hw_tests=HWTestConfig.DefaultList(file_bugs=True),
1478   # TODO(sosa): Restore temp removal of vm testing once devserver bug
1479   # crbug.com/251309 is fixed.
1480   vm_tests=None,
1481 )
1482
1483 _release.add_config('fox-wtm2-release',
1484   boards=['fox_wtm2'],
1485   # Until these are configured and ready, disable them.
1486   signer_tests=False,
1487   vm_tests=None,
1488   hw_tests=[],
1489 )
1490
1491 _release.add_config('link-release',
1492   boards=['link'],
1493   useflags=_release['useflags'] + ['highdpi'],
1494 )
1495
1496 _release.add_config('lumpy-release',
1497   boards=['lumpy'],
1498   critical_for_chrome=True,
1499 )
1500
1501 _release.add_config('parrot-release',
1502   boards=['parrot'],
1503 )
1504
1505 _release.add_config('parrot32-release',
1506   boards=['parrot32'],
1507   # TODO(moch): Need to setup machines in the lab with this configuration
1508   # Until then disabling hw_tests so that builder works
1509   hw_tests=[],
1510 )
1511
1512 _release.add_config('parrot64-release',
1513   boards=['parrot64'],
1514   # TODO(moch): Need to setup machines in the lab with this configuration
1515   # Until then disabling hw_tests so that builder works
1516   hw_tests=[],
1517   # TODO(sosa): Restore temp removal of vm testing once devserver bug
1518   # crbug.com/251309 is fixed.
1519   vm_tests=None,
1520 )
1521
1522 _release.add_config('peppy-release',
1523   boards=['peppy'],
1524   hw_tests=[],
1525   # TODO(sosa): Restore temp removal of vm testing once devserver bug
1526   # crbug.com/251309 is fixed.
1527   vm_tests=None,
1528 )
1529
1530 _release.add_config('slippy-release',
1531   boards=['slippy'],
1532   hw_tests=[],
1533   # TODO(sosa): Restore temp removal of vm testing once devserver bug
1534   # crbug.com/251309 is fixed.
1535   vm_tests=None,
1536 )
1537
1538 _release.add_config('sonic-release',
1539   sonic,
1540 )
1541
1542 _release.add_config('stout-release',
1543   boards=['stout'],
1544   hw_tests=HWTestConfig.DefaultList(num=3, file_bugs=True),
1545 )
1546
1547 _release.add_config('stout32-release',
1548   boards=['stout32'],
1549 )
1550
1551 _release.add_config('stumpy-release',
1552   boards=['stumpy'],
1553 )
1554
1555 _release.add_config('wolf-release',
1556   boards=['wolf'],
1557   hw_tests=[],
1558   vm_tests=None,
1559 )
1560
1561 ### Arm release configs.
1562
1563 _arm_release = _release.derive(arm)
1564
1565 _arm_release.add_config('daisy-release',
1566   boards=['daisy'],
1567   critical_for_chrome=True,
1568 )
1569
1570 _arm_release.add_config('daisy_spring-release',
1571   boards=['daisy_spring'],
1572 )
1573
1574 _arm_release.add_config('peach_pit-release',
1575   boards=['peach_pit'],
1576   hw_tests=[],
1577 )
1578
1579 # Factory and Firmware releases much inherit from these classes.  Modifications
1580 # for these release builders should go here.
1581
1582 # Naming conventions also must be followed.  Factory and firmware branches must
1583 # end in -factory or -firmware suffixes.
1584
1585 _factory_release = _release.derive(
1586   upload_hw_test_artifacts=False,
1587   upload_symbols=False,
1588   hw_tests=[],
1589   description='Factory Builds',
1590 )
1591
1592 _firmware = _config(
1593   images=[],
1594   packages=('virtual/chromeos-firmware',),
1595   usepkg_setup_board=True,
1596   usepkg_build_packages=True,
1597   sync_chrome=False,
1598   build_tests=False,
1599   unittests=False,
1600   vm_tests=None,
1601   hw_tests=[],
1602   dev_installer_prebuilts=False,
1603   upload_hw_test_artifacts=False,
1604   upload_symbols=False,
1605   signer_tests=False,
1606   trybot_list=False,
1607 )
1608
1609 _firmware_release = _release.derive(_firmware,
1610   description='Firmware Canary',
1611 )
1612
1613 _depthcharge_release = _firmware_release.derive(useflags=['depthcharge'])
1614
1615 _depthcharge_full_internal = full.derive(
1616   internal,
1617   _firmware,
1618   useflags=['depthcharge'],
1619   description='Firmware Informational',
1620 )
1621
1622 _x86_firmware_boards = (
1623   'butterfly',
1624   'falco',
1625   'link',
1626   'lumpy',
1627   'parrot',
1628   'peppy',
1629   'stout',
1630   'stout32',
1631   'slippy',
1632   'stumpy',
1633   'wolf',
1634   'x86-mario',
1635 )
1636
1637 _x86_depthcharge_firmware_boards = (
1638   'link',
1639 )
1640
1641 _arm_firmware_boards = (
1642   'daisy',
1643   'daisy_spring',
1644 )
1645
1646 def _AddFirmwareConfigs():
1647   """Add x86 and arm firmware configs."""
1648   for board in _x86_firmware_boards:
1649     _firmware_release.add_config('%s-%s' % (board, CONFIG_TYPE_FIRMWARE),
1650       boards=[board],
1651     )
1652
1653   for board in _x86_depthcharge_firmware_boards:
1654     _depthcharge_release.add_config(
1655         '%s-%s-%s' % (board, 'depthcharge', CONFIG_TYPE_FIRMWARE),
1656         boards=[board],
1657     )
1658     _depthcharge_full_internal.add_config(
1659         '%s-%s-%s-%s' % (board, 'depthcharge', CONFIG_TYPE_FULL,
1660                          CONFIG_TYPE_FIRMWARE),
1661         boards=[board],
1662     )
1663
1664   for board in _arm_firmware_boards:
1665     _firmware_release.add_config('%s-%s' % (board, CONFIG_TYPE_FIRMWARE),
1666       arm,
1667       boards=[board],
1668     )
1669
1670 _AddFirmwareConfigs()
1671
1672
1673 # This is an example factory branch configuration for x86.
1674 # Modify it to match your factory branch.
1675 _factory_release.add_config('x86-mario-factory',
1676   boards=['x86-mario'],
1677 )
1678
1679 # This is an example factory branch configuration for arm.
1680 # Modify it to match your factory branch.
1681 _factory_release.add_config('daisy-factory',
1682   arm,
1683   boards=['daisy'],
1684 )
1685
1686
1687 def _GetDisplayPosition(config_name, type_order=CONFIG_TYPE_DUMP_ORDER):
1688   """Given a config_name, return display position specified by suffix_order.
1689
1690   Arguments:
1691     config_name: Name of config to look up.
1692     type_order: A tuple/list of config types in the order they are to be
1693                 displayed.
1694
1695   If config name does not contain any of the suffixes, returns the index
1696   position after the last element of suffix_order.
1697   """
1698   for index, config_type in enumerate(type_order):
1699     if config_name.endswith('-' + config_type) or config_name == config_type:
1700       return index
1701
1702   return len(type_order)
1703
1704
1705 def _InjectDisplayPosition(config_source):
1706   """Add field to help buildbot masters order builders on the waterfall."""
1707   def _GetSortKey(items):
1708     my_config = items[1]
1709     # Allow configs to override the display_position.
1710     return (my_config.get('display_position', 1000000),
1711             _GetDisplayPosition(my_config['name']),
1712             my_config['internal'], my_config['vm_tests'])
1713
1714   source = sorted(config_source.iteritems(), key=_GetSortKey)
1715   return dict((name, dict(value.items() + [('display_position', idx)]))
1716               for idx, (name, value) in enumerate(source))
1717
1718
1719 def main(argv=None):
1720   if not argv:
1721     argv = sys.argv[1:]
1722
1723   usage = "usage: %prog [options] [config1 ... configN]"
1724   parser = optparse.OptionParser(usage=usage)
1725
1726   parser.add_option('-c', '--compare', action='store', type='string',
1727                     default=None, metavar='file_name',
1728                     help=('Compare current config against a saved on disk '
1729                           'serialized version of a config.'))
1730   parser.add_option('-d', '--dump', action='store_true', default=False,
1731                     help=('Dump the configs in JSON format.'))
1732   parser.add_option('--for-buildbot', action='store_true', default=False,
1733                     help="Include the display position in json data.")
1734
1735   options, configs = parser.parse_args(argv)
1736
1737   if options.compare and options.dump:
1738     parser.error('Cannot run with --load and --dump at the same time!')
1739   elif not options.compare and not options.dump:
1740     parser.print_help()
1741     sys.exit(0)
1742
1743   convert = lambda x:x
1744   if options.for_buildbot:
1745     convert = _InjectDisplayPosition
1746
1747   my_config = convert(config)
1748
1749   # If configs specified, only dump/load those.
1750   if configs:
1751     temp_config = dict()
1752     for c in configs:
1753       temp_config[c] = my_config[c]
1754
1755     my_config = temp_config
1756
1757   if options.dump:
1758     print json.dumps(my_config, cls=_JSONEncoder)
1759   elif options.compare:
1760     with open(options.compare, 'rb') as f:
1761       original = convert(json.load(f))
1762
1763     my_config = json.loads(json.dumps(my_config, cls=_JSONEncoder))
1764     for key in sorted(set(my_config.keys() + original.keys())):
1765       obj1, obj2 = original.get(key), my_config.get(key)
1766       if obj1 == obj2:
1767         continue
1768       elif obj1 is None:
1769         print '%s: added to config\n' % (key,)
1770         continue
1771       elif obj2 is None:
1772         print '%s: removed from config\n' % (key,)
1773         continue
1774
1775       print '%s:' % (key,)
1776
1777       for subkey in sorted(set(obj1.keys() + obj2.keys())):
1778         sobj1, sobj2 = obj1.get(subkey), obj2.get(subkey)
1779         if sobj1 != sobj2:
1780           print ' %s: %r, %r' % (subkey, sobj1, sobj2)
1781
1782       print
1783
1784
1785 if __name__ == '__main__':
1786   main()