blob: cff7d2fafb69b6c1ebd98b1e097e6e6e1a2f4fe9 [file] [log] [blame]
Mike Frysingerf1ba7ad2022-09-12 05:42:57 -04001# Copyright 2012 The ChromiumOS Authors
Brian Harring3fec5a82012-03-01 05:57:03 -08002# Use of this source code is governed by a BSD-style license that can be
3# found in the LICENSE file.
4
5"""Main builder code for Chromium OS.
6
7Used by Chromium OS buildbot configuration for all Chromium OS builds including
8full and pre-flight-queue builds.
9"""
10
Chris McDonaldb55b7032021-06-17 16:41:32 -060011import distutils.version # pylint: disable=import-error,no-name-in-module
Brian Harring3fec5a82012-03-01 05:57:03 -080012import glob
Aviv Keshet669eb5e2014-06-23 08:53:01 -070013import json
Chris McDonaldb55b7032021-06-17 16:41:32 -060014import logging
Mike Frysingerb0b0caa2015-11-07 01:05:18 -050015import optparse # pylint: disable=deprecated-module
Brian Harring3fec5a82012-03-01 05:57:03 -080016import os
Aviv Keshetcf9c2722014-02-25 15:15:10 -080017import pickle
Brian Harring3fec5a82012-03-01 05:57:03 -080018import sys
19
Mike Frysingere4d68c22015-02-04 21:26:24 -050020from chromite.cbuildbot import builders
Chris McDonaldb55b7032021-06-17 16:41:32 -060021from chromite.cbuildbot import cbuildbot_alerts
Don Garrett88b8d782014-05-13 17:30:55 -070022from chromite.cbuildbot import cbuildbot_run
Don Garrett88b8d782014-05-13 17:30:55 -070023from chromite.cbuildbot import repository
Aviv Keshet420de512015-05-18 14:28:48 -070024from chromite.cbuildbot import topology
Don Garrett88b8d782014-05-13 17:30:55 -070025from chromite.cbuildbot.stages import completion_stages
Jared Loucksa9e94bf2021-06-28 10:03:31 -060026from chromite.cbuildbot.stages import test_stages
Ningning Xiaf342b952017-02-15 14:13:33 -080027from chromite.lib import builder_status_lib
Brian Harringc92a7012012-02-29 10:11:34 -080028from chromite.lib import cgroups
Chris McDonaldb55b7032021-06-17 16:41:32 -060029from chromite.lib import cidb
Brian Harringa184efa2012-03-04 11:51:25 -080030from chromite.lib import cleanup
Brian Harringb6cf9142012-09-01 20:43:17 -070031from chromite.lib import commandline
Ningning Xia6a718052016-12-22 10:08:15 -080032from chromite.lib import config_lib
33from chromite.lib import constants
Brian Harring1b8c4c82012-05-29 23:03:04 -070034from chromite.lib import cros_build_lib
Ningning Xia6a718052016-12-22 10:08:15 -080035from chromite.lib import failures_lib
David James97d95872012-11-16 15:09:56 -080036from chromite.lib import git
Stefan Zagerd49d9ff2014-08-15 21:33:37 -070037from chromite.lib import gob_util
Brian Harringaf019fb2012-05-10 15:06:13 -070038from chromite.lib import osutils
David James6450a0a2012-12-04 07:59:53 -080039from chromite.lib import parallel
Don Garrettb4318362014-10-03 15:49:36 -070040from chromite.lib import retry_stats
Brian Harring3fec5a82012-03-01 05:57:03 -080041from chromite.lib import sudo
Michael Mortensen3e86c1e2019-11-21 15:51:54 -070042from chromite.lib import tee
David James3432acd2013-11-27 10:02:18 -080043from chromite.lib import timeout_util
Paul Hobbsfcf10342015-12-29 15:52:31 -080044from chromite.lib import ts_mon_config
Dhanya Ganesh39a48a82018-12-06 16:01:11 -070045from chromite.lib.buildstore import BuildStore
Brian Harring3fec5a82012-03-01 05:57:03 -080046
Ryan Cuiadd49122012-03-21 22:19:58 -070047
Alex Klein1699fab2022-09-08 08:46:06 -060048_DEFAULT_LOG_DIR = "cbuildbot_logs"
49_BUILDBOT_LOG_FILE = "cbuildbot.log"
50_DEFAULT_EXT_BUILDROOT = "trybot"
51_DEFAULT_INT_BUILDROOT = "trybot-internal"
52_BUILDBOT_REQUIRED_BINARIES = ("pbzip2",)
53_API_VERSION_ATTR = "api_version"
54BOARD_DIM_LABEL = "label-board"
55MODEL_DIM_LABEL = "label-model"
56POOL_DIM_LABEL = "label-pool"
Brian Harring3fec5a82012-03-01 05:57:03 -080057
58
Brian Harring3fec5a82012-03-01 05:57:03 -080059def _BackupPreviousLog(log_file, backup_limit=25):
Alex Klein1699fab2022-09-08 08:46:06 -060060 """Rename previous log.
Brian Harring3fec5a82012-03-01 05:57:03 -080061
Alex Klein1699fab2022-09-08 08:46:06 -060062 Args:
Trent Apted66736d82023-05-25 10:38:28 +100063 log_file: The absolute path to the previous log.
64 backup_limit: Maximum number of old logs to keep.
Alex Klein1699fab2022-09-08 08:46:06 -060065 """
66 if os.path.exists(log_file):
67 old_logs = sorted(
68 glob.glob(log_file + ".*"), key=distutils.version.LooseVersion
69 )
Brian Harring3fec5a82012-03-01 05:57:03 -080070
Alex Klein1699fab2022-09-08 08:46:06 -060071 if len(old_logs) >= backup_limit:
72 os.remove(old_logs[0])
Brian Harring3fec5a82012-03-01 05:57:03 -080073
Alex Klein1699fab2022-09-08 08:46:06 -060074 last = 0
75 if old_logs:
76 last = int(old_logs.pop().rpartition(".")[2])
Brian Harring3fec5a82012-03-01 05:57:03 -080077
Alex Klein1699fab2022-09-08 08:46:06 -060078 os.rename(log_file, log_file + "." + str(last + 1))
Brian Harring3fec5a82012-03-01 05:57:03 -080079
Ryan Cui5616a512012-08-17 13:39:36 -070080
Gaurav Shah298aa372014-01-31 09:27:24 -080081def _IsDistributedBuilder(options, chrome_rev, build_config):
Alex Klein1699fab2022-09-08 08:46:06 -060082 """Determines whether the builder should be a DistributedBuilder.
Gaurav Shah298aa372014-01-31 09:27:24 -080083
Alex Klein1699fab2022-09-08 08:46:06 -060084 Args:
Trent Apted66736d82023-05-25 10:38:28 +100085 options: options passed on the commandline.
86 chrome_rev: Chrome revision to build.
87 build_config: Builder configuration dictionary.
Gaurav Shah298aa372014-01-31 09:27:24 -080088
Alex Klein1699fab2022-09-08 08:46:06 -060089 Returns:
Trent Apted66736d82023-05-25 10:38:28 +100090 True if the builder should be a distributed_builder
Alex Klein1699fab2022-09-08 08:46:06 -060091 """
92 if not options.buildbot:
93 return False
94 elif chrome_rev in (
95 constants.CHROME_REV_TOT,
96 constants.CHROME_REV_LOCAL,
97 constants.CHROME_REV_SPEC,
98 ):
99 # We don't do distributed logic to TOT Chrome PFQ's, nor local
100 # chrome roots (e.g. chrome try bots)
101 # TODO(davidjames): Update any builders that rely on this logic to use
102 # manifest_version=False instead.
103 return False
104 elif build_config["manifest_version"]:
105 return True
106
Gaurav Shah298aa372014-01-31 09:27:24 -0800107 return False
Gaurav Shah298aa372014-01-31 09:27:24 -0800108
109
Don Garretta52a5b02015-06-02 14:52:57 -0700110def _RunBuildStagesWrapper(options, site_config, build_config):
Alex Klein1699fab2022-09-08 08:46:06 -0600111 """Helper function that wraps RunBuildStages()."""
112 logging.info(
113 "cbuildbot was executed with args %s", cros_build_lib.CmdToStr(sys.argv)
114 )
Brian Harring3fec5a82012-03-01 05:57:03 -0800115
Alex Klein1699fab2022-09-08 08:46:06 -0600116 chrome_rev = build_config["chrome_rev"]
117 if options.chrome_rev:
118 chrome_rev = options.chrome_rev
119 if chrome_rev == constants.CHROME_REV_TOT:
120 options.chrome_version = gob_util.GetTipOfTrunkRevision(
121 constants.CHROMIUM_GOB_URL
122 )
123 options.chrome_rev = constants.CHROME_REV_SPEC
David Jamesa0a664e2013-02-13 09:52:01 -0800124
Alex Klein1699fab2022-09-08 08:46:06 -0600125 # If it's likely we'll need to build Chrome, fetch the source.
126 if build_config["sync_chrome"] is None:
127 options.managed_chrome = chrome_rev != constants.CHROME_REV_LOCAL and (
128 not build_config["usepkg_build_packages"]
129 or chrome_rev
130 or build_config["profile"]
131 )
Matt Tennant0940c382014-01-21 20:43:55 -0800132 else:
Alex Klein1699fab2022-09-08 08:46:06 -0600133 options.managed_chrome = build_config["sync_chrome"]
Mike Frysingere4d68c22015-02-04 21:26:24 -0500134
Alex Klein1699fab2022-09-08 08:46:06 -0600135 chrome_root_mgr = None
136 if options.managed_chrome:
137 # Create a temp directory for syncing Chrome source.
138 chrome_root_mgr = osutils.TempDir(prefix="chrome_root_")
139 options.chrome_root = chrome_root_mgr.tempdir
140
141 # We are done munging options values, so freeze options object now to avoid
142 # further abuse of it.
143 # TODO(mtennant): one by one identify each options value override and see if
144 # it can be handled another way. Try to push this freeze closer and closer
145 # to the start of the script (e.g. in or after _PostParseCheck).
146 options.Freeze()
147
148 metadata_dump_dict = {
149 # A detected default has been set before now if it wasn't explicit.
150 "branch": options.branch,
151 }
152 if options.metadata_dump:
Mike Frysinger31fdddd2023-02-24 15:50:55 -0500153 with open(options.metadata_dump, "rb") as metadata_file:
154 metadata_dump_dict = json.load(metadata_file)
Alex Klein1699fab2022-09-08 08:46:06 -0600155
156 with parallel.Manager() as manager:
157 builder_run = cbuildbot_run.BuilderRun(
158 options, site_config, build_config, manager
159 )
160 buildstore = BuildStore()
161 if metadata_dump_dict:
162 builder_run.attrs.metadata.UpdateWithDict(metadata_dump_dict)
163
164 if builder_run.config.builder_class_name is None:
165 # TODO: This should get relocated to chromeos_config.
166 if _IsDistributedBuilder(options, chrome_rev, build_config):
167 builder_cls_name = "simple_builders.DistributedBuilder"
168 else:
169 builder_cls_name = "simple_builders.SimpleBuilder"
170 builder_cls = builders.GetBuilderClass(builder_cls_name)
171 builder = builder_cls(builder_run, buildstore)
172 else:
173 builder = builders.Builder(builder_run, buildstore)
174
175 try:
176 if not builder.Run():
177 sys.exit(1)
178 finally:
179 if chrome_root_mgr:
180 chrome_root_mgr.Cleanup()
Brian Harring3fec5a82012-03-01 05:57:03 -0800181
182
Brian Harring3fec5a82012-03-01 05:57:03 -0800183def _CheckChromeVersionOption(_option, _opt_str, value, parser):
Alex Klein1699fab2022-09-08 08:46:06 -0600184 """Upgrade other options based on chrome_version being passed."""
185 value = value.strip()
Brian Harring3fec5a82012-03-01 05:57:03 -0800186
Alex Klein1699fab2022-09-08 08:46:06 -0600187 if parser.values.chrome_rev is None and value:
188 parser.values.chrome_rev = constants.CHROME_REV_SPEC
Brian Harring3fec5a82012-03-01 05:57:03 -0800189
Alex Klein1699fab2022-09-08 08:46:06 -0600190 parser.values.chrome_version = value
Brian Harring3fec5a82012-03-01 05:57:03 -0800191
192
193def _CheckChromeRootOption(_option, _opt_str, value, parser):
Alex Klein1699fab2022-09-08 08:46:06 -0600194 """Validate and convert chrome_root to full-path form."""
195 if parser.values.chrome_rev is None:
196 parser.values.chrome_rev = constants.CHROME_REV_LOCAL
Brian Harring3fec5a82012-03-01 05:57:03 -0800197
Alex Klein1699fab2022-09-08 08:46:06 -0600198 parser.values.chrome_root = value
Brian Harring3fec5a82012-03-01 05:57:03 -0800199
200
David Jamesac8c2a72013-02-13 18:44:33 -0800201def FindCacheDir(_parser, _options):
Alex Klein1699fab2022-09-08 08:46:06 -0600202 return None
Brian Harringae0a5322012-09-15 01:46:51 -0700203
204
Ryan Cui5ba7e152012-05-10 14:36:52 -0700205class CustomGroup(optparse.OptionGroup):
Alex Klein1699fab2022-09-08 08:46:06 -0600206 """Custom option group which supports arguments passed-through to trybot."""
David Jameseecba232014-06-11 11:35:11 -0700207
Alex Klein1699fab2022-09-08 08:46:06 -0600208 def add_remote_option(self, *args, **kwargs):
209 """For arguments that are passed-through to remote trybot."""
210 return optparse.OptionGroup.add_option(
211 self, *args, remote_pass_through=True, **kwargs
212 )
Ryan Cui5ba7e152012-05-10 14:36:52 -0700213
214
Ryan Cui1c13a252012-10-16 15:00:16 -0700215class CustomOption(commandline.FilteringOption):
Alex Klein1699fab2022-09-08 08:46:06 -0600216 """Subclass FilteringOption class to implement pass-through and api."""
Ryan Cui5ba7e152012-05-10 14:36:52 -0700217
Alex Klein1699fab2022-09-08 08:46:06 -0600218 def __init__(self, *args, **kwargs):
219 # The remote_pass_through argument specifies whether we should directly
220 # pass the argument (with its value) onto the remote trybot.
221 self.pass_through = kwargs.pop("remote_pass_through", False)
222 self.api_version = int(kwargs.pop("api", "0"))
223 commandline.FilteringOption.__init__(self, *args, **kwargs)
Ryan Cui5ba7e152012-05-10 14:36:52 -0700224
Ryan Cui5ba7e152012-05-10 14:36:52 -0700225
Ryan Cui1c13a252012-10-16 15:00:16 -0700226class CustomParser(commandline.FilteringParser):
Alex Klein1699fab2022-09-08 08:46:06 -0600227 """Custom option parser which supports arguments passed-through to trybot"""
Matt Tennante8179042013-10-01 15:47:32 -0700228
Alex Klein1699fab2022-09-08 08:46:06 -0600229 DEFAULT_OPTION_CLASS = CustomOption
Brian Harringb6cf9142012-09-01 20:43:17 -0700230
Alex Klein1699fab2022-09-08 08:46:06 -0600231 def add_remote_option(self, *args, **kwargs):
232 """For arguments that are passed-through to remote trybot."""
233 return self.add_option(*args, remote_pass_through=True, **kwargs)
Brian Harringb6cf9142012-09-01 20:43:17 -0700234
235
Don Garrett86881cb2017-02-15 15:41:55 -0800236def CreateParser():
Alex Klein1699fab2022-09-08 08:46:06 -0600237 """Expose _CreateParser publicly."""
238 # Name _CreateParser is needed for commandline library.
239 return _CreateParser()
Don Garrett86881cb2017-02-15 15:41:55 -0800240
241
Brian Harring3fec5a82012-03-01 05:57:03 -0800242def _CreateParser():
Alex Klein1699fab2022-09-08 08:46:06 -0600243 """Generate and return the parser with all the options."""
244 # Parse options
245 usage = "usage: %prog [options] buildbot_config [buildbot_config ...]"
246 parser = CustomParser(usage=usage, caching=FindCacheDir)
Brian Harring3fec5a82012-03-01 05:57:03 -0800247
Alex Klein1699fab2022-09-08 08:46:06 -0600248 # Main options
249 parser.add_remote_option(
250 "-b",
251 "--branch",
Trent Apted66736d82023-05-25 10:38:28 +1000252 help=(
253 "The manifest branch to test. The branch to "
254 "check the buildroot out to."
255 ),
Alex Klein1699fab2022-09-08 08:46:06 -0600256 )
257 parser.add_option(
258 "-r",
259 "--buildroot",
260 type="path",
261 dest="buildroot",
Trent Apted66736d82023-05-25 10:38:28 +1000262 help=(
263 "Root directory where source is checked out to, and "
264 "where the build occurs. For external build configs, "
265 "defaults to 'trybot' directory at top level of your "
266 "repo-managed checkout."
267 ),
Alex Klein1699fab2022-09-08 08:46:06 -0600268 )
269 parser.add_option(
270 "--workspace",
271 type="path",
272 api=constants.REEXEC_API_WORKSPACE,
273 help="Root directory for a secondary checkout .",
274 )
275 parser.add_option(
276 "--bootstrap-dir",
277 type="path",
Trent Apted66736d82023-05-25 10:38:28 +1000278 help=(
279 "Bootstrapping cbuildbot may involve checking out "
280 "multiple copies of chromite. All these checkouts "
281 "will be contained in the directory specified here. "
282 "Default:%s"
283 )
284 % osutils.GetGlobalTempDir(),
Alex Klein1699fab2022-09-08 08:46:06 -0600285 )
286 parser.add_remote_option(
287 "--android_rev",
288 type="choice",
289 choices=constants.VALID_ANDROID_REVISIONS,
290 help=(
291 "Revision of Android to use, of type [%s]"
292 % "|".join(constants.VALID_ANDROID_REVISIONS)
293 ),
294 )
295 parser.add_remote_option(
296 "--chrome_rev",
297 type="choice",
298 choices=constants.VALID_CHROME_REVISIONS,
299 help=(
300 "Revision of Chrome to use, of type [%s]"
301 % "|".join(constants.VALID_CHROME_REVISIONS)
302 ),
303 )
304 parser.add_remote_option(
305 "--profile", help="Name of profile to sub-specify board variant."
306 )
307 # TODO(crbug.com/279618): Running GOMA is under development. Following
308 # flags are added for development purpose due to repository dependency,
309 # but not officially supported yet.
310 parser.add_option(
311 "--goma_dir",
312 type="path",
313 api=constants.REEXEC_API_GOMA,
Trent Apted66736d82023-05-25 10:38:28 +1000314 help=(
315 "Specify a directory containing goma. When this is "
316 "set, GOMA is used to build Chrome."
317 ),
Alex Klein1699fab2022-09-08 08:46:06 -0600318 )
319 parser.add_option(
320 "--chromeos_goma_dir",
321 type="path",
322 api=constants.REEXEC_API_CHROMEOS_GOMA_DIR,
Trent Apted66736d82023-05-25 10:38:28 +1000323 help="Specify a directory containing goma for build package.",
Alex Klein1699fab2022-09-08 08:46:06 -0600324 )
Alex Klein1699fab2022-09-08 08:46:06 -0600325 group = CustomGroup(parser, "Deprecated Options")
Don Garrett211df8c2017-09-06 13:33:02 -0700326
Alex Klein1699fab2022-09-08 08:46:06 -0600327 parser.add_option(
328 "--local",
329 action="store_true",
330 default=False,
331 help="Deprecated. See cros tryjob.",
332 )
333 parser.add_option(
334 "--remote",
335 action="store_true",
336 default=False,
337 help="Deprecated. See cros tryjob.",
338 )
Don Garrett211df8c2017-09-06 13:33:02 -0700339
Alex Klein1699fab2022-09-08 08:46:06 -0600340 #
341 # Patch selection options.
342 #
Mike Frysinger81af6ef2013-04-03 02:24:09 -0400343
Alex Klein1699fab2022-09-08 08:46:06 -0600344 group = CustomGroup(parser, "Patch Options")
Mike Frysinger81af6ef2013-04-03 02:24:09 -0400345
Alex Klein1699fab2022-09-08 08:46:06 -0600346 group.add_remote_option(
347 "-g",
348 "--gerrit-patches",
349 action="split_extend",
350 type="string",
351 default=[],
352 metavar="'Id1 *int_Id2...IdN'",
Trent Apted66736d82023-05-25 10:38:28 +1000353 help=(
354 "Space-separated list of short-form Gerrit "
355 "Change-Id's or change numbers to patch. "
356 "Please prepend '*' to internal Change-Id's"
357 ),
Alex Klein1699fab2022-09-08 08:46:06 -0600358 )
Mike Frysinger81af6ef2013-04-03 02:24:09 -0400359
Alex Klein1699fab2022-09-08 08:46:06 -0600360 parser.add_argument_group(group)
Mike Frysinger81af6ef2013-04-03 02:24:09 -0400361
Alex Klein1699fab2022-09-08 08:46:06 -0600362 #
363 # Remote trybot options.
364 #
Mike Frysinger81af6ef2013-04-03 02:24:09 -0400365
Alex Klein1699fab2022-09-08 08:46:06 -0600366 group = CustomGroup(parser, "Options used to configure tryjob behavior.")
367 group.add_remote_option(
368 "--hwtest",
369 action="store_true",
370 default=False,
371 help="Run the HWTest stage (tests on real hardware)",
372 )
373 group.add_option(
374 "--hwtest_dut_dimensions",
375 type="string",
376 action="split_extend",
377 default=None,
Trent Apted66736d82023-05-25 10:38:28 +1000378 help=(
379 "Space-separated list of key:val Swarming bot "
380 "dimensions to run each builders SkylabHWTest "
381 "stages against (this overrides the configured "
382 "DUT dimensions for each test). Requires at least "
383 '"label-board", "label-model", and "label-pool".'
384 ),
Alex Klein1699fab2022-09-08 08:46:06 -0600385 )
386 group.add_remote_option(
387 "--channel",
388 action="split_extend",
389 dest="channels",
390 default=[],
Trent Apted66736d82023-05-25 10:38:28 +1000391 help=(
392 "Specify a channel for a payloads trybot. Can "
393 "be specified multiple times. No valid for "
394 "non-payloads configs."
395 ),
Alex Klein1699fab2022-09-08 08:46:06 -0600396 )
Mike Frysinger81af6ef2013-04-03 02:24:09 -0400397
Alex Klein1699fab2022-09-08 08:46:06 -0600398 parser.add_argument_group(group)
Mike Frysinger81af6ef2013-04-03 02:24:09 -0400399
Alex Klein1699fab2022-09-08 08:46:06 -0600400 #
401 # Advanced options.
402 #
Ryan Cuif4f84be2012-07-09 18:50:41 -0700403
Alex Klein1699fab2022-09-08 08:46:06 -0600404 group = CustomGroup(
405 parser,
406 "Advanced Options",
407 "Caution: use these options at your own risk.",
408 )
Brian Harring3fec5a82012-03-01 05:57:03 -0800409
Alex Klein1699fab2022-09-08 08:46:06 -0600410 group.add_remote_option(
411 "--bootstrap-args",
412 action="append",
413 default=[],
Trent Apted66736d82023-05-25 10:38:28 +1000414 help=(
415 "Args passed directly to the bootstrap re-exec "
416 "to skip verification by the bootstrap code"
417 ),
Alex Klein1699fab2022-09-08 08:46:06 -0600418 )
419 group.add_remote_option(
420 "--buildbot",
421 action="store_true",
422 dest="buildbot",
423 default=False,
Trent Apted66736d82023-05-25 10:38:28 +1000424 help=(
425 "This is running on a buildbot. "
426 "This can be used to make a build operate "
427 "like an official builder, e.g. generate "
428 "new version numbers and archive official "
429 "artifacts and such. This should only be "
430 "used if you are confident in what you are "
431 "doing, as it will make automated commits."
432 ),
Alex Klein1699fab2022-09-08 08:46:06 -0600433 )
434 parser.add_remote_option(
435 "--repo-cache",
436 type="path",
437 dest="_repo_cache",
438 help="Present for backwards compatibility, ignored.",
439 )
440 group.add_remote_option(
441 "--no-buildbot-tags",
442 action="store_false",
443 dest="enable_buildbot_tags",
444 default=True,
Trent Apted66736d82023-05-25 10:38:28 +1000445 help=(
446 "Suppress buildbot specific tags from log "
447 "output. This is used to hide recursive "
448 "cbuilbot runs on the waterfall."
449 ),
Alex Klein1699fab2022-09-08 08:46:06 -0600450 )
451 group.add_remote_option(
452 "--buildnumber", type="int", default=0, help="build number"
453 )
454 group.add_option(
455 "--chrome_root",
456 action="callback",
457 type="path",
458 callback=_CheckChromeRootOption,
459 help="Local checkout of Chrome to use.",
460 )
461 group.add_remote_option(
462 "--chrome_version",
463 action="callback",
464 type="string",
465 dest="chrome_version",
466 callback=_CheckChromeVersionOption,
Trent Apted66736d82023-05-25 10:38:28 +1000467 help=(
468 "Used with SPEC logic to force a particular "
469 "git revision of chrome rather than the "
470 "latest."
471 ),
Alex Klein1699fab2022-09-08 08:46:06 -0600472 )
473 group.add_remote_option(
474 "--clobber",
475 action="store_true",
476 default=False,
477 help="Clears an old checkout before syncing",
478 )
479 group.add_remote_option(
480 "--latest-toolchain",
481 action="store_true",
482 default=False,
483 help="Use the latest toolchain.",
484 )
485 parser.add_option(
486 "--log_dir",
487 dest="log_dir",
488 type="path",
489 help="Directory where logs are stored.",
490 )
491 group.add_remote_option(
492 "--maxarchives",
493 type="int",
494 dest="max_archive_builds",
495 default=3,
496 help="Change the local saved build count limit.",
497 )
498 parser.add_remote_option(
499 "--manifest-repo-url", help="Overrides the default manifest repo url."
500 )
501 group.add_remote_option(
502 "--compilecheck",
503 action="store_true",
504 default=False,
505 help="Only verify compilation and unit tests.",
506 )
507 group.add_remote_option(
508 "--noarchive",
509 action="store_false",
510 dest="archive",
511 default=True,
512 help="Don't run archive stage.",
513 )
514 group.add_remote_option(
515 "--nobootstrap",
516 action="store_false",
517 dest="bootstrap",
518 default=True,
Trent Apted66736d82023-05-25 10:38:28 +1000519 help="Don't checkout and run from a standalone chromite repo.",
Alex Klein1699fab2022-09-08 08:46:06 -0600520 )
521 group.add_remote_option(
522 "--nobuild",
523 action="store_false",
524 dest="build",
525 default=True,
526 help="Don't actually build (for cbuildbot dev)",
527 )
528 group.add_remote_option(
529 "--noclean",
530 action="store_false",
531 dest="clean",
532 default=True,
533 help="Don't clean the buildroot",
534 )
535 group.add_remote_option(
536 "--nocgroups",
537 action="store_false",
538 dest="cgroups",
539 default=True,
540 help="Disable cbuildbots usage of cgroups.",
541 )
542 group.add_remote_option(
543 "--nochromesdk",
544 action="store_false",
545 dest="chrome_sdk",
546 default=True,
Trent Apted66736d82023-05-25 10:38:28 +1000547 help=(
548 "Don't run the ChromeSDK stage which builds "
549 "Chrome outside of the chroot."
550 ),
Alex Klein1699fab2022-09-08 08:46:06 -0600551 )
552 group.add_remote_option(
553 "--noprebuilts",
554 action="store_false",
555 dest="prebuilts",
556 default=True,
557 help="Don't upload prebuilts.",
558 )
559 group.add_remote_option(
560 "--nopatch",
561 action="store_false",
562 dest="postsync_patch",
563 default=True,
Trent Apted66736d82023-05-25 10:38:28 +1000564 help=(
565 "Don't run PatchChanges stage. This does not "
566 "disable patching in of chromite patches "
567 "during BootstrapStage."
568 ),
Alex Klein1699fab2022-09-08 08:46:06 -0600569 )
570 group.add_remote_option(
571 "--nopaygen",
572 action="store_false",
573 dest="paygen",
574 default=True,
575 help="Don't generate payloads.",
576 )
577 group.add_remote_option(
578 "--noreexec",
579 action="store_false",
580 dest="postsync_reexec",
581 default=True,
582 help="Don't reexec into the buildroot after syncing.",
583 )
584 group.add_remote_option(
585 "--nosdk",
586 action="store_true",
587 default=False,
588 help="Re-create the SDK from scratch.",
589 )
590 group.add_remote_option(
591 "--nosync",
592 action="store_false",
593 dest="sync",
594 default=True,
595 help="Don't sync before building.",
596 )
597 group.add_remote_option(
598 "--notests",
599 action="store_false",
600 dest="tests",
601 default=True,
Trent Apted66736d82023-05-25 10:38:28 +1000602 help=(
603 "Override values from buildconfig, run no "
604 "tests, and build no autotest and artifacts."
605 ),
Alex Klein1699fab2022-09-08 08:46:06 -0600606 )
607 group.add_remote_option(
608 "--novmtests",
609 action="store_false",
610 dest="vmtests",
611 default=True,
Trent Apted66736d82023-05-25 10:38:28 +1000612 help="Override values from buildconfig, run no vmtests.",
Alex Klein1699fab2022-09-08 08:46:06 -0600613 )
614 group.add_remote_option(
615 "--noimagetests",
616 action="store_false",
617 dest="image_test",
618 default=True,
Trent Apted66736d82023-05-25 10:38:28 +1000619 help="Override values from buildconfig and run no image tests.",
Alex Klein1699fab2022-09-08 08:46:06 -0600620 )
621 group.add_remote_option(
622 "--nouprev",
623 action="store_false",
624 dest="uprev",
625 default=True,
Trent Apted66736d82023-05-25 10:38:28 +1000626 help="Override values from buildconfig and never uprev.",
Alex Klein1699fab2022-09-08 08:46:06 -0600627 )
628 group.add_option(
629 "--reference-repo",
Trent Apted66736d82023-05-25 10:38:28 +1000630 help=(
631 "Reuse git data stored in an existing repo "
632 "checkout. This can drastically reduce the network "
633 "time spent setting up the trybot checkout. By "
634 "default, if this option isn't given but cbuildbot "
635 "is invoked from a repo checkout, cbuildbot will "
636 "use the repo root."
637 ),
Alex Klein1699fab2022-09-08 08:46:06 -0600638 )
639 group.add_option(
640 "--resume",
641 action="store_true",
642 default=False,
643 help="Skip stages already successfully completed.",
644 )
645 group.add_remote_option(
646 "--timeout",
647 type="int",
648 default=0,
Trent Apted66736d82023-05-25 10:38:28 +1000649 help=(
650 "Specify the maximum amount of time this job "
651 "can run for, at which point the build will be "
652 "aborted. If set to zero, then there is no "
653 "timeout."
654 ),
Alex Klein1699fab2022-09-08 08:46:06 -0600655 )
656 group.add_remote_option(
657 "--version",
658 dest="force_version",
Trent Apted66736d82023-05-25 10:38:28 +1000659 help=(
660 "Used with manifest logic. Forces use of this "
661 "version rather than create or get latest. "
662 "Examples: 4815.0.0-rc1, 4815.1.2"
663 ),
Alex Klein1699fab2022-09-08 08:46:06 -0600664 )
665 group.add_remote_option(
666 "--git-cache-dir",
667 type="path",
668 api=constants.REEXEC_API_GIT_CACHE_DIR,
Trent Apted66736d82023-05-25 10:38:28 +1000669 help=(
670 "Specify the cache directory to store the "
671 "project caches populated by the git-cache "
672 "tool. Bootstrap the projects based on the git "
673 "cache files instead of fetching them directly "
674 "from the GoB servers."
675 ),
Alex Klein1699fab2022-09-08 08:46:06 -0600676 )
677 group.add_remote_option(
678 "--chrome-preload-dir",
679 type="path",
680 api=constants.REEXEC_API_CHROME_PRELOAD_DIR,
Trent Apted66736d82023-05-25 10:38:28 +1000681 help=(
682 "Specify a preloaded chrome source cache "
683 "directory populated by the git-cache tool. "
684 "Bootstrap chrome based on the cached files "
685 "instead of fetching them directly from the GoB "
686 "servers. When both this argument and "
687 "--git-cache-dir are provided this value will "
688 "be preferred for the chrome source cache."
689 ),
Alex Klein1699fab2022-09-08 08:46:06 -0600690 )
691 group.add_remote_option(
692 "--source_cache",
693 action="store_true",
694 default=False,
695 help="Whether to utilize cache snapshot mounts.",
696 )
697 group.add_remote_option(
698 "--debug-cidb",
699 action="store_true",
700 default=False,
701 help="Force Debug CIDB to be used.",
702 )
703 # cbuildbot ChromeOS Findit options
704 group.add_remote_option(
705 "--cbb_build_packages",
706 action="split_extend",
707 dest="cbb_build_packages",
708 default=[],
Trent Apted66736d82023-05-25 10:38:28 +1000709 help=(
710 "Specify an explicit list of packages to build "
711 "for integration with Findit."
712 ),
Alex Klein1699fab2022-09-08 08:46:06 -0600713 )
714 group.add_remote_option(
715 "--cbb_snapshot_revision",
716 type="string",
717 dest="cbb_snapshot_revision",
718 default=None,
Trent Apted66736d82023-05-25 10:38:28 +1000719 help="Snapshot manifest revision to sync to for building.",
Alex Klein1699fab2022-09-08 08:46:06 -0600720 )
721 group.add_remote_option(
722 "--no-publish-prebuilt-confs",
723 dest="publish",
724 action="store_false",
725 default=True,
726 help="Don't publish git commits to prebuilt.conf or sdk_version.conf",
727 )
Mike Frysinger81af6ef2013-04-03 02:24:09 -0400728
Alex Klein1699fab2022-09-08 08:46:06 -0600729 parser.add_argument_group(group)
Mike Frysinger81af6ef2013-04-03 02:24:09 -0400730
Alex Klein1699fab2022-09-08 08:46:06 -0600731 #
732 # Internal options.
733 #
Mike Frysinger81af6ef2013-04-03 02:24:09 -0400734
Alex Klein1699fab2022-09-08 08:46:06 -0600735 group = CustomGroup(
736 parser,
737 "Internal Chromium OS Build Team Options",
738 "Caution: these are for meant for the Chromium OS build team only",
739 )
Mike Frysinger81af6ef2013-04-03 02:24:09 -0400740
Alex Klein1699fab2022-09-08 08:46:06 -0600741 group.add_remote_option(
742 "--archive-base",
743 type="gs_path",
Trent Apted66736d82023-05-25 10:38:28 +1000744 help=(
745 "Base GS URL (gs://<bucket_name>/<path>) to "
746 "upload archive artifacts to"
747 ),
Alex Klein1699fab2022-09-08 08:46:06 -0600748 )
749 group.add_remote_option(
750 "--cq-gerrit-query",
751 dest="cq_gerrit_override",
Trent Apted66736d82023-05-25 10:38:28 +1000752 help=(
753 "If given, this gerrit query will be used to find what patches to "
754 "test, rather than the normal 'CommitQueue>=1 AND Verified=1 AND "
755 "CodeReview=2' query it defaults to. Use with care- note "
756 "additionally this setting only has an effect if the buildbot "
757 "target is a cq target, and we're in buildbot mode."
758 ),
Alex Klein1699fab2022-09-08 08:46:06 -0600759 )
760 group.add_option(
761 "--pass-through",
762 action="append",
763 type="string",
764 dest="pass_through_args",
765 default=[],
766 )
767 group.add_option(
768 "--reexec-api-version",
769 action="store_true",
770 dest="output_api_version",
771 default=False,
Trent Apted66736d82023-05-25 10:38:28 +1000772 help=(
773 "Used for handling forwards/backwards compatibility "
774 "with --resume and --bootstrap"
775 ),
Alex Klein1699fab2022-09-08 08:46:06 -0600776 )
777 group.add_option(
778 "--remote-trybot",
779 action="store_true",
780 default=False,
781 help="Indicates this is running on a remote trybot machine",
782 )
783 group.add_option(
784 "--buildbucket-id",
785 api=constants.REEXEC_API_GOMA, # Approximate.
Trent Apted66736d82023-05-25 10:38:28 +1000786 help=(
787 "The unique ID in buildbucket of current build "
788 "generated by buildbucket."
789 ),
Alex Klein1699fab2022-09-08 08:46:06 -0600790 )
791 group.add_remote_option(
792 "--remote-patches",
793 action="split_extend",
794 default=[],
Trent Apted66736d82023-05-25 10:38:28 +1000795 help=(
796 "Patches uploaded by the trybot client when run using the -p option"
797 ),
Alex Klein1699fab2022-09-08 08:46:06 -0600798 )
799 # Note the default here needs to be hardcoded to 3; that is the last version
800 # that lacked this functionality.
801 group.add_option(
802 "--remote-version",
803 type="int",
804 default=3,
805 help="Deprecated and ignored.",
806 )
807 group.add_option("--sourceroot", type="path", default=constants.SOURCE_ROOT)
808 group.add_remote_option(
809 "--test-bootstrap",
810 action="store_true",
811 default=False,
Trent Apted66736d82023-05-25 10:38:28 +1000812 help=(
813 "Causes cbuildbot to bootstrap itself twice, "
814 "in the sequence A->B->C: A(unpatched) patches "
815 "and bootstraps B; B patches and bootstraps C"
816 ),
Alex Klein1699fab2022-09-08 08:46:06 -0600817 )
818 group.add_remote_option(
819 "--validation_pool",
Trent Apted66736d82023-05-25 10:38:28 +1000820 help=(
821 "Path to a pickled validation pool. Intended "
822 "for use only with the commit queue."
823 ),
Alex Klein1699fab2022-09-08 08:46:06 -0600824 )
825 group.add_remote_option(
826 "--metadata_dump",
Trent Apted66736d82023-05-25 10:38:28 +1000827 help=(
828 "Path to a json dumped metadata file. This "
829 "will be used as the initial metadata."
830 ),
Alex Klein1699fab2022-09-08 08:46:06 -0600831 )
832 group.add_remote_option(
833 "--master-build-id",
834 type="int",
835 api=constants.REEXEC_API_MASTER_BUILD_ID,
Trent Apted66736d82023-05-25 10:38:28 +1000836 help="cidb build id of the master build to this slave build.",
Alex Klein1699fab2022-09-08 08:46:06 -0600837 )
838 group.add_remote_option(
839 "--master-buildbucket-id",
840 api=constants.REEXEC_API_MASTER_BUILDBUCKET_ID,
Trent Apted66736d82023-05-25 10:38:28 +1000841 help="buildbucket id of the master build to this slave build.",
Alex Klein1699fab2022-09-08 08:46:06 -0600842 )
843 # TODO(nxia): crbug.com/778838
844 # cbuildbot doesn't use pickle files anymore, remove this.
845 group.add_remote_option(
846 "--mock-slave-status",
847 metavar="MOCK_SLAVE_STATUS_PICKLE_FILE",
Trent Apted66736d82023-05-25 10:38:28 +1000848 help=(
849 "Override the result of the _FetchSlaveStatuses "
850 "method of MasterSlaveSyncCompletionStage, by "
851 "specifying a file with a pickle of the result "
852 "to be returned."
853 ),
Alex Klein1699fab2022-09-08 08:46:06 -0600854 )
855 group.add_option(
856 "--previous-build-state",
857 type="string",
858 default="",
859 api=constants.REEXEC_API_PREVIOUS_BUILD_STATE,
Trent Apted66736d82023-05-25 10:38:28 +1000860 help=(
861 "A base64-encoded BuildSummary object describing the "
862 "previous build run on the same build machine."
863 ),
Alex Klein1699fab2022-09-08 08:46:06 -0600864 )
Mike Frysinger81af6ef2013-04-03 02:24:09 -0400865
Alex Klein1699fab2022-09-08 08:46:06 -0600866 parser.add_argument_group(group)
Ryan Cuif4f84be2012-07-09 18:50:41 -0700867
Alex Klein1699fab2022-09-08 08:46:06 -0600868 #
869 # Debug options
870 #
871 # Temporary hack; in place till --dry-run replaces --debug.
872 # pylint: disable=protected-access
873 group = parser.debug_group
874 debug = [x for x in group.option_list if x._long_opts == ["--debug"]][0]
875 debug.help += " Currently functions as --dry-run in addition."
876 debug.pass_through = True
877 group.add_option(
878 "--notee",
879 action="store_false",
880 dest="tee",
881 default=True,
Trent Apted66736d82023-05-25 10:38:28 +1000882 help=(
883 "Disable logging and internal tee process. Primarily "
884 "used for debugging cbuildbot itself."
885 ),
Alex Klein1699fab2022-09-08 08:46:06 -0600886 )
887 return parser
Brian Harring3fec5a82012-03-01 05:57:03 -0800888
889
Mike Frysinger80bba8a2017-08-18 15:28:36 -0400890def _FinishParsing(options):
Alex Klein1699fab2022-09-08 08:46:06 -0600891 """Perform some parsing tasks that need to take place after optparse.
Ryan Cui85867972012-02-23 18:21:49 -0800892
Alex Klein1699fab2022-09-08 08:46:06 -0600893 This function needs to be easily testable! Keep it free of
894 environment-dependent code. Put more detailed usage validation in
895 _PostParseCheck().
Brian Harring3fec5a82012-03-01 05:57:03 -0800896
Alex Klein1699fab2022-09-08 08:46:06 -0600897 Args:
Trent Apted66736d82023-05-25 10:38:28 +1000898 options: The options object returned by optparse
Alex Klein1699fab2022-09-08 08:46:06 -0600899 """
900 # Populate options.pass_through_args.
901 accepted, _ = commandline.FilteringParser.FilterArgs(
902 options.parsed_args, lambda x: x.opt_inst.pass_through
903 )
904 options.pass_through_args.extend(accepted)
Brian Harring07039b52012-05-13 17:56:47 -0700905
Alex Klein1699fab2022-09-08 08:46:06 -0600906 if options.local or options.remote:
907 cros_build_lib.Die("Deprecated usage. Please use cros tryjob instead.")
Don Garrettcc0ee522017-09-13 14:28:42 -0700908
Alex Klein1699fab2022-09-08 08:46:06 -0600909 if not options.buildroot:
910 cros_build_lib.Die("A buildroot is required to build.")
Don Garrett211df8c2017-09-06 13:33:02 -0700911
Alex Klein1699fab2022-09-08 08:46:06 -0600912 if options.chrome_root:
913 if options.chrome_rev != constants.CHROME_REV_LOCAL:
914 cros_build_lib.Die(
915 "Chrome rev must be %s if chrome_root is set."
916 % constants.CHROME_REV_LOCAL
917 )
918 elif options.chrome_rev == constants.CHROME_REV_LOCAL:
919 cros_build_lib.Die(
920 "Chrome root must be set if chrome_rev is %s."
921 % constants.CHROME_REV_LOCAL
922 )
Brian Harring3fec5a82012-03-01 05:57:03 -0800923
Alex Klein1699fab2022-09-08 08:46:06 -0600924 if options.chrome_version:
925 if options.chrome_rev != constants.CHROME_REV_SPEC:
926 cros_build_lib.Die(
927 "Chrome rev must be %s if chrome_version is set."
928 % constants.CHROME_REV_SPEC
929 )
930 elif options.chrome_rev == constants.CHROME_REV_SPEC:
931 cros_build_lib.Die(
932 "Chrome rev must not be %s if chrome_version is not set."
933 % constants.CHROME_REV_SPEC
934 )
Brian Harring3fec5a82012-03-01 05:57:03 -0800935
Alex Klein1699fab2022-09-08 08:46:06 -0600936 patches = bool(options.gerrit_patches)
Ryan Cuieaa9efd2012-04-25 17:56:45 -0700937
Alex Klein9e7b29e2023-04-11 16:10:31 -0600938 # When running in release mode, make sure we are running with checked-in
939 # code. We want checked-in cbuildbot/scripts to prevent errors, and we want
940 # to build a release image with checked-in code for CrOS packages.
Alex Klein1699fab2022-09-08 08:46:06 -0600941 if options.buildbot and patches and not options.debug:
942 cros_build_lib.Die(
943 "Cannot provide patches when running with --buildbot!"
944 )
David James5734ea32012-08-15 20:23:49 -0700945
Alex Klein1699fab2022-09-08 08:46:06 -0600946 if options.buildbot and options.remote_trybot:
947 cros_build_lib.Die(
948 "--buildbot and --remote-trybot cannot be used together."
949 )
Ryan Cuiba41ad32012-03-08 17:15:29 -0800950
Alex Klein1699fab2022-09-08 08:46:06 -0600951 # Record whether --debug was set explicitly vs. it was inferred.
952 options.debug_forced = options.debug
953 # We force --debug to be set for builds that are not 'official'.
954 options.debug = options.debug or not options.buildbot
Brian Harring3fec5a82012-03-01 05:57:03 -0800955
Alex Klein1699fab2022-09-08 08:46:06 -0600956 options.hwtest_dut_override = ParseHWTestDUTDims(
957 options.hwtest_dut_dimensions
958 )
959
Jared Loucksa9e94bf2021-06-28 10:03:31 -0600960
961def ParseHWTestDUTDims(dims):
Alex Klein1699fab2022-09-08 08:46:06 -0600962 """Parse HWTest DUT dimensions into a valid HWTestDUTOverride object.
Jared Loucksa9e94bf2021-06-28 10:03:31 -0600963
Alex Klein1699fab2022-09-08 08:46:06 -0600964 Raises an error if any of board, model, or pool is missing.
965 """
966 if not dims:
967 return None
968 board = model = pool = None
969 extra_dims = []
970 for dim in dims:
971 if dim.startswith(BOARD_DIM_LABEL):
972 # Remove one extra character to account for the ":" or "=" symbol
973 # separating the label from the dimension itself.
974 board = dim[len(BOARD_DIM_LABEL) + 1 :]
975 elif dim.startswith(MODEL_DIM_LABEL):
976 model = dim[len(MODEL_DIM_LABEL) + 1 :]
977 elif dim.startswith(POOL_DIM_LABEL):
978 pool = dim[len(POOL_DIM_LABEL) + 1 :]
979 else:
980 extra_dims.append(dim)
Jared Loucksa9e94bf2021-06-28 10:03:31 -0600981
Alex Klein1699fab2022-09-08 08:46:06 -0600982 if not (board and model and pool):
983 cros_build_lib.Die(
984 "HWTest DUT dimensions must include board, model, and "
985 "pool (given %s)." % dims
986 )
Jared Loucksa9e94bf2021-06-28 10:03:31 -0600987
Alex Klein1699fab2022-09-08 08:46:06 -0600988 return test_stages.HWTestDUTOverride(board, model, pool, extra_dims)
Jared Loucksa9e94bf2021-06-28 10:03:31 -0600989
Brian Harring3fec5a82012-03-01 05:57:03 -0800990
Mike Frysinger27e21b72018-07-12 14:20:21 -0400991# pylint: disable=unused-argument
Mike Frysinger80bba8a2017-08-18 15:28:36 -0400992def _PostParseCheck(parser, options, site_config):
Alex Klein1699fab2022-09-08 08:46:06 -0600993 """Perform some usage validation after we've parsed the arguments
Brian Harring3fec5a82012-03-01 05:57:03 -0800994
Alex Klein1699fab2022-09-08 08:46:06 -0600995 Args:
Trent Apted66736d82023-05-25 10:38:28 +1000996 parser: Option parser that was used to parse arguments.
997 options: The options returned by optparse.
998 site_config: config_lib.SiteConfig containing all config info.
Alex Klein1699fab2022-09-08 08:46:06 -0600999 """
Don Garrett0a873e02015-06-30 17:55:10 -07001000
Alex Klein1699fab2022-09-08 08:46:06 -06001001 if not options.branch:
1002 options.branch = git.GetChromiteTrackingBranch()
Ryan Cuie1e4e662012-05-21 16:39:46 -07001003
Alex Klein1699fab2022-09-08 08:46:06 -06001004 # Because the default cache dir depends on other options, FindCacheDir
1005 # always returns None, and we setup the default here.
1006 if options.cache_dir is None:
1007 # Note, options.sourceroot is set regardless of the path
1008 # actually existing.
1009 options.cache_dir = os.path.join(options.buildroot, ".cache")
1010 options.cache_dir = os.path.abspath(options.cache_dir)
1011 parser.ConfigureCacheDir(options.cache_dir)
Brian Harringae0a5322012-09-15 01:46:51 -07001012
Alex Klein1699fab2022-09-08 08:46:06 -06001013 osutils.SafeMakedirsNonRoot(options.cache_dir)
Ryan Cui5ba7e152012-05-10 14:36:52 -07001014
Alex Klein1699fab2022-09-08 08:46:06 -06001015 # Ensure that all args are legitimate config targets.
1016 if options.build_config_name not in site_config:
1017 cros_build_lib.Die(
1018 'Unknown build config: "%s"' % options.build_config_name
1019 )
Don Garrett4bb21682014-03-03 16:16:23 -08001020
Alex Klein1699fab2022-09-08 08:46:06 -06001021 build_config = site_config[options.build_config_name]
1022 is_payloads_build = build_config.build_type == constants.PAYLOADS_TYPE
Don Garrett4af20982015-05-29 19:02:23 -07001023
Alex Klein1699fab2022-09-08 08:46:06 -06001024 if options.channels and not is_payloads_build:
1025 cros_build_lib.Die(
1026 "--channel must only be used with a payload config,"
1027 " not target (%s)." % options.build_config_name
1028 )
Don Garrett5af1d262014-05-16 15:49:37 -07001029
Alex Klein1699fab2022-09-08 08:46:06 -06001030 if not options.channels and is_payloads_build:
1031 cros_build_lib.Die(
Trent Apted66736d82023-05-25 10:38:28 +10001032 "payload configs (%s) require --channel to do anything useful."
1033 % options.build_config_name
Alex Klein1699fab2022-09-08 08:46:06 -06001034 )
Matt Tennant763497d2014-01-17 16:45:54 -08001035
Alex Klein1699fab2022-09-08 08:46:06 -06001036 # If the build config explicitly forces the debug flag, set the debug flag
1037 # as if it was set from the command line.
1038 if build_config.debug:
1039 options.debug = True
Don Garrett370839f2017-10-19 18:32:34 -07001040
Alex Klein1699fab2022-09-08 08:46:06 -06001041 if not (config_lib.isTryjobConfig(build_config) or options.buildbot):
1042 cros_build_lib.Die(
1043 "Refusing to run non-tryjob config as a tryjob.\n"
1044 'Please "repo sync && cros tryjob --list %s" for alternatives.\n'
1045 "See go/cros-explicit-tryjob-build-configs-psa.",
1046 build_config.name,
1047 )
Don Garrett02d2f582017-11-08 14:01:24 -08001048
Alex Klein1699fab2022-09-08 08:46:06 -06001049 # The --version option is not compatible with an external target unless the
1050 # --buildbot option is specified. More correctly, only "paladin versions"
1051 # will work with external targets, and those are only used with --buildbot.
1052 # If --buildbot is specified, then user should know what they are doing and
1053 # only specify a version that will work. See crbug.com/311648.
1054 if options.force_version and not (
1055 options.buildbot or build_config.internal
1056 ):
1057 cros_build_lib.Die(
1058 "Cannot specify --version without --buildbot for an"
1059 " external target (%s)." % options.build_config_name
1060 )
Matt Tennant763497d2014-01-17 16:45:54 -08001061
Ryan Cui85867972012-02-23 18:21:49 -08001062
Don Garrett597ddff2017-02-17 18:29:37 -08001063def ParseCommandLine(parser, argv):
Alex Klein1699fab2022-09-08 08:46:06 -06001064 """Completely parse the commandline arguments"""
1065 (options, args) = parser.parse_args(argv)
Brian Harring37e559b2012-05-22 20:47:32 -07001066
Alex Klein1699fab2022-09-08 08:46:06 -06001067 # Handle the request for the reexec command line API version number.
1068 if options.output_api_version:
1069 print(constants.REEXEC_API_VERSION)
1070 sys.exit(0)
Brian Harring37e559b2012-05-22 20:47:32 -07001071
Alex Klein1699fab2022-09-08 08:46:06 -06001072 # Record the configs targeted. Strip out null arguments.
1073 build_config_names = [x for x in args if x]
1074 if len(build_config_names) != 1:
1075 cros_build_lib.Die(
1076 "Expected exactly one build config. Got: %r", build_config_names
1077 )
1078 options.build_config_name = build_config_names[-1]
Don Garrettf0761152017-10-19 19:38:27 -07001079
Alex Klein1699fab2022-09-08 08:46:06 -06001080 _FinishParsing(options)
1081 return options
Ryan Cui85867972012-02-23 18:21:49 -08001082
1083
Alex Klein1699fab2022-09-08 08:46:06 -06001084_ENVIRONMENT_PROD = "prod"
1085_ENVIRONMENT_DEBUG = "debug"
1086_ENVIRONMENT_STANDALONE = "standalone"
Aviv Keshet420de512015-05-18 14:28:48 -07001087
1088
1089def _GetRunEnvironment(options, build_config):
Alex Klein1699fab2022-09-08 08:46:06 -06001090 """Determine whether this is a prod/debug/standalone run."""
1091 if options.debug_cidb:
1092 return _ENVIRONMENT_DEBUG
Don Garretta90f0142018-02-28 14:25:19 -08001093
Alex Klein1699fab2022-09-08 08:46:06 -06001094 # One of these arguments should always be set if running on a real builder.
1095 # If we aren't on a real builder, we are standalone.
1096 if not options.buildbot and not options.remote_trybot:
1097 return _ENVIRONMENT_STANDALONE
Aviv Keshet420de512015-05-18 14:28:48 -07001098
Alex Klein1699fab2022-09-08 08:46:06 -06001099 if build_config["debug_cidb"]:
1100 return _ENVIRONMENT_DEBUG
Aviv Keshet420de512015-05-18 14:28:48 -07001101
Alex Klein1699fab2022-09-08 08:46:06 -06001102 return _ENVIRONMENT_PROD
Aviv Keshet420de512015-05-18 14:28:48 -07001103
1104
Gabe Blackde694a32015-02-19 15:11:11 -08001105def _SetupConnections(options, build_config):
George Engelbrecht7e07c702022-09-19 17:03:55 -06001106 """Set up CIDB connections using the appropriate Setup call.
Aviv Keshet2982af52014-08-13 16:07:57 -07001107
Alex Klein1699fab2022-09-08 08:46:06 -06001108 Args:
Trent Apted66736d82023-05-25 10:38:28 +10001109 options: Command line options structure.
1110 build_config: Config object for this build.
Alex Klein1699fab2022-09-08 08:46:06 -06001111 """
George Engelbrecht7e07c702022-09-19 17:03:55 -06001112 # Outline:
1113 # 1) Based on options and build_config, decide whether we are a production
1114 # run, debug run, or standalone run.
1115 # 2) Set up cidb instance accordingly.
Alex Klein9e7b29e2023-04-11 16:10:31 -06001116 # 3) Update topology info from cidb, so that any other service set up can
1117 # use topology.
George Engelbrecht7e07c702022-09-19 17:03:55 -06001118 # 4) Set up any other services.
1119 run_type = _GetRunEnvironment(options, build_config)
1120
1121 if run_type == _ENVIRONMENT_PROD:
1122 cidb.CIDBConnectionFactory.SetupProdCidb()
1123 context = ts_mon_config.SetupTsMonGlobalState(
1124 "cbuildbot", indirect=True
1125 )
1126 elif run_type == _ENVIRONMENT_DEBUG:
1127 cidb.CIDBConnectionFactory.SetupDebugCidb()
1128 context = ts_mon_config.TrivialContextManager()
1129 else:
1130 cidb.CIDBConnectionFactory.SetupNoCidb()
1131 context = ts_mon_config.TrivialContextManager()
Aviv Keshet62d1a0e2014-08-22 21:16:13 -07001132
Alex Klein1699fab2022-09-08 08:46:06 -06001133 topology.FetchTopology()
1134 return context
Paul Hobbsd5a0f812016-07-26 16:10:31 -07001135
Aviv Keshet2982af52014-08-13 16:07:57 -07001136
Dean Liaoe5b0aca2018-01-24 15:27:26 +08001137class _MockMethodWithReturnValue(object):
Alex Klein1699fab2022-09-08 08:46:06 -06001138 """A method mocker which just returns the specific value."""
Dean Liaoe5b0aca2018-01-24 15:27:26 +08001139
Alex Klein1699fab2022-09-08 08:46:06 -06001140 def __init__(self, return_value):
1141 self.return_value = return_value
1142
1143 def __call__(self, *args, **kwargs):
1144 return self.return_value
Dean Liaoe5b0aca2018-01-24 15:27:26 +08001145
1146
1147class _ObjectMethodPatcher(object):
Alex Klein1699fab2022-09-08 08:46:06 -06001148 """A simplified mock.object.patch.
Dean Liaoe5b0aca2018-01-24 15:27:26 +08001149
Alex Klein1699fab2022-09-08 08:46:06 -06001150 It is a context manager that patches an object's method with specified
1151 return value.
Dean Liaoe5b0aca2018-01-24 15:27:26 +08001152 """
Dean Liaoe5b0aca2018-01-24 15:27:26 +08001153
Alex Klein1699fab2022-09-08 08:46:06 -06001154 def __init__(self, target, attr, return_value=None):
1155 """Constructor.
Dean Liaoe5b0aca2018-01-24 15:27:26 +08001156
Alex Klein1699fab2022-09-08 08:46:06 -06001157 Args:
Trent Apted66736d82023-05-25 10:38:28 +10001158 target: object to patch.
1159 attr: method name of the object to patch.
1160 return_value: the return value when calling target.attr
Alex Klein1699fab2022-09-08 08:46:06 -06001161 """
1162 self.target = target
1163 self.attr = attr
1164 self.return_value = return_value
1165 self.original_attr = None
1166 self.new_attr = _MockMethodWithReturnValue(self.return_value)
1167
1168 def __enter__(self):
1169 self.original_attr = self.target.__dict__[self.attr]
1170 setattr(self.target, self.attr, self.new_attr)
1171
1172 def __exit__(self, *args):
1173 if self.target and self.original_attr:
1174 setattr(self.target, self.attr, self.original_attr)
Dean Liaoe5b0aca2018-01-24 15:27:26 +08001175
1176
Matt Tennant759e2352013-09-27 15:14:44 -07001177# TODO(build): This function is too damn long.
Ryan Cui85867972012-02-23 18:21:49 -08001178def main(argv):
Alex Klein1699fab2022-09-08 08:46:06 -06001179 # We get false positives with the options object.
1180 # pylint: disable=attribute-defined-outside-init
Mike Frysinger80bba8a2017-08-18 15:28:36 -04001181
Alex Klein1699fab2022-09-08 08:46:06 -06001182 # Turn on strict sudo checks.
1183 cros_build_lib.STRICT_SUDO = True
David James59a0a2b2013-03-22 14:04:44 -07001184
Alex Klein1699fab2022-09-08 08:46:06 -06001185 # Set umask to 022 so files created by buildbot are readable.
1186 os.umask(0o22)
Ryan Cui85867972012-02-23 18:21:49 -08001187
Alex Klein1699fab2022-09-08 08:46:06 -06001188 parser = _CreateParser()
1189 options = ParseCommandLine(parser, argv)
Don Garrett0a873e02015-06-30 17:55:10 -07001190
Alex Klein1699fab2022-09-08 08:46:06 -06001191 # Fetch our site_config now, because we need it to do anything else.
1192 site_config = config_lib.GetConfig()
Don Garrettb85658c2015-06-30 19:07:22 -07001193
Alex Klein1699fab2022-09-08 08:46:06 -06001194 _PostParseCheck(parser, options, site_config)
Brian Harring3fec5a82012-03-01 05:57:03 -08001195
Alex Klein1699fab2022-09-08 08:46:06 -06001196 cros_build_lib.AssertOutsideChroot()
Zdenek Behan98ec2fb2012-08-31 17:12:18 +02001197
Alex Klein1699fab2022-09-08 08:46:06 -06001198 if options.enable_buildbot_tags:
1199 cbuildbot_alerts.EnableBuildbotMarkers()
Matt Tennant759e2352013-09-27 15:14:44 -07001200
Alex Klein1699fab2022-09-08 08:46:06 -06001201 if (
1202 options.buildbot
1203 and not options.debug
1204 and not cros_build_lib.HostIsCIBuilder()
1205 ):
1206 # --buildbot can only be used on a real builder, unless it's debug.
1207 cros_build_lib.Die("This host is not a supported build machine.")
Ningning Xiac691e432016-08-11 14:52:59 -07001208
Alex Klein1699fab2022-09-08 08:46:06 -06001209 # Only one config arg is allowed in this mode, which was confirmed earlier.
1210 build_config = site_config[options.build_config_name]
Brian Harring3fec5a82012-03-01 05:57:03 -08001211
Alex Klein1699fab2022-09-08 08:46:06 -06001212 # TODO: Re-enable this block when reference_repo support handles this
1213 # properly. (see chromium:330775)
1214 # if options.reference_repo is None:
1215 # repo_path = os.path.join(options.sourceroot, '.repo')
1216 # # If we're being run from a repo checkout, reuse the repo's git pool to
1217 # # cut down on sync time.
1218 # if os.path.exists(repo_path):
1219 # options.reference_repo = options.sourceroot
Don Garrettbbd7b552014-05-16 13:15:21 -07001220
Alex Klein1699fab2022-09-08 08:46:06 -06001221 if options.reference_repo:
1222 if not os.path.exists(options.reference_repo):
1223 parser.error(
1224 "Reference path %s does not exist" % (options.reference_repo,)
1225 )
1226 elif not os.path.exists(os.path.join(options.reference_repo, ".repo")):
1227 parser.error(
1228 "Reference path %s does not look to be the base of a "
1229 "repo checkout; no .repo exists in the root."
1230 % (options.reference_repo,)
1231 )
David Jamesdac7a912013-11-18 11:14:44 -08001232
Alex Klein1699fab2022-09-08 08:46:06 -06001233 if (options.buildbot or options.remote_trybot) and not options.resume:
1234 missing = osutils.FindMissingBinaries(_BUILDBOT_REQUIRED_BINARIES)
1235 if missing:
1236 parser.error(
1237 "Option --buildbot/--remote-trybot requires the following "
1238 "binaries which couldn't be found in $PATH: %s"
Trent Apted66736d82023-05-25 10:38:28 +10001239 % ", ".join(missing)
Alex Klein1699fab2022-09-08 08:46:06 -06001240 )
Brian Harring351ce442012-03-09 16:38:14 -08001241
Alex Klein1699fab2022-09-08 08:46:06 -06001242 if options.reference_repo:
1243 options.reference_repo = os.path.abspath(options.reference_repo)
David Jamesdac7a912013-11-18 11:14:44 -08001244
Alex Klein1699fab2022-09-08 08:46:06 -06001245 # Sanity check of buildroot- specifically that it's not pointing into the
1246 # midst of an existing repo since git-repo doesn't support nesting.
1247 if not repository.IsARepoRoot(options.buildroot) and git.FindRepoDir(
1248 options.buildroot
1249 ):
1250 cros_build_lib.Die(
1251 "Configured buildroot %s is a subdir of an existing repo checkout."
1252 % options.buildroot
1253 )
Brian Harring3fec5a82012-03-01 05:57:03 -08001254
Alex Klein1699fab2022-09-08 08:46:06 -06001255 if not options.log_dir:
1256 options.log_dir = os.path.join(options.buildroot, _DEFAULT_LOG_DIR)
Chris Sosab5ea3b42012-10-25 15:25:20 -07001257
Alex Klein1699fab2022-09-08 08:46:06 -06001258 log_file = None
1259 if options.tee:
1260 log_file = os.path.join(options.log_dir, _BUILDBOT_LOG_FILE)
1261 osutils.SafeMakedirs(options.log_dir)
1262 _BackupPreviousLog(log_file)
Brian Harringd166aaf2012-05-14 18:31:53 -07001263
Alex Klein1699fab2022-09-08 08:46:06 -06001264 with cros_build_lib.ContextManagerStack() as stack:
1265 # Preserve chromite; we might be running from there!
1266 options.preserve_paths = set(["chromite"])
1267 if log_file is not None:
Alex Klein9e7b29e2023-04-11 16:10:31 -06001268 # We don't want the critical section to try to clean up the tee
1269 # process, so we run Tee (forked off) outside of it. This prevents a
1270 # deadlock because the Tee process only exits when its pipe is
1271 # closed, and the critical section accidentally holds on to that
1272 # file handle.
Alex Klein1699fab2022-09-08 08:46:06 -06001273 stack.Add(tee.Tee, log_file)
1274 options.preserve_paths.add(_DEFAULT_LOG_DIR)
David Jamescebc7272013-07-17 16:45:05 -07001275
Alex Klein1699fab2022-09-08 08:46:06 -06001276 critical_section = stack.Add(cleanup.EnforcedCleanupSection)
1277 stack.Add(sudo.SudoKeepAlive)
Brian Harringd166aaf2012-05-14 18:31:53 -07001278
Alex Klein1699fab2022-09-08 08:46:06 -06001279 if not options.resume:
1280 # If we're in resume mode, use our parents tempdir rather than
1281 # nesting another layer.
Andrew Lamb5a727f92022-09-30 20:39:46 +00001282 stack.Add(osutils.TempDir, prefix="cbb", set_global=True)
Alex Klein1699fab2022-09-08 08:46:06 -06001283 logging.debug("Cbuildbot tempdir is %r.", os.environ.get("TMP"))
Brian Harringd166aaf2012-05-14 18:31:53 -07001284
Alex Klein1699fab2022-09-08 08:46:06 -06001285 if options.cgroups:
1286 stack.Add(cgroups.SimpleContainChildren, "cbuildbot")
Brian Harringa184efa2012-03-04 11:51:25 -08001287
Alex Klein1699fab2022-09-08 08:46:06 -06001288 # Mark everything between EnforcedCleanupSection and here as having to
1289 # be rolled back via the contextmanager cleanup handlers. This
1290 # ensures that sudo bits cannot outlive cbuildbot, that anything
1291 # cgroups would kill gets killed, etc.
1292 stack.Add(critical_section.ForkWatchdog)
Brian Harringd166aaf2012-05-14 18:31:53 -07001293
Alex Klein1699fab2022-09-08 08:46:06 -06001294 if options.mock_slave_status is not None:
Mike Frysinger31fdddd2023-02-24 15:50:55 -05001295 with open(options.mock_slave_status, "rb") as f:
Alex Klein1699fab2022-09-08 08:46:06 -06001296 mock_statuses = pickle.load(f)
1297 for key, value in mock_statuses.items():
1298 mock_statuses[key] = builder_status_lib.BuilderStatus(
1299 **value
1300 )
1301 stack.Add(
1302 _ObjectMethodPatcher,
Mike Nicholsa1414162021-04-22 20:07:22 +00001303 completion_stages.MasterSlaveSyncCompletionStage,
Alex Klein1699fab2022-09-08 08:46:06 -06001304 "_FetchSlaveStatuses",
1305 return_value=mock_statuses,
1306 )
Aviv Keshetcf9c2722014-02-25 15:15:10 -08001307
Alex Klein1699fab2022-09-08 08:46:06 -06001308 stack.Add(_SetupConnections, options, build_config)
1309 retry_stats.SetupStats()
Aviv Keshet2982af52014-08-13 16:07:57 -07001310
Alex Klein1699fab2022-09-08 08:46:06 -06001311 timeout_display_message = (
1312 "This build has reached the timeout deadline set by the master. "
1313 "Either this stage or a previous one took too long (see stage "
1314 "timing historical summary in ReportStage) or the build failed "
1315 "to start on time."
1316 )
Prathmesh Prabhu80e05df2014-12-11 15:20:33 -08001317
Alex Klein1699fab2022-09-08 08:46:06 -06001318 if options.timeout > 0:
1319 stack.Add(
1320 timeout_util.FatalTimeout,
1321 options.timeout,
1322 timeout_display_message,
1323 )
1324 try:
1325 _RunBuildStagesWrapper(options, site_config, build_config)
1326 except failures_lib.ExitEarlyException as ex:
Alex Klein9e7b29e2023-04-11 16:10:31 -06001327 # This build finished successfully. Do not re-raise
1328 # ExitEarlyException.
Alex Klein1699fab2022-09-08 08:46:06 -06001329 logging.info("One stage exited early: %s", ex)