blob: df2926908af5b84e7d63890e53c967f967060187 [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
Ningning Xiaf342b952017-02-15 14:13:33 -080028from chromite.lib import builder_status_lib
Anuj Jamwal258529f2023-09-08 17:32:55 +000029from chromite.lib import buildstore
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
Anuj Jamwal258529f2023-09-08 17:32:55 +000047from chromite.utils import hostname_util
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"
Brian Harring3fec5a82012-03-01 05:57:03 -080056
57
Brian Harring3fec5a82012-03-01 05:57:03 -080058def _BackupPreviousLog(log_file, backup_limit=25):
Alex Klein1699fab2022-09-08 08:46:06 -060059 """Rename previous log.
Brian Harring3fec5a82012-03-01 05:57:03 -080060
Alex Klein1699fab2022-09-08 08:46:06 -060061 Args:
Trent Apted66736d82023-05-25 10:38:28 +100062 log_file: The absolute path to the previous log.
63 backup_limit: Maximum number of old logs to keep.
Alex Klein1699fab2022-09-08 08:46:06 -060064 """
65 if os.path.exists(log_file):
66 old_logs = sorted(
67 glob.glob(log_file + ".*"), key=distutils.version.LooseVersion
68 )
Brian Harring3fec5a82012-03-01 05:57:03 -080069
Alex Klein1699fab2022-09-08 08:46:06 -060070 if len(old_logs) >= backup_limit:
71 os.remove(old_logs[0])
Brian Harring3fec5a82012-03-01 05:57:03 -080072
Alex Klein1699fab2022-09-08 08:46:06 -060073 last = 0
74 if old_logs:
75 last = int(old_logs.pop().rpartition(".")[2])
Brian Harring3fec5a82012-03-01 05:57:03 -080076
Alex Klein1699fab2022-09-08 08:46:06 -060077 os.rename(log_file, log_file + "." + str(last + 1))
Brian Harring3fec5a82012-03-01 05:57:03 -080078
Ryan Cui5616a512012-08-17 13:39:36 -070079
Gaurav Shah298aa372014-01-31 09:27:24 -080080def _IsDistributedBuilder(options, chrome_rev, build_config):
Alex Klein1699fab2022-09-08 08:46:06 -060081 """Determines whether the builder should be a DistributedBuilder.
Gaurav Shah298aa372014-01-31 09:27:24 -080082
Alex Klein1699fab2022-09-08 08:46:06 -060083 Args:
Trent Apted66736d82023-05-25 10:38:28 +100084 options: options passed on the commandline.
85 chrome_rev: Chrome revision to build.
86 build_config: Builder configuration dictionary.
Gaurav Shah298aa372014-01-31 09:27:24 -080087
Alex Klein1699fab2022-09-08 08:46:06 -060088 Returns:
Trent Apted66736d82023-05-25 10:38:28 +100089 True if the builder should be a distributed_builder
Alex Klein1699fab2022-09-08 08:46:06 -060090 """
91 if not options.buildbot:
92 return False
93 elif chrome_rev in (
94 constants.CHROME_REV_TOT,
95 constants.CHROME_REV_LOCAL,
96 constants.CHROME_REV_SPEC,
97 ):
98 # We don't do distributed logic to TOT Chrome PFQ's, nor local
99 # chrome roots (e.g. chrome try bots)
100 # TODO(davidjames): Update any builders that rely on this logic to use
101 # manifest_version=False instead.
102 return False
103 elif build_config["manifest_version"]:
104 return True
105
Gaurav Shah298aa372014-01-31 09:27:24 -0800106 return False
Gaurav Shah298aa372014-01-31 09:27:24 -0800107
108
Don Garretta52a5b02015-06-02 14:52:57 -0700109def _RunBuildStagesWrapper(options, site_config, build_config):
Alex Klein1699fab2022-09-08 08:46:06 -0600110 """Helper function that wraps RunBuildStages()."""
111 logging.info(
112 "cbuildbot was executed with args %s", cros_build_lib.CmdToStr(sys.argv)
113 )
Brian Harring3fec5a82012-03-01 05:57:03 -0800114
Alex Klein1699fab2022-09-08 08:46:06 -0600115 chrome_rev = build_config["chrome_rev"]
116 if options.chrome_rev:
117 chrome_rev = options.chrome_rev
118 if chrome_rev == constants.CHROME_REV_TOT:
119 options.chrome_version = gob_util.GetTipOfTrunkRevision(
120 constants.CHROMIUM_GOB_URL
121 )
122 options.chrome_rev = constants.CHROME_REV_SPEC
David Jamesa0a664e2013-02-13 09:52:01 -0800123
Alex Klein1699fab2022-09-08 08:46:06 -0600124 # If it's likely we'll need to build Chrome, fetch the source.
125 if build_config["sync_chrome"] is None:
126 options.managed_chrome = chrome_rev != constants.CHROME_REV_LOCAL and (
127 not build_config["usepkg_build_packages"]
128 or chrome_rev
129 or build_config["profile"]
130 )
Matt Tennant0940c382014-01-21 20:43:55 -0800131 else:
Alex Klein1699fab2022-09-08 08:46:06 -0600132 options.managed_chrome = build_config["sync_chrome"]
Mike Frysingere4d68c22015-02-04 21:26:24 -0500133
Alex Klein1699fab2022-09-08 08:46:06 -0600134 chrome_root_mgr = None
135 if options.managed_chrome:
136 # Create a temp directory for syncing Chrome source.
137 chrome_root_mgr = osutils.TempDir(prefix="chrome_root_")
138 options.chrome_root = chrome_root_mgr.tempdir
139
140 # We are done munging options values, so freeze options object now to avoid
141 # further abuse of it.
142 # TODO(mtennant): one by one identify each options value override and see if
143 # it can be handled another way. Try to push this freeze closer and closer
144 # to the start of the script (e.g. in or after _PostParseCheck).
145 options.Freeze()
146
147 metadata_dump_dict = {
148 # A detected default has been set before now if it wasn't explicit.
149 "branch": options.branch,
150 }
151 if options.metadata_dump:
Mike Frysinger31fdddd2023-02-24 15:50:55 -0500152 with open(options.metadata_dump, "rb") as metadata_file:
153 metadata_dump_dict = json.load(metadata_file)
Alex Klein1699fab2022-09-08 08:46:06 -0600154
155 with parallel.Manager() as manager:
156 builder_run = cbuildbot_run.BuilderRun(
157 options, site_config, build_config, manager
158 )
Anuj Jamwal258529f2023-09-08 17:32:55 +0000159 build_store = buildstore.BuildStore()
Alex Klein1699fab2022-09-08 08:46:06 -0600160 if metadata_dump_dict:
161 builder_run.attrs.metadata.UpdateWithDict(metadata_dump_dict)
162
163 if builder_run.config.builder_class_name is None:
164 # TODO: This should get relocated to chromeos_config.
165 if _IsDistributedBuilder(options, chrome_rev, build_config):
166 builder_cls_name = "simple_builders.DistributedBuilder"
167 else:
168 builder_cls_name = "simple_builders.SimpleBuilder"
169 builder_cls = builders.GetBuilderClass(builder_cls_name)
Anuj Jamwal258529f2023-09-08 17:32:55 +0000170 builder = builder_cls(builder_run, build_store)
Alex Klein1699fab2022-09-08 08:46:06 -0600171 else:
Anuj Jamwal258529f2023-09-08 17:32:55 +0000172 builder = builders.Builder(builder_run, build_store)
Alex Klein1699fab2022-09-08 08:46:06 -0600173
174 try:
175 if not builder.Run():
176 sys.exit(1)
177 finally:
178 if chrome_root_mgr:
179 chrome_root_mgr.Cleanup()
Brian Harring3fec5a82012-03-01 05:57:03 -0800180
181
Brian Harring3fec5a82012-03-01 05:57:03 -0800182def _CheckChromeVersionOption(_option, _opt_str, value, parser):
Alex Klein1699fab2022-09-08 08:46:06 -0600183 """Upgrade other options based on chrome_version being passed."""
184 value = value.strip()
Brian Harring3fec5a82012-03-01 05:57:03 -0800185
Alex Klein1699fab2022-09-08 08:46:06 -0600186 if parser.values.chrome_rev is None and value:
187 parser.values.chrome_rev = constants.CHROME_REV_SPEC
Brian Harring3fec5a82012-03-01 05:57:03 -0800188
Alex Klein1699fab2022-09-08 08:46:06 -0600189 parser.values.chrome_version = value
Brian Harring3fec5a82012-03-01 05:57:03 -0800190
191
192def _CheckChromeRootOption(_option, _opt_str, value, parser):
Alex Klein1699fab2022-09-08 08:46:06 -0600193 """Validate and convert chrome_root to full-path form."""
194 if parser.values.chrome_rev is None:
195 parser.values.chrome_rev = constants.CHROME_REV_LOCAL
Brian Harring3fec5a82012-03-01 05:57:03 -0800196
Alex Klein1699fab2022-09-08 08:46:06 -0600197 parser.values.chrome_root = value
Brian Harring3fec5a82012-03-01 05:57:03 -0800198
199
David Jamesac8c2a72013-02-13 18:44:33 -0800200def FindCacheDir(_parser, _options):
Alex Klein1699fab2022-09-08 08:46:06 -0600201 return None
Brian Harringae0a5322012-09-15 01:46:51 -0700202
203
Ryan Cui5ba7e152012-05-10 14:36:52 -0700204class CustomGroup(optparse.OptionGroup):
Alex Klein1699fab2022-09-08 08:46:06 -0600205 """Custom option group which supports arguments passed-through to trybot."""
David Jameseecba232014-06-11 11:35:11 -0700206
Alex Klein1699fab2022-09-08 08:46:06 -0600207 def add_remote_option(self, *args, **kwargs):
208 """For arguments that are passed-through to remote trybot."""
209 return optparse.OptionGroup.add_option(
210 self, *args, remote_pass_through=True, **kwargs
211 )
Ryan Cui5ba7e152012-05-10 14:36:52 -0700212
213
Ryan Cui1c13a252012-10-16 15:00:16 -0700214class CustomOption(commandline.FilteringOption):
Alex Klein1699fab2022-09-08 08:46:06 -0600215 """Subclass FilteringOption class to implement pass-through and api."""
Ryan Cui5ba7e152012-05-10 14:36:52 -0700216
Alex Klein1699fab2022-09-08 08:46:06 -0600217 def __init__(self, *args, **kwargs):
218 # The remote_pass_through argument specifies whether we should directly
219 # pass the argument (with its value) onto the remote trybot.
220 self.pass_through = kwargs.pop("remote_pass_through", False)
221 self.api_version = int(kwargs.pop("api", "0"))
222 commandline.FilteringOption.__init__(self, *args, **kwargs)
Ryan Cui5ba7e152012-05-10 14:36:52 -0700223
Ryan Cui5ba7e152012-05-10 14:36:52 -0700224
Ryan Cui1c13a252012-10-16 15:00:16 -0700225class CustomParser(commandline.FilteringParser):
Alex Klein1699fab2022-09-08 08:46:06 -0600226 """Custom option parser which supports arguments passed-through to trybot"""
Matt Tennante8179042013-10-01 15:47:32 -0700227
Alex Klein1699fab2022-09-08 08:46:06 -0600228 DEFAULT_OPTION_CLASS = CustomOption
Brian Harringb6cf9142012-09-01 20:43:17 -0700229
Alex Klein1699fab2022-09-08 08:46:06 -0600230 def add_remote_option(self, *args, **kwargs):
231 """For arguments that are passed-through to remote trybot."""
232 return self.add_option(*args, remote_pass_through=True, **kwargs)
Brian Harringb6cf9142012-09-01 20:43:17 -0700233
234
Don Garrett86881cb2017-02-15 15:41:55 -0800235def CreateParser():
Alex Klein1699fab2022-09-08 08:46:06 -0600236 """Expose _CreateParser publicly."""
237 # Name _CreateParser is needed for commandline library.
238 return _CreateParser()
Don Garrett86881cb2017-02-15 15:41:55 -0800239
240
Brian Harring3fec5a82012-03-01 05:57:03 -0800241def _CreateParser():
Alex Klein1699fab2022-09-08 08:46:06 -0600242 """Generate and return the parser with all the options."""
243 # Parse options
244 usage = "usage: %prog [options] buildbot_config [buildbot_config ...]"
245 parser = CustomParser(usage=usage, caching=FindCacheDir)
Brian Harring3fec5a82012-03-01 05:57:03 -0800246
Alex Klein1699fab2022-09-08 08:46:06 -0600247 # Main options
248 parser.add_remote_option(
249 "-b",
250 "--branch",
Trent Apted66736d82023-05-25 10:38:28 +1000251 help=(
252 "The manifest branch to test. The branch to "
253 "check the buildroot out to."
254 ),
Alex Klein1699fab2022-09-08 08:46:06 -0600255 )
256 parser.add_option(
257 "-r",
258 "--buildroot",
259 type="path",
260 dest="buildroot",
Trent Apted66736d82023-05-25 10:38:28 +1000261 help=(
262 "Root directory where source is checked out to, and "
263 "where the build occurs. For external build configs, "
264 "defaults to 'trybot' directory at top level of your "
265 "repo-managed checkout."
266 ),
Alex Klein1699fab2022-09-08 08:46:06 -0600267 )
268 parser.add_option(
269 "--workspace",
270 type="path",
271 api=constants.REEXEC_API_WORKSPACE,
272 help="Root directory for a secondary checkout .",
273 )
274 parser.add_option(
275 "--bootstrap-dir",
276 type="path",
Trent Apted66736d82023-05-25 10:38:28 +1000277 help=(
278 "Bootstrapping cbuildbot may involve checking out "
279 "multiple copies of chromite. All these checkouts "
280 "will be contained in the directory specified here. "
Mike Frysingerace4eae2023-05-26 21:09:43 -0400281 f"(Default: {tempfile.gettempdir()})"
282 ),
Alex Klein1699fab2022-09-08 08:46:06 -0600283 )
284 parser.add_remote_option(
Alex Klein1699fab2022-09-08 08:46:06 -0600285 "--chrome_rev",
286 type="choice",
287 choices=constants.VALID_CHROME_REVISIONS,
288 help=(
289 "Revision of Chrome to use, of type [%s]"
290 % "|".join(constants.VALID_CHROME_REVISIONS)
291 ),
292 )
293 parser.add_remote_option(
294 "--profile", help="Name of profile to sub-specify board variant."
295 )
296 # TODO(crbug.com/279618): Running GOMA is under development. Following
297 # flags are added for development purpose due to repository dependency,
298 # but not officially supported yet.
299 parser.add_option(
300 "--goma_dir",
301 type="path",
302 api=constants.REEXEC_API_GOMA,
Trent Apted66736d82023-05-25 10:38:28 +1000303 help=(
304 "Specify a directory containing goma. When this is "
305 "set, GOMA is used to build Chrome."
306 ),
Alex Klein1699fab2022-09-08 08:46:06 -0600307 )
308 parser.add_option(
309 "--chromeos_goma_dir",
310 type="path",
311 api=constants.REEXEC_API_CHROMEOS_GOMA_DIR,
Trent Apted66736d82023-05-25 10:38:28 +1000312 help="Specify a directory containing goma for build package.",
Alex Klein1699fab2022-09-08 08:46:06 -0600313 )
Alex Klein1699fab2022-09-08 08:46:06 -0600314 group = CustomGroup(parser, "Deprecated Options")
Don Garrett211df8c2017-09-06 13:33:02 -0700315
Alex Klein1699fab2022-09-08 08:46:06 -0600316 parser.add_option(
317 "--local",
318 action="store_true",
319 default=False,
320 help="Deprecated. See cros tryjob.",
321 )
322 parser.add_option(
323 "--remote",
324 action="store_true",
325 default=False,
326 help="Deprecated. See cros tryjob.",
327 )
Don Garrett211df8c2017-09-06 13:33:02 -0700328
Alex Klein1699fab2022-09-08 08:46:06 -0600329 #
330 # Patch selection options.
331 #
Mike Frysinger81af6ef2013-04-03 02:24:09 -0400332
Alex Klein1699fab2022-09-08 08:46:06 -0600333 group = CustomGroup(parser, "Patch Options")
Mike Frysinger81af6ef2013-04-03 02:24:09 -0400334
Alex Klein1699fab2022-09-08 08:46:06 -0600335 group.add_remote_option(
336 "-g",
337 "--gerrit-patches",
338 action="split_extend",
339 type="string",
340 default=[],
341 metavar="'Id1 *int_Id2...IdN'",
Trent Apted66736d82023-05-25 10:38:28 +1000342 help=(
343 "Space-separated list of short-form Gerrit "
344 "Change-Id's or change numbers to patch. "
345 "Please prepend '*' to internal Change-Id's"
346 ),
Alex Klein1699fab2022-09-08 08:46:06 -0600347 )
Mike Frysinger81af6ef2013-04-03 02:24:09 -0400348
Alex Klein1699fab2022-09-08 08:46:06 -0600349 parser.add_argument_group(group)
Mike Frysinger81af6ef2013-04-03 02:24:09 -0400350
Alex Klein1699fab2022-09-08 08:46:06 -0600351 #
352 # Remote trybot options.
353 #
Mike Frysinger81af6ef2013-04-03 02:24:09 -0400354
Alex Klein1699fab2022-09-08 08:46:06 -0600355 group = CustomGroup(parser, "Options used to configure tryjob behavior.")
356 group.add_remote_option(
Alex Klein1699fab2022-09-08 08:46:06 -0600357 "--channel",
358 action="split_extend",
359 dest="channels",
360 default=[],
Trent Apted66736d82023-05-25 10:38:28 +1000361 help=(
362 "Specify a channel for a payloads trybot. Can "
363 "be specified multiple times. No valid for "
364 "non-payloads configs."
365 ),
Alex Klein1699fab2022-09-08 08:46:06 -0600366 )
Mike Frysinger81af6ef2013-04-03 02:24:09 -0400367
Alex Klein1699fab2022-09-08 08:46:06 -0600368 parser.add_argument_group(group)
Mike Frysinger81af6ef2013-04-03 02:24:09 -0400369
Alex Klein1699fab2022-09-08 08:46:06 -0600370 #
371 # Advanced options.
372 #
Ryan Cuif4f84be2012-07-09 18:50:41 -0700373
Alex Klein1699fab2022-09-08 08:46:06 -0600374 group = CustomGroup(
375 parser,
376 "Advanced Options",
377 "Caution: use these options at your own risk.",
378 )
Brian Harring3fec5a82012-03-01 05:57:03 -0800379
Alex Klein1699fab2022-09-08 08:46:06 -0600380 group.add_remote_option(
381 "--bootstrap-args",
382 action="append",
383 default=[],
Trent Apted66736d82023-05-25 10:38:28 +1000384 help=(
385 "Args passed directly to the bootstrap re-exec "
386 "to skip verification by the bootstrap code"
387 ),
Alex Klein1699fab2022-09-08 08:46:06 -0600388 )
389 group.add_remote_option(
390 "--buildbot",
391 action="store_true",
392 dest="buildbot",
393 default=False,
Trent Apted66736d82023-05-25 10:38:28 +1000394 help=(
395 "This is running on a buildbot. "
396 "This can be used to make a build operate "
397 "like an official builder, e.g. generate "
398 "new version numbers and archive official "
399 "artifacts and such. This should only be "
400 "used if you are confident in what you are "
401 "doing, as it will make automated commits."
402 ),
Alex Klein1699fab2022-09-08 08:46:06 -0600403 )
404 parser.add_remote_option(
405 "--repo-cache",
406 type="path",
407 dest="_repo_cache",
408 help="Present for backwards compatibility, ignored.",
409 )
410 group.add_remote_option(
411 "--no-buildbot-tags",
412 action="store_false",
413 dest="enable_buildbot_tags",
414 default=True,
Trent Apted66736d82023-05-25 10:38:28 +1000415 help=(
416 "Suppress buildbot specific tags from log "
417 "output. This is used to hide recursive "
418 "cbuilbot runs on the waterfall."
419 ),
Alex Klein1699fab2022-09-08 08:46:06 -0600420 )
421 group.add_remote_option(
422 "--buildnumber", type="int", default=0, help="build number"
423 )
424 group.add_option(
425 "--chrome_root",
426 action="callback",
427 type="path",
428 callback=_CheckChromeRootOption,
429 help="Local checkout of Chrome to use.",
430 )
431 group.add_remote_option(
432 "--chrome_version",
433 action="callback",
434 type="string",
435 dest="chrome_version",
436 callback=_CheckChromeVersionOption,
Trent Apted66736d82023-05-25 10:38:28 +1000437 help=(
438 "Used with SPEC logic to force a particular "
439 "git revision of chrome rather than the "
440 "latest."
441 ),
Alex Klein1699fab2022-09-08 08:46:06 -0600442 )
443 group.add_remote_option(
444 "--clobber",
445 action="store_true",
446 default=False,
447 help="Clears an old checkout before syncing",
448 )
449 group.add_remote_option(
450 "--latest-toolchain",
451 action="store_true",
452 default=False,
453 help="Use the latest toolchain.",
454 )
455 parser.add_option(
456 "--log_dir",
457 dest="log_dir",
458 type="path",
459 help="Directory where logs are stored.",
460 )
461 group.add_remote_option(
462 "--maxarchives",
463 type="int",
464 dest="max_archive_builds",
465 default=3,
466 help="Change the local saved build count limit.",
467 )
468 parser.add_remote_option(
469 "--manifest-repo-url", help="Overrides the default manifest repo url."
470 )
471 group.add_remote_option(
Alex Klein1699fab2022-09-08 08:46:06 -0600472 "--noarchive",
473 action="store_false",
474 dest="archive",
475 default=True,
476 help="Don't run archive stage.",
477 )
478 group.add_remote_option(
479 "--nobootstrap",
480 action="store_false",
481 dest="bootstrap",
482 default=True,
Trent Apted66736d82023-05-25 10:38:28 +1000483 help="Don't checkout and run from a standalone chromite repo.",
Alex Klein1699fab2022-09-08 08:46:06 -0600484 )
485 group.add_remote_option(
486 "--nobuild",
487 action="store_false",
488 dest="build",
489 default=True,
490 help="Don't actually build (for cbuildbot dev)",
491 )
492 group.add_remote_option(
493 "--noclean",
494 action="store_false",
495 dest="clean",
496 default=True,
497 help="Don't clean the buildroot",
498 )
499 group.add_remote_option(
500 "--nocgroups",
501 action="store_false",
502 dest="cgroups",
503 default=True,
504 help="Disable cbuildbots usage of cgroups.",
505 )
506 group.add_remote_option(
507 "--nochromesdk",
508 action="store_false",
509 dest="chrome_sdk",
510 default=True,
Trent Apted66736d82023-05-25 10:38:28 +1000511 help=(
512 "Don't run the ChromeSDK stage which builds "
513 "Chrome outside of the chroot."
514 ),
Alex Klein1699fab2022-09-08 08:46:06 -0600515 )
516 group.add_remote_option(
517 "--noprebuilts",
518 action="store_false",
519 dest="prebuilts",
520 default=True,
521 help="Don't upload prebuilts.",
522 )
523 group.add_remote_option(
524 "--nopatch",
525 action="store_false",
526 dest="postsync_patch",
527 default=True,
Trent Apted66736d82023-05-25 10:38:28 +1000528 help=(
529 "Don't run PatchChanges stage. This does not "
530 "disable patching in of chromite patches "
531 "during BootstrapStage."
532 ),
Alex Klein1699fab2022-09-08 08:46:06 -0600533 )
534 group.add_remote_option(
Alex Klein1699fab2022-09-08 08:46:06 -0600535 "--noreexec",
536 action="store_false",
537 dest="postsync_reexec",
538 default=True,
539 help="Don't reexec into the buildroot after syncing.",
540 )
541 group.add_remote_option(
542 "--nosdk",
543 action="store_true",
544 default=False,
545 help="Re-create the SDK from scratch.",
546 )
547 group.add_remote_option(
548 "--nosync",
549 action="store_false",
550 dest="sync",
551 default=True,
552 help="Don't sync before building.",
553 )
554 group.add_remote_option(
555 "--notests",
556 action="store_false",
557 dest="tests",
558 default=True,
Trent Apted66736d82023-05-25 10:38:28 +1000559 help=(
560 "Override values from buildconfig, run no "
561 "tests, and build no autotest and artifacts."
562 ),
Alex Klein1699fab2022-09-08 08:46:06 -0600563 )
564 group.add_remote_option(
565 "--novmtests",
566 action="store_false",
567 dest="vmtests",
568 default=True,
Trent Apted66736d82023-05-25 10:38:28 +1000569 help="Override values from buildconfig, run no vmtests.",
Alex Klein1699fab2022-09-08 08:46:06 -0600570 )
571 group.add_remote_option(
572 "--noimagetests",
573 action="store_false",
574 dest="image_test",
575 default=True,
Trent Apted66736d82023-05-25 10:38:28 +1000576 help="Override values from buildconfig and run no image tests.",
Alex Klein1699fab2022-09-08 08:46:06 -0600577 )
578 group.add_remote_option(
579 "--nouprev",
580 action="store_false",
581 dest="uprev",
582 default=True,
Trent Apted66736d82023-05-25 10:38:28 +1000583 help="Override values from buildconfig and never uprev.",
Alex Klein1699fab2022-09-08 08:46:06 -0600584 )
585 group.add_option(
586 "--reference-repo",
Trent Apted66736d82023-05-25 10:38:28 +1000587 help=(
588 "Reuse git data stored in an existing repo "
589 "checkout. This can drastically reduce the network "
590 "time spent setting up the trybot checkout. By "
591 "default, if this option isn't given but cbuildbot "
592 "is invoked from a repo checkout, cbuildbot will "
593 "use the repo root."
594 ),
Alex Klein1699fab2022-09-08 08:46:06 -0600595 )
596 group.add_option(
597 "--resume",
598 action="store_true",
599 default=False,
600 help="Skip stages already successfully completed.",
601 )
602 group.add_remote_option(
603 "--timeout",
604 type="int",
605 default=0,
Trent Apted66736d82023-05-25 10:38:28 +1000606 help=(
607 "Specify the maximum amount of time this job "
608 "can run for, at which point the build will be "
609 "aborted. If set to zero, then there is no "
610 "timeout."
611 ),
Alex Klein1699fab2022-09-08 08:46:06 -0600612 )
613 group.add_remote_option(
614 "--version",
615 dest="force_version",
Trent Apted66736d82023-05-25 10:38:28 +1000616 help=(
617 "Used with manifest logic. Forces use of this "
618 "version rather than create or get latest. "
619 "Examples: 4815.0.0-rc1, 4815.1.2"
620 ),
Alex Klein1699fab2022-09-08 08:46:06 -0600621 )
622 group.add_remote_option(
623 "--git-cache-dir",
624 type="path",
625 api=constants.REEXEC_API_GIT_CACHE_DIR,
Trent Apted66736d82023-05-25 10:38:28 +1000626 help=(
627 "Specify the cache directory to store the "
628 "project caches populated by the git-cache "
629 "tool. Bootstrap the projects based on the git "
630 "cache files instead of fetching them directly "
631 "from the GoB servers."
632 ),
Alex Klein1699fab2022-09-08 08:46:06 -0600633 )
634 group.add_remote_option(
635 "--chrome-preload-dir",
636 type="path",
637 api=constants.REEXEC_API_CHROME_PRELOAD_DIR,
Trent Apted66736d82023-05-25 10:38:28 +1000638 help=(
639 "Specify a preloaded chrome source cache "
640 "directory populated by the git-cache tool. "
641 "Bootstrap chrome based on the cached files "
642 "instead of fetching them directly from the GoB "
643 "servers. When both this argument and "
644 "--git-cache-dir are provided this value will "
645 "be preferred for the chrome source cache."
646 ),
Alex Klein1699fab2022-09-08 08:46:06 -0600647 )
648 group.add_remote_option(
649 "--source_cache",
650 action="store_true",
651 default=False,
652 help="Whether to utilize cache snapshot mounts.",
653 )
654 group.add_remote_option(
655 "--debug-cidb",
656 action="store_true",
657 default=False,
658 help="Force Debug CIDB to be used.",
659 )
660 # cbuildbot ChromeOS Findit options
661 group.add_remote_option(
662 "--cbb_build_packages",
663 action="split_extend",
664 dest="cbb_build_packages",
665 default=[],
Trent Apted66736d82023-05-25 10:38:28 +1000666 help=(
667 "Specify an explicit list of packages to build "
668 "for integration with Findit."
669 ),
Alex Klein1699fab2022-09-08 08:46:06 -0600670 )
671 group.add_remote_option(
672 "--cbb_snapshot_revision",
673 type="string",
674 dest="cbb_snapshot_revision",
675 default=None,
Trent Apted66736d82023-05-25 10:38:28 +1000676 help="Snapshot manifest revision to sync to for building.",
Alex Klein1699fab2022-09-08 08:46:06 -0600677 )
678 group.add_remote_option(
679 "--no-publish-prebuilt-confs",
680 dest="publish",
681 action="store_false",
682 default=True,
683 help="Don't publish git commits to prebuilt.conf or sdk_version.conf",
684 )
Mike Frysinger81af6ef2013-04-03 02:24:09 -0400685
Alex Klein1699fab2022-09-08 08:46:06 -0600686 parser.add_argument_group(group)
Mike Frysinger81af6ef2013-04-03 02:24:09 -0400687
Alex Klein1699fab2022-09-08 08:46:06 -0600688 #
689 # Internal options.
690 #
Mike Frysinger81af6ef2013-04-03 02:24:09 -0400691
Alex Klein1699fab2022-09-08 08:46:06 -0600692 group = CustomGroup(
693 parser,
694 "Internal Chromium OS Build Team Options",
695 "Caution: these are for meant for the Chromium OS build team only",
696 )
Mike Frysinger81af6ef2013-04-03 02:24:09 -0400697
Alex Klein1699fab2022-09-08 08:46:06 -0600698 group.add_remote_option(
699 "--archive-base",
700 type="gs_path",
Trent Apted66736d82023-05-25 10:38:28 +1000701 help=(
702 "Base GS URL (gs://<bucket_name>/<path>) to "
703 "upload archive artifacts to"
704 ),
Alex Klein1699fab2022-09-08 08:46:06 -0600705 )
706 group.add_remote_option(
707 "--cq-gerrit-query",
708 dest="cq_gerrit_override",
Trent Apted66736d82023-05-25 10:38:28 +1000709 help=(
710 "If given, this gerrit query will be used to find what patches to "
711 "test, rather than the normal 'CommitQueue>=1 AND Verified=1 AND "
712 "CodeReview=2' query it defaults to. Use with care- note "
713 "additionally this setting only has an effect if the buildbot "
714 "target is a cq target, and we're in buildbot mode."
715 ),
Alex Klein1699fab2022-09-08 08:46:06 -0600716 )
717 group.add_option(
718 "--pass-through",
719 action="append",
720 type="string",
721 dest="pass_through_args",
722 default=[],
723 )
724 group.add_option(
725 "--reexec-api-version",
726 action="store_true",
727 dest="output_api_version",
728 default=False,
Trent Apted66736d82023-05-25 10:38:28 +1000729 help=(
730 "Used for handling forwards/backwards compatibility "
731 "with --resume and --bootstrap"
732 ),
Alex Klein1699fab2022-09-08 08:46:06 -0600733 )
734 group.add_option(
735 "--remote-trybot",
736 action="store_true",
737 default=False,
738 help="Indicates this is running on a remote trybot machine",
739 )
740 group.add_option(
741 "--buildbucket-id",
742 api=constants.REEXEC_API_GOMA, # Approximate.
Trent Apted66736d82023-05-25 10:38:28 +1000743 help=(
744 "The unique ID in buildbucket of current build "
745 "generated by buildbucket."
746 ),
Alex Klein1699fab2022-09-08 08:46:06 -0600747 )
748 group.add_remote_option(
749 "--remote-patches",
750 action="split_extend",
751 default=[],
Trent Apted66736d82023-05-25 10:38:28 +1000752 help=(
753 "Patches uploaded by the trybot client when run using the -p option"
754 ),
Alex Klein1699fab2022-09-08 08:46:06 -0600755 )
756 # Note the default here needs to be hardcoded to 3; that is the last version
757 # that lacked this functionality.
758 group.add_option(
759 "--remote-version",
760 type="int",
761 default=3,
762 help="Deprecated and ignored.",
763 )
764 group.add_option("--sourceroot", type="path", default=constants.SOURCE_ROOT)
765 group.add_remote_option(
766 "--test-bootstrap",
767 action="store_true",
768 default=False,
Trent Apted66736d82023-05-25 10:38:28 +1000769 help=(
770 "Causes cbuildbot to bootstrap itself twice, "
771 "in the sequence A->B->C: A(unpatched) patches "
772 "and bootstraps B; B patches and bootstraps C"
773 ),
Alex Klein1699fab2022-09-08 08:46:06 -0600774 )
775 group.add_remote_option(
776 "--validation_pool",
Trent Apted66736d82023-05-25 10:38:28 +1000777 help=(
778 "Path to a pickled validation pool. Intended "
779 "for use only with the commit queue."
780 ),
Alex Klein1699fab2022-09-08 08:46:06 -0600781 )
782 group.add_remote_option(
783 "--metadata_dump",
Trent Apted66736d82023-05-25 10:38:28 +1000784 help=(
785 "Path to a json dumped metadata file. This "
786 "will be used as the initial metadata."
787 ),
Alex Klein1699fab2022-09-08 08:46:06 -0600788 )
789 group.add_remote_option(
790 "--master-build-id",
791 type="int",
792 api=constants.REEXEC_API_MASTER_BUILD_ID,
Trent Apted66736d82023-05-25 10:38:28 +1000793 help="cidb build id of the master build to this slave build.",
Alex Klein1699fab2022-09-08 08:46:06 -0600794 )
795 group.add_remote_option(
796 "--master-buildbucket-id",
797 api=constants.REEXEC_API_MASTER_BUILDBUCKET_ID,
Trent Apted66736d82023-05-25 10:38:28 +1000798 help="buildbucket id of the master build to this slave build.",
Alex Klein1699fab2022-09-08 08:46:06 -0600799 )
800 # TODO(nxia): crbug.com/778838
801 # cbuildbot doesn't use pickle files anymore, remove this.
802 group.add_remote_option(
803 "--mock-slave-status",
804 metavar="MOCK_SLAVE_STATUS_PICKLE_FILE",
Trent Apted66736d82023-05-25 10:38:28 +1000805 help=(
806 "Override the result of the _FetchSlaveStatuses "
807 "method of MasterSlaveSyncCompletionStage, by "
808 "specifying a file with a pickle of the result "
809 "to be returned."
810 ),
Alex Klein1699fab2022-09-08 08:46:06 -0600811 )
812 group.add_option(
813 "--previous-build-state",
814 type="string",
815 default="",
816 api=constants.REEXEC_API_PREVIOUS_BUILD_STATE,
Trent Apted66736d82023-05-25 10:38:28 +1000817 help=(
818 "A base64-encoded BuildSummary object describing the "
819 "previous build run on the same build machine."
820 ),
Alex Klein1699fab2022-09-08 08:46:06 -0600821 )
Mike Frysinger81af6ef2013-04-03 02:24:09 -0400822
Alex Klein1699fab2022-09-08 08:46:06 -0600823 parser.add_argument_group(group)
Ryan Cuif4f84be2012-07-09 18:50:41 -0700824
Alex Klein1699fab2022-09-08 08:46:06 -0600825 #
826 # Debug options
827 #
828 # Temporary hack; in place till --dry-run replaces --debug.
829 # pylint: disable=protected-access
830 group = parser.debug_group
831 debug = [x for x in group.option_list if x._long_opts == ["--debug"]][0]
832 debug.help += " Currently functions as --dry-run in addition."
833 debug.pass_through = True
834 group.add_option(
835 "--notee",
836 action="store_false",
837 dest="tee",
838 default=True,
Trent Apted66736d82023-05-25 10:38:28 +1000839 help=(
840 "Disable logging and internal tee process. Primarily "
841 "used for debugging cbuildbot itself."
842 ),
Alex Klein1699fab2022-09-08 08:46:06 -0600843 )
844 return parser
Brian Harring3fec5a82012-03-01 05:57:03 -0800845
846
Mike Frysinger80bba8a2017-08-18 15:28:36 -0400847def _FinishParsing(options):
Alex Klein1699fab2022-09-08 08:46:06 -0600848 """Perform some parsing tasks that need to take place after optparse.
Ryan Cui85867972012-02-23 18:21:49 -0800849
Alex Klein1699fab2022-09-08 08:46:06 -0600850 This function needs to be easily testable! Keep it free of
851 environment-dependent code. Put more detailed usage validation in
852 _PostParseCheck().
Brian Harring3fec5a82012-03-01 05:57:03 -0800853
Alex Klein1699fab2022-09-08 08:46:06 -0600854 Args:
Trent Apted66736d82023-05-25 10:38:28 +1000855 options: The options object returned by optparse
Alex Klein1699fab2022-09-08 08:46:06 -0600856 """
857 # Populate options.pass_through_args.
858 accepted, _ = commandline.FilteringParser.FilterArgs(
859 options.parsed_args, lambda x: x.opt_inst.pass_through
860 )
861 options.pass_through_args.extend(accepted)
Brian Harring07039b52012-05-13 17:56:47 -0700862
Alex Klein1699fab2022-09-08 08:46:06 -0600863 if options.local or options.remote:
864 cros_build_lib.Die("Deprecated usage. Please use cros tryjob instead.")
Don Garrettcc0ee522017-09-13 14:28:42 -0700865
Alex Klein1699fab2022-09-08 08:46:06 -0600866 if not options.buildroot:
867 cros_build_lib.Die("A buildroot is required to build.")
Don Garrett211df8c2017-09-06 13:33:02 -0700868
Alex Klein1699fab2022-09-08 08:46:06 -0600869 if options.chrome_root:
870 if options.chrome_rev != constants.CHROME_REV_LOCAL:
871 cros_build_lib.Die(
872 "Chrome rev must be %s if chrome_root is set."
873 % constants.CHROME_REV_LOCAL
874 )
875 elif options.chrome_rev == constants.CHROME_REV_LOCAL:
876 cros_build_lib.Die(
877 "Chrome root must be set if chrome_rev is %s."
878 % constants.CHROME_REV_LOCAL
879 )
Brian Harring3fec5a82012-03-01 05:57:03 -0800880
Alex Klein1699fab2022-09-08 08:46:06 -0600881 if options.chrome_version:
882 if options.chrome_rev != constants.CHROME_REV_SPEC:
883 cros_build_lib.Die(
884 "Chrome rev must be %s if chrome_version is set."
885 % constants.CHROME_REV_SPEC
886 )
887 elif options.chrome_rev == constants.CHROME_REV_SPEC:
888 cros_build_lib.Die(
889 "Chrome rev must not be %s if chrome_version is not set."
890 % constants.CHROME_REV_SPEC
891 )
Brian Harring3fec5a82012-03-01 05:57:03 -0800892
Alex Klein1699fab2022-09-08 08:46:06 -0600893 patches = bool(options.gerrit_patches)
Ryan Cuieaa9efd2012-04-25 17:56:45 -0700894
Alex Klein9e7b29e2023-04-11 16:10:31 -0600895 # When running in release mode, make sure we are running with checked-in
896 # code. We want checked-in cbuildbot/scripts to prevent errors, and we want
897 # to build a release image with checked-in code for CrOS packages.
Alex Klein1699fab2022-09-08 08:46:06 -0600898 if options.buildbot and patches and not options.debug:
899 cros_build_lib.Die(
900 "Cannot provide patches when running with --buildbot!"
901 )
David James5734ea32012-08-15 20:23:49 -0700902
Alex Klein1699fab2022-09-08 08:46:06 -0600903 if options.buildbot and options.remote_trybot:
904 cros_build_lib.Die(
905 "--buildbot and --remote-trybot cannot be used together."
906 )
Ryan Cuiba41ad32012-03-08 17:15:29 -0800907
Alex Klein1699fab2022-09-08 08:46:06 -0600908 # Record whether --debug was set explicitly vs. it was inferred.
909 options.debug_forced = options.debug
910 # We force --debug to be set for builds that are not 'official'.
911 options.debug = options.debug or not options.buildbot
Brian Harring3fec5a82012-03-01 05:57:03 -0800912
Brian Harring3fec5a82012-03-01 05:57:03 -0800913
Mike Frysinger27e21b72018-07-12 14:20:21 -0400914# pylint: disable=unused-argument
Mike Frysinger80bba8a2017-08-18 15:28:36 -0400915def _PostParseCheck(parser, options, site_config):
Alex Klein1699fab2022-09-08 08:46:06 -0600916 """Perform some usage validation after we've parsed the arguments
Brian Harring3fec5a82012-03-01 05:57:03 -0800917
Alex Klein1699fab2022-09-08 08:46:06 -0600918 Args:
Trent Apted66736d82023-05-25 10:38:28 +1000919 parser: Option parser that was used to parse arguments.
920 options: The options returned by optparse.
921 site_config: config_lib.SiteConfig containing all config info.
Alex Klein1699fab2022-09-08 08:46:06 -0600922 """
Don Garrett0a873e02015-06-30 17:55:10 -0700923
Alex Klein1699fab2022-09-08 08:46:06 -0600924 if not options.branch:
925 options.branch = git.GetChromiteTrackingBranch()
Ryan Cuie1e4e662012-05-21 16:39:46 -0700926
Alex Klein1699fab2022-09-08 08:46:06 -0600927 # Because the default cache dir depends on other options, FindCacheDir
928 # always returns None, and we setup the default here.
929 if options.cache_dir is None:
930 # Note, options.sourceroot is set regardless of the path
931 # actually existing.
932 options.cache_dir = os.path.join(options.buildroot, ".cache")
933 options.cache_dir = os.path.abspath(options.cache_dir)
934 parser.ConfigureCacheDir(options.cache_dir)
Brian Harringae0a5322012-09-15 01:46:51 -0700935
Alex Klein1699fab2022-09-08 08:46:06 -0600936 osutils.SafeMakedirsNonRoot(options.cache_dir)
Ryan Cui5ba7e152012-05-10 14:36:52 -0700937
Alex Klein1699fab2022-09-08 08:46:06 -0600938 # Ensure that all args are legitimate config targets.
939 if options.build_config_name not in site_config:
940 cros_build_lib.Die(
941 'Unknown build config: "%s"' % options.build_config_name
942 )
Don Garrett4bb21682014-03-03 16:16:23 -0800943
Alex Klein1699fab2022-09-08 08:46:06 -0600944 build_config = site_config[options.build_config_name]
Don Garrett4af20982015-05-29 19:02:23 -0700945
Mike Frysingeraf204492023-07-10 02:29:19 -0400946 if options.channels:
Alex Klein1699fab2022-09-08 08:46:06 -0600947 cros_build_lib.Die(
948 "--channel must only be used with a payload config,"
949 " not target (%s)." % options.build_config_name
950 )
Don Garrett5af1d262014-05-16 15:49:37 -0700951
Alex Klein1699fab2022-09-08 08:46:06 -0600952 # If the build config explicitly forces the debug flag, set the debug flag
953 # as if it was set from the command line.
954 if build_config.debug:
955 options.debug = True
Don Garrett370839f2017-10-19 18:32:34 -0700956
Alex Klein1699fab2022-09-08 08:46:06 -0600957 if not (config_lib.isTryjobConfig(build_config) or options.buildbot):
958 cros_build_lib.Die(
959 "Refusing to run non-tryjob config as a tryjob.\n"
960 'Please "repo sync && cros tryjob --list %s" for alternatives.\n'
961 "See go/cros-explicit-tryjob-build-configs-psa.",
962 build_config.name,
963 )
Don Garrett02d2f582017-11-08 14:01:24 -0800964
Alex Klein1699fab2022-09-08 08:46:06 -0600965 # The --version option is not compatible with an external target unless the
966 # --buildbot option is specified. More correctly, only "paladin versions"
967 # will work with external targets, and those are only used with --buildbot.
968 # If --buildbot is specified, then user should know what they are doing and
969 # only specify a version that will work. See crbug.com/311648.
970 if options.force_version and not (
971 options.buildbot or build_config.internal
972 ):
973 cros_build_lib.Die(
974 "Cannot specify --version without --buildbot for an"
975 " external target (%s)." % options.build_config_name
976 )
Matt Tennant763497d2014-01-17 16:45:54 -0800977
Ryan Cui85867972012-02-23 18:21:49 -0800978
Don Garrett597ddff2017-02-17 18:29:37 -0800979def ParseCommandLine(parser, argv):
Alex Klein1699fab2022-09-08 08:46:06 -0600980 """Completely parse the commandline arguments"""
981 (options, args) = parser.parse_args(argv)
Brian Harring37e559b2012-05-22 20:47:32 -0700982
Alex Klein1699fab2022-09-08 08:46:06 -0600983 # Handle the request for the reexec command line API version number.
984 if options.output_api_version:
985 print(constants.REEXEC_API_VERSION)
986 sys.exit(0)
Brian Harring37e559b2012-05-22 20:47:32 -0700987
Alex Klein1699fab2022-09-08 08:46:06 -0600988 # Record the configs targeted. Strip out null arguments.
989 build_config_names = [x for x in args if x]
990 if len(build_config_names) != 1:
991 cros_build_lib.Die(
992 "Expected exactly one build config. Got: %r", build_config_names
993 )
994 options.build_config_name = build_config_names[-1]
Don Garrettf0761152017-10-19 19:38:27 -0700995
Alex Klein1699fab2022-09-08 08:46:06 -0600996 _FinishParsing(options)
997 return options
Ryan Cui85867972012-02-23 18:21:49 -0800998
999
Alex Klein1699fab2022-09-08 08:46:06 -06001000_ENVIRONMENT_PROD = "prod"
1001_ENVIRONMENT_DEBUG = "debug"
1002_ENVIRONMENT_STANDALONE = "standalone"
Aviv Keshet420de512015-05-18 14:28:48 -07001003
1004
1005def _GetRunEnvironment(options, build_config):
Alex Klein1699fab2022-09-08 08:46:06 -06001006 """Determine whether this is a prod/debug/standalone run."""
1007 if options.debug_cidb:
1008 return _ENVIRONMENT_DEBUG
Don Garretta90f0142018-02-28 14:25:19 -08001009
Alex Klein1699fab2022-09-08 08:46:06 -06001010 # One of these arguments should always be set if running on a real builder.
1011 # If we aren't on a real builder, we are standalone.
1012 if not options.buildbot and not options.remote_trybot:
1013 return _ENVIRONMENT_STANDALONE
Aviv Keshet420de512015-05-18 14:28:48 -07001014
Alex Klein1699fab2022-09-08 08:46:06 -06001015 if build_config["debug_cidb"]:
1016 return _ENVIRONMENT_DEBUG
Aviv Keshet420de512015-05-18 14:28:48 -07001017
Alex Klein1699fab2022-09-08 08:46:06 -06001018 return _ENVIRONMENT_PROD
Aviv Keshet420de512015-05-18 14:28:48 -07001019
1020
Gabe Blackde694a32015-02-19 15:11:11 -08001021def _SetupConnections(options, build_config):
George Engelbrecht7e07c702022-09-19 17:03:55 -06001022 """Set up CIDB connections using the appropriate Setup call.
Aviv Keshet2982af52014-08-13 16:07:57 -07001023
Alex Klein1699fab2022-09-08 08:46:06 -06001024 Args:
Trent Apted66736d82023-05-25 10:38:28 +10001025 options: Command line options structure.
1026 build_config: Config object for this build.
Alex Klein1699fab2022-09-08 08:46:06 -06001027 """
George Engelbrecht7e07c702022-09-19 17:03:55 -06001028 # Outline:
1029 # 1) Based on options and build_config, decide whether we are a production
1030 # run, debug run, or standalone run.
1031 # 2) Set up cidb instance accordingly.
Alex Klein9e7b29e2023-04-11 16:10:31 -06001032 # 3) Update topology info from cidb, so that any other service set up can
1033 # use topology.
George Engelbrecht7e07c702022-09-19 17:03:55 -06001034 # 4) Set up any other services.
1035 run_type = _GetRunEnvironment(options, build_config)
1036
1037 if run_type == _ENVIRONMENT_PROD:
1038 cidb.CIDBConnectionFactory.SetupProdCidb()
1039 context = ts_mon_config.SetupTsMonGlobalState(
1040 "cbuildbot", indirect=True
1041 )
1042 elif run_type == _ENVIRONMENT_DEBUG:
1043 cidb.CIDBConnectionFactory.SetupDebugCidb()
1044 context = ts_mon_config.TrivialContextManager()
1045 else:
1046 cidb.CIDBConnectionFactory.SetupNoCidb()
1047 context = ts_mon_config.TrivialContextManager()
Aviv Keshet62d1a0e2014-08-22 21:16:13 -07001048
Alex Klein1699fab2022-09-08 08:46:06 -06001049 topology.FetchTopology()
1050 return context
Paul Hobbsd5a0f812016-07-26 16:10:31 -07001051
Aviv Keshet2982af52014-08-13 16:07:57 -07001052
Alex Klein074f94f2023-06-22 10:32:06 -06001053class _MockMethodWithReturnValue:
Alex Klein1699fab2022-09-08 08:46:06 -06001054 """A method mocker which just returns the specific value."""
Dean Liaoe5b0aca2018-01-24 15:27:26 +08001055
Alex Klein1699fab2022-09-08 08:46:06 -06001056 def __init__(self, return_value):
1057 self.return_value = return_value
1058
1059 def __call__(self, *args, **kwargs):
1060 return self.return_value
Dean Liaoe5b0aca2018-01-24 15:27:26 +08001061
1062
Alex Klein074f94f2023-06-22 10:32:06 -06001063class _ObjectMethodPatcher:
Alex Klein1699fab2022-09-08 08:46:06 -06001064 """A simplified mock.object.patch.
Dean Liaoe5b0aca2018-01-24 15:27:26 +08001065
Alex Klein1699fab2022-09-08 08:46:06 -06001066 It is a context manager that patches an object's method with specified
1067 return value.
Dean Liaoe5b0aca2018-01-24 15:27:26 +08001068 """
Dean Liaoe5b0aca2018-01-24 15:27:26 +08001069
Alex Klein1699fab2022-09-08 08:46:06 -06001070 def __init__(self, target, attr, return_value=None):
1071 """Constructor.
Dean Liaoe5b0aca2018-01-24 15:27:26 +08001072
Alex Klein1699fab2022-09-08 08:46:06 -06001073 Args:
Trent Apted66736d82023-05-25 10:38:28 +10001074 target: object to patch.
1075 attr: method name of the object to patch.
1076 return_value: the return value when calling target.attr
Alex Klein1699fab2022-09-08 08:46:06 -06001077 """
1078 self.target = target
1079 self.attr = attr
1080 self.return_value = return_value
1081 self.original_attr = None
1082 self.new_attr = _MockMethodWithReturnValue(self.return_value)
1083
1084 def __enter__(self):
1085 self.original_attr = self.target.__dict__[self.attr]
1086 setattr(self.target, self.attr, self.new_attr)
1087
1088 def __exit__(self, *args):
1089 if self.target and self.original_attr:
1090 setattr(self.target, self.attr, self.original_attr)
Dean Liaoe5b0aca2018-01-24 15:27:26 +08001091
1092
Matt Tennant759e2352013-09-27 15:14:44 -07001093# TODO(build): This function is too damn long.
Ryan Cui85867972012-02-23 18:21:49 -08001094def main(argv):
Alex Klein1699fab2022-09-08 08:46:06 -06001095 # We get false positives with the options object.
1096 # pylint: disable=attribute-defined-outside-init
Mike Frysinger80bba8a2017-08-18 15:28:36 -04001097
Alex Klein1699fab2022-09-08 08:46:06 -06001098 # Turn on strict sudo checks.
1099 cros_build_lib.STRICT_SUDO = True
David James59a0a2b2013-03-22 14:04:44 -07001100
Alex Klein1699fab2022-09-08 08:46:06 -06001101 # Set umask to 022 so files created by buildbot are readable.
1102 os.umask(0o22)
Ryan Cui85867972012-02-23 18:21:49 -08001103
Alex Klein1699fab2022-09-08 08:46:06 -06001104 parser = _CreateParser()
1105 options = ParseCommandLine(parser, argv)
Don Garrett0a873e02015-06-30 17:55:10 -07001106
Alex Klein1699fab2022-09-08 08:46:06 -06001107 # Fetch our site_config now, because we need it to do anything else.
1108 site_config = config_lib.GetConfig()
Don Garrettb85658c2015-06-30 19:07:22 -07001109
Alex Klein1699fab2022-09-08 08:46:06 -06001110 _PostParseCheck(parser, options, site_config)
Brian Harring3fec5a82012-03-01 05:57:03 -08001111
Alex Klein1699fab2022-09-08 08:46:06 -06001112 cros_build_lib.AssertOutsideChroot()
Zdenek Behan98ec2fb2012-08-31 17:12:18 +02001113
Alex Klein1699fab2022-09-08 08:46:06 -06001114 if options.enable_buildbot_tags:
1115 cbuildbot_alerts.EnableBuildbotMarkers()
Matt Tennant759e2352013-09-27 15:14:44 -07001116
Alex Klein1699fab2022-09-08 08:46:06 -06001117 if (
1118 options.buildbot
1119 and not options.debug
Anuj Jamwal258529f2023-09-08 17:32:55 +00001120 and not hostname_util.host_is_ci_builder()
Alex Klein1699fab2022-09-08 08:46:06 -06001121 ):
1122 # --buildbot can only be used on a real builder, unless it's debug.
1123 cros_build_lib.Die("This host is not a supported build machine.")
Ningning Xiac691e432016-08-11 14:52:59 -07001124
Alex Klein1699fab2022-09-08 08:46:06 -06001125 # Only one config arg is allowed in this mode, which was confirmed earlier.
1126 build_config = site_config[options.build_config_name]
Brian Harring3fec5a82012-03-01 05:57:03 -08001127
Alex Klein1699fab2022-09-08 08:46:06 -06001128 # TODO: Re-enable this block when reference_repo support handles this
1129 # properly. (see chromium:330775)
1130 # if options.reference_repo is None:
1131 # repo_path = os.path.join(options.sourceroot, '.repo')
1132 # # If we're being run from a repo checkout, reuse the repo's git pool to
1133 # # cut down on sync time.
1134 # if os.path.exists(repo_path):
1135 # options.reference_repo = options.sourceroot
Don Garrettbbd7b552014-05-16 13:15:21 -07001136
Alex Klein1699fab2022-09-08 08:46:06 -06001137 if options.reference_repo:
1138 if not os.path.exists(options.reference_repo):
1139 parser.error(
1140 "Reference path %s does not exist" % (options.reference_repo,)
1141 )
1142 elif not os.path.exists(os.path.join(options.reference_repo, ".repo")):
1143 parser.error(
1144 "Reference path %s does not look to be the base of a "
1145 "repo checkout; no .repo exists in the root."
1146 % (options.reference_repo,)
1147 )
David Jamesdac7a912013-11-18 11:14:44 -08001148
Alex Klein1699fab2022-09-08 08:46:06 -06001149 if (options.buildbot or options.remote_trybot) and not options.resume:
1150 missing = osutils.FindMissingBinaries(_BUILDBOT_REQUIRED_BINARIES)
1151 if missing:
1152 parser.error(
1153 "Option --buildbot/--remote-trybot requires the following "
1154 "binaries which couldn't be found in $PATH: %s"
Trent Apted66736d82023-05-25 10:38:28 +10001155 % ", ".join(missing)
Alex Klein1699fab2022-09-08 08:46:06 -06001156 )
Brian Harring351ce442012-03-09 16:38:14 -08001157
Alex Klein1699fab2022-09-08 08:46:06 -06001158 if options.reference_repo:
1159 options.reference_repo = os.path.abspath(options.reference_repo)
David Jamesdac7a912013-11-18 11:14:44 -08001160
Alex Klein1699fab2022-09-08 08:46:06 -06001161 # Sanity check of buildroot- specifically that it's not pointing into the
1162 # midst of an existing repo since git-repo doesn't support nesting.
1163 if not repository.IsARepoRoot(options.buildroot) and git.FindRepoDir(
1164 options.buildroot
1165 ):
1166 cros_build_lib.Die(
1167 "Configured buildroot %s is a subdir of an existing repo checkout."
1168 % options.buildroot
1169 )
Brian Harring3fec5a82012-03-01 05:57:03 -08001170
Alex Klein1699fab2022-09-08 08:46:06 -06001171 if not options.log_dir:
1172 options.log_dir = os.path.join(options.buildroot, _DEFAULT_LOG_DIR)
Chris Sosab5ea3b42012-10-25 15:25:20 -07001173
Alex Klein1699fab2022-09-08 08:46:06 -06001174 log_file = None
1175 if options.tee:
1176 log_file = os.path.join(options.log_dir, _BUILDBOT_LOG_FILE)
1177 osutils.SafeMakedirs(options.log_dir)
1178 _BackupPreviousLog(log_file)
Brian Harringd166aaf2012-05-14 18:31:53 -07001179
Mike Frysinger321fecd2023-06-16 10:40:51 -04001180 with contextlib.ExitStack() as stack:
Alex Klein1699fab2022-09-08 08:46:06 -06001181 # Preserve chromite; we might be running from there!
1182 options.preserve_paths = set(["chromite"])
1183 if log_file is not None:
Alex Klein9e7b29e2023-04-11 16:10:31 -06001184 # We don't want the critical section to try to clean up the tee
1185 # process, so we run Tee (forked off) outside of it. This prevents a
1186 # deadlock because the Tee process only exits when its pipe is
1187 # closed, and the critical section accidentally holds on to that
1188 # file handle.
Mike Frysinger321fecd2023-06-16 10:40:51 -04001189 stack.enter_context(tee.Tee(log_file))
Alex Klein1699fab2022-09-08 08:46:06 -06001190 options.preserve_paths.add(_DEFAULT_LOG_DIR)
David Jamescebc7272013-07-17 16:45:05 -07001191
Mike Frysinger321fecd2023-06-16 10:40:51 -04001192 critical_section = stack.enter_context(cleanup.EnforcedCleanupSection())
1193 stack.enter_context(sudo.SudoKeepAlive())
Brian Harringd166aaf2012-05-14 18:31:53 -07001194
Alex Klein1699fab2022-09-08 08:46:06 -06001195 if not options.resume:
1196 # If we're in resume mode, use our parents tempdir rather than
1197 # nesting another layer.
Mike Frysinger321fecd2023-06-16 10:40:51 -04001198 stack.enter_context(osutils.TempDir(prefix="cbb", set_global=True))
Alex Klein1699fab2022-09-08 08:46:06 -06001199 logging.debug("Cbuildbot tempdir is %r.", os.environ.get("TMP"))
Brian Harringd166aaf2012-05-14 18:31:53 -07001200
Alex Klein1699fab2022-09-08 08:46:06 -06001201 if options.cgroups:
Mike Frysinger321fecd2023-06-16 10:40:51 -04001202 stack.enter_context(cgroups.SimpleContainChildren("cbuildbot"))
Brian Harringa184efa2012-03-04 11:51:25 -08001203
Alex Klein1699fab2022-09-08 08:46:06 -06001204 # Mark everything between EnforcedCleanupSection and here as having to
1205 # be rolled back via the contextmanager cleanup handlers. This
1206 # ensures that sudo bits cannot outlive cbuildbot, that anything
1207 # cgroups would kill gets killed, etc.
Mike Frysinger321fecd2023-06-16 10:40:51 -04001208 stack.enter_context(critical_section.ForkWatchdog())
Brian Harringd166aaf2012-05-14 18:31:53 -07001209
Alex Klein1699fab2022-09-08 08:46:06 -06001210 if options.mock_slave_status is not None:
Mike Frysinger31fdddd2023-02-24 15:50:55 -05001211 with open(options.mock_slave_status, "rb") as f:
Alex Klein1699fab2022-09-08 08:46:06 -06001212 mock_statuses = pickle.load(f)
1213 for key, value in mock_statuses.items():
1214 mock_statuses[key] = builder_status_lib.BuilderStatus(
1215 **value
1216 )
Mike Frysinger321fecd2023-06-16 10:40:51 -04001217 stack.enter_context(
1218 _ObjectMethodPatcher(
1219 completion_stages.MasterSlaveSyncCompletionStage,
1220 "_FetchSlaveStatuses",
1221 return_value=mock_statuses,
1222 )
Alex Klein1699fab2022-09-08 08:46:06 -06001223 )
Aviv Keshetcf9c2722014-02-25 15:15:10 -08001224
Mike Frysinger321fecd2023-06-16 10:40:51 -04001225 stack.enter_context(_SetupConnections(options, build_config))
Alex Klein1699fab2022-09-08 08:46:06 -06001226 retry_stats.SetupStats()
Aviv Keshet2982af52014-08-13 16:07:57 -07001227
Alex Klein1699fab2022-09-08 08:46:06 -06001228 timeout_display_message = (
1229 "This build has reached the timeout deadline set by the master. "
1230 "Either this stage or a previous one took too long (see stage "
1231 "timing historical summary in ReportStage) or the build failed "
1232 "to start on time."
1233 )
Prathmesh Prabhu80e05df2014-12-11 15:20:33 -08001234
Alex Klein1699fab2022-09-08 08:46:06 -06001235 if options.timeout > 0:
Mike Frysinger321fecd2023-06-16 10:40:51 -04001236 stack.enter_context(
1237 timeout_util.FatalTimeout(
1238 options.timeout,
1239 timeout_display_message,
1240 )
Alex Klein1699fab2022-09-08 08:46:06 -06001241 )
1242 try:
1243 _RunBuildStagesWrapper(options, site_config, build_config)
1244 except failures_lib.ExitEarlyException as ex:
Alex Klein9e7b29e2023-04-11 16:10:31 -06001245 # This build finished successfully. Do not re-raise
1246 # ExitEarlyException.
Alex Klein1699fab2022-09-08 08:46:06 -06001247 logging.info("One stage exited early: %s", ex)