Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(620)

Side by Side Diff: bin/cbuildbot.py

Issue 3200006: Add all pfq configurations and add build_image / run_unit_tests. (Closed) Base URL: http://src.chromium.org/git/crosutils.git
Patch Set: Fix typo in arm-generic Created 10 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | bin/cbuildbot_config.py » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 #!/usr/bin/python 1 #!/usr/bin/python
2 2
3 # Copyright (c) 2010 The Chromium OS Authors. All rights reserved. 3 # Copyright (c) 2010 The Chromium OS Authors. All rights reserved.
4 # Use of this source code is governed by a BSD-style license that can be 4 # Use of this source code is governed by a BSD-style license that can be
5 # found in the LICENSE file. 5 # found in the LICENSE file.
6 6
7 """CBuildbot is wrapper around the build process used by the pre-flight queue""" 7 """CBuildbot is wrapper around the build process used by the pre-flight queue"""
8 8
9 import errno 9 import errno
10 import re 10 import re
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
50 50
51 # Print out the command before running. 51 # Print out the command before running.
52 if print_cmd: 52 if print_cmd:
53 print >> sys.stderr, 'CBUILDBOT -- RunCommand: ', ' '.join(cmd) 53 print >> sys.stderr, 'CBUILDBOT -- RunCommand: ', ' '.join(cmd)
54 54
55 proc = subprocess.Popen(cmd, cwd=cwd, stdin=stdin, 55 proc = subprocess.Popen(cmd, cwd=cwd, stdin=stdin,
56 stdout=stdout, stderr=stderr) 56 stdout=stdout, stderr=stderr)
57 (output, error) = proc.communicate(input) 57 (output, error) = proc.communicate(input)
58 if exit_code: 58 if exit_code:
59 return proc.returncode 59 return proc.returncode
60
60 if not error_ok and proc.returncode != 0: 61 if not error_ok and proc.returncode != 0:
61 raise Exception('Command "%s" failed.\n' % (' '.join(cmd)) + 62 raise Exception('Command "%s" failed.\n' % (' '.join(cmd)) +
62 (error_message or error or output or '')) 63 (error_message or error or output or ''))
64
63 return output 65 return output
64 66
65 67
66 def MakeDir(path, parents=False): 68 def MakeDir(path, parents=False):
67 """Basic wrapper around os.mkdirs. 69 """Basic wrapper around os.mkdirs.
68 70
69 Keyword arguments: 71 Keyword arguments:
70 path -- Path to create. 72 path -- Path to create.
71 parents -- Follow mkdir -p logic. 73 parents -- Follow mkdir -p logic.
72 74
(...skipping 17 matching lines...) Expand all
90 """ 92 """
91 while retries > 0: 93 while retries > 0:
92 try: 94 try:
93 RunCommand(['repo', 'sync'], cwd=buildroot) 95 RunCommand(['repo', 'sync'], cwd=buildroot)
94 if rw_checkout: 96 if rw_checkout:
95 # Always re-run in case of new git repos or repo sync 97 # Always re-run in case of new git repos or repo sync
96 # failed in a previous run because of a forced Stop Build. 98 # failed in a previous run because of a forced Stop Build.
97 RunCommand(['repo', 'forall', '-c', 'git', 'config', 99 RunCommand(['repo', 'forall', '-c', 'git', 'config',
98 'url.ssh://git@gitrw.chromium.org:9222.pushinsteadof', 100 'url.ssh://git@gitrw.chromium.org:9222.pushinsteadof',
99 'http://git.chromium.org/git'], cwd=buildroot) 101 'http://git.chromium.org/git'], cwd=buildroot)
102
100 retries = 0 103 retries = 0
101 except: 104 except:
102 retries -= 1 105 retries -= 1
103 if retries > 0: 106 if retries > 0:
104 print >> sys.stderr, 'CBUILDBOT -- Repo Sync Failed, retrying' 107 print >> sys.stderr, 'CBUILDBOT -- Repo Sync Failed, retrying'
105 else: 108 else:
106 print >> sys.stderr, 'CBUILDBOT -- Retries exhausted' 109 print >> sys.stderr, 'CBUILDBOT -- Retries exhausted'
107 raise 110 raise
108 111
109 # =========================== Command Helpers ================================= 112 # =========================== Command Helpers =================================
(...skipping 13 matching lines...) Expand all
123 # Parse line using re to get tuple. 126 # Parse line using re to get tuple.
124 result_array = re.findall('.+name=\"([\w-]+)\".+path=\"(\S+)".+', output) 127 result_array = re.findall('.+name=\"([\w-]+)\".+path=\"(\S+)".+', output)
125 128
126 # Create the array. 129 # Create the array.
127 for result in result_array: 130 for result in result_array:
128 if len(result) != 2: 131 if len(result) != 2:
129 print >> sys.stderr, 'Found in correct xml object %s', result 132 print >> sys.stderr, 'Found in correct xml object %s', result
130 else: 133 else:
131 # Remove pre-pended src directory from manifest. 134 # Remove pre-pended src directory from manifest.
132 manifest_tuples.append([result[0], result[1].replace('src/', '')]) 135 manifest_tuples.append([result[0], result[1].replace('src/', '')])
136
133 return manifest_tuples 137 return manifest_tuples
134 138
135 139
136 def _GetCrosWorkOnSrcPath(buildroot, board, package, debug=False): 140 def _GetCrosWorkOnSrcPath(buildroot, board, package, debug=False):
137 """Returns ${CROS_WORKON_SRC_PATH} for given package.""" 141 """Returns ${CROS_WORKON_SRC_PATH} for given package."""
138 cwd = os.path.join(buildroot, 'src', 'scripts') 142 cwd = os.path.join(buildroot, 'src', 'scripts')
139 equery_cmd = ('equery-%s which %s' % (board, package)).split() 143 equery_cmd = ('equery-%s which %s' % (board, package)).split()
140 ebuild_path = RunCommand(equery_cmd, cwd=cwd, redirect_stdout=True, 144 ebuild_path = RunCommand(equery_cmd, cwd=cwd, redirect_stdout=True,
141 redirect_stderr=True, enter_chroot=True, 145 redirect_stderr=True, enter_chroot=True,
142 error_ok=True, print_cmd=debug) 146 error_ok=True, print_cmd=debug)
143 if ebuild_path: 147 if ebuild_path:
144 ebuild_cmd = ('ebuild-%s %s info' % (board, ebuild_path)).split() 148 ebuild_cmd = ('ebuild-%s %s info' % (board, ebuild_path)).split()
145 cros_workon_output = RunCommand(ebuild_cmd, cwd=cwd, 149 cros_workon_output = RunCommand(ebuild_cmd, cwd=cwd,
146 redirect_stdout=True, redirect_stderr=True, 150 redirect_stdout=True, redirect_stderr=True,
147 enter_chroot=True, print_cmd=debug) 151 enter_chroot=True, print_cmd=debug)
148 152
149 temp = re.findall('CROS_WORKON_SRCDIR="(\S+)"', cros_workon_output) 153 temp = re.findall('CROS_WORKON_SRCDIR="(\S+)"', cros_workon_output)
150 if temp: 154 if temp:
151 return temp[0] 155 return temp[0]
156
152 return None 157 return None
153 158
154 159
155 def _CreateRepoDictionary(buildroot, board, debug=False): 160 def _CreateRepoDictionary(buildroot, board, debug=False):
156 """Returns the repo->list_of_ebuilds dictionary.""" 161 """Returns the repo->list_of_ebuilds dictionary."""
157 repo_dictionary = {} 162 repo_dictionary = {}
158 manifest_tuples = _GetAllGitRepos(buildroot) 163 manifest_tuples = _GetAllGitRepos(buildroot)
159 print >> sys.stderr, 'Creating dictionary of git repos to portage packages ... ' 164 print >> sys.stderr, (
165 'Creating dictionary of git repos to portage packages ...')
160 166
161 cwd = os.path.join(buildroot, 'src', 'scripts') 167 cwd = os.path.join(buildroot, 'src', 'scripts')
162 get_all_workon_pkgs_cmd = './cros_workon list --all'.split() 168 get_all_workon_pkgs_cmd = './cros_workon list --all'.split()
163 packages = RunCommand(get_all_workon_pkgs_cmd, cwd=cwd, 169 packages = RunCommand(get_all_workon_pkgs_cmd, cwd=cwd,
164 redirect_stdout=True, redirect_stderr=True, 170 redirect_stdout=True, redirect_stderr=True,
165 enter_chroot=True, print_cmd=debug) 171 enter_chroot=True, print_cmd=debug)
166 for package in packages.split(): 172 for package in packages.split():
167 cros_workon_src_path = _GetCrosWorkOnSrcPath(buildroot, board, package) 173 cros_workon_src_path = _GetCrosWorkOnSrcPath(buildroot, board, package)
168 if cros_workon_src_path: 174 if cros_workon_src_path:
169 for tuple in manifest_tuples: 175 for tuple in manifest_tuples:
170 # This path tends to have the user's home_dir prepended to it. 176 # This path tends to have the user's home_dir prepended to it.
171 if cros_workon_src_path.endswith(tuple[1]): 177 if cros_workon_src_path.endswith(tuple[1]):
172 print >> sys.stderr, ('For %s found matching package %s' % 178 print >> sys.stderr, ('For %s found matching package %s' %
173 (tuple[0], package)) 179 (tuple[0], package))
174 if repo_dictionary.has_key(tuple[0]): 180 if repo_dictionary.has_key(tuple[0]):
175 repo_dictionary[tuple[0]] += [package] 181 repo_dictionary[tuple[0]] += [package]
176 else: 182 else:
177 repo_dictionary[tuple[0]] = [package] 183 repo_dictionary[tuple[0]] = [package]
184
178 return repo_dictionary 185 return repo_dictionary
179 186
180 187
181 def _ParseRevisionString(revision_string, repo_dictionary): 188 def _ParseRevisionString(revision_string, repo_dictionary):
182 """Parses the given revision_string into a revision dictionary. 189 """Parses the given revision_string into a revision dictionary.
183 190
184 Returns a list of tuples that contain [portage_package_name, commit_id] to 191 Returns a list of tuples that contain [portage_package_name, commit_id] to
185 update. 192 update.
186 193
187 Keyword arguments: 194 Keyword arguments:
188 revision_string -- revision_string with format 195 revision_string -- revision_string with format
189 'repo1.git@commit_1 repo2.git@commit2 ...'. 196 'repo1.git@commit_1 repo2.git@commit2 ...'.
190 repo_dictionary -- dictionary with git repository names as keys (w/out git) 197 repo_dictionary -- dictionary with git repository names as keys (w/out git)
191 to portage package names. 198 to portage package names.
192 199
193 """ 200 """
194 # Using a dictionary removes duplicates. 201 # Using a dictionary removes duplicates.
195 revisions = {} 202 revisions = {}
196 for revision in revision_string.split(): 203 for revision in revision_string.split():
197 # Format 'package@commit-id'. 204 # Format 'package@commit-id'.
198 revision_tuple = revision.split('@') 205 revision_tuple = revision.split('@')
199 if len(revision_tuple) != 2: 206 if len(revision_tuple) != 2:
200 print >> sys.stderr, 'Incorrectly formatted revision %s' % revision 207 print >> sys.stderr, 'Incorrectly formatted revision %s' % revision
208
201 repo_name = revision_tuple[0].replace('.git', '') 209 repo_name = revision_tuple[0].replace('.git', '')
202 # Might not have entry if no matching ebuild. 210 # Might not have entry if no matching ebuild.
203 if repo_dictionary.has_key(repo_name): 211 if repo_dictionary.has_key(repo_name):
204 # May be many corresponding packages to a given git repo e.g. kernel). 212 # May be many corresponding packages to a given git repo e.g. kernel).
205 for package in repo_dictionary[repo_name]: 213 for package in repo_dictionary[repo_name]:
206 revisions[package] = revision_tuple[1] 214 revisions[package] = revision_tuple[1]
215
207 return revisions.items() 216 return revisions.items()
208 217
209 218
210 def _UprevFromRevisionList(buildroot, revision_list): 219 def _UprevFromRevisionList(buildroot, revision_list):
211 """Uprevs based on revision list.""" 220 """Uprevs based on revision list."""
212 if not revision_list: 221 if not revision_list:
213 print >> sys.stderr, 'No packages found to uprev' 222 print >> sys.stderr, 'No packages found to uprev'
214 return 223 return
224
215 package_str = '' 225 package_str = ''
216 commit_str = '' 226 commit_str = ''
217 for package, revision in revision_list: 227 for package, revision in revision_list:
218 package_str += package + ' ' 228 package_str += package + ' '
219 commit_str += revision + ' ' 229 commit_str += revision + ' '
230
220 package_str = package_str.strip() 231 package_str = package_str.strip()
221 commit_str = commit_str.strip() 232 commit_str = commit_str.strip()
222 233
223 cwd = os.path.join(buildroot, 'src', 'scripts') 234 cwd = os.path.join(buildroot, 'src', 'scripts')
224 RunCommand(['./cros_mark_as_stable', 235 RunCommand(['./cros_mark_as_stable',
225 '--tracking_branch="cros/master"', 236 '--tracking_branch="cros/master"',
226 '--packages="%s"' % package_str, 237 '--packages="%s"' % package_str,
227 '--commit_ids="%s"' % commit_str, 238 '--commit_ids="%s"' % commit_str,
228 'commit'], 239 'commit'],
229 cwd=cwd, enter_chroot=True) 240 cwd=cwd, enter_chroot=True)
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
262 def _SetupBoard(buildroot, board='x86-generic'): 273 def _SetupBoard(buildroot, board='x86-generic'):
263 """Wrapper around setup_board.""" 274 """Wrapper around setup_board."""
264 cwd = os.path.join(buildroot, 'src', 'scripts') 275 cwd = os.path.join(buildroot, 'src', 'scripts')
265 RunCommand(['./setup_board', '--fast', '--default', '--board=%s' % board], 276 RunCommand(['./setup_board', '--fast', '--default', '--board=%s' % board],
266 cwd=cwd) 277 cwd=cwd)
267 278
268 279
269 def _Build(buildroot): 280 def _Build(buildroot):
270 """Wrapper around build_packages.""" 281 """Wrapper around build_packages."""
271 cwd = os.path.join(buildroot, 'src', 'scripts') 282 cwd = os.path.join(buildroot, 'src', 'scripts')
272 RunCommand(['./build_packages'], cwd=cwd) 283 RunCommand(['./build_packages'], cwd=cwd, enter_chroot=True)
284
285 def _BuildImage(buildroot):
286 cwd = os.path.join(buildroot, 'src', 'scripts')
287 RunCommand(['./build_image'], cwd=cwd)
288
289 def _RunUnitTests(buildroot):
290 cwd = os.path.join(buildroot, 'src', 'scripts')
291 RunCommand(['./cros_run_unit_tests'], cwd=cwd)
273 292
274 293
275 def _UprevPackages(buildroot, revisionfile, board): 294 def _UprevPackages(buildroot, revisionfile, board):
276 """Uprevs a package based on given revisionfile. 295 """Uprevs a package based on given revisionfile.
277 296
278 If revisionfile is set to None or does not resolve to an actual file, this 297 If revisionfile is set to None or does not resolve to an actual file, this
279 function will uprev all packages. 298 function will uprev all packages.
280 299
281 Keyword arguments: 300 Keyword arguments:
282 revisionfile -- string specifying a file that contains a list of revisions to 301 revisionfile -- string specifying a file that contains a list of revisions to
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
321 RunCommand(['./cros_mark_as_stable', '--srcroot=..', 340 RunCommand(['./cros_mark_as_stable', '--srcroot=..',
322 '--tracking_branch="cros/master"', 341 '--tracking_branch="cros/master"',
323 '--push_options', '--bypass-hooks -f', 'push'], 342 '--push_options', '--bypass-hooks -f', 'push'],
324 cwd=cwd) 343 cwd=cwd)
325 344
326 345
327 def _GetConfig(config_name): 346 def _GetConfig(config_name):
328 """Gets the configuration for the build""" 347 """Gets the configuration for the build"""
329 default = config['default'] 348 default = config['default']
330 buildconfig = {} 349 buildconfig = {}
331 if config.has_key(config_name): 350 if not config.has_key(config_name):
332 buildconfig = config[config_name] 351 print >> sys.stderr, 'Non-existent configuration specified.'
352 print >> sys.stderr, 'Please specify one of:'
353 config_names = config.keys()
354 config_names.sort()
355 for name in config_names:
356 print >> sys.stderr, ' %s' % name
357 sys.exit(1)
358
359 buildconfig = config[config_name]
360
333 for key in default.iterkeys(): 361 for key in default.iterkeys():
334 if not buildconfig.has_key(key): 362 if not buildconfig.has_key(key):
335 buildconfig[key] = default[key] 363 buildconfig[key] = default[key]
364
336 return buildconfig 365 return buildconfig
337 366
338 367
339 def main(): 368 def main():
340 # Parse options 369 # Parse options
341 usage = "usage: %prog [options] cbuildbot_config" 370 usage = "usage: %prog [options] cbuildbot_config"
342 parser = optparse.OptionParser(usage=usage) 371 parser = optparse.OptionParser(usage=usage)
343 parser.add_option('-r', '--buildroot', 372 parser.add_option('-r', '--buildroot',
344 help='root directory where build occurs', default=".") 373 help='root directory where build occurs', default=".")
345 parser.add_option('-n', '--buildnumber', 374 parser.add_option('-n', '--buildnumber',
346 help='build number', type='int', default=0) 375 help='build number', type='int', default=0)
347 parser.add_option('-f', '--revisionfile', 376 parser.add_option('-f', '--revisionfile',
348 help='file where new revisions are stored') 377 help='file where new revisions are stored')
349 parser.add_option('--noclobber', action='store_false', dest='clobber', 378 parser.add_option('--noclobber', action='store_false', dest='clobber',
350 default=True, 379 default=True,
351 help='Disables clobbering the buildroot on failure') 380 help='Disables clobbering the buildroot on failure')
352 (options, args) = parser.parse_args() 381 (options, args) = parser.parse_args()
353 382
354 buildroot = options.buildroot 383 buildroot = options.buildroot
355 revisionfile = options.revisionfile 384 revisionfile = options.revisionfile
356 clobber = options.clobber 385 clobber = options.clobber
357 386
358 if len(args) == 1: 387 if len(args) == 1:
359 buildconfig = _GetConfig(args[0]) 388 buildconfig = _GetConfig(args[0])
360 else: 389 else:
361 print >> sys.stderr, "Missing configuration description" 390 print >> sys.stderr, "Missing configuration description"
362 parser.print_usage() 391 parser.print_usage()
363 sys.exit(1) 392 sys.exit(1)
393
364 try: 394 try:
365 if not os.path.isdir(buildroot): 395 if not os.path.isdir(buildroot):
366 _FullCheckout(buildroot) 396 _FullCheckout(buildroot)
367 else: 397 else:
368 _IncrementalCheckout(buildroot) 398 _IncrementalCheckout(buildroot)
399
369 chroot_path = os.path.join(buildroot, 'chroot') 400 chroot_path = os.path.join(buildroot, 'chroot')
370 if not os.path.isdir(chroot_path): 401 if not os.path.isdir(chroot_path):
371 _MakeChroot(buildroot) 402 _MakeChroot(buildroot)
403
372 boardpath = os.path.join(chroot_path, 'build', buildconfig['board']) 404 boardpath = os.path.join(chroot_path, 'build', buildconfig['board'])
373 if not os.path.isdir(boardpath): 405 if not os.path.isdir(boardpath):
374 _SetupBoard(buildroot, board=buildconfig['board']) 406 _SetupBoard(buildroot, board=buildconfig['board'])
407
375 if buildconfig['uprev']: 408 if buildconfig['uprev']:
376 _UprevPackages(buildroot, revisionfile, board=buildconfig['board']) 409 _UprevPackages(buildroot, revisionfile, board=buildconfig['board'])
410
377 _Build(buildroot) 411 _Build(buildroot)
412 if buildconfig['unittests']:
413 _RunUnitTests(buildroot)
414
415 _BuildImage(buildroot)
378 if buildconfig['uprev']: 416 if buildconfig['uprev']:
379 if buildconfig['master']: 417 if buildconfig['master']:
380 # Master bot needs to check if the other slaves completed. 418 # Master bot needs to check if the other slaves completed.
381 if cbuildbot_comm.HaveSlavesCompleted(config): 419 if cbuildbot_comm.HaveSlavesCompleted(config):
382 _UprevPush(buildroot) 420 _UprevPush(buildroot)
383 _UprevCleanup(buildroot) 421 _UprevCleanup(buildroot)
384 else: 422 else:
385 # At least one of the slaves failed or we timed out. 423 # At least one of the slaves failed or we timed out.
386 _UprevCleanup(buildroot) 424 _UprevCleanup(buildroot)
387 sys.stderr('CBUILDBOT - One of the slaves has failed!!!') 425 sys.stderr('CBUILDBOT - One of the slaves has failed!!!')
388 sys.exit(1) 426 sys.exit(1)
389 else: 427 else:
390 # Publish my status to the master. 428 # Publish my status to the master if its expecting it.
391 cbuildbot_comm.PublishStatus(cbuildbot_comm.STATUS_BUILD_COMPLETE) 429 if buildconfig['important']:
430 cbuildbot_comm.PublishStatus(cbuildbot_comm.STATUS_BUILD_COMPLETE)
431
392 _UprevCleanup(buildroot) 432 _UprevCleanup(buildroot)
393 except: 433 except:
394 # Something went wrong, cleanup (being paranoid) for next build. 434 # Something went wrong, cleanup (being paranoid) for next build.
395 if clobber: 435 if clobber:
396 RunCommand(['sudo', 'rm', '-rf', buildroot], print_cmd=False) 436 RunCommand(['sudo', 'rm', '-rf', buildroot], print_cmd=False)
437
397 # Send failure to master bot. 438 # Send failure to master bot.
398 if not buildconfig['master']: 439 if not buildconfig['master'] and buildconfig['important']:
399 cbuildbot_comm.PublishStatus(cbuildbot_comm.STATUS_BUILD_FAILED) 440 cbuildbot_comm.PublishStatus(cbuildbot_comm.STATUS_BUILD_FAILED)
441
400 raise 442 raise
401 443
402 444
403 if __name__ == '__main__': 445 if __name__ == '__main__':
404 main() 446 main()
OLDNEW
« no previous file with comments | « no previous file | bin/cbuildbot_config.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698