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

Unified Diff: tools/bots/bot.py

Issue 11236012: Add script for pub buildbots. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Respond to review. Created 8 years, 2 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 side-by-side diff with in-line comments
Download patch
Index: tools/bots/bot.py
diff --git a/tools/bots/bot.py b/tools/bots/bot.py
new file mode 100644
index 0000000000000000000000000000000000000000..7d40ba4caf6f123f830cb14be491140467f72b35
--- /dev/null
+++ b/tools/bots/bot.py
@@ -0,0 +1,236 @@
+#!/usr/bin/python
+
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""
+Shared code for use in the buildbot scripts.
+"""
+
+import optparse
+import os
+from os.path import abspath
+from os.path import dirname
+import subprocess
+import sys
+
+DART_PATH = dirname(dirname(dirname(abspath(__file__))))
+
+NO_COLOR_ENV = dict(os.environ)
+NO_COLOR_ENV['TERM'] = 'nocolor'
+
+BUILDER_NAME = 'BUILDBOT_BUILDERNAME'
+BUILDER_CLOBBER = 'BUILDBOT_CLOBBER'
+
+
+class BuildInfo(object):
+ """
+ Encapsulation of build information.
+
+ - compiler: None, 'dart2dart', 'dart2js' or 'dartc'.
+ - runtime: 'd8', 'ie', 'ff', 'safari', 'chrome', 'opera', or None.
+ - mode: 'debug' or 'release'.
+ - system: 'linux', 'mac', or 'win7'.
+ - checked: True if we should run in checked mode, otherwise False.
+ - host_checked: True if we should run in host checked mode, otherwise False.
+ - shard_index: The shard we are running, None when not specified.
+ - total_shards: The total number of shards, None when not specified.
+ - is_buildbot: True if we are on a buildbot (or emulating it).
+ - test_set: Specification of a non standard test set or None.
+ """
+ def __init__(self, compiler, runtime, mode, system, checked=False,
+ host_checked=False, shard_index=None, total_shards=None,
+ is_buildbot=False, test_set=None):
+ self.compiler = compiler
+ self.runtime = runtime
+ self.mode = mode
+ self.system = system
+ self.checked = checked
+ self.host_checked = host_checked
+ self.shard_index = shard_index
+ self.total_shards = total_shards
+ self.is_buildbot = is_buildbot
+ self.test_set = test_set
+
+ def PrintBuildInfo(self):
+ shard_description = ""
+ if self.shard_index:
+ shard_description = " shard %s of %s" % (self.shard_index,
+ self.total_shards)
+ print ("compiler: %s, runtime: %s mode: %s, system: %s,"
+ " checked: %s, host-checked: %s, test-set: %s%s"
+ ) % (self.compiler, self.runtime, self.mode, self.system,
+ self.checked, self.host_checked, self.test_set,
+ shard_description)
+
+
+class BuildStep(object):
+ """
+ A context manager for handling build steps.
+
+ When the context manager is entered, it prints the "@@@BUILD_STEP __@@@"
+ message. If it exits from an error being raised it displays the
+ "@@@STEP_FAILURE@@@" message.
+
+ If swallow_error is True, then this will catch and discard any OSError that
+ is thrown. This lets you run later BuildSteps if the current one fails.
+ """
+ def __init__(self, name, swallow_error=False):
+ self.name = name
+ self.swallow_error = swallow_error
+
+ def __enter__(self):
+ print '@@@BUILD_STEP %s@@@' % self.name
+
+ def __exit__(self, type, value, traceback):
+ if value:
+ print '@@@STEP_FAILURE@@@'
+ if self.swallow_error and isinstance(value, OSError):
+ return True
+
+
+def RunBot(parse_name, custom_steps):
+ """
+ The main function for running a buildbot.
+
+ A buildbot script should invoke this once. The parse_name function will be
+ called with the name of the buildbot and should return an instance of
+ BuildInfo. This function will then set up the bot, build the SDK etc. When
+ that's done, it will call custom_steps, passing in the BuildInfo object.
+
+ In that, you can perform any bot-specific build steps.
+
+ This function will not return. It will call sys.exit() with an appropriate
+ exit code.
+ """
+ if len(sys.argv) == 0:
+ print 'Script pathname not known, giving up.'
+ sys.exit(1)
+
+ name, is_buildbot = GetBotName()
+ build_info = parse_name(name, is_buildbot)
+ if not build_info:
+ print 'Could not handle unfamiliar bot name "%s".' % name
+ sys.exit(1)
+
+ # Print out the buildinfo for easy debugging.
+ build_info.PrintBuildInfo()
+
+ # Make sure we are in the dart directory
+ os.chdir(DART_PATH)
+
+ try:
+ Clobber(build_info.mode)
+ BuildSDK(build_info.mode, build_info.system)
+
+ custom_steps(build_info)
+ except OSError as e:
+ sys.exit(e.errno)
+
+ sys.exit(0)
+
+
+def GetBotName():
+ """
+ Gets the name of the current buildbot.
+
+ Returns a tuple of the buildbot name and a flag to indicate if we are actually
+ a buildbot (True), or just a user pretending to be one (False).
+ """
+ # For testing the bot locally, allow the user to pass in a buildbot name.
+ parser = optparse.OptionParser()
+ parser.add_option('-n', '--name', dest='name', help='The name of the build'
+ 'bot you would like to emulate (ex: vm-mac-debug)', default=None)
+ args, _ = parser.parse_args()
+
+ if args.name:
+ return args.name, False
+
+ name = os.environ.get(BUILDER_NAME)
+ if not name:
+ print 'Use -n $BUILDBOT_NAME for the bot you would like to emulate.'
+ sys.exit(1)
+
+ return name, True
+
+
+def Clobber(mode):
+ """
+ Clobbers the builder before we do the build, if appropriate.
+
+ - mode: either 'debug' or 'release'
+ """
+ if os.environ.get(BUILDER_CLOBBER) != "1":
+ return
+
+ with BuildStep('Clobber'):
+ cmd = [sys.executable,
+ './tools/clean_output_directory.py',
+ '--mode=' + mode]
+ print 'Clobbering %s' % (' '.join(cmd))
+ RunProcess(cmd)
+
+
+def BuildSDK(mode, system):
+ """
+ Builds the SDK.
+
+ - mode: either 'debug' or 'release'
+ - system: either 'linux', 'mac', or 'win7'
+ """
+ with BuildStep('Build SDK'):
+ args = [sys.executable, './tools/build.py', '--mode=' + mode, 'create_sdk']
+ print 'Building SDK: %s' % (' '.join(args))
+ RunProcess(args)
+
+
+def RunTest(name, build_info, targets, flags=None):
+ """
+ Runs test.py with the given settings.
+ """
+ if not flags:
+ flags = []
+
+ step_name = GetStepName(name, flags)
+ with BuildStep(step_name):
+ sys.stdout.flush()
+
+ cmd = [
+ sys.executable, os.path.join(os.curdir, 'tools', 'test.py'),
+ '--step_name=' + step_name,
+ '--mode=' + build_info.mode,
+ '--compiler=' + build_info.compiler,
+ '--runtime=' + build_info.runtime,
+ '--progress=buildbot',
+ '-v', '--time', '--use-sdk', '--report'
+ ]
+
+ if build_info.checked:
+ cmd.append('--checked')
+
+ cmd.extend(flags)
+ cmd.extend(targets)
+
+ print 'Running: %s' % (' '.join(cmd))
+ RunProcess(cmd)
+
+
+def RunProcess(command):
+ """
+ Runs command.
+
+ If a non-zero exit code is returned, raises an OSError with errno as the exit
+ code.
+ """
+ exit_code = subprocess.call(command, env=NO_COLOR_ENV)
+ if exit_code != 0:
+ raise OSError(exit_code)
+
+
+def GetStepName(name, flags):
+ """
+ Filters out flags with '=' as this breaks the /stats feature of the buildbot.
+ """
+ flags = [x for x in flags if not '=' in x]
+ return ('%s tests %s' % (name, ' '.join(flags))).strip()

Powered by Google App Engine
This is Rietveld 408576698