blob: b828570acfe88c48e3e7531700a299e1b89a6094 [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 Garrett86881cb2017-02-15 15:41:55 -080021from chromite.lib import config_lib
Don Garrettc4114cc2016-11-01 20:04:06 -070022from chromite.lib import cros_build_lib
23from chromite.lib import cros_logging as logging
Don Garrettc4114cc2016-11-01 20:04:06 -070024from chromite.lib import osutils
Don Garrett86881cb2017-02-15 15:41:55 -080025from chromite.scripts import cbuildbot
Don Garrettc4114cc2016-11-01 20:04:06 -070026
Don Garrett86881cb2017-02-15 15:41:55 -080027def PreParseArguments(argv):
Don Garrettc4114cc2016-11-01 20:04:06 -070028 """Extract the branch name from cbuildbot command line arguments.
29
30 Ignores all arguments, other than the branch name.
31
32 Args:
33 argv: The command line arguments to parse.
34
35 Returns:
36 Branch as a string ('master' if nothing is specified).
37 """
38 # Must match cbuildbot._CreateParser().
Don Garrett86881cb2017-02-15 15:41:55 -080039 parser = cbuildbot.CreateParser()
Don Garrettc4114cc2016-11-01 20:04:06 -070040
41 # Extract the branch argument, if present, ignore the rest.
Don Garrett86881cb2017-02-15 15:41:55 -080042 options, _ = parser.parse_args(argv)
43
44 # This option isn't required for cbuildbot, but is for us.
45 if not options.buildroot:
46 cros_build_lib.Die('--buildroot is a required option.')
47
48 return options
Don Garrettc4114cc2016-11-01 20:04:06 -070049
50
Don Garrett7ade05a2017-02-17 13:31:47 -080051def CleanBuildroot(branchname, buildroot):
52 """Some kinds of branch transitions break builds.
53
54 This method tries to detect cases where that can happen, and clobber what's
55 needed to succeed. However, the clobbers are costly, and should be avoided
56 if necessary.
57
58 Currently, we only check to see if we are moving between branches, but
59 other checks can be added, as needed.
60
61 Args:
62 branchname: Name of branch to checkout. None for no branch.
63 buildroot: Directory with old buildroot to clean as needed.
64 """
65 # Cleanups to consider, in order of severity.
66 # 1) osutils.RmDir('chroot')
67 # 2) osutils.RmDir('.cache')
68 # 3) EmptyDir(buildroot, excludes=['.repo'])
69 # 4) EmptyDir(buildroot)
70
71 state_file = os.path.join(buildroot, '.bootstrap_state')
72 new_state = branchname or 'TOT'
73
74 try:
75 old_state = osutils.ReadFile(state_file)
76 except IOError:
77 old_state = None
78
79 if old_state != new_state:
80 # If we are changing branches, clobber the chroot. Note that this chroot
81 # clobber is unsafe if the chroot is in use, but since no build is in
82 # progress (and we don't use chroot the), this should be okay.
83 logging.info('Unmatched buildroot state, wipe chroot: %s -> %s',
84 old_state, new_state)
85 osutils.RmDir(os.path.join(buildroot, 'chroot'),
86 ignore_missing=True, sudo=True)
87
88 # Finished!
89 osutils.WriteFile(state_file, new_state)
90
91
Don Garrett86881cb2017-02-15 15:41:55 -080092def InitialCheckout(branchname, buildroot, git_cache_dir):
93 """Preliminary ChromeOS checkout.
94
95 Perform a complete checkout of ChromeOS on the specified branch. This does NOT
96 match what the build needs, but ensures the buildroot both has a 'hot'
97 checkout, and is close enough that the branched cbuildbot can successfully get
98 the right checkout.
99
100 This checks out full ChromeOS, even if a ChromiumOS build is going to be
101 performed. This is because we have no knowledge of the build config to be
102 used.
Don Garrettc4114cc2016-11-01 20:04:06 -0700103
104 Args:
Don Garrett86881cb2017-02-15 15:41:55 -0800105 branchname: Name of branch to checkout. None for no branch.
106 buildroot: Directory to checkout into.
107 git_cache_dir: Directory to use for git cache. None to not use it.
Don Garrettc4114cc2016-11-01 20:04:06 -0700108 """
Don Garrett7ade05a2017-02-17 13:31:47 -0800109 logging.info('Bootstrap script starting initial sync on branch: %s',
110 branchname)
111
Don Garrett86881cb2017-02-15 15:41:55 -0800112 site_config = config_lib.GetConfig()
113 manifest_url = site_config.params['MANIFEST_INT_URL']
Don Garrettc4114cc2016-11-01 20:04:06 -0700114
Don Garrett86881cb2017-02-15 15:41:55 -0800115 repo = repository.RepoRepository(manifest_url, buildroot,
116 branch=branchname,
117 git_cache_dir=git_cache_dir)
118 repo.Sync()
Don Garrettc4114cc2016-11-01 20:04:06 -0700119
120
Don Garrett86881cb2017-02-15 15:41:55 -0800121def RunCbuildbot(buildroot, argv):
Don Garrettc4114cc2016-11-01 20:04:06 -0700122 """Start cbuildbot in specified directory with all arguments.
123
124 Args:
Don Garrett86881cb2017-02-15 15:41:55 -0800125 buildroot: Root of ChromeOS checkout to run cbuildbot in.
Don Garrettc4114cc2016-11-01 20:04:06 -0700126 argv: All command line arguments to pass as list of strings.
127
128 Returns:
129 Return code of cbuildbot as an integer.
130 """
Don Garrett86881cb2017-02-15 15:41:55 -0800131 logging.info('Bootstrap cbuildbot in: %s', buildroot)
132 cbuildbot_cmd = os.path.join(buildroot, 'chromite', 'bin', 'cbuildbot')
133 result = cros_build_lib.RunCommand([cbuildbot_cmd] + argv,
Don Garrettc4114cc2016-11-01 20:04:06 -0700134 error_code_ok=True,
Don Garrett86881cb2017-02-15 15:41:55 -0800135 cwd=buildroot)
Don Garrettc4114cc2016-11-01 20:04:06 -0700136
137 logging.debug('cbuildbot result is: %s', result.returncode)
138 return result.returncode
139
140
141def main(argv):
142 """main method of script.
143
144 Args:
145 argv: All command line arguments to pass as list of strings.
146
147 Returns:
148 Return code of cbuildbot as an integer.
149 """
150 # Specified branch, or 'master'
Don Garrett86881cb2017-02-15 15:41:55 -0800151 options = PreParseArguments(argv)
Don Garrettc4114cc2016-11-01 20:04:06 -0700152
Don Garrett86881cb2017-02-15 15:41:55 -0800153 branchname = options.branch
154 buildroot = options.buildroot
155 git_cache_dir = options.git_cache_dir
156
Don Garrett7ade05a2017-02-17 13:31:47 -0800157 # Ensure buildroot exists.
158 osutils.SafeMakedirs(buildroot)
159
160 # Sometimes, we have to cleanup things that can break cbuildbot, especially
161 # on the branch.
162 CleanBuildroot(branchname, buildroot)
163
Don Garrett86881cb2017-02-15 15:41:55 -0800164 # Get a checkout close enough the branched cbuildbot can handle it.
165 InitialCheckout(branchname, buildroot, git_cache_dir)
166
167 # Run cbuildbot inside the full ChromeOS checkout, on the specified branch.
168 RunCbuildbot(buildroot, argv)