blob: 14cba0bf717fbe7fc07d3b37b021dcd5741230ea [file] [log] [blame]
#!/usr/bin/python
# Copyright (c) 2011 The Chromium OS Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
"""Main builder code for Chromium OS.
Used by Chromium OS buildbot configuration for all Chromium OS builds including
full and pre-flight-queue builds.
"""
import errno
import optparse
import os
import sys
import traceback
if __name__ == '__main__':
import constants
sys.path.append(constants.SOURCE_ROOT)
import chromite.buildbot.cbuildbot_comm as cbuildbot_comm
import chromite.buildbot.cbuildbot_config as cbuildbot_config
import chromite.buildbot.cbuildbot_stages as stages
import chromite.lib.cros_build_lib as cros_lib
def _GetConfig(config_name):
"""Gets the configuration for the build"""
build_config = {}
if not cbuildbot_config.config.has_key(config_name):
Warning('Non-existent configuration specified.')
Warning('Please specify one of:')
config_names = config.keys()
config_names.sort()
for name in config_names:
Warning(' %s' % name)
sys.exit(1)
return cbuildbot_config.config[config_name]
def RunBuildStages(bot_id, options, build_config):
"""Run the requested build stages."""
try:
if options.sync:
stages.SyncStage(bot_id, options, build_config).Run()
if options.build:
stages.BuildBoardStage(bot_id, options, build_config).Run()
if options.uprev:
stages.UprevStage(bot_id, options, build_config).Run()
if options.build:
stages.BuildTargetStage(bot_id, options, build_config).Run()
# TODO(sosa): We only want to archive artifacts if we have artifacts to
# archive. Today this means we have at least built an image. We should
# make this more general and have dependencies within stages themselves ...
# i.e. archive -> build_target ... however someday it might be
# archive->sync.
try:
if options.tests:
stages.TestStage(bot_id, options, build_config).Run()
# Control master / slave logic here.
if build_config['master']:
if cbuildbot_comm.HaveSlavesCompleted(cbuildbot_config.config):
stages.PushChangesStage(bot_id, options, build_config).Run()
else:
cros_lib.Die('One of the other slaves failed.')
elif build_config['important']:
cbuildbot_comm.PublishStatus(cbuildbot_comm.STATUS_BUILD_COMPLETE)
finally:
if options.archive:
stages.ArchiveStage(bot_id, options, build_config).Run()
cros_lib.Info('BUILD ARTIFACTS FOR THIS BUILD CAN BE FOUND AT:')
cros_lib.Info(stages.BuilderStage.archive_url)
except:
# Send failure to master.
if not build_config['master'] and build_config['important']:
cbuildbot_comm.PublishStatus(cbuildbot_comm.STATUS_BUILD_FAILED)
raise
def RunEverything(bot_id, options, build_config):
"""Pull out the meat of main() in a unittest friendly manner"""
completed_stages_file = os.path.join(options.buildroot, '.completed_stages')
if options.resume and os.path.exists(completed_stages_file):
with open(completed_stages_file, 'r') as load_file:
stages.BuilderStage.Results.RestoreCompletedStages(load_file)
try:
RunBuildStages(bot_id, options, build_config)
except Exception as e:
traceback.print_exc()
print '\n'
print '\n'
# Made sure cbuildbot returns an error exit code if we are failing.
sys.exit(1)
finally:
stages.BuilderStage.Results.Report(sys.stdout)
# An error here can override sys.exit, but we'll get a stacktrace
# and error out anyway
with open(completed_stages_file, 'w+') as save_file:
stages.BuilderStage.Results.SaveCompletedStages(save_file)
def main():
# Parse options
usage = "usage: %prog [options] cbuildbot_config"
parser = optparse.OptionParser(usage=usage)
parser.add_option('-a', '--acl', default='private',
help='ACL to set on GSD archives')
parser.add_option('--buildbot', action='store_true', default=False,
help='This is running on a buildbot')
parser.add_option('-r', '--buildroot',
help='root directory where build occurs', default=".")
parser.add_option('-n', '--buildnumber',
help='build number', type='int', default=0)
parser.add_option('--chrome_rev', default=None, type='string',
dest='chrome_rev',
help=('Chrome_rev of type [tot|latest_release|'
'sticky_release]'))
parser.add_option('-g', '--gsutil', default='', help='Location of gsutil')
parser.add_option('-c', '--gsutil_archive', default='',
help='Datastore archive location')
parser.add_option('--clobber', action='store_true', dest='clobber',
default=False,
help='Clobbers an old checkout before syncing')
parser.add_option('--debug', action='store_true', dest='debug',
default=False,
help='Override some options to run as a developer.')
parser.add_option('--noarchive', action='store_false', dest='archive',
default=True,
help="Don't run archive stage.")
parser.add_option('--nobuild', action='store_false', dest='build',
default=True,
help="Don't actually build (for cbuildbot dev")
parser.add_option('--noprebuilts', action='store_false', dest='prebuilts',
default=True,
help="Don't upload prebuilts.")
parser.add_option('--nosync', action='store_false', dest='sync',
default=True,
help="Don't sync before building.")
parser.add_option('--notests', action='store_false', dest='tests',
default=True,
help='Override values from buildconfig and run no tests.')
parser.add_option('--resume', action='store_true',
default=False,
help='Skip stages already successfully completed.')
parser.add_option('-f', '--revisionfile',
help='file where new revisions are stored')
parser.add_option('-t', '--tracking-branch', dest='tracking_branch',
default='cros/master', help='Run the buildbot on a branch')
parser.add_option('--nouprev', action='store_false', dest='uprev',
default=True,
help='Override values from buildconfig and never uprev.')
parser.add_option('-u', '--url', dest='url',
default='http://git.chromium.org/git/manifest',
help='Run the buildbot on internal manifest')
(options, args) = parser.parse_args()
if len(args) >= 1:
bot_id = args[-1]
build_config = _GetConfig(bot_id)
else:
parser.error('Invalid usage. Use -h to see usage.')
RunEverything(bot_id, options, build_config)
if __name__ == '__main__':
main()