blob: c7dca52b51cea805c9f7aaa4b76d3f32a3b7b9c8 [file] [log] [blame]
Mike Frysingere58c0e22017-10-04 15:43:30 -04001# -*- coding: utf-8 -*-
Don Garrettc4114cc2016-11-01 20:04:06 -07002# Copyright 2016 The Chromium OS Authors. All rights reserved.
3# Use of this source code is governed by a BSD-style license that can be
4# found in the LICENSE file.
5
6"""Bootstrap for cbuildbot.
7
8This script is intended to checkout chromite on the branch specified by -b or
9--branch (as normally accepted by cbuildbot), and then invoke cbuildbot. Most
10arguments are not parsed, only passed along. If a branch is not specified, this
11script will use 'master'.
12
13Among other things, this allows us to invoke build configs that exist on a given
14branch, but not on TOT.
15"""
16
17from __future__ import print_function
18
Benjamin Gordon90b2dd92018-04-12 14:04:21 -060019import base64
Don Garrett125d4dc2017-04-25 16:26:03 -070020import functools
Don Garrettc4114cc2016-11-01 20:04:06 -070021import os
Prathmesh Prabhuc41a0f52018-04-03 13:26:52 -070022import time
Don Garrettc4114cc2016-11-01 20:04:06 -070023
24from chromite.cbuildbot import repository
Don Garrett597ddff2017-02-17 18:29:37 -080025from chromite.cbuildbot.stages import sync_stages
Benjamin Gordon90b2dd92018-04-12 14:04:21 -060026from chromite.lib import build_summary
Don Garrett86881cb2017-02-15 15:41:55 -080027from chromite.lib import config_lib
Don Garretta50bf492017-09-28 18:33:02 -070028from chromite.lib import constants
Don Garrettc4114cc2016-11-01 20:04:06 -070029from chromite.lib import cros_build_lib
30from chromite.lib import cros_logging as logging
Don Garrettacbb2392017-05-11 18:27:41 -070031from chromite.lib import metrics
Don Garrettc4114cc2016-11-01 20:04:06 -070032from chromite.lib import osutils
Don Garrettacbb2392017-05-11 18:27:41 -070033from chromite.lib import ts_mon_config
Don Garrett86881cb2017-02-15 15:41:55 -080034from chromite.scripts import cbuildbot
Don Garrettc4114cc2016-11-01 20:04:06 -070035
Don Garrett60967922017-04-12 18:51:44 -070036# This number should be incremented when we change the layout of the buildroot
37# in a non-backwards compatible way. This wipes all buildroots.
Don Garrettbf90cdf2017-05-19 15:54:02 -070038BUILDROOT_BUILDROOT_LAYOUT = 2
Prathmesh Prabhuc41a0f52018-04-03 13:26:52 -070039_DISTFILES_CACHE_EXPIRY_HOURS = 8 * 24
Don Garrett60967922017-04-12 18:51:44 -070040
Don Garrettacbb2392017-05-11 18:27:41 -070041# Metrics reported to Monarch.
Don Garrett45e77412017-06-14 16:57:55 -070042METRIC_ACTIVE = 'chromeos/chromite/cbuildbot_launch/active'
Don Garrettacbb2392017-05-11 18:27:41 -070043METRIC_INVOKED = 'chromeos/chromite/cbuildbot_launch/invoked'
44METRIC_COMPLETED = 'chromeos/chromite/cbuildbot_launch/completed'
45METRIC_PREP = 'chromeos/chromite/cbuildbot_launch/prep_completed'
46METRIC_CLEAN = 'chromeos/chromite/cbuildbot_launch/clean_buildroot_durations'
47METRIC_INITIAL = 'chromeos/chromite/cbuildbot_launch/initial_checkout_durations'
48METRIC_CBUILDBOT = 'chromeos/chromite/cbuildbot_launch/cbuildbot_durations'
49METRIC_CLOBBER = 'chromeos/chromite/cbuildbot_launch/clobber'
50METRIC_BRANCH_CLEANUP = 'chromeos/chromite/cbuildbot_launch/branch_cleanup'
Prathmesh Prabhuc41a0f52018-04-03 13:26:52 -070051METRIC_DISTFILES_CLEANUP = (
52 'chromeos/chromite/cbuildbot_launch/distfiles_cleanup')
Don Garrett066e6f52017-09-28 19:14:01 -070053METRIC_DEPOT_TOOLS = 'chromeos/chromite/cbuildbot_launch/depot_tools_prep'
Don Garrettacbb2392017-05-11 18:27:41 -070054
Benjamin Gordon90b2dd92018-04-12 14:04:21 -060055# Builder state
56BUILDER_STATE_FILENAME = '.cbuildbot_build_state.json'
57
Don Garrett60967922017-04-12 18:51:44 -070058
Don Garrett125d4dc2017-04-25 16:26:03 -070059def StageDecorator(functor):
60 """A Decorator that adds buildbot stage tags around a method.
61
Don Garrettacbb2392017-05-11 18:27:41 -070062 It uses the method name as the stage name, and assumes failure on a true
63 return value, or an exception.
Don Garrett125d4dc2017-04-25 16:26:03 -070064 """
65 @functools.wraps(functor)
66 def wrapped_functor(*args, **kwargs):
67 try:
68 logging.PrintBuildbotStepName(functor.__name__)
Don Garrettacbb2392017-05-11 18:27:41 -070069 result = functor(*args, **kwargs)
Don Garrett125d4dc2017-04-25 16:26:03 -070070 except Exception:
71 logging.PrintBuildbotStepFailure()
72 raise
73
Don Garrettacbb2392017-05-11 18:27:41 -070074 if result:
75 logging.PrintBuildbotStepFailure()
76 return result
77
Don Garrett125d4dc2017-04-25 16:26:03 -070078 return wrapped_functor
79
80
Don Garrettb5fc08b2017-11-20 21:51:16 +000081def field(fields, **kwargs):
Don Garrettacbb2392017-05-11 18:27:41 -070082 """Helper for inserting more fields into a metrics fields dictionary.
83
84 Args:
85 fields: Dictionary of metrics fields.
86 kwargs: Each argument is a key/value pair to insert into dict.
87
88 Returns:
89 Copy of original dictionary with kwargs set as fields.
90 """
91 f = fields.copy()
92 f.update(kwargs)
93 return f
94
Don Garretta50bf492017-09-28 18:33:02 -070095
96def PrependPath(prepend):
97 """Generate path with new directory at the beginning.
98
99 Args:
100 prepend: Directory to add at the beginning of the path.
101
102 Returns:
103 Extended path as a string.
104 """
105 return os.pathsep.join([prepend, os.environ.get('PATH', os.defpath)])
106
107
Don Garrett86881cb2017-02-15 15:41:55 -0800108def PreParseArguments(argv):
Don Garrettc4114cc2016-11-01 20:04:06 -0700109 """Extract the branch name from cbuildbot command line arguments.
110
Don Garrettc4114cc2016-11-01 20:04:06 -0700111 Args:
112 argv: The command line arguments to parse.
113
114 Returns:
115 Branch as a string ('master' if nothing is specified).
116 """
Don Garrett86881cb2017-02-15 15:41:55 -0800117 parser = cbuildbot.CreateParser()
Mike Frysinger80bba8a2017-08-18 15:28:36 -0400118 options = cbuildbot.ParseCommandLine(parser, argv)
Don Garrettd1d90dd2017-06-13 17:35:52 -0700119 options.Freeze()
Don Garrett86881cb2017-02-15 15:41:55 -0800120
121 # This option isn't required for cbuildbot, but is for us.
122 if not options.buildroot:
123 cros_build_lib.Die('--buildroot is a required option.')
124
125 return options
Don Garrettc4114cc2016-11-01 20:04:06 -0700126
127
Benjamin Gordon8b6d4122018-04-26 13:38:39 -0600128def GetCurrentBuildState(options, branch):
Benjamin Gordon90b2dd92018-04-12 14:04:21 -0600129 """Extract information about the current build state from command-line args.
130
131 Args:
132 options: A parsed options object from a cbuildbot parser.
Benjamin Gordon8b6d4122018-04-26 13:38:39 -0600133 branch: The name of the branch this builder was called with.
Benjamin Gordon90b2dd92018-04-12 14:04:21 -0600134
135 Returns:
136 A BuildSummary object describing the current build.
137 """
138 build_state = build_summary.BuildSummary(
Benjamin Gordon8b6d4122018-04-26 13:38:39 -0600139 status=constants.BUILDER_STATUS_INFLIGHT,
140 buildroot_layout=BUILDROOT_BUILDROOT_LAYOUT,
141 branch=branch)
Benjamin Gordon90b2dd92018-04-12 14:04:21 -0600142 if options.buildnumber:
143 build_state.build_number = options.buildnumber
144 if options.buildbucket_id:
145 build_state.buildbucket_id = options.buildbucket_id
146 if options.master_build_id:
147 build_state.master_build_id = options.master_build_id
148 return build_state
149
150
151def GetLastBuildState(root):
152 """Fetch the state of the last build run from |root|.
153
154 If the saved state file can't be read or doesn't contain valid JSON, a default
155 state will be returned.
156
157 Args:
158 root: Root of the working directory tree as a string.
159
160 Returns:
161 A BuildSummary object representing the previous build.
162 """
163 state_file = os.path.join(root, BUILDER_STATE_FILENAME)
164
165 state = build_summary.BuildSummary()
Benjamin Gordon8b6d4122018-04-26 13:38:39 -0600166
Benjamin Gordon90b2dd92018-04-12 14:04:21 -0600167 try:
168 state_raw = osutils.ReadFile(state_file)
169 state.from_json(state_raw)
170 except IOError as e:
171 logging.warning('Unable to read %s: %s', state_file, e)
172 return state
173 except ValueError as e:
174 logging.warning('Saved state file %s is not valid JSON: %s', state_file, e)
175 return state
176
177 if not state.is_valid():
178 logging.warning('Previous build state is not valid. Ignoring.')
Benjamin Gordon8b6d4122018-04-26 13:38:39 -0600179 state = build_summary.BuildSummary()
Benjamin Gordon90b2dd92018-04-12 14:04:21 -0600180
181 return state
182
183
184def SetLastBuildState(root, new_state):
185 """Save the state of the last build under |root|.
186
187 Args:
188 root: Root of the working directory tree as a string.
189 new_state: BuildSummary object containing the state to be saved.
190 """
191 state_file = os.path.join(root, BUILDER_STATE_FILENAME)
192 osutils.WriteFile(state_file, new_state.to_json())
193
Benjamin Gordon8b6d4122018-04-26 13:38:39 -0600194 # Remove old state file. Its contents have been migrated into the new file.
195 old_state_file = os.path.join(root, '.cbuildbot_launch_state')
196 osutils.SafeUnlink(old_state_file)
197
Benjamin Gordon90b2dd92018-04-12 14:04:21 -0600198
Prathmesh Prabhuc41a0f52018-04-03 13:26:52 -0700199def _MaybeCleanDistfiles(repo, distfiles_ts, metrics_fields):
200 """Cleans the distfiles directory if too old.
201
202 Args:
203 repo: repository.RepoRepository instance.
204 distfiles_ts: A timestamp str for the last time distfiles was cleaned. May
205 be None.
206 metrics_fields: Dictionary of fields to include in metrics.
207
208 Returns:
209 The new distfiles_ts to persist in state.
210 """
211
212 if distfiles_ts is None:
213 return None
214
215 distfiles_age = (time.time() - distfiles_ts) / 3600.0
216 if distfiles_age < _DISTFILES_CACHE_EXPIRY_HOURS:
217 return distfiles_ts
218
219 logging.info('Remove old distfiles cache (cache expiry %d hours)',
220 _DISTFILES_CACHE_EXPIRY_HOURS)
221 osutils.RmDir(os.path.join(repo.directory, '.cache', 'distfiles'),
222 ignore_missing=True, sudo=True)
223 metrics.Counter(METRIC_DISTFILES_CLEANUP).increment(
224 field(metrics_fields, reason='cache_expired'))
225 # Cleaned cache, so reset distfiles_ts
226 return None
227
228
Don Garrett125d4dc2017-04-25 16:26:03 -0700229@StageDecorator
Benjamin Gordon90b2dd92018-04-12 14:04:21 -0600230def CleanBuildRoot(root, repo, metrics_fields, build_state):
Don Garrett7ade05a2017-02-17 13:31:47 -0800231 """Some kinds of branch transitions break builds.
232
Don Garrettbf90cdf2017-05-19 15:54:02 -0700233 This method ensures that cbuildbot's buildroot is a clean checkout on the
234 given branch when it starts. If necessary (a branch transition) it will wipe
235 assorted state that cannot be safely reused from the previous build.
Don Garrett7ade05a2017-02-17 13:31:47 -0800236
Don Garrett7ade05a2017-02-17 13:31:47 -0800237 Args:
Don Garrettbf90cdf2017-05-19 15:54:02 -0700238 root: Root directory owned by cbuildbot_launch.
Don Garrettf324bc32017-05-23 14:00:53 -0700239 repo: repository.RepoRepository instance.
Don Garrettacbb2392017-05-11 18:27:41 -0700240 metrics_fields: Dictionary of fields to include in metrics.
Benjamin Gordon90b2dd92018-04-12 14:04:21 -0600241 build_state: BuildSummary object containing the current build state that
Benjamin Gordon8b6d4122018-04-26 13:38:39 -0600242 will be saved into the cleaned root. The distfiles_ts property will
243 be updated if the distfiles cache is cleaned.
Don Garrett7ade05a2017-02-17 13:31:47 -0800244 """
Benjamin Gordon8b6d4122018-04-26 13:38:39 -0600245 previous_state = GetLastBuildState(root)
246 build_state.distfiles_ts = _MaybeCleanDistfiles(
247 repo, previous_state.distfiles_ts, metrics_fields)
Don Garrette17e1d92017-04-12 15:28:19 -0700248
Benjamin Gordon8b6d4122018-04-26 13:38:39 -0600249 if previous_state.buildroot_layout != BUILDROOT_BUILDROOT_LAYOUT:
Don Garrett125d4dc2017-04-25 16:26:03 -0700250 logging.PrintBuildbotStepText('Unknown layout: Wiping buildroot.')
Don Garrettb5fc08b2017-11-20 21:51:16 +0000251 metrics.Counter(METRIC_CLOBBER).increment(
252 field(metrics_fields, reason='layout_change'))
Benjamin Gordonaee36b82018-02-05 14:25:26 -0700253 chroot_dir = os.path.join(root, constants.DEFAULT_CHROOT_DIR)
Don Garrettb5fc08b2017-11-20 21:51:16 +0000254 if os.path.exists(chroot_dir) or os.path.exists(chroot_dir + '.img'):
255 cros_build_lib.CleanupChrootMount(chroot_dir, delete_image=True)
256 osutils.RmDir(root, ignore_missing=True, sudo=True)
Don Garrettf324bc32017-05-23 14:00:53 -0700257 else:
Benjamin Gordon8b6d4122018-04-26 13:38:39 -0600258 if previous_state.branch != repo.branch:
Don Garrettf324bc32017-05-23 14:00:53 -0700259 logging.PrintBuildbotStepText('Branch change: Cleaning buildroot.')
Benjamin Gordon8b6d4122018-04-26 13:38:39 -0600260 logging.info('Unmatched branch: %s -> %s', previous_state.branch,
261 repo.branch)
Don Garrettacbb2392017-05-11 18:27:41 -0700262 metrics.Counter(METRIC_BRANCH_CLEANUP).increment(
Benjamin Gordon8b6d4122018-04-26 13:38:39 -0600263 field(metrics_fields, old_branch=previous_state.branch))
Don Garrett39963602017-02-27 14:41:58 -0800264
Don Garrettf324bc32017-05-23 14:00:53 -0700265 logging.info('Remove Chroot.')
Benjamin Gordonaee36b82018-02-05 14:25:26 -0700266 chroot_dir = os.path.join(repo.directory, constants.DEFAULT_CHROOT_DIR)
Benjamin Gordon59ba2f82017-08-28 15:31:06 -0600267 if os.path.exists(chroot_dir) or os.path.exists(chroot_dir + '.img'):
268 cros_build_lib.CleanupChrootMount(chroot_dir, delete_image=True)
269 osutils.RmDir(chroot_dir, ignore_missing=True, sudo=True)
Don Garrett7ade05a2017-02-17 13:31:47 -0800270
Don Garrettf324bc32017-05-23 14:00:53 -0700271 logging.info('Remove Chrome checkout.')
Don Garrettbf90cdf2017-05-19 15:54:02 -0700272 osutils.RmDir(os.path.join(repo.directory, '.cache', 'distfiles'),
Don Garrettf324bc32017-05-23 14:00:53 -0700273 ignore_missing=True, sudo=True)
274
275 try:
276 # If there is any failure doing the cleanup, wipe everything.
277 repo.BuildRootGitCleanup(prune_all=True)
278 except Exception:
279 logging.info('Checkout cleanup failed, wiping buildroot:', exc_info=True)
Don Garrettacbb2392017-05-11 18:27:41 -0700280 metrics.Counter(METRIC_CLOBBER).increment(
Don Garrettb5fc08b2017-11-20 21:51:16 +0000281 field(metrics_fields, reason='repo_cleanup_failure'))
Don Garrettbf90cdf2017-05-19 15:54:02 -0700282 repository.ClearBuildRoot(repo.directory)
Don Garrett39963602017-02-27 14:41:58 -0800283
Don Garrettbf90cdf2017-05-19 15:54:02 -0700284 # Ensure buildroot exists. Save the state we are prepped for.
285 osutils.SafeMakedirs(repo.directory)
Benjamin Gordon8b6d4122018-04-26 13:38:39 -0600286 if not build_state.distfiles_ts:
287 build_state.distfiles_ts = time.time()
Benjamin Gordon90b2dd92018-04-12 14:04:21 -0600288 SetLastBuildState(root, build_state)
Don Garrett7ade05a2017-02-17 13:31:47 -0800289
290
Don Garrett125d4dc2017-04-25 16:26:03 -0700291@StageDecorator
Don Garrettf324bc32017-05-23 14:00:53 -0700292def InitialCheckout(repo):
Don Garrett86881cb2017-02-15 15:41:55 -0800293 """Preliminary ChromeOS checkout.
294
295 Perform a complete checkout of ChromeOS on the specified branch. This does NOT
296 match what the build needs, but ensures the buildroot both has a 'hot'
297 checkout, and is close enough that the branched cbuildbot can successfully get
298 the right checkout.
299
300 This checks out full ChromeOS, even if a ChromiumOS build is going to be
301 performed. This is because we have no knowledge of the build config to be
302 used.
Don Garrettc4114cc2016-11-01 20:04:06 -0700303
304 Args:
Don Garrettf324bc32017-05-23 14:00:53 -0700305 repo: repository.RepoRepository instance.
Don Garrettc4114cc2016-11-01 20:04:06 -0700306 """
Don Garrettf324bc32017-05-23 14:00:53 -0700307 logging.PrintBuildbotStepText('Branch: %s' % repo.branch)
Don Garrett7ade05a2017-02-17 13:31:47 -0800308 logging.info('Bootstrap script starting initial sync on branch: %s',
Don Garrettf324bc32017-05-23 14:00:53 -0700309 repo.branch)
Don Garrett76496912017-05-11 16:59:11 -0700310 repo.Sync(detach=True)
Don Garrettc4114cc2016-11-01 20:04:06 -0700311
312
Don Garrett125d4dc2017-04-25 16:26:03 -0700313@StageDecorator
Don Garrett066e6f52017-09-28 19:14:01 -0700314def DepotToolsEnsureBootstrap(depot_tools_path):
315 """Start cbuildbot in specified directory with all arguments.
316
317 Args:
318 buildroot: Directory to be passed to cbuildbot with --buildroot.
319 depot_tools_path: Directory for depot_tools to be used by cbuildbot.
320 argv: Command line options passed to cbuildbot_launch.
321
322 Returns:
323 Return code of cbuildbot as an integer.
324 """
325 ensure_bootstrap_script = os.path.join(depot_tools_path, 'ensure_bootstrap')
326 if os.path.exists(ensure_bootstrap_script):
327 extra_env = {'PATH': PrependPath(depot_tools_path)}
328 cros_build_lib.RunCommand(
329 [ensure_bootstrap_script], extra_env=extra_env, cwd=depot_tools_path)
330 else:
331 # This is normal when checking out branches older than this script.
332 logging.warn('ensure_bootstrap not found, skipping: %s',
333 ensure_bootstrap_script)
334
335
336@StageDecorator
Don Garrett6e5c6b92018-04-06 17:58:49 -0700337def Cbuildbot(buildroot, depot_tools_path, argv):
Don Garrettc4114cc2016-11-01 20:04:06 -0700338 """Start cbuildbot in specified directory with all arguments.
339
340 Args:
Don Garrettbf90cdf2017-05-19 15:54:02 -0700341 buildroot: Directory to be passed to cbuildbot with --buildroot.
Don Garretta50bf492017-09-28 18:33:02 -0700342 depot_tools_path: Directory for depot_tools to be used by cbuildbot.
Don Garrettd1d90dd2017-06-13 17:35:52 -0700343 argv: Command line options passed to cbuildbot_launch.
Don Garrettc4114cc2016-11-01 20:04:06 -0700344
345 Returns:
346 Return code of cbuildbot as an integer.
347 """
Don Garrettbf90cdf2017-05-19 15:54:02 -0700348 logging.info('Bootstrap cbuildbot in: %s', buildroot)
Don Garrettbf90cdf2017-05-19 15:54:02 -0700349
Don Garrettd1d90dd2017-06-13 17:35:52 -0700350 # Fixup buildroot parameter.
351 argv = argv[:]
352 for i in xrange(len(argv)):
353 if argv[i] in ('-r', '--buildroot'):
354 argv[i+1] = buildroot
Don Garrett597ddff2017-02-17 18:29:37 -0800355
Don Garrettd1d90dd2017-06-13 17:35:52 -0700356 # This filters out command line arguments not supported by older versions
357 # of cbuildbot.
358 parser = cbuildbot.CreateParser()
Mike Frysinger80bba8a2017-08-18 15:28:36 -0400359 options = cbuildbot.ParseCommandLine(parser, argv)
Don Garrettd1d90dd2017-06-13 17:35:52 -0700360 cbuildbot_path = os.path.join(buildroot, 'chromite', 'bin', 'cbuildbot')
Don Garrett597ddff2017-02-17 18:29:37 -0800361 cmd = sync_stages.BootstrapStage.FilterArgsForTargetCbuildbot(
Don Garrettbf90cdf2017-05-19 15:54:02 -0700362 buildroot, cbuildbot_path, options)
Don Garrett597ddff2017-02-17 18:29:37 -0800363
Don Garretta50bf492017-09-28 18:33:02 -0700364 # We want cbuildbot to use branched depot_tools scripts from our manifest,
365 # so that depot_tools is branched to match cbuildbot.
366 logging.info('Adding depot_tools into PATH: %s', depot_tools_path)
367 extra_env = {'PATH': PrependPath(depot_tools_path)}
368
369 result = cros_build_lib.RunCommand(
370 cmd, extra_env=extra_env, error_code_ok=True, cwd=buildroot)
Don Garrettacbb2392017-05-11 18:27:41 -0700371 return result.returncode
Don Garrettc4114cc2016-11-01 20:04:06 -0700372
Don Garrett60967922017-04-12 18:51:44 -0700373
Benjamin Gordonaee36b82018-02-05 14:25:26 -0700374@StageDecorator
375def CleanupChroot(buildroot):
376 """Unmount/clean up an image-based chroot without deleting the backing image.
377
378 Args:
379 buildroot: Directory containing the chroot to be cleaned up.
380 """
381 chroot_dir = os.path.join(buildroot, constants.DEFAULT_CHROOT_DIR)
382 logging.info('Cleaning up chroot at %s', chroot_dir)
383 if os.path.exists(chroot_dir) or os.path.exists(chroot_dir + '.img'):
384 cros_build_lib.CleanupChrootMount(chroot_dir, delete_image=False)
385
386
Don Garrettf15d65b2017-04-12 12:39:55 -0700387def ConfigureGlobalEnvironment():
388 """Setup process wide environmental changes."""
Don Garrettf15d65b2017-04-12 12:39:55 -0700389 # Set umask to 022 so files created by buildbot are readable.
390 os.umask(0o22)
391
Don Garrett86fec482017-05-17 18:13:33 -0700392 # These variables can interfere with LANG / locale behavior.
393 unwanted_local_vars = [
394 'LC_ALL', 'LC_CTYPE', 'LC_COLLATE', 'LC_TIME', 'LC_NUMERIC',
395 'LC_MONETARY', 'LC_MESSAGES', 'LC_PAPER', 'LC_NAME', 'LC_ADDRESS',
396 'LC_TELEPHONE', 'LC_MEASUREMENT', 'LC_IDENTIFICATION',
397 ]
398 for v in unwanted_local_vars:
399 os.environ.pop(v, None)
400
401 # This variable is required for repo sync's to work in all cases.
402 os.environ['LANG'] = 'en_US.UTF-8'
403
Don Garrettc4114cc2016-11-01 20:04:06 -0700404
Don Garrettacbb2392017-05-11 18:27:41 -0700405def _main(argv):
Don Garrettc4114cc2016-11-01 20:04:06 -0700406 """main method of script.
407
408 Args:
409 argv: All command line arguments to pass as list of strings.
410
411 Returns:
412 Return code of cbuildbot as an integer.
413 """
Don Garrettd1d90dd2017-06-13 17:35:52 -0700414 options = PreParseArguments(argv)
415
416 branchname = options.branch or 'master'
417 root = options.buildroot
418 buildroot = os.path.join(root, 'repository')
Don Garretta50bf492017-09-28 18:33:02 -0700419 depot_tools_path = os.path.join(buildroot, constants.DEPOT_TOOLS_SUBPATH)
Don Garrettd1d90dd2017-06-13 17:35:52 -0700420
421 metrics_fields = {
422 'branch_name': branchname,
Don Garrettf0761152017-10-19 19:38:27 -0700423 'build_config': options.build_config_name,
Don Garrettd1d90dd2017-06-13 17:35:52 -0700424 'tryjob': options.remote_trybot,
425 }
Don Garrettf15d65b2017-04-12 12:39:55 -0700426
Mike Nichols76573362018-05-08 20:11:53 -0600427 with ts_mon_config.SetupTsMonGlobalState(
428 'cbuildbot_launch', indirect=True,
429 job_name=metrics_fields['build_config']):
430 # Does the entire build pass or fail.
431 with metrics.Presence(METRIC_ACTIVE, metrics_fields), \
432 metrics.SuccessCounter(METRIC_COMPLETED, metrics_fields) as s_fields:
Don Garrettc4114cc2016-11-01 20:04:06 -0700433
Mike Nichols76573362018-05-08 20:11:53 -0600434 # Preliminary set, mostly command line parsing.
435 with metrics.SuccessCounter(METRIC_INVOKED, metrics_fields):
436 if options.enable_buildbot_tags:
437 logging.EnableBuildbotMarkers()
438 ConfigureGlobalEnvironment()
Don Garrett86881cb2017-02-15 15:41:55 -0800439
Mike Nichols76573362018-05-08 20:11:53 -0600440 # Prepare the buildroot with source for the build.
441 with metrics.SuccessCounter(METRIC_PREP, metrics_fields):
442 site_config = config_lib.GetConfig()
443 manifest_url = site_config.params['MANIFEST_INT_URL']
444 repo = repository.RepoRepository(manifest_url, buildroot,
445 branch=branchname,
446 git_cache_dir=options.git_cache_dir)
447 previous_build_state = GetLastBuildState(root)
Don Garrett86881cb2017-02-15 15:41:55 -0800448
Mike Nichols76573362018-05-08 20:11:53 -0600449 # Clean up the buildroot to a safe state.
450 with metrics.SecondsTimer(METRIC_CLEAN, fields=metrics_fields):
451 build_state = GetCurrentBuildState(options, branchname)
452 CleanBuildRoot(root, repo, metrics_fields, build_state)
Don Garrettacbb2392017-05-11 18:27:41 -0700453
Mike Nichols76573362018-05-08 20:11:53 -0600454 # Get a checkout close enough to the branch that cbuildbot can
455 # handle it.
456 if options.sync:
457 with metrics.SecondsTimer(METRIC_INITIAL, fields=metrics_fields):
458 InitialCheckout(repo)
Don Garrettacbb2392017-05-11 18:27:41 -0700459
Mike Nichols76573362018-05-08 20:11:53 -0600460 # Get a checkout close enough to the branch that cbuildbot can
461 # handle it.
462 with metrics.SecondsTimer(METRIC_DEPOT_TOOLS, fields=metrics_fields):
463 DepotToolsEnsureBootstrap(depot_tools_path)
Don Garrett066e6f52017-09-28 19:14:01 -0700464
Mike Nichols76573362018-05-08 20:11:53 -0600465 # Run cbuildbot inside the full ChromeOS checkout, on the
466 # specified branch.
467 with metrics.SecondsTimer(METRIC_CBUILDBOT, fields=metrics_fields):
468 if previous_build_state.is_valid():
469 argv.append('--previous-build-state')
470 argv.append(base64.b64encode(previous_build_state.to_json()))
Benjamin Gordon90b2dd92018-04-12 14:04:21 -0600471
Mike Nichols76573362018-05-08 20:11:53 -0600472 result = Cbuildbot(buildroot, depot_tools_path, argv)
473 s_fields['success'] = (result == 0)
Benjamin Gordon90b2dd92018-04-12 14:04:21 -0600474
Mike Nichols76573362018-05-08 20:11:53 -0600475 build_state.status = (
476 constants.BUILDER_STATUS_PASSED
477 if result == 0 else constants.BUILDER_STATUS_FAILED)
478 SetLastBuildState(root, build_state)
Benjamin Gordon90b2dd92018-04-12 14:04:21 -0600479
Mike Nichols76573362018-05-08 20:11:53 -0600480 CleanupChroot(buildroot)
481 return result
Don Garrettacbb2392017-05-11 18:27:41 -0700482
483def main(argv):
Mike Nichols76573362018-05-08 20:11:53 -0600484 return _main(argv)