blob: 34a3aba50f0b6af3f5f7f7d2c9a35ba56c56ec9f [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
74 state_file = os.path.join(buildroot, '.bootstrap_state')
75 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.
86 logging.info('Unmatched buildroot state, wipe chroot: %s -> %s',
87 old_state, new_state)
88 osutils.RmDir(os.path.join(buildroot, 'chroot'),
89 ignore_missing=True, sudo=True)
90
91 # Finished!
92 osutils.WriteFile(state_file, new_state)
93
94
Don Garrett86881cb2017-02-15 15:41:55 -080095def InitialCheckout(branchname, buildroot, git_cache_dir):
96 """Preliminary ChromeOS checkout.
97
98 Perform a complete checkout of ChromeOS on the specified branch. This does NOT
99 match what the build needs, but ensures the buildroot both has a 'hot'
100 checkout, and is close enough that the branched cbuildbot can successfully get
101 the right checkout.
102
103 This checks out full ChromeOS, even if a ChromiumOS build is going to be
104 performed. This is because we have no knowledge of the build config to be
105 used.
Don Garrettc4114cc2016-11-01 20:04:06 -0700106
107 Args:
Don Garrett86881cb2017-02-15 15:41:55 -0800108 branchname: Name of branch to checkout. None for no branch.
109 buildroot: Directory to checkout into.
110 git_cache_dir: Directory to use for git cache. None to not use it.
Don Garrettc4114cc2016-11-01 20:04:06 -0700111 """
Don Garrett7ade05a2017-02-17 13:31:47 -0800112 logging.info('Bootstrap script starting initial sync on branch: %s',
113 branchname)
114
Don Garrett86881cb2017-02-15 15:41:55 -0800115 site_config = config_lib.GetConfig()
116 manifest_url = site_config.params['MANIFEST_INT_URL']
Don Garrettc4114cc2016-11-01 20:04:06 -0700117
Don Garrett86881cb2017-02-15 15:41:55 -0800118 repo = repository.RepoRepository(manifest_url, buildroot,
119 branch=branchname,
120 git_cache_dir=git_cache_dir)
121 repo.Sync()
Don Garrettc4114cc2016-11-01 20:04:06 -0700122
123
Don Garrett597ddff2017-02-17 18:29:37 -0800124def RunCbuildbot(options):
Don Garrettc4114cc2016-11-01 20:04:06 -0700125 """Start cbuildbot in specified directory with all arguments.
126
127 Args:
Don Garrett597ddff2017-02-17 18:29:37 -0800128 options: Parse command line options.
Don Garrettc4114cc2016-11-01 20:04:06 -0700129
130 Returns:
131 Return code of cbuildbot as an integer.
132 """
Don Garrett597ddff2017-02-17 18:29:37 -0800133 logging.info('Bootstrap cbuildbot in: %s', options.buildroot)
134 cbuildbot_path = os.path.join(
135 options.buildroot, 'chromite', 'bin', 'cbuildbot')
136
137 cmd = sync_stages.BootstrapStage.FilterArgsForTargetCbuildbot(
138 options.buildroot, cbuildbot_path, options)
139
140 result = cros_build_lib.RunCommand(
141 cmd, error_code_ok=True, cwd=options.buildroot)
Don Garrettc4114cc2016-11-01 20:04:06 -0700142
143 logging.debug('cbuildbot result is: %s', result.returncode)
144 return result.returncode
145
146
147def main(argv):
148 """main method of script.
149
150 Args:
151 argv: All command line arguments to pass as list of strings.
152
153 Returns:
154 Return code of cbuildbot as an integer.
155 """
156 # Specified branch, or 'master'
Don Garrett86881cb2017-02-15 15:41:55 -0800157 options = PreParseArguments(argv)
Don Garrettc4114cc2016-11-01 20:04:06 -0700158
Don Garrett86881cb2017-02-15 15:41:55 -0800159 branchname = options.branch
160 buildroot = options.buildroot
161 git_cache_dir = options.git_cache_dir
162
Don Garrett7ade05a2017-02-17 13:31:47 -0800163 # Ensure buildroot exists.
164 osutils.SafeMakedirs(buildroot)
165
166 # Sometimes, we have to cleanup things that can break cbuildbot, especially
167 # on the branch.
168 CleanBuildroot(branchname, buildroot)
169
Don Garrett86881cb2017-02-15 15:41:55 -0800170 # Get a checkout close enough the branched cbuildbot can handle it.
171 InitialCheckout(branchname, buildroot, git_cache_dir)
172
173 # Run cbuildbot inside the full ChromeOS checkout, on the specified branch.
Don Garrett597ddff2017-02-17 18:29:37 -0800174 return RunCbuildbot(options)