blob: a2f6f1ace1c443c339acaa1ef0aaa5d126131449 [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
Mike Frysinger321fecd2023-06-16 10:40:51 -040011import contextlib
Chris McDonaldb55b7032021-06-17 16:41:32 -060012import distutils.version # pylint: disable=import-error,no-name-in-module
Brian Harring3fec5a82012-03-01 05:57:03 -080013import glob
Aviv Keshet669eb5e2014-06-23 08:53:01 -070014import json
Chris McDonaldb55b7032021-06-17 16:41:32 -060015import logging
Mike Frysingerb0b0caa2015-11-07 01:05:18 -050016import optparse # pylint: disable=deprecated-module
Brian Harring3fec5a82012-03-01 05:57:03 -080017import os
Aviv Keshetcf9c2722014-02-25 15:15:10 -080018import pickle
Brian Harring3fec5a82012-03-01 05:57:03 -080019import sys
Mike Frysingerace4eae2023-05-26 21:09:43 -040020import tempfile
Brian Harring3fec5a82012-03-01 05:57:03 -080021
Mike Frysingere4d68c22015-02-04 21:26:24 -050022from chromite.cbuildbot import builders
Chris McDonaldb55b7032021-06-17 16:41:32 -060023from chromite.cbuildbot import cbuildbot_alerts
Don Garrett88b8d782014-05-13 17:30:55 -070024from chromite.cbuildbot import cbuildbot_run
Don Garrett88b8d782014-05-13 17:30:55 -070025from chromite.cbuildbot import repository
Aviv Keshet420de512015-05-18 14:28:48 -070026from chromite.cbuildbot import topology
Don Garrett88b8d782014-05-13 17:30:55 -070027from chromite.cbuildbot.stages import completion_stages
Jared Loucksa9e94bf2021-06-28 10:03:31 -060028from chromite.cbuildbot.stages import test_stages
Ningning Xiaf342b952017-02-15 14:13:33 -080029from chromite.lib import builder_status_lib
Brian Harringc92a7012012-02-29 10:11:34 -080030from chromite.lib import cgroups
Chris McDonaldb55b7032021-06-17 16:41:32 -060031from chromite.lib import cidb
Brian Harringa184efa2012-03-04 11:51:25 -080032from chromite.lib import cleanup
Brian Harringb6cf9142012-09-01 20:43:17 -070033from chromite.lib import commandline
Ningning Xia6a718052016-12-22 10:08:15 -080034from chromite.lib import config_lib
35from chromite.lib import constants
Brian Harring1b8c4c82012-05-29 23:03:04 -070036from chromite.lib import cros_build_lib
Ningning Xia6a718052016-12-22 10:08:15 -080037from chromite.lib import failures_lib
David James97d95872012-11-16 15:09:56 -080038from chromite.lib import git
Stefan Zagerd49d9ff2014-08-15 21:33:37 -070039from chromite.lib import gob_util
Brian Harringaf019fb2012-05-10 15:06:13 -070040from chromite.lib import osutils
David James6450a0a2012-12-04 07:59:53 -080041from chromite.lib import parallel
Don Garrettb4318362014-10-03 15:49:36 -070042from chromite.lib import retry_stats
Brian Harring3fec5a82012-03-01 05:57:03 -080043from chromite.lib import sudo
Michael Mortensen3e86c1e2019-11-21 15:51:54 -070044from chromite.lib import tee
David James3432acd2013-11-27 10:02:18 -080045from chromite.lib import timeout_util
Paul Hobbsfcf10342015-12-29 15:52:31 -080046from chromite.lib import ts_mon_config
Dhanya Ganesh39a48a82018-12-06 16:01:11 -070047from chromite.lib.buildstore import BuildStore
Brian Harring3fec5a82012-03-01 05:57:03 -080048
Ryan Cuiadd49122012-03-21 22:19:58 -070049
Alex Klein1699fab2022-09-08 08:46:06 -060050_DEFAULT_LOG_DIR = "cbuildbot_logs"
51_BUILDBOT_LOG_FILE = "cbuildbot.log"
52_DEFAULT_EXT_BUILDROOT = "trybot"
53_DEFAULT_INT_BUILDROOT = "trybot-internal"
54_BUILDBOT_REQUIRED_BINARIES = ("pbzip2",)
55_API_VERSION_ATTR = "api_version"
56BOARD_DIM_LABEL = "label-board"
57MODEL_DIM_LABEL = "label-model"
58POOL_DIM_LABEL = "label-pool"
Brian Harring3fec5a82012-03-01 05:57:03 -080059
60
Brian Harring3fec5a82012-03-01 05:57:03 -080061def _BackupPreviousLog(log_file, backup_limit=25):
Alex Klein1699fab2022-09-08 08:46:06 -060062 """Rename previous log.
Brian Harring3fec5a82012-03-01 05:57:03 -080063
Alex Klein1699fab2022-09-08 08:46:06 -060064 Args:
Trent Apted66736d82023-05-25 10:38:28 +100065 log_file: The absolute path to the previous log.
66 backup_limit: Maximum number of old logs to keep.
Alex Klein1699fab2022-09-08 08:46:06 -060067 """
68 if os.path.exists(log_file):
69 old_logs = sorted(
70 glob.glob(log_file + ".*"), key=distutils.version.LooseVersion
71 )
Brian Harring3fec5a82012-03-01 05:57:03 -080072
Alex Klein1699fab2022-09-08 08:46:06 -060073 if len(old_logs) >= backup_limit:
74 os.remove(old_logs[0])
Brian Harring3fec5a82012-03-01 05:57:03 -080075
Alex Klein1699fab2022-09-08 08:46:06 -060076 last = 0
77 if old_logs:
78 last = int(old_logs.pop().rpartition(".")[2])
Brian Harring3fec5a82012-03-01 05:57:03 -080079
Alex Klein1699fab2022-09-08 08:46:06 -060080 os.rename(log_file, log_file + "." + str(last + 1))
Brian Harring3fec5a82012-03-01 05:57:03 -080081
Ryan Cui5616a512012-08-17 13:39:36 -070082
Gaurav Shah298aa372014-01-31 09:27:24 -080083def _IsDistributedBuilder(options, chrome_rev, build_config):
Alex Klein1699fab2022-09-08 08:46:06 -060084 """Determines whether the builder should be a DistributedBuilder.
Gaurav Shah298aa372014-01-31 09:27:24 -080085
Alex Klein1699fab2022-09-08 08:46:06 -060086 Args:
Trent Apted66736d82023-05-25 10:38:28 +100087 options: options passed on the commandline.
88 chrome_rev: Chrome revision to build.
89 build_config: Builder configuration dictionary.
Gaurav Shah298aa372014-01-31 09:27:24 -080090
Alex Klein1699fab2022-09-08 08:46:06 -060091 Returns:
Trent Apted66736d82023-05-25 10:38:28 +100092 True if the builder should be a distributed_builder
Alex Klein1699fab2022-09-08 08:46:06 -060093 """
94 if not options.buildbot:
95 return False
96 elif chrome_rev in (
97 constants.CHROME_REV_TOT,
98 constants.CHROME_REV_LOCAL,
99 constants.CHROME_REV_SPEC,
100 ):
101 # We don't do distributed logic to TOT Chrome PFQ's, nor local
102 # chrome roots (e.g. chrome try bots)
103 # TODO(davidjames): Update any builders that rely on this logic to use
104 # manifest_version=False instead.
105 return False
106 elif build_config["manifest_version"]:
107 return True
108
Gaurav Shah298aa372014-01-31 09:27:24 -0800109 return False
Gaurav Shah298aa372014-01-31 09:27:24 -0800110
111
Don Garretta52a5b02015-06-02 14:52:57 -0700112def _RunBuildStagesWrapper(options, site_config, build_config):
Alex Klein1699fab2022-09-08 08:46:06 -0600113 """Helper function that wraps RunBuildStages()."""
114 logging.info(
115 "cbuildbot was executed with args %s", cros_build_lib.CmdToStr(sys.argv)
116 )
Brian Harring3fec5a82012-03-01 05:57:03 -0800117
Alex Klein1699fab2022-09-08 08:46:06 -0600118 chrome_rev = build_config["chrome_rev"]
119 if options.chrome_rev:
120 chrome_rev = options.chrome_rev
121 if chrome_rev == constants.CHROME_REV_TOT:
122 options.chrome_version = gob_util.GetTipOfTrunkRevision(
123 constants.CHROMIUM_GOB_URL
124 )
125 options.chrome_rev = constants.CHROME_REV_SPEC
David Jamesa0a664e2013-02-13 09:52:01 -0800126
Alex Klein1699fab2022-09-08 08:46:06 -0600127 # If it's likely we'll need to build Chrome, fetch the source.
128 if build_config["sync_chrome"] is None:
129 options.managed_chrome = chrome_rev != constants.CHROME_REV_LOCAL and (
130 not build_config["usepkg_build_packages"]
131 or chrome_rev
132 or build_config["profile"]
133 )
Matt Tennant0940c382014-01-21 20:43:55 -0800134 else:
Alex Klein1699fab2022-09-08 08:46:06 -0600135 options.managed_chrome = build_config["sync_chrome"]
Mike Frysingere4d68c22015-02-04 21:26:24 -0500136
Alex Klein1699fab2022-09-08 08:46:06 -0600137 chrome_root_mgr = None
138 if options.managed_chrome:
139 # Create a temp directory for syncing Chrome source.
140 chrome_root_mgr = osutils.TempDir(prefix="chrome_root_")
141 options.chrome_root = chrome_root_mgr.tempdir
142
143 # We are done munging options values, so freeze options object now to avoid
144 # further abuse of it.
145 # TODO(mtennant): one by one identify each options value override and see if
146 # it can be handled another way. Try to push this freeze closer and closer
147 # to the start of the script (e.g. in or after _PostParseCheck).
148 options.Freeze()
149
150 metadata_dump_dict = {
151 # A detected default has been set before now if it wasn't explicit.
152 "branch": options.branch,
153 }
154 if options.metadata_dump:
Mike Frysinger31fdddd2023-02-24 15:50:55 -0500155 with open(options.metadata_dump, "rb") as metadata_file:
156 metadata_dump_dict = json.load(metadata_file)
Alex Klein1699fab2022-09-08 08:46:06 -0600157
158 with parallel.Manager() as manager:
159 builder_run = cbuildbot_run.BuilderRun(
160 options, site_config, build_config, manager
161 )
162 buildstore = BuildStore()
163 if metadata_dump_dict:
164 builder_run.attrs.metadata.UpdateWithDict(metadata_dump_dict)
165
166 if builder_run.config.builder_class_name is None:
167 # TODO: This should get relocated to chromeos_config.
168 if _IsDistributedBuilder(options, chrome_rev, build_config):
169 builder_cls_name = "simple_builders.DistributedBuilder"
170 else:
171 builder_cls_name = "simple_builders.SimpleBuilder"
172 builder_cls = builders.GetBuilderClass(builder_cls_name)
173 builder = builder_cls(builder_run, buildstore)
174 else:
175 builder = builders.Builder(builder_run, buildstore)
176
177 try:
178 if not builder.Run():
179 sys.exit(1)
180 finally:
181 if chrome_root_mgr:
182 chrome_root_mgr.Cleanup()
Brian Harring3fec5a82012-03-01 05:57:03 -0800183
184
Brian Harring3fec5a82012-03-01 05:57:03 -0800185def _CheckChromeVersionOption(_option, _opt_str, value, parser):
Alex Klein1699fab2022-09-08 08:46:06 -0600186 """Upgrade other options based on chrome_version being passed."""
187 value = value.strip()
Brian Harring3fec5a82012-03-01 05:57:03 -0800188
Alex Klein1699fab2022-09-08 08:46:06 -0600189 if parser.values.chrome_rev is None and value:
190 parser.values.chrome_rev = constants.CHROME_REV_SPEC
Brian Harring3fec5a82012-03-01 05:57:03 -0800191
Alex Klein1699fab2022-09-08 08:46:06 -0600192 parser.values.chrome_version = value
Brian Harring3fec5a82012-03-01 05:57:03 -0800193
194
195def _CheckChromeRootOption(_option, _opt_str, value, parser):
Alex Klein1699fab2022-09-08 08:46:06 -0600196 """Validate and convert chrome_root to full-path form."""
197 if parser.values.chrome_rev is None:
198 parser.values.chrome_rev = constants.CHROME_REV_LOCAL
Brian Harring3fec5a82012-03-01 05:57:03 -0800199
Alex Klein1699fab2022-09-08 08:46:06 -0600200 parser.values.chrome_root = value
Brian Harring3fec5a82012-03-01 05:57:03 -0800201
202
David Jamesac8c2a72013-02-13 18:44:33 -0800203def FindCacheDir(_parser, _options):
Alex Klein1699fab2022-09-08 08:46:06 -0600204 return None
Brian Harringae0a5322012-09-15 01:46:51 -0700205
206
Ryan Cui5ba7e152012-05-10 14:36:52 -0700207class CustomGroup(optparse.OptionGroup):
Alex Klein1699fab2022-09-08 08:46:06 -0600208 """Custom option group which supports arguments passed-through to trybot."""
David Jameseecba232014-06-11 11:35:11 -0700209
Alex Klein1699fab2022-09-08 08:46:06 -0600210 def add_remote_option(self, *args, **kwargs):
211 """For arguments that are passed-through to remote trybot."""
212 return optparse.OptionGroup.add_option(
213 self, *args, remote_pass_through=True, **kwargs
214 )
Ryan Cui5ba7e152012-05-10 14:36:52 -0700215
216
Ryan Cui1c13a252012-10-16 15:00:16 -0700217class CustomOption(commandline.FilteringOption):
Alex Klein1699fab2022-09-08 08:46:06 -0600218 """Subclass FilteringOption class to implement pass-through and api."""
Ryan Cui5ba7e152012-05-10 14:36:52 -0700219
Alex Klein1699fab2022-09-08 08:46:06 -0600220 def __init__(self, *args, **kwargs):
221 # The remote_pass_through argument specifies whether we should directly
222 # pass the argument (with its value) onto the remote trybot.
223 self.pass_through = kwargs.pop("remote_pass_through", False)
224 self.api_version = int(kwargs.pop("api", "0"))
225 commandline.FilteringOption.__init__(self, *args, **kwargs)
Ryan Cui5ba7e152012-05-10 14:36:52 -0700226
Ryan Cui5ba7e152012-05-10 14:36:52 -0700227
Ryan Cui1c13a252012-10-16 15:00:16 -0700228class CustomParser(commandline.FilteringParser):
Alex Klein1699fab2022-09-08 08:46:06 -0600229 """Custom option parser which supports arguments passed-through to trybot"""
Matt Tennante8179042013-10-01 15:47:32 -0700230
Alex Klein1699fab2022-09-08 08:46:06 -0600231 DEFAULT_OPTION_CLASS = CustomOption
Brian Harringb6cf9142012-09-01 20:43:17 -0700232
Alex Klein1699fab2022-09-08 08:46:06 -0600233 def add_remote_option(self, *args, **kwargs):
234 """For arguments that are passed-through to remote trybot."""
235 return self.add_option(*args, remote_pass_through=True, **kwargs)
Brian Harringb6cf9142012-09-01 20:43:17 -0700236
237
Don Garrett86881cb2017-02-15 15:41:55 -0800238def CreateParser():
Alex Klein1699fab2022-09-08 08:46:06 -0600239 """Expose _CreateParser publicly."""
240 # Name _CreateParser is needed for commandline library.
241 return _CreateParser()
Don Garrett86881cb2017-02-15 15:41:55 -0800242
243
Brian Harring3fec5a82012-03-01 05:57:03 -0800244def _CreateParser():
Alex Klein1699fab2022-09-08 08:46:06 -0600245 """Generate and return the parser with all the options."""
246 # Parse options
247 usage = "usage: %prog [options] buildbot_config [buildbot_config ...]"
248 parser = CustomParser(usage=usage, caching=FindCacheDir)
Brian Harring3fec5a82012-03-01 05:57:03 -0800249
Alex Klein1699fab2022-09-08 08:46:06 -0600250 # Main options
251 parser.add_remote_option(
252 "-b",
253 "--branch",
Trent Apted66736d82023-05-25 10:38:28 +1000254 help=(
255 "The manifest branch to test. The branch to "
256 "check the buildroot out to."
257 ),
Alex Klein1699fab2022-09-08 08:46:06 -0600258 )
259 parser.add_option(
260 "-r",
261 "--buildroot",
262 type="path",
263 dest="buildroot",
Trent Apted66736d82023-05-25 10:38:28 +1000264 help=(
265 "Root directory where source is checked out to, and "
266 "where the build occurs. For external build configs, "
267 "defaults to 'trybot' directory at top level of your "
268 "repo-managed checkout."
269 ),
Alex Klein1699fab2022-09-08 08:46:06 -0600270 )
271 parser.add_option(
272 "--workspace",
273 type="path",
274 api=constants.REEXEC_API_WORKSPACE,
275 help="Root directory for a secondary checkout .",
276 )
277 parser.add_option(
278 "--bootstrap-dir",
279 type="path",
Trent Apted66736d82023-05-25 10:38:28 +1000280 help=(
281 "Bootstrapping cbuildbot may involve checking out "
282 "multiple copies of chromite. All these checkouts "
283 "will be contained in the directory specified here. "
Mike Frysingerace4eae2023-05-26 21:09:43 -0400284 f"(Default: {tempfile.gettempdir()})"
285 ),
Alex Klein1699fab2022-09-08 08:46:06 -0600286 )
287 parser.add_remote_option(
288 "--android_rev",
289 type="choice",
290 choices=constants.VALID_ANDROID_REVISIONS,
291 help=(
292 "Revision of Android to use, of type [%s]"
293 % "|".join(constants.VALID_ANDROID_REVISIONS)
294 ),
295 )
296 parser.add_remote_option(
297 "--chrome_rev",
298 type="choice",
299 choices=constants.VALID_CHROME_REVISIONS,
300 help=(
301 "Revision of Chrome to use, of type [%s]"
302 % "|".join(constants.VALID_CHROME_REVISIONS)
303 ),
304 )
305 parser.add_remote_option(
306 "--profile", help="Name of profile to sub-specify board variant."
307 )
308 # TODO(crbug.com/279618): Running GOMA is under development. Following
309 # flags are added for development purpose due to repository dependency,
310 # but not officially supported yet.
311 parser.add_option(
312 "--goma_dir",
313 type="path",
314 api=constants.REEXEC_API_GOMA,
Trent Apted66736d82023-05-25 10:38:28 +1000315 help=(
316 "Specify a directory containing goma. When this is "
317 "set, GOMA is used to build Chrome."
318 ),
Alex Klein1699fab2022-09-08 08:46:06 -0600319 )
320 parser.add_option(
321 "--chromeos_goma_dir",
322 type="path",
323 api=constants.REEXEC_API_CHROMEOS_GOMA_DIR,
Trent Apted66736d82023-05-25 10:38:28 +1000324 help="Specify a directory containing goma for build package.",
Alex Klein1699fab2022-09-08 08:46:06 -0600325 )
Alex Klein1699fab2022-09-08 08:46:06 -0600326 group = CustomGroup(parser, "Deprecated Options")
Don Garrett211df8c2017-09-06 13:33:02 -0700327
Alex Klein1699fab2022-09-08 08:46:06 -0600328 parser.add_option(
329 "--local",
330 action="store_true",
331 default=False,
332 help="Deprecated. See cros tryjob.",
333 )
334 parser.add_option(
335 "--remote",
336 action="store_true",
337 default=False,
338 help="Deprecated. See cros tryjob.",
339 )
Don Garrett211df8c2017-09-06 13:33:02 -0700340
Alex Klein1699fab2022-09-08 08:46:06 -0600341 #
342 # Patch selection options.
343 #
Mike Frysinger81af6ef2013-04-03 02:24:09 -0400344
Alex Klein1699fab2022-09-08 08:46:06 -0600345 group = CustomGroup(parser, "Patch Options")
Mike Frysinger81af6ef2013-04-03 02:24:09 -0400346
Alex Klein1699fab2022-09-08 08:46:06 -0600347 group.add_remote_option(
348 "-g",
349 "--gerrit-patches",
350 action="split_extend",
351 type="string",
352 default=[],
353 metavar="'Id1 *int_Id2...IdN'",
Trent Apted66736d82023-05-25 10:38:28 +1000354 help=(
355 "Space-separated list of short-form Gerrit "
356 "Change-Id's or change numbers to patch. "
357 "Please prepend '*' to internal Change-Id's"
358 ),
Alex Klein1699fab2022-09-08 08:46:06 -0600359 )
Mike Frysinger81af6ef2013-04-03 02:24:09 -0400360
Alex Klein1699fab2022-09-08 08:46:06 -0600361 parser.add_argument_group(group)
Mike Frysinger81af6ef2013-04-03 02:24:09 -0400362
Alex Klein1699fab2022-09-08 08:46:06 -0600363 #
364 # Remote trybot options.
365 #
Mike Frysinger81af6ef2013-04-03 02:24:09 -0400366
Alex Klein1699fab2022-09-08 08:46:06 -0600367 group = CustomGroup(parser, "Options used to configure tryjob behavior.")
368 group.add_remote_option(
369 "--hwtest",
370 action="store_true",
371 default=False,
372 help="Run the HWTest stage (tests on real hardware)",
373 )
374 group.add_option(
375 "--hwtest_dut_dimensions",
376 type="string",
377 action="split_extend",
378 default=None,
Trent Apted66736d82023-05-25 10:38:28 +1000379 help=(
380 "Space-separated list of key:val Swarming bot "
381 "dimensions to run each builders SkylabHWTest "
382 "stages against (this overrides the configured "
383 "DUT dimensions for each test). Requires at least "
384 '"label-board", "label-model", and "label-pool".'
385 ),
Alex Klein1699fab2022-09-08 08:46:06 -0600386 )
387 group.add_remote_option(
388 "--channel",
389 action="split_extend",
390 dest="channels",
391 default=[],
Trent Apted66736d82023-05-25 10:38:28 +1000392 help=(
393 "Specify a channel for a payloads trybot. Can "
394 "be specified multiple times. No valid for "
395 "non-payloads configs."
396 ),
Alex Klein1699fab2022-09-08 08:46:06 -0600397 )
Mike Frysinger81af6ef2013-04-03 02:24:09 -0400398
Alex Klein1699fab2022-09-08 08:46:06 -0600399 parser.add_argument_group(group)
Mike Frysinger81af6ef2013-04-03 02:24:09 -0400400
Alex Klein1699fab2022-09-08 08:46:06 -0600401 #
402 # Advanced options.
403 #
Ryan Cuif4f84be2012-07-09 18:50:41 -0700404
Alex Klein1699fab2022-09-08 08:46:06 -0600405 group = CustomGroup(
406 parser,
407 "Advanced Options",
408 "Caution: use these options at your own risk.",
409 )
Brian Harring3fec5a82012-03-01 05:57:03 -0800410
Alex Klein1699fab2022-09-08 08:46:06 -0600411 group.add_remote_option(
412 "--bootstrap-args",
413 action="append",
414 default=[],
Trent Apted66736d82023-05-25 10:38:28 +1000415 help=(
416 "Args passed directly to the bootstrap re-exec "
417 "to skip verification by the bootstrap code"
418 ),
Alex Klein1699fab2022-09-08 08:46:06 -0600419 )
420 group.add_remote_option(
421 "--buildbot",
422 action="store_true",
423 dest="buildbot",
424 default=False,
Trent Apted66736d82023-05-25 10:38:28 +1000425 help=(
426 "This is running on a buildbot. "
427 "This can be used to make a build operate "
428 "like an official builder, e.g. generate "
429 "new version numbers and archive official "
430 "artifacts and such. This should only be "
431 "used if you are confident in what you are "
432 "doing, as it will make automated commits."
433 ),
Alex Klein1699fab2022-09-08 08:46:06 -0600434 )
435 parser.add_remote_option(
436 "--repo-cache",
437 type="path",
438 dest="_repo_cache",
439 help="Present for backwards compatibility, ignored.",
440 )
441 group.add_remote_option(
442 "--no-buildbot-tags",
443 action="store_false",
444 dest="enable_buildbot_tags",
445 default=True,
Trent Apted66736d82023-05-25 10:38:28 +1000446 help=(
447 "Suppress buildbot specific tags from log "
448 "output. This is used to hide recursive "
449 "cbuilbot runs on the waterfall."
450 ),
Alex Klein1699fab2022-09-08 08:46:06 -0600451 )
452 group.add_remote_option(
453 "--buildnumber", type="int", default=0, help="build number"
454 )
455 group.add_option(
456 "--chrome_root",
457 action="callback",
458 type="path",
459 callback=_CheckChromeRootOption,
460 help="Local checkout of Chrome to use.",
461 )
462 group.add_remote_option(
463 "--chrome_version",
464 action="callback",
465 type="string",
466 dest="chrome_version",
467 callback=_CheckChromeVersionOption,
Trent Apted66736d82023-05-25 10:38:28 +1000468 help=(
469 "Used with SPEC logic to force a particular "
470 "git revision of chrome rather than the "
471 "latest."
472 ),
Alex Klein1699fab2022-09-08 08:46:06 -0600473 )
474 group.add_remote_option(
475 "--clobber",
476 action="store_true",
477 default=False,
478 help="Clears an old checkout before syncing",
479 )
480 group.add_remote_option(
481 "--latest-toolchain",
482 action="store_true",
483 default=False,
484 help="Use the latest toolchain.",
485 )
486 parser.add_option(
487 "--log_dir",
488 dest="log_dir",
489 type="path",
490 help="Directory where logs are stored.",
491 )
492 group.add_remote_option(
493 "--maxarchives",
494 type="int",
495 dest="max_archive_builds",
496 default=3,
497 help="Change the local saved build count limit.",
498 )
499 parser.add_remote_option(
500 "--manifest-repo-url", help="Overrides the default manifest repo url."
501 )
502 group.add_remote_option(
503 "--compilecheck",
504 action="store_true",
505 default=False,
506 help="Only verify compilation and unit tests.",
507 )
508 group.add_remote_option(
509 "--noarchive",
510 action="store_false",
511 dest="archive",
512 default=True,
513 help="Don't run archive stage.",
514 )
515 group.add_remote_option(
516 "--nobootstrap",
517 action="store_false",
518 dest="bootstrap",
519 default=True,
Trent Apted66736d82023-05-25 10:38:28 +1000520 help="Don't checkout and run from a standalone chromite repo.",
Alex Klein1699fab2022-09-08 08:46:06 -0600521 )
522 group.add_remote_option(
523 "--nobuild",
524 action="store_false",
525 dest="build",
526 default=True,
527 help="Don't actually build (for cbuildbot dev)",
528 )
529 group.add_remote_option(
530 "--noclean",
531 action="store_false",
532 dest="clean",
533 default=True,
534 help="Don't clean the buildroot",
535 )
536 group.add_remote_option(
537 "--nocgroups",
538 action="store_false",
539 dest="cgroups",
540 default=True,
541 help="Disable cbuildbots usage of cgroups.",
542 )
543 group.add_remote_option(
544 "--nochromesdk",
545 action="store_false",
546 dest="chrome_sdk",
547 default=True,
Trent Apted66736d82023-05-25 10:38:28 +1000548 help=(
549 "Don't run the ChromeSDK stage which builds "
550 "Chrome outside of the chroot."
551 ),
Alex Klein1699fab2022-09-08 08:46:06 -0600552 )
553 group.add_remote_option(
554 "--noprebuilts",
555 action="store_false",
556 dest="prebuilts",
557 default=True,
558 help="Don't upload prebuilts.",
559 )
560 group.add_remote_option(
561 "--nopatch",
562 action="store_false",
563 dest="postsync_patch",
564 default=True,
Trent Apted66736d82023-05-25 10:38:28 +1000565 help=(
566 "Don't run PatchChanges stage. This does not "
567 "disable patching in of chromite patches "
568 "during BootstrapStage."
569 ),
Alex Klein1699fab2022-09-08 08:46:06 -0600570 )
571 group.add_remote_option(
572 "--nopaygen",
573 action="store_false",
574 dest="paygen",
575 default=True,
576 help="Don't generate payloads.",
577 )
578 group.add_remote_option(
579 "--noreexec",
580 action="store_false",
581 dest="postsync_reexec",
582 default=True,
583 help="Don't reexec into the buildroot after syncing.",
584 )
585 group.add_remote_option(
586 "--nosdk",
587 action="store_true",
588 default=False,
589 help="Re-create the SDK from scratch.",
590 )
591 group.add_remote_option(
592 "--nosync",
593 action="store_false",
594 dest="sync",
595 default=True,
596 help="Don't sync before building.",
597 )
598 group.add_remote_option(
599 "--notests",
600 action="store_false",
601 dest="tests",
602 default=True,
Trent Apted66736d82023-05-25 10:38:28 +1000603 help=(
604 "Override values from buildconfig, run no "
605 "tests, and build no autotest and artifacts."
606 ),
Alex Klein1699fab2022-09-08 08:46:06 -0600607 )
608 group.add_remote_option(
609 "--novmtests",
610 action="store_false",
611 dest="vmtests",
612 default=True,
Trent Apted66736d82023-05-25 10:38:28 +1000613 help="Override values from buildconfig, run no vmtests.",
Alex Klein1699fab2022-09-08 08:46:06 -0600614 )
615 group.add_remote_option(
616 "--noimagetests",
617 action="store_false",
618 dest="image_test",
619 default=True,
Trent Apted66736d82023-05-25 10:38:28 +1000620 help="Override values from buildconfig and run no image tests.",
Alex Klein1699fab2022-09-08 08:46:06 -0600621 )
622 group.add_remote_option(
623 "--nouprev",
624 action="store_false",
625 dest="uprev",
626 default=True,
Trent Apted66736d82023-05-25 10:38:28 +1000627 help="Override values from buildconfig and never uprev.",
Alex Klein1699fab2022-09-08 08:46:06 -0600628 )
629 group.add_option(
630 "--reference-repo",
Trent Apted66736d82023-05-25 10:38:28 +1000631 help=(
632 "Reuse git data stored in an existing repo "
633 "checkout. This can drastically reduce the network "
634 "time spent setting up the trybot checkout. By "
635 "default, if this option isn't given but cbuildbot "
636 "is invoked from a repo checkout, cbuildbot will "
637 "use the repo root."
638 ),
Alex Klein1699fab2022-09-08 08:46:06 -0600639 )
640 group.add_option(
641 "--resume",
642 action="store_true",
643 default=False,
644 help="Skip stages already successfully completed.",
645 )
646 group.add_remote_option(
647 "--timeout",
648 type="int",
649 default=0,
Trent Apted66736d82023-05-25 10:38:28 +1000650 help=(
651 "Specify the maximum amount of time this job "
652 "can run for, at which point the build will be "
653 "aborted. If set to zero, then there is no "
654 "timeout."
655 ),
Alex Klein1699fab2022-09-08 08:46:06 -0600656 )
657 group.add_remote_option(
658 "--version",
659 dest="force_version",
Trent Apted66736d82023-05-25 10:38:28 +1000660 help=(
661 "Used with manifest logic. Forces use of this "
662 "version rather than create or get latest. "
663 "Examples: 4815.0.0-rc1, 4815.1.2"
664 ),
Alex Klein1699fab2022-09-08 08:46:06 -0600665 )
666 group.add_remote_option(
667 "--git-cache-dir",
668 type="path",
669 api=constants.REEXEC_API_GIT_CACHE_DIR,
Trent Apted66736d82023-05-25 10:38:28 +1000670 help=(
671 "Specify the cache directory to store the "
672 "project caches populated by the git-cache "
673 "tool. Bootstrap the projects based on the git "
674 "cache files instead of fetching them directly "
675 "from the GoB servers."
676 ),
Alex Klein1699fab2022-09-08 08:46:06 -0600677 )
678 group.add_remote_option(
679 "--chrome-preload-dir",
680 type="path",
681 api=constants.REEXEC_API_CHROME_PRELOAD_DIR,
Trent Apted66736d82023-05-25 10:38:28 +1000682 help=(
683 "Specify a preloaded chrome source cache "
684 "directory populated by the git-cache tool. "
685 "Bootstrap chrome based on the cached files "
686 "instead of fetching them directly from the GoB "
687 "servers. When both this argument and "
688 "--git-cache-dir are provided this value will "
689 "be preferred for the chrome source cache."
690 ),
Alex Klein1699fab2022-09-08 08:46:06 -0600691 )
692 group.add_remote_option(
693 "--source_cache",
694 action="store_true",
695 default=False,
696 help="Whether to utilize cache snapshot mounts.",
697 )
698 group.add_remote_option(
699 "--debug-cidb",
700 action="store_true",
701 default=False,
702 help="Force Debug CIDB to be used.",
703 )
704 # cbuildbot ChromeOS Findit options
705 group.add_remote_option(
706 "--cbb_build_packages",
707 action="split_extend",
708 dest="cbb_build_packages",
709 default=[],
Trent Apted66736d82023-05-25 10:38:28 +1000710 help=(
711 "Specify an explicit list of packages to build "
712 "for integration with Findit."
713 ),
Alex Klein1699fab2022-09-08 08:46:06 -0600714 )
715 group.add_remote_option(
716 "--cbb_snapshot_revision",
717 type="string",
718 dest="cbb_snapshot_revision",
719 default=None,
Trent Apted66736d82023-05-25 10:38:28 +1000720 help="Snapshot manifest revision to sync to for building.",
Alex Klein1699fab2022-09-08 08:46:06 -0600721 )
722 group.add_remote_option(
723 "--no-publish-prebuilt-confs",
724 dest="publish",
725 action="store_false",
726 default=True,
727 help="Don't publish git commits to prebuilt.conf or sdk_version.conf",
728 )
Mike Frysinger81af6ef2013-04-03 02:24:09 -0400729
Alex Klein1699fab2022-09-08 08:46:06 -0600730 parser.add_argument_group(group)
Mike Frysinger81af6ef2013-04-03 02:24:09 -0400731
Alex Klein1699fab2022-09-08 08:46:06 -0600732 #
733 # Internal options.
734 #
Mike Frysinger81af6ef2013-04-03 02:24:09 -0400735
Alex Klein1699fab2022-09-08 08:46:06 -0600736 group = CustomGroup(
737 parser,
738 "Internal Chromium OS Build Team Options",
739 "Caution: these are for meant for the Chromium OS build team only",
740 )
Mike Frysinger81af6ef2013-04-03 02:24:09 -0400741
Alex Klein1699fab2022-09-08 08:46:06 -0600742 group.add_remote_option(
743 "--archive-base",
744 type="gs_path",
Trent Apted66736d82023-05-25 10:38:28 +1000745 help=(
746 "Base GS URL (gs://<bucket_name>/<path>) to "
747 "upload archive artifacts to"
748 ),
Alex Klein1699fab2022-09-08 08:46:06 -0600749 )
750 group.add_remote_option(
751 "--cq-gerrit-query",
752 dest="cq_gerrit_override",
Trent Apted66736d82023-05-25 10:38:28 +1000753 help=(
754 "If given, this gerrit query will be used to find what patches to "
755 "test, rather than the normal 'CommitQueue>=1 AND Verified=1 AND "
756 "CodeReview=2' query it defaults to. Use with care- note "
757 "additionally this setting only has an effect if the buildbot "
758 "target is a cq target, and we're in buildbot mode."
759 ),
Alex Klein1699fab2022-09-08 08:46:06 -0600760 )
761 group.add_option(
762 "--pass-through",
763 action="append",
764 type="string",
765 dest="pass_through_args",
766 default=[],
767 )
768 group.add_option(
769 "--reexec-api-version",
770 action="store_true",
771 dest="output_api_version",
772 default=False,
Trent Apted66736d82023-05-25 10:38:28 +1000773 help=(
774 "Used for handling forwards/backwards compatibility "
775 "with --resume and --bootstrap"
776 ),
Alex Klein1699fab2022-09-08 08:46:06 -0600777 )
778 group.add_option(
779 "--remote-trybot",
780 action="store_true",
781 default=False,
782 help="Indicates this is running on a remote trybot machine",
783 )
784 group.add_option(
785 "--buildbucket-id",
786 api=constants.REEXEC_API_GOMA, # Approximate.
Trent Apted66736d82023-05-25 10:38:28 +1000787 help=(
788 "The unique ID in buildbucket of current build "
789 "generated by buildbucket."
790 ),
Alex Klein1699fab2022-09-08 08:46:06 -0600791 )
792 group.add_remote_option(
793 "--remote-patches",
794 action="split_extend",
795 default=[],
Trent Apted66736d82023-05-25 10:38:28 +1000796 help=(
797 "Patches uploaded by the trybot client when run using the -p option"
798 ),
Alex Klein1699fab2022-09-08 08:46:06 -0600799 )
800 # Note the default here needs to be hardcoded to 3; that is the last version
801 # that lacked this functionality.
802 group.add_option(
803 "--remote-version",
804 type="int",
805 default=3,
806 help="Deprecated and ignored.",
807 )
808 group.add_option("--sourceroot", type="path", default=constants.SOURCE_ROOT)
809 group.add_remote_option(
810 "--test-bootstrap",
811 action="store_true",
812 default=False,
Trent Apted66736d82023-05-25 10:38:28 +1000813 help=(
814 "Causes cbuildbot to bootstrap itself twice, "
815 "in the sequence A->B->C: A(unpatched) patches "
816 "and bootstraps B; B patches and bootstraps C"
817 ),
Alex Klein1699fab2022-09-08 08:46:06 -0600818 )
819 group.add_remote_option(
820 "--validation_pool",
Trent Apted66736d82023-05-25 10:38:28 +1000821 help=(
822 "Path to a pickled validation pool. Intended "
823 "for use only with the commit queue."
824 ),
Alex Klein1699fab2022-09-08 08:46:06 -0600825 )
826 group.add_remote_option(
827 "--metadata_dump",
Trent Apted66736d82023-05-25 10:38:28 +1000828 help=(
829 "Path to a json dumped metadata file. This "
830 "will be used as the initial metadata."
831 ),
Alex Klein1699fab2022-09-08 08:46:06 -0600832 )
833 group.add_remote_option(
834 "--master-build-id",
835 type="int",
836 api=constants.REEXEC_API_MASTER_BUILD_ID,
Trent Apted66736d82023-05-25 10:38:28 +1000837 help="cidb build id of the master build to this slave build.",
Alex Klein1699fab2022-09-08 08:46:06 -0600838 )
839 group.add_remote_option(
840 "--master-buildbucket-id",
841 api=constants.REEXEC_API_MASTER_BUILDBUCKET_ID,
Trent Apted66736d82023-05-25 10:38:28 +1000842 help="buildbucket id of the master build to this slave build.",
Alex Klein1699fab2022-09-08 08:46:06 -0600843 )
844 # TODO(nxia): crbug.com/778838
845 # cbuildbot doesn't use pickle files anymore, remove this.
846 group.add_remote_option(
847 "--mock-slave-status",
848 metavar="MOCK_SLAVE_STATUS_PICKLE_FILE",
Trent Apted66736d82023-05-25 10:38:28 +1000849 help=(
850 "Override the result of the _FetchSlaveStatuses "
851 "method of MasterSlaveSyncCompletionStage, by "
852 "specifying a file with a pickle of the result "
853 "to be returned."
854 ),
Alex Klein1699fab2022-09-08 08:46:06 -0600855 )
856 group.add_option(
857 "--previous-build-state",
858 type="string",
859 default="",
860 api=constants.REEXEC_API_PREVIOUS_BUILD_STATE,
Trent Apted66736d82023-05-25 10:38:28 +1000861 help=(
862 "A base64-encoded BuildSummary object describing the "
863 "previous build run on the same build machine."
864 ),
Alex Klein1699fab2022-09-08 08:46:06 -0600865 )
Mike Frysinger81af6ef2013-04-03 02:24:09 -0400866
Alex Klein1699fab2022-09-08 08:46:06 -0600867 parser.add_argument_group(group)
Ryan Cuif4f84be2012-07-09 18:50:41 -0700868
Alex Klein1699fab2022-09-08 08:46:06 -0600869 #
870 # Debug options
871 #
872 # Temporary hack; in place till --dry-run replaces --debug.
873 # pylint: disable=protected-access
874 group = parser.debug_group
875 debug = [x for x in group.option_list if x._long_opts == ["--debug"]][0]
876 debug.help += " Currently functions as --dry-run in addition."
877 debug.pass_through = True
878 group.add_option(
879 "--notee",
880 action="store_false",
881 dest="tee",
882 default=True,
Trent Apted66736d82023-05-25 10:38:28 +1000883 help=(
884 "Disable logging and internal tee process. Primarily "
885 "used for debugging cbuildbot itself."
886 ),
Alex Klein1699fab2022-09-08 08:46:06 -0600887 )
888 return parser
Brian Harring3fec5a82012-03-01 05:57:03 -0800889
890
Mike Frysinger80bba8a2017-08-18 15:28:36 -0400891def _FinishParsing(options):
Alex Klein1699fab2022-09-08 08:46:06 -0600892 """Perform some parsing tasks that need to take place after optparse.
Ryan Cui85867972012-02-23 18:21:49 -0800893
Alex Klein1699fab2022-09-08 08:46:06 -0600894 This function needs to be easily testable! Keep it free of
895 environment-dependent code. Put more detailed usage validation in
896 _PostParseCheck().
Brian Harring3fec5a82012-03-01 05:57:03 -0800897
Alex Klein1699fab2022-09-08 08:46:06 -0600898 Args:
Trent Apted66736d82023-05-25 10:38:28 +1000899 options: The options object returned by optparse
Alex Klein1699fab2022-09-08 08:46:06 -0600900 """
901 # Populate options.pass_through_args.
902 accepted, _ = commandline.FilteringParser.FilterArgs(
903 options.parsed_args, lambda x: x.opt_inst.pass_through
904 )
905 options.pass_through_args.extend(accepted)
Brian Harring07039b52012-05-13 17:56:47 -0700906
Alex Klein1699fab2022-09-08 08:46:06 -0600907 if options.local or options.remote:
908 cros_build_lib.Die("Deprecated usage. Please use cros tryjob instead.")
Don Garrettcc0ee522017-09-13 14:28:42 -0700909
Alex Klein1699fab2022-09-08 08:46:06 -0600910 if not options.buildroot:
911 cros_build_lib.Die("A buildroot is required to build.")
Don Garrett211df8c2017-09-06 13:33:02 -0700912
Alex Klein1699fab2022-09-08 08:46:06 -0600913 if options.chrome_root:
914 if options.chrome_rev != constants.CHROME_REV_LOCAL:
915 cros_build_lib.Die(
916 "Chrome rev must be %s if chrome_root is set."
917 % constants.CHROME_REV_LOCAL
918 )
919 elif options.chrome_rev == constants.CHROME_REV_LOCAL:
920 cros_build_lib.Die(
921 "Chrome root must be set if chrome_rev is %s."
922 % constants.CHROME_REV_LOCAL
923 )
Brian Harring3fec5a82012-03-01 05:57:03 -0800924
Alex Klein1699fab2022-09-08 08:46:06 -0600925 if options.chrome_version:
926 if options.chrome_rev != constants.CHROME_REV_SPEC:
927 cros_build_lib.Die(
928 "Chrome rev must be %s if chrome_version is set."
929 % constants.CHROME_REV_SPEC
930 )
931 elif options.chrome_rev == constants.CHROME_REV_SPEC:
932 cros_build_lib.Die(
933 "Chrome rev must not be %s if chrome_version is not set."
934 % constants.CHROME_REV_SPEC
935 )
Brian Harring3fec5a82012-03-01 05:57:03 -0800936
Alex Klein1699fab2022-09-08 08:46:06 -0600937 patches = bool(options.gerrit_patches)
Ryan Cuieaa9efd2012-04-25 17:56:45 -0700938
Alex Klein9e7b29e2023-04-11 16:10:31 -0600939 # When running in release mode, make sure we are running with checked-in
940 # code. We want checked-in cbuildbot/scripts to prevent errors, and we want
941 # to build a release image with checked-in code for CrOS packages.
Alex Klein1699fab2022-09-08 08:46:06 -0600942 if options.buildbot and patches and not options.debug:
943 cros_build_lib.Die(
944 "Cannot provide patches when running with --buildbot!"
945 )
David James5734ea32012-08-15 20:23:49 -0700946
Alex Klein1699fab2022-09-08 08:46:06 -0600947 if options.buildbot and options.remote_trybot:
948 cros_build_lib.Die(
949 "--buildbot and --remote-trybot cannot be used together."
950 )
Ryan Cuiba41ad32012-03-08 17:15:29 -0800951
Alex Klein1699fab2022-09-08 08:46:06 -0600952 # Record whether --debug was set explicitly vs. it was inferred.
953 options.debug_forced = options.debug
954 # We force --debug to be set for builds that are not 'official'.
955 options.debug = options.debug or not options.buildbot
Brian Harring3fec5a82012-03-01 05:57:03 -0800956
Alex Klein1699fab2022-09-08 08:46:06 -0600957 options.hwtest_dut_override = ParseHWTestDUTDims(
958 options.hwtest_dut_dimensions
959 )
960
Jared Loucksa9e94bf2021-06-28 10:03:31 -0600961
962def ParseHWTestDUTDims(dims):
Alex Klein1699fab2022-09-08 08:46:06 -0600963 """Parse HWTest DUT dimensions into a valid HWTestDUTOverride object.
Jared Loucksa9e94bf2021-06-28 10:03:31 -0600964
Alex Klein1699fab2022-09-08 08:46:06 -0600965 Raises an error if any of board, model, or pool is missing.
966 """
967 if not dims:
968 return None
969 board = model = pool = None
970 extra_dims = []
971 for dim in dims:
972 if dim.startswith(BOARD_DIM_LABEL):
973 # Remove one extra character to account for the ":" or "=" symbol
974 # separating the label from the dimension itself.
975 board = dim[len(BOARD_DIM_LABEL) + 1 :]
976 elif dim.startswith(MODEL_DIM_LABEL):
977 model = dim[len(MODEL_DIM_LABEL) + 1 :]
978 elif dim.startswith(POOL_DIM_LABEL):
979 pool = dim[len(POOL_DIM_LABEL) + 1 :]
980 else:
981 extra_dims.append(dim)
Jared Loucksa9e94bf2021-06-28 10:03:31 -0600982
Alex Klein1699fab2022-09-08 08:46:06 -0600983 if not (board and model and pool):
984 cros_build_lib.Die(
985 "HWTest DUT dimensions must include board, model, and "
986 "pool (given %s)." % dims
987 )
Jared Loucksa9e94bf2021-06-28 10:03:31 -0600988
Alex Klein1699fab2022-09-08 08:46:06 -0600989 return test_stages.HWTestDUTOverride(board, model, pool, extra_dims)
Jared Loucksa9e94bf2021-06-28 10:03:31 -0600990
Brian Harring3fec5a82012-03-01 05:57:03 -0800991
Mike Frysinger27e21b72018-07-12 14:20:21 -0400992# pylint: disable=unused-argument
Mike Frysinger80bba8a2017-08-18 15:28:36 -0400993def _PostParseCheck(parser, options, site_config):
Alex Klein1699fab2022-09-08 08:46:06 -0600994 """Perform some usage validation after we've parsed the arguments
Brian Harring3fec5a82012-03-01 05:57:03 -0800995
Alex Klein1699fab2022-09-08 08:46:06 -0600996 Args:
Trent Apted66736d82023-05-25 10:38:28 +1000997 parser: Option parser that was used to parse arguments.
998 options: The options returned by optparse.
999 site_config: config_lib.SiteConfig containing all config info.
Alex Klein1699fab2022-09-08 08:46:06 -06001000 """
Don Garrett0a873e02015-06-30 17:55:10 -07001001
Alex Klein1699fab2022-09-08 08:46:06 -06001002 if not options.branch:
1003 options.branch = git.GetChromiteTrackingBranch()
Ryan Cuie1e4e662012-05-21 16:39:46 -07001004
Alex Klein1699fab2022-09-08 08:46:06 -06001005 # Because the default cache dir depends on other options, FindCacheDir
1006 # always returns None, and we setup the default here.
1007 if options.cache_dir is None:
1008 # Note, options.sourceroot is set regardless of the path
1009 # actually existing.
1010 options.cache_dir = os.path.join(options.buildroot, ".cache")
1011 options.cache_dir = os.path.abspath(options.cache_dir)
1012 parser.ConfigureCacheDir(options.cache_dir)
Brian Harringae0a5322012-09-15 01:46:51 -07001013
Alex Klein1699fab2022-09-08 08:46:06 -06001014 osutils.SafeMakedirsNonRoot(options.cache_dir)
Ryan Cui5ba7e152012-05-10 14:36:52 -07001015
Alex Klein1699fab2022-09-08 08:46:06 -06001016 # Ensure that all args are legitimate config targets.
1017 if options.build_config_name not in site_config:
1018 cros_build_lib.Die(
1019 'Unknown build config: "%s"' % options.build_config_name
1020 )
Don Garrett4bb21682014-03-03 16:16:23 -08001021
Alex Klein1699fab2022-09-08 08:46:06 -06001022 build_config = site_config[options.build_config_name]
1023 is_payloads_build = build_config.build_type == constants.PAYLOADS_TYPE
Don Garrett4af20982015-05-29 19:02:23 -07001024
Alex Klein1699fab2022-09-08 08:46:06 -06001025 if options.channels and not is_payloads_build:
1026 cros_build_lib.Die(
1027 "--channel must only be used with a payload config,"
1028 " not target (%s)." % options.build_config_name
1029 )
Don Garrett5af1d262014-05-16 15:49:37 -07001030
Alex Klein1699fab2022-09-08 08:46:06 -06001031 if not options.channels and is_payloads_build:
1032 cros_build_lib.Die(
Trent Apted66736d82023-05-25 10:38:28 +10001033 "payload configs (%s) require --channel to do anything useful."
1034 % options.build_config_name
Alex Klein1699fab2022-09-08 08:46:06 -06001035 )
Matt Tennant763497d2014-01-17 16:45:54 -08001036
Alex Klein1699fab2022-09-08 08:46:06 -06001037 # If the build config explicitly forces the debug flag, set the debug flag
1038 # as if it was set from the command line.
1039 if build_config.debug:
1040 options.debug = True
Don Garrett370839f2017-10-19 18:32:34 -07001041
Alex Klein1699fab2022-09-08 08:46:06 -06001042 if not (config_lib.isTryjobConfig(build_config) or options.buildbot):
1043 cros_build_lib.Die(
1044 "Refusing to run non-tryjob config as a tryjob.\n"
1045 'Please "repo sync && cros tryjob --list %s" for alternatives.\n'
1046 "See go/cros-explicit-tryjob-build-configs-psa.",
1047 build_config.name,
1048 )
Don Garrett02d2f582017-11-08 14:01:24 -08001049
Alex Klein1699fab2022-09-08 08:46:06 -06001050 # The --version option is not compatible with an external target unless the
1051 # --buildbot option is specified. More correctly, only "paladin versions"
1052 # will work with external targets, and those are only used with --buildbot.
1053 # If --buildbot is specified, then user should know what they are doing and
1054 # only specify a version that will work. See crbug.com/311648.
1055 if options.force_version and not (
1056 options.buildbot or build_config.internal
1057 ):
1058 cros_build_lib.Die(
1059 "Cannot specify --version without --buildbot for an"
1060 " external target (%s)." % options.build_config_name
1061 )
Matt Tennant763497d2014-01-17 16:45:54 -08001062
Ryan Cui85867972012-02-23 18:21:49 -08001063
Don Garrett597ddff2017-02-17 18:29:37 -08001064def ParseCommandLine(parser, argv):
Alex Klein1699fab2022-09-08 08:46:06 -06001065 """Completely parse the commandline arguments"""
1066 (options, args) = parser.parse_args(argv)
Brian Harring37e559b2012-05-22 20:47:32 -07001067
Alex Klein1699fab2022-09-08 08:46:06 -06001068 # Handle the request for the reexec command line API version number.
1069 if options.output_api_version:
1070 print(constants.REEXEC_API_VERSION)
1071 sys.exit(0)
Brian Harring37e559b2012-05-22 20:47:32 -07001072
Alex Klein1699fab2022-09-08 08:46:06 -06001073 # Record the configs targeted. Strip out null arguments.
1074 build_config_names = [x for x in args if x]
1075 if len(build_config_names) != 1:
1076 cros_build_lib.Die(
1077 "Expected exactly one build config. Got: %r", build_config_names
1078 )
1079 options.build_config_name = build_config_names[-1]
Don Garrettf0761152017-10-19 19:38:27 -07001080
Alex Klein1699fab2022-09-08 08:46:06 -06001081 _FinishParsing(options)
1082 return options
Ryan Cui85867972012-02-23 18:21:49 -08001083
1084
Alex Klein1699fab2022-09-08 08:46:06 -06001085_ENVIRONMENT_PROD = "prod"
1086_ENVIRONMENT_DEBUG = "debug"
1087_ENVIRONMENT_STANDALONE = "standalone"
Aviv Keshet420de512015-05-18 14:28:48 -07001088
1089
1090def _GetRunEnvironment(options, build_config):
Alex Klein1699fab2022-09-08 08:46:06 -06001091 """Determine whether this is a prod/debug/standalone run."""
1092 if options.debug_cidb:
1093 return _ENVIRONMENT_DEBUG
Don Garretta90f0142018-02-28 14:25:19 -08001094
Alex Klein1699fab2022-09-08 08:46:06 -06001095 # One of these arguments should always be set if running on a real builder.
1096 # If we aren't on a real builder, we are standalone.
1097 if not options.buildbot and not options.remote_trybot:
1098 return _ENVIRONMENT_STANDALONE
Aviv Keshet420de512015-05-18 14:28:48 -07001099
Alex Klein1699fab2022-09-08 08:46:06 -06001100 if build_config["debug_cidb"]:
1101 return _ENVIRONMENT_DEBUG
Aviv Keshet420de512015-05-18 14:28:48 -07001102
Alex Klein1699fab2022-09-08 08:46:06 -06001103 return _ENVIRONMENT_PROD
Aviv Keshet420de512015-05-18 14:28:48 -07001104
1105
Gabe Blackde694a32015-02-19 15:11:11 -08001106def _SetupConnections(options, build_config):
George Engelbrecht7e07c702022-09-19 17:03:55 -06001107 """Set up CIDB connections using the appropriate Setup call.
Aviv Keshet2982af52014-08-13 16:07:57 -07001108
Alex Klein1699fab2022-09-08 08:46:06 -06001109 Args:
Trent Apted66736d82023-05-25 10:38:28 +10001110 options: Command line options structure.
1111 build_config: Config object for this build.
Alex Klein1699fab2022-09-08 08:46:06 -06001112 """
George Engelbrecht7e07c702022-09-19 17:03:55 -06001113 # Outline:
1114 # 1) Based on options and build_config, decide whether we are a production
1115 # run, debug run, or standalone run.
1116 # 2) Set up cidb instance accordingly.
Alex Klein9e7b29e2023-04-11 16:10:31 -06001117 # 3) Update topology info from cidb, so that any other service set up can
1118 # use topology.
George Engelbrecht7e07c702022-09-19 17:03:55 -06001119 # 4) Set up any other services.
1120 run_type = _GetRunEnvironment(options, build_config)
1121
1122 if run_type == _ENVIRONMENT_PROD:
1123 cidb.CIDBConnectionFactory.SetupProdCidb()
1124 context = ts_mon_config.SetupTsMonGlobalState(
1125 "cbuildbot", indirect=True
1126 )
1127 elif run_type == _ENVIRONMENT_DEBUG:
1128 cidb.CIDBConnectionFactory.SetupDebugCidb()
1129 context = ts_mon_config.TrivialContextManager()
1130 else:
1131 cidb.CIDBConnectionFactory.SetupNoCidb()
1132 context = ts_mon_config.TrivialContextManager()
Aviv Keshet62d1a0e2014-08-22 21:16:13 -07001133
Alex Klein1699fab2022-09-08 08:46:06 -06001134 topology.FetchTopology()
1135 return context
Paul Hobbsd5a0f812016-07-26 16:10:31 -07001136
Aviv Keshet2982af52014-08-13 16:07:57 -07001137
Dean Liaoe5b0aca2018-01-24 15:27:26 +08001138class _MockMethodWithReturnValue(object):
Alex Klein1699fab2022-09-08 08:46:06 -06001139 """A method mocker which just returns the specific value."""
Dean Liaoe5b0aca2018-01-24 15:27:26 +08001140
Alex Klein1699fab2022-09-08 08:46:06 -06001141 def __init__(self, return_value):
1142 self.return_value = return_value
1143
1144 def __call__(self, *args, **kwargs):
1145 return self.return_value
Dean Liaoe5b0aca2018-01-24 15:27:26 +08001146
1147
1148class _ObjectMethodPatcher(object):
Alex Klein1699fab2022-09-08 08:46:06 -06001149 """A simplified mock.object.patch.
Dean Liaoe5b0aca2018-01-24 15:27:26 +08001150
Alex Klein1699fab2022-09-08 08:46:06 -06001151 It is a context manager that patches an object's method with specified
1152 return value.
Dean Liaoe5b0aca2018-01-24 15:27:26 +08001153 """
Dean Liaoe5b0aca2018-01-24 15:27:26 +08001154
Alex Klein1699fab2022-09-08 08:46:06 -06001155 def __init__(self, target, attr, return_value=None):
1156 """Constructor.
Dean Liaoe5b0aca2018-01-24 15:27:26 +08001157
Alex Klein1699fab2022-09-08 08:46:06 -06001158 Args:
Trent Apted66736d82023-05-25 10:38:28 +10001159 target: object to patch.
1160 attr: method name of the object to patch.
1161 return_value: the return value when calling target.attr
Alex Klein1699fab2022-09-08 08:46:06 -06001162 """
1163 self.target = target
1164 self.attr = attr
1165 self.return_value = return_value
1166 self.original_attr = None
1167 self.new_attr = _MockMethodWithReturnValue(self.return_value)
1168
1169 def __enter__(self):
1170 self.original_attr = self.target.__dict__[self.attr]
1171 setattr(self.target, self.attr, self.new_attr)
1172
1173 def __exit__(self, *args):
1174 if self.target and self.original_attr:
1175 setattr(self.target, self.attr, self.original_attr)
Dean Liaoe5b0aca2018-01-24 15:27:26 +08001176
1177
Matt Tennant759e2352013-09-27 15:14:44 -07001178# TODO(build): This function is too damn long.
Ryan Cui85867972012-02-23 18:21:49 -08001179def main(argv):
Alex Klein1699fab2022-09-08 08:46:06 -06001180 # We get false positives with the options object.
1181 # pylint: disable=attribute-defined-outside-init
Mike Frysinger80bba8a2017-08-18 15:28:36 -04001182
Alex Klein1699fab2022-09-08 08:46:06 -06001183 # Turn on strict sudo checks.
1184 cros_build_lib.STRICT_SUDO = True
David James59a0a2b2013-03-22 14:04:44 -07001185
Alex Klein1699fab2022-09-08 08:46:06 -06001186 # Set umask to 022 so files created by buildbot are readable.
1187 os.umask(0o22)
Ryan Cui85867972012-02-23 18:21:49 -08001188
Alex Klein1699fab2022-09-08 08:46:06 -06001189 parser = _CreateParser()
1190 options = ParseCommandLine(parser, argv)
Don Garrett0a873e02015-06-30 17:55:10 -07001191
Alex Klein1699fab2022-09-08 08:46:06 -06001192 # Fetch our site_config now, because we need it to do anything else.
1193 site_config = config_lib.GetConfig()
Don Garrettb85658c2015-06-30 19:07:22 -07001194
Alex Klein1699fab2022-09-08 08:46:06 -06001195 _PostParseCheck(parser, options, site_config)
Brian Harring3fec5a82012-03-01 05:57:03 -08001196
Alex Klein1699fab2022-09-08 08:46:06 -06001197 cros_build_lib.AssertOutsideChroot()
Zdenek Behan98ec2fb2012-08-31 17:12:18 +02001198
Alex Klein1699fab2022-09-08 08:46:06 -06001199 if options.enable_buildbot_tags:
1200 cbuildbot_alerts.EnableBuildbotMarkers()
Matt Tennant759e2352013-09-27 15:14:44 -07001201
Alex Klein1699fab2022-09-08 08:46:06 -06001202 if (
1203 options.buildbot
1204 and not options.debug
1205 and not cros_build_lib.HostIsCIBuilder()
1206 ):
1207 # --buildbot can only be used on a real builder, unless it's debug.
1208 cros_build_lib.Die("This host is not a supported build machine.")
Ningning Xiac691e432016-08-11 14:52:59 -07001209
Alex Klein1699fab2022-09-08 08:46:06 -06001210 # Only one config arg is allowed in this mode, which was confirmed earlier.
1211 build_config = site_config[options.build_config_name]
Brian Harring3fec5a82012-03-01 05:57:03 -08001212
Alex Klein1699fab2022-09-08 08:46:06 -06001213 # TODO: Re-enable this block when reference_repo support handles this
1214 # properly. (see chromium:330775)
1215 # if options.reference_repo is None:
1216 # repo_path = os.path.join(options.sourceroot, '.repo')
1217 # # If we're being run from a repo checkout, reuse the repo's git pool to
1218 # # cut down on sync time.
1219 # if os.path.exists(repo_path):
1220 # options.reference_repo = options.sourceroot
Don Garrettbbd7b552014-05-16 13:15:21 -07001221
Alex Klein1699fab2022-09-08 08:46:06 -06001222 if options.reference_repo:
1223 if not os.path.exists(options.reference_repo):
1224 parser.error(
1225 "Reference path %s does not exist" % (options.reference_repo,)
1226 )
1227 elif not os.path.exists(os.path.join(options.reference_repo, ".repo")):
1228 parser.error(
1229 "Reference path %s does not look to be the base of a "
1230 "repo checkout; no .repo exists in the root."
1231 % (options.reference_repo,)
1232 )
David Jamesdac7a912013-11-18 11:14:44 -08001233
Alex Klein1699fab2022-09-08 08:46:06 -06001234 if (options.buildbot or options.remote_trybot) and not options.resume:
1235 missing = osutils.FindMissingBinaries(_BUILDBOT_REQUIRED_BINARIES)
1236 if missing:
1237 parser.error(
1238 "Option --buildbot/--remote-trybot requires the following "
1239 "binaries which couldn't be found in $PATH: %s"
Trent Apted66736d82023-05-25 10:38:28 +10001240 % ", ".join(missing)
Alex Klein1699fab2022-09-08 08:46:06 -06001241 )
Brian Harring351ce442012-03-09 16:38:14 -08001242
Alex Klein1699fab2022-09-08 08:46:06 -06001243 if options.reference_repo:
1244 options.reference_repo = os.path.abspath(options.reference_repo)
David Jamesdac7a912013-11-18 11:14:44 -08001245
Alex Klein1699fab2022-09-08 08:46:06 -06001246 # Sanity check of buildroot- specifically that it's not pointing into the
1247 # midst of an existing repo since git-repo doesn't support nesting.
1248 if not repository.IsARepoRoot(options.buildroot) and git.FindRepoDir(
1249 options.buildroot
1250 ):
1251 cros_build_lib.Die(
1252 "Configured buildroot %s is a subdir of an existing repo checkout."
1253 % options.buildroot
1254 )
Brian Harring3fec5a82012-03-01 05:57:03 -08001255
Alex Klein1699fab2022-09-08 08:46:06 -06001256 if not options.log_dir:
1257 options.log_dir = os.path.join(options.buildroot, _DEFAULT_LOG_DIR)
Chris Sosab5ea3b42012-10-25 15:25:20 -07001258
Alex Klein1699fab2022-09-08 08:46:06 -06001259 log_file = None
1260 if options.tee:
1261 log_file = os.path.join(options.log_dir, _BUILDBOT_LOG_FILE)
1262 osutils.SafeMakedirs(options.log_dir)
1263 _BackupPreviousLog(log_file)
Brian Harringd166aaf2012-05-14 18:31:53 -07001264
Mike Frysinger321fecd2023-06-16 10:40:51 -04001265 with contextlib.ExitStack() as stack:
Alex Klein1699fab2022-09-08 08:46:06 -06001266 # Preserve chromite; we might be running from there!
1267 options.preserve_paths = set(["chromite"])
1268 if log_file is not None:
Alex Klein9e7b29e2023-04-11 16:10:31 -06001269 # We don't want the critical section to try to clean up the tee
1270 # process, so we run Tee (forked off) outside of it. This prevents a
1271 # deadlock because the Tee process only exits when its pipe is
1272 # closed, and the critical section accidentally holds on to that
1273 # file handle.
Mike Frysinger321fecd2023-06-16 10:40:51 -04001274 stack.enter_context(tee.Tee(log_file))
Alex Klein1699fab2022-09-08 08:46:06 -06001275 options.preserve_paths.add(_DEFAULT_LOG_DIR)
David Jamescebc7272013-07-17 16:45:05 -07001276
Mike Frysinger321fecd2023-06-16 10:40:51 -04001277 critical_section = stack.enter_context(cleanup.EnforcedCleanupSection())
1278 stack.enter_context(sudo.SudoKeepAlive())
Brian Harringd166aaf2012-05-14 18:31:53 -07001279
Alex Klein1699fab2022-09-08 08:46:06 -06001280 if not options.resume:
1281 # If we're in resume mode, use our parents tempdir rather than
1282 # nesting another layer.
Mike Frysinger321fecd2023-06-16 10:40:51 -04001283 stack.enter_context(osutils.TempDir(prefix="cbb", set_global=True))
Alex Klein1699fab2022-09-08 08:46:06 -06001284 logging.debug("Cbuildbot tempdir is %r.", os.environ.get("TMP"))
Brian Harringd166aaf2012-05-14 18:31:53 -07001285
Alex Klein1699fab2022-09-08 08:46:06 -06001286 if options.cgroups:
Mike Frysinger321fecd2023-06-16 10:40:51 -04001287 stack.enter_context(cgroups.SimpleContainChildren("cbuildbot"))
Brian Harringa184efa2012-03-04 11:51:25 -08001288
Alex Klein1699fab2022-09-08 08:46:06 -06001289 # Mark everything between EnforcedCleanupSection and here as having to
1290 # be rolled back via the contextmanager cleanup handlers. This
1291 # ensures that sudo bits cannot outlive cbuildbot, that anything
1292 # cgroups would kill gets killed, etc.
Mike Frysinger321fecd2023-06-16 10:40:51 -04001293 stack.enter_context(critical_section.ForkWatchdog())
Brian Harringd166aaf2012-05-14 18:31:53 -07001294
Alex Klein1699fab2022-09-08 08:46:06 -06001295 if options.mock_slave_status is not None:
Mike Frysinger31fdddd2023-02-24 15:50:55 -05001296 with open(options.mock_slave_status, "rb") as f:
Alex Klein1699fab2022-09-08 08:46:06 -06001297 mock_statuses = pickle.load(f)
1298 for key, value in mock_statuses.items():
1299 mock_statuses[key] = builder_status_lib.BuilderStatus(
1300 **value
1301 )
Mike Frysinger321fecd2023-06-16 10:40:51 -04001302 stack.enter_context(
1303 _ObjectMethodPatcher(
1304 completion_stages.MasterSlaveSyncCompletionStage,
1305 "_FetchSlaveStatuses",
1306 return_value=mock_statuses,
1307 )
Alex Klein1699fab2022-09-08 08:46:06 -06001308 )
Aviv Keshetcf9c2722014-02-25 15:15:10 -08001309
Mike Frysinger321fecd2023-06-16 10:40:51 -04001310 stack.enter_context(_SetupConnections(options, build_config))
Alex Klein1699fab2022-09-08 08:46:06 -06001311 retry_stats.SetupStats()
Aviv Keshet2982af52014-08-13 16:07:57 -07001312
Alex Klein1699fab2022-09-08 08:46:06 -06001313 timeout_display_message = (
1314 "This build has reached the timeout deadline set by the master. "
1315 "Either this stage or a previous one took too long (see stage "
1316 "timing historical summary in ReportStage) or the build failed "
1317 "to start on time."
1318 )
Prathmesh Prabhu80e05df2014-12-11 15:20:33 -08001319
Alex Klein1699fab2022-09-08 08:46:06 -06001320 if options.timeout > 0:
Mike Frysinger321fecd2023-06-16 10:40:51 -04001321 stack.enter_context(
1322 timeout_util.FatalTimeout(
1323 options.timeout,
1324 timeout_display_message,
1325 )
Alex Klein1699fab2022-09-08 08:46:06 -06001326 )
1327 try:
1328 _RunBuildStagesWrapper(options, site_config, build_config)
1329 except failures_lib.ExitEarlyException as ex:
Alex Klein9e7b29e2023-04-11 16:10:31 -06001330 # This build finished successfully. Do not re-raise
1331 # ExitEarlyException.
Alex Klein1699fab2022-09-08 08:46:06 -06001332 logging.info("One stage exited early: %s", ex)