blob: 97bb14f1d506c3a30d5649e8a35ddafc75a47ca1 [file] [log] [blame]
Don Garrettc4114cc2016-11-01 20:04:06 -07001# Copyright 2016 The Chromium OS Authors. All rights reserved.
2# Use of this source code is governed by a BSD-style license that can be
3# found in the LICENSE file.
4
5"""Bootstrap for cbuildbot.
6
7This script is intended to checkout chromite on the branch specified by -b or
8--branch (as normally accepted by cbuildbot), and then invoke cbuildbot. Most
9arguments are not parsed, only passed along. If a branch is not specified, this
10script will use 'master'.
11
12Among other things, this allows us to invoke build configs that exist on a given
13branch, but not on TOT.
14"""
15
16from __future__ import print_function
17
18import os
19
20from chromite.cbuildbot import repository
Don Garrett597ddff2017-02-17 18:29:37 -080021from chromite.cbuildbot.stages import sync_stages
Don Garrett86881cb2017-02-15 15:41:55 -080022from chromite.lib import config_lib
Don Garrettc4114cc2016-11-01 20:04:06 -070023from chromite.lib import cros_build_lib
24from chromite.lib import cros_logging as logging
Don Garrettc4114cc2016-11-01 20:04:06 -070025from chromite.lib import osutils
Don Garrett86881cb2017-02-15 15:41:55 -080026from chromite.scripts import cbuildbot
Don Garrettc4114cc2016-11-01 20:04:06 -070027
Don Garrett597ddff2017-02-17 18:29:37 -080028
Don Garrett86881cb2017-02-15 15:41:55 -080029def PreParseArguments(argv):
Don Garrettc4114cc2016-11-01 20:04:06 -070030 """Extract the branch name from cbuildbot command line arguments.
31
32 Ignores all arguments, other than the branch name.
33
34 Args:
35 argv: The command line arguments to parse.
36
37 Returns:
38 Branch as a string ('master' if nothing is specified).
39 """
Don Garrett86881cb2017-02-15 15:41:55 -080040 parser = cbuildbot.CreateParser()
Don Garrett597ddff2017-02-17 18:29:37 -080041 options, args = cbuildbot.ParseCommandLine(parser, argv)
Don Garrett86881cb2017-02-15 15:41:55 -080042
43 # This option isn't required for cbuildbot, but is for us.
44 if not options.buildroot:
45 cros_build_lib.Die('--buildroot is a required option.')
46
Don Garrett597ddff2017-02-17 18:29:37 -080047 # Save off the build targets, in a mirror of cbuildbot code.
48 options.build_targets = args
49 options.Freeze()
50
Don Garrett86881cb2017-02-15 15:41:55 -080051 return options
Don Garrettc4114cc2016-11-01 20:04:06 -070052
53
Don Garrett7ade05a2017-02-17 13:31:47 -080054def CleanBuildroot(branchname, buildroot):
55 """Some kinds of branch transitions break builds.
56
57 This method tries to detect cases where that can happen, and clobber what's
58 needed to succeed. However, the clobbers are costly, and should be avoided
59 if necessary.
60
61 Currently, we only check to see if we are moving between branches, but
62 other checks can be added, as needed.
63
64 Args:
65 branchname: Name of branch to checkout. None for no branch.
66 buildroot: Directory with old buildroot to clean as needed.
67 """
68 # Cleanups to consider, in order of severity.
69 # 1) osutils.RmDir('chroot')
70 # 2) osutils.RmDir('.cache')
71 # 3) EmptyDir(buildroot, excludes=['.repo'])
72 # 4) EmptyDir(buildroot)
73
Don Garrett0c54ed72017-03-03 11:18:57 -080074 state_file = os.path.join(buildroot, '.cbuildbot_launch_state')
Don Garrett7ade05a2017-02-17 13:31:47 -080075 new_state = branchname or 'TOT'
76
77 try:
78 old_state = osutils.ReadFile(state_file)
79 except IOError:
80 old_state = None
81
82 if old_state != new_state:
83 # If we are changing branches, clobber the chroot. Note that this chroot
84 # clobber is unsafe if the chroot is in use, but since no build is in
85 # progress (and we don't use chroot the), this should be okay.
Don Garrett39963602017-02-27 14:41:58 -080086 logging.info(
87 'Unmatched buildroot state, wipe chroot/Chrome Checkout: %s -> %s',
88 old_state, new_state)
89
90 # Wipe chroot.
Don Garrett7ade05a2017-02-17 13:31:47 -080091 osutils.RmDir(os.path.join(buildroot, 'chroot'),
92 ignore_missing=True, sudo=True)
93
Don Garrett39963602017-02-27 14:41:58 -080094 # Wipe Chrome build related files.
95 osutils.RmDir(os.path.join(buildroot, '.cache', 'distfiles'),
96 ignore_missing=True, sudo=True)
97
Don Garrett7ade05a2017-02-17 13:31:47 -080098 # Finished!
99 osutils.WriteFile(state_file, new_state)
100
101
Don Garrett86881cb2017-02-15 15:41:55 -0800102def InitialCheckout(branchname, buildroot, git_cache_dir):
103 """Preliminary ChromeOS checkout.
104
105 Perform a complete checkout of ChromeOS on the specified branch. This does NOT
106 match what the build needs, but ensures the buildroot both has a 'hot'
107 checkout, and is close enough that the branched cbuildbot can successfully get
108 the right checkout.
109
110 This checks out full ChromeOS, even if a ChromiumOS build is going to be
111 performed. This is because we have no knowledge of the build config to be
112 used.
Don Garrettc4114cc2016-11-01 20:04:06 -0700113
114 Args:
Don Garrett86881cb2017-02-15 15:41:55 -0800115 branchname: Name of branch to checkout. None for no branch.
116 buildroot: Directory to checkout into.
117 git_cache_dir: Directory to use for git cache. None to not use it.
Don Garrettc4114cc2016-11-01 20:04:06 -0700118 """
Don Garrett7ade05a2017-02-17 13:31:47 -0800119 logging.info('Bootstrap script starting initial sync on branch: %s',
120 branchname)
121
Don Garrett86881cb2017-02-15 15:41:55 -0800122 site_config = config_lib.GetConfig()
123 manifest_url = site_config.params['MANIFEST_INT_URL']
Don Garrettc4114cc2016-11-01 20:04:06 -0700124
Don Garrett86881cb2017-02-15 15:41:55 -0800125 repo = repository.RepoRepository(manifest_url, buildroot,
126 branch=branchname,
127 git_cache_dir=git_cache_dir)
128 repo.Sync()
Don Garrettc4114cc2016-11-01 20:04:06 -0700129
130
Don Garrett597ddff2017-02-17 18:29:37 -0800131def RunCbuildbot(options):
Don Garrettc4114cc2016-11-01 20:04:06 -0700132 """Start cbuildbot in specified directory with all arguments.
133
134 Args:
Don Garrett597ddff2017-02-17 18:29:37 -0800135 options: Parse command line options.
Don Garrettc4114cc2016-11-01 20:04:06 -0700136
137 Returns:
138 Return code of cbuildbot as an integer.
139 """
Don Garrett597ddff2017-02-17 18:29:37 -0800140 logging.info('Bootstrap cbuildbot in: %s', options.buildroot)
141 cbuildbot_path = os.path.join(
142 options.buildroot, 'chromite', 'bin', 'cbuildbot')
143
144 cmd = sync_stages.BootstrapStage.FilterArgsForTargetCbuildbot(
145 options.buildroot, cbuildbot_path, options)
146
147 result = cros_build_lib.RunCommand(
148 cmd, error_code_ok=True, cwd=options.buildroot)
Don Garrettc4114cc2016-11-01 20:04:06 -0700149
150 logging.debug('cbuildbot result is: %s', result.returncode)
151 return result.returncode
152
153
154def main(argv):
155 """main method of script.
156
157 Args:
158 argv: All command line arguments to pass as list of strings.
159
160 Returns:
161 Return code of cbuildbot as an integer.
162 """
163 # Specified branch, or 'master'
Don Garrett86881cb2017-02-15 15:41:55 -0800164 options = PreParseArguments(argv)
Don Garrettc4114cc2016-11-01 20:04:06 -0700165
Don Garrett86881cb2017-02-15 15:41:55 -0800166 branchname = options.branch
167 buildroot = options.buildroot
168 git_cache_dir = options.git_cache_dir
169
Don Garrett7ade05a2017-02-17 13:31:47 -0800170 # Ensure buildroot exists.
171 osutils.SafeMakedirs(buildroot)
172
173 # Sometimes, we have to cleanup things that can break cbuildbot, especially
174 # on the branch.
175 CleanBuildroot(branchname, buildroot)
176
Don Garrett86881cb2017-02-15 15:41:55 -0800177 # Get a checkout close enough the branched cbuildbot can handle it.
178 InitialCheckout(branchname, buildroot, git_cache_dir)
179
180 # Run cbuildbot inside the full ChromeOS checkout, on the specified branch.
Don Garrett597ddff2017-02-17 18:29:37 -0800181 return RunCbuildbot(options)