Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 1 #!/usr/bin/python | |
| 2 | |
| 3 # Copyright (c) 2012 The Chromium Authors. All rights reserved. | |
| 4 # Use of this source code is governed by a BSD-style license that can be | |
| 5 # found in the LICENSE file. | |
| 6 | |
| 7 """ | |
| 8 Shared code for use in the buildbot scripts. | |
| 9 """ | |
| 10 | |
| 11 import optparse | |
| 12 import os | |
| 13 from os.path import abspath | |
| 14 from os.path import dirname | |
| 15 import subprocess | |
| 16 import sys | |
| 17 | |
| 18 DART_PATH = dirname(dirname(dirname(abspath(__file__)))) | |
| 19 | |
| 20 NO_COLOR_ENV = dict(os.environ) | |
| 21 NO_COLOR_ENV['TERM'] = 'nocolor' | |
| 22 | |
| 23 BUILDER_NAME = 'BUILDBOT_BUILDERNAME' | |
| 24 BUILDER_CLOBBER = 'BUILDBOT_CLOBBER' | |
| 25 | |
| 26 | |
| 27 class BuildInfo(object): | |
| 28 """ | |
| 29 Encapsulation of build information. | |
| 30 | |
| 31 - compiler: 'dart2js' or None when the builder has an incorrect name | |
|
Emily Fortuna
2012/10/23 23:09:49
Some of these comments should be updated if this i
Bob Nystrom
2012/10/24 00:46:44
Good catch. Done.
| |
| 32 - runtime: 'd8', 'ie', 'ff', 'safari', 'chrome', 'opera' | |
| 33 - mode: 'debug' or 'release' | |
| 34 - system: 'linux', 'mac', or 'win7' | |
| 35 - checked: True if we should run in checked mode, otherwise False | |
| 36 - host_checked: True if we should run in host checked mode, otherwise False | |
| 37 - shard_index: The shard we are running, None when not specified. | |
| 38 - total_shards: The total number of shards, None when not specified. | |
| 39 - is_buildbot: True if we are on a buildbot (or emulating it). | |
| 40 - test_set: Specification of a non standard test set, default None | |
| 41 """ | |
| 42 def __init__(self, compiler, runtime, mode, system, checked=False, | |
| 43 host_checked=False, shard_index=None, total_shards=None, | |
| 44 is_buildbot=False, test_set=None): | |
| 45 self.compiler = compiler | |
| 46 self.runtime = runtime | |
| 47 self.mode = mode | |
| 48 self.system = system | |
| 49 self.checked = checked | |
| 50 self.host_checked = host_checked | |
| 51 self.shard_index = shard_index | |
| 52 self.total_shards = total_shards | |
| 53 self.is_buildbot = is_buildbot | |
| 54 self.test_set = test_set | |
| 55 | |
| 56 def PrintBuildInfo(self): | |
| 57 shard_description = "" | |
| 58 if self.shard_index: | |
| 59 shard_description = " shard %s of %s" % (self.shard_index, | |
| 60 self.total_shards) | |
| 61 print ("compiler: %s, runtime: %s mode: %s, system: %s," | |
| 62 " checked: %s, host-checked: %s, test-set: %s%s" | |
| 63 ) % (self.compiler, self.runtime, self.mode, self.system, | |
| 64 self.checked, self.host_checked, self.test_set, | |
| 65 shard_description) | |
| 66 | |
| 67 | |
| 68 class BuildStep(object): | |
| 69 """ | |
| 70 A context manager for handling build steps. | |
| 71 | |
| 72 When the context manager is entered, it prints the "@@@BUILD_STEP __@@@" | |
| 73 message. If it exits from an error being raised it displays the | |
| 74 "@@@STEP_FAILURE@@@" message. | |
| 75 """ | |
| 76 def __init__(self, name): | |
| 77 self.name = name | |
| 78 | |
| 79 def __enter__(self): | |
| 80 print '@@@BUILD_STEP %s@@@' % self.name | |
| 81 | |
| 82 def __exit__(self, type, value, traceback): | |
| 83 if value: | |
| 84 print '@@@STEP_FAILURE@@@' | |
| 85 | |
| 86 | |
| 87 def RunBot(parse_name, custom_steps): | |
| 88 """ | |
| 89 The main function for running a buildbot. | |
| 90 | |
| 91 A buildbot script should invoke this once. The parse_name function will be | |
| 92 called with the name of the buildbot and should return an instance of | |
| 93 BuildInfo. This function will then set up the bot, build the SDK etc. When | |
| 94 that's done, it will call custom_steps, passing in the BuildInfo object. | |
| 95 | |
| 96 In that, you can perform any bot-specific build steps. | |
| 97 | |
| 98 This function will not return. It will call sys.exit() with an appropriate | |
| 99 exit code. | |
| 100 """ | |
| 101 if len(sys.argv) == 0: | |
| 102 print 'Script pathname not known, giving up.' | |
| 103 sys.exit(1) | |
| 104 | |
| 105 name = GetBotName() | |
| 106 build_info = parse_name(name) | |
| 107 if not build_info: | |
| 108 print 'Could not handle unfamiliar bot name "%s".' % name | |
| 109 sys.exit(1) | |
| 110 | |
| 111 # Make sure we are in the dart directory | |
| 112 os.chdir(DART_PATH) | |
| 113 | |
| 114 try: | |
| 115 Clobber(build_info.mode) | |
| 116 BuildSDK(build_info.mode, build_info.system) | |
| 117 | |
| 118 custom_steps(build_info) | |
| 119 except OSError as e: | |
| 120 sys.exit(e.errno) | |
| 121 | |
| 122 sys.exit(0) | |
| 123 | |
| 124 | |
| 125 def GetBotName(): | |
| 126 """ | |
| 127 Gets the name of the current buildbot. | |
| 128 """ | |
| 129 # For testing the bot locally, allow the user to pass in a buildbot name. | |
| 130 parser = optparse.OptionParser() | |
| 131 parser.add_option('-n', '--name', dest='name', help='The name of the build' | |
| 132 'bot you would like to emulate (ex: vm-mac-debug)', default=None) | |
| 133 args, _ = parser.parse_args() | |
| 134 | |
| 135 if args.name: | |
| 136 return args.name | |
| 137 | |
| 138 name = os.environ.get(BUILDER_NAME) | |
| 139 if not name: | |
| 140 print 'Use -n $BUILDBOT_NAME for the bot you would like to emulate.' | |
| 141 sys.exit(1) | |
| 142 | |
| 143 return name | |
| 144 | |
| 145 | |
| 146 def Clobber(mode): | |
| 147 """ | |
| 148 Clobbers the builder before we do the build, if appropriate. | |
| 149 | |
| 150 - mode: either 'debug' or 'release' | |
| 151 """ | |
| 152 if os.environ.get(BUILDER_CLOBBER) != "1": | |
| 153 return | |
| 154 | |
| 155 with BuildStep('Clobber'): | |
| 156 cmd = [sys.executable, | |
| 157 './tools/clean_output_directory.py', | |
| 158 '--mode=' + mode] | |
| 159 print 'Clobbering %s' % (' '.join(cmd)) | |
| 160 RunProcess(cmd) | |
| 161 | |
| 162 | |
| 163 def BuildSDK(mode, system): | |
| 164 """ | |
| 165 Builds the SDK. | |
| 166 | |
| 167 - mode: either 'debug' or 'release' | |
| 168 - system: either 'linux', 'mac', or 'win7' | |
| 169 """ | |
| 170 with BuildStep('Build SDK'): | |
| 171 args = [sys.executable, './tools/build.py', '--mode=' + mode, 'create_sdk'] | |
| 172 print 'Building SDK: %s' % (' '.join(args)) | |
| 173 RunProcess(args) | |
| 174 | |
| 175 | |
| 176 def RunTest(name, build_info, targets, flags=None): | |
| 177 """ | |
| 178 Runs test.py with the given settings. | |
| 179 """ | |
| 180 if not flags: | |
| 181 flags = [] | |
| 182 | |
| 183 step_name = GetStepName(name, flags) | |
| 184 with BuildStep(step_name): | |
| 185 sys.stdout.flush() | |
| 186 | |
| 187 cmd = [ | |
| 188 sys.executable, os.path.join(os.curdir, 'tools', 'test.py'), | |
| 189 '--step_name=' + step_name, | |
| 190 '--mode=' + build_info.mode, | |
| 191 '--compiler=' + build_info.compiler, | |
| 192 '--runtime=' + build_info.runtime, | |
| 193 '--progress=buildbot', | |
| 194 '-v', '--time', '--use-sdk', '--report' | |
| 195 ] | |
| 196 | |
| 197 if build_info.checked: | |
| 198 cmd.append('--checked') | |
| 199 | |
| 200 cmd.extend(flags) | |
| 201 cmd.extend(targets) | |
| 202 | |
| 203 print 'Running: %s' % (' '.join(cmd)) | |
| 204 RunProcess(cmd) | |
| 205 | |
| 206 | |
| 207 def RunProcess(command): | |
| 208 """ | |
| 209 Runs command. | |
| 210 | |
| 211 If a non-zero exit code is returned, raises an OSError with errno as the exit | |
| 212 code. | |
| 213 """ | |
| 214 exit_code = subprocess.call(command, env=NO_COLOR_ENV) | |
| 215 if exit_code != 0: | |
| 216 raise OSError(exit_code) | |
| 217 | |
| 218 | |
| 219 def GetStepName(name, flags): | |
| 220 """ | |
| 221 Filters out flags with '=' as this breaks the /stats feature of the buildbot. | |
| 222 """ | |
| 223 flags = [x for x in flags if not '=' in x] | |
| 224 return ('%s tests %s' % (name, ' '.join(flags))).strip() | |
| OLD | NEW |