blob: fde3949fa047d2ca52120525751b3b1746b84400 [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
Don Garrette17e1d92017-04-12 15:28:19 -070019import stat
Don Garrettc4114cc2016-11-01 20:04:06 -070020
21from chromite.cbuildbot import repository
Don Garrett597ddff2017-02-17 18:29:37 -080022from chromite.cbuildbot.stages import sync_stages
Don Garrett86881cb2017-02-15 15:41:55 -080023from chromite.lib import config_lib
Don Garrettc4114cc2016-11-01 20:04:06 -070024from chromite.lib import cros_build_lib
25from chromite.lib import cros_logging as logging
Don Garrettc4114cc2016-11-01 20:04:06 -070026from chromite.lib import osutils
Don Garrett86881cb2017-02-15 15:41:55 -080027from chromite.scripts import cbuildbot
Don Garrettc4114cc2016-11-01 20:04:06 -070028
Don Garrett597ddff2017-02-17 18:29:37 -080029
Don Garrett86881cb2017-02-15 15:41:55 -080030def PreParseArguments(argv):
Don Garrettc4114cc2016-11-01 20:04:06 -070031 """Extract the branch name from cbuildbot command line arguments.
32
33 Ignores all arguments, other than the branch name.
34
35 Args:
36 argv: The command line arguments to parse.
37
38 Returns:
39 Branch as a string ('master' if nothing is specified).
40 """
Don Garrett86881cb2017-02-15 15:41:55 -080041 parser = cbuildbot.CreateParser()
Don Garrett597ddff2017-02-17 18:29:37 -080042 options, args = cbuildbot.ParseCommandLine(parser, argv)
Don Garrett86881cb2017-02-15 15:41:55 -080043
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
Don Garrett597ddff2017-02-17 18:29:37 -080048 # Save off the build targets, in a mirror of cbuildbot code.
49 options.build_targets = args
50 options.Freeze()
51
Don Garrett86881cb2017-02-15 15:41:55 -080052 return options
Don Garrettc4114cc2016-11-01 20:04:06 -070053
54
Don Garrett7ade05a2017-02-17 13:31:47 -080055def CleanBuildroot(branchname, buildroot):
56 """Some kinds of branch transitions break builds.
57
58 This method tries to detect cases where that can happen, and clobber what's
59 needed to succeed. However, the clobbers are costly, and should be avoided
60 if necessary.
61
62 Currently, we only check to see if we are moving between branches, but
63 other checks can be added, as needed.
64
65 Args:
66 branchname: Name of branch to checkout. None for no branch.
67 buildroot: Directory with old buildroot to clean as needed.
68 """
69 # Cleanups to consider, in order of severity.
70 # 1) osutils.RmDir('chroot')
71 # 2) osutils.RmDir('.cache')
72 # 3) EmptyDir(buildroot, excludes=['.repo'])
Don Garrettf15d65b2017-04-12 12:39:55 -070073 # 4) rm -rf buildroot
Don Garrett7ade05a2017-02-17 13:31:47 -080074
Don Garrette17e1d92017-04-12 15:28:19 -070075 # TODO(dgarrett): Replace this block with fix for crbug.com/711048
76 try:
77 # Fix for bad checkouts from crbug.com/710900
78 st = os.stat(buildroot)
79 if not bool(st.st_mode & stat.S_IRGRP):
80 osutils.RmDir(buildroot, sudo=True)
81 except OSError:
82 # If the directory doesn't exist, the permissions will be okay.
83 pass
84
85 # Ensure buildroot exists.
86 osutils.SafeMakedirs(buildroot)
87
Don Garrett0c54ed72017-03-03 11:18:57 -080088 state_file = os.path.join(buildroot, '.cbuildbot_launch_state')
Don Garrett7ade05a2017-02-17 13:31:47 -080089 new_state = branchname or 'TOT'
90
91 try:
92 old_state = osutils.ReadFile(state_file)
93 except IOError:
94 old_state = None
95
96 if old_state != new_state:
97 # If we are changing branches, clobber the chroot. Note that this chroot
98 # clobber is unsafe if the chroot is in use, but since no build is in
99 # progress (and we don't use chroot the), this should be okay.
Don Garrett39963602017-02-27 14:41:58 -0800100 logging.info(
101 'Unmatched buildroot state, wipe chroot/Chrome Checkout: %s -> %s',
102 old_state, new_state)
103
104 # Wipe chroot.
Don Garrett7ade05a2017-02-17 13:31:47 -0800105 osutils.RmDir(os.path.join(buildroot, 'chroot'),
106 ignore_missing=True, sudo=True)
107
Don Garrett39963602017-02-27 14:41:58 -0800108 # Wipe Chrome build related files.
109 osutils.RmDir(os.path.join(buildroot, '.cache', 'distfiles'),
110 ignore_missing=True, sudo=True)
111
Don Garrett7ade05a2017-02-17 13:31:47 -0800112 # Finished!
113 osutils.WriteFile(state_file, new_state)
114
115
Don Garrett86881cb2017-02-15 15:41:55 -0800116def InitialCheckout(branchname, buildroot, git_cache_dir):
117 """Preliminary ChromeOS checkout.
118
119 Perform a complete checkout of ChromeOS on the specified branch. This does NOT
120 match what the build needs, but ensures the buildroot both has a 'hot'
121 checkout, and is close enough that the branched cbuildbot can successfully get
122 the right checkout.
123
124 This checks out full ChromeOS, even if a ChromiumOS build is going to be
125 performed. This is because we have no knowledge of the build config to be
126 used.
Don Garrettc4114cc2016-11-01 20:04:06 -0700127
128 Args:
Don Garrett86881cb2017-02-15 15:41:55 -0800129 branchname: Name of branch to checkout. None for no branch.
130 buildroot: Directory to checkout into.
131 git_cache_dir: Directory to use for git cache. None to not use it.
Don Garrettc4114cc2016-11-01 20:04:06 -0700132 """
Don Garrett7ade05a2017-02-17 13:31:47 -0800133 logging.info('Bootstrap script starting initial sync on branch: %s',
134 branchname)
135
Don Garrett86881cb2017-02-15 15:41:55 -0800136 site_config = config_lib.GetConfig()
137 manifest_url = site_config.params['MANIFEST_INT_URL']
Don Garrettc4114cc2016-11-01 20:04:06 -0700138
Don Garrett86881cb2017-02-15 15:41:55 -0800139 repo = repository.RepoRepository(manifest_url, buildroot,
140 branch=branchname,
141 git_cache_dir=git_cache_dir)
142 repo.Sync()
Don Garrettc4114cc2016-11-01 20:04:06 -0700143
144
Don Garrett597ddff2017-02-17 18:29:37 -0800145def RunCbuildbot(options):
Don Garrettc4114cc2016-11-01 20:04:06 -0700146 """Start cbuildbot in specified directory with all arguments.
147
148 Args:
Don Garrett597ddff2017-02-17 18:29:37 -0800149 options: Parse command line options.
Don Garrettc4114cc2016-11-01 20:04:06 -0700150
151 Returns:
152 Return code of cbuildbot as an integer.
153 """
Don Garrett597ddff2017-02-17 18:29:37 -0800154 logging.info('Bootstrap cbuildbot in: %s', options.buildroot)
155 cbuildbot_path = os.path.join(
156 options.buildroot, 'chromite', 'bin', 'cbuildbot')
157
158 cmd = sync_stages.BootstrapStage.FilterArgsForTargetCbuildbot(
159 options.buildroot, cbuildbot_path, options)
160
161 result = cros_build_lib.RunCommand(
162 cmd, error_code_ok=True, cwd=options.buildroot)
Don Garrettc4114cc2016-11-01 20:04:06 -0700163
164 logging.debug('cbuildbot result is: %s', result.returncode)
165 return result.returncode
166
Don Garrettf15d65b2017-04-12 12:39:55 -0700167def ConfigureGlobalEnvironment():
168 """Setup process wide environmental changes."""
Don Garrettf15d65b2017-04-12 12:39:55 -0700169 # Set umask to 022 so files created by buildbot are readable.
170 os.umask(0o22)
171
Don Garrettc4114cc2016-11-01 20:04:06 -0700172
173def main(argv):
174 """main method of script.
175
176 Args:
177 argv: All command line arguments to pass as list of strings.
178
179 Returns:
180 Return code of cbuildbot as an integer.
181 """
Don Garrettf15d65b2017-04-12 12:39:55 -0700182 ConfigureGlobalEnvironment()
183
Don Garrettc4114cc2016-11-01 20:04:06 -0700184 # Specified branch, or 'master'
Don Garrett86881cb2017-02-15 15:41:55 -0800185 options = PreParseArguments(argv)
Don Garrettc4114cc2016-11-01 20:04:06 -0700186
Don Garrett86881cb2017-02-15 15:41:55 -0800187 branchname = options.branch
188 buildroot = options.buildroot
189 git_cache_dir = options.git_cache_dir
190
Don Garrett7ade05a2017-02-17 13:31:47 -0800191 # Sometimes, we have to cleanup things that can break cbuildbot, especially
192 # on the branch.
193 CleanBuildroot(branchname, buildroot)
194
Don Garrett86881cb2017-02-15 15:41:55 -0800195 # Get a checkout close enough the branched cbuildbot can handle it.
196 InitialCheckout(branchname, buildroot, git_cache_dir)
197
198 # Run cbuildbot inside the full ChromeOS checkout, on the specified branch.
Don Garrett597ddff2017-02-17 18:29:37 -0800199 return RunCbuildbot(options)