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

Side by Side Diff: build/android/buildbot/bb_run_bot.py

Issue 16688002: Port remaining android buildbot code into python (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 7 years, 6 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 | Annotate | Revision Log
« no previous file with comments | « build/android/buildbot/bb_host_steps.py ('k') | build/android/buildbot/bb_utils.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/env python 1 #!/usr/bin/env python
2 # 2 #
3 # Copyright (c) 2013 The Chromium Authors. All rights reserved. 3 # Copyright (c) 2013 The Chromium 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 import collections 7 import collections
8 import copy 8 import copy
9 import json 9 import json
10 import optparse
11 import os 10 import os
12 import pipes 11 import pipes
12 import re
13 import subprocess 13 import subprocess
14 import sys 14 import sys
15 15
16 import bb_utils 16 import bb_utils
17 17
18 sys.path.append(os.path.join(os.path.dirname(__file__), '..')) 18 BotConfig = collections.namedtuple(
19 from pylib import buildbot_report 19 'BotConfig', ['bot_id', 'host_obj', 'test_obj'])
20 20
21 CHROME_SRC = os.path.abspath( 21 HostConfig = collections.namedtuple(
22 os.path.join(os.path.dirname(__file__), '..', '..', '..')) 22 'HostConfig', ['host_step_args', 'extra_gyp_defines', 'target_arch'])
23 23
24 GLOBAL_SLAVE_PROPS = {} 24 TestConfig = collections.namedtuple('Tests', ['tests', 'extra_args'])
25 25
26 BotConfig = collections.namedtuple(
27 'BotConfig', ['bot_id', 'host_opts', 'test_obj', 'slave_props'])
28 TestConfig = collections.namedtuple('Tests', ['tests', 'extra_args'])
29 Command = collections.namedtuple(
30 'Command', ['step_name', 'command', 'testing_cmd'])
31 26
32 CommandToString = bb_utils.CommandToString 27 def DictDiff(d1, d2):
28 diff = []
29 for key in sorted(set(d1.keys() + d2.keys())):
30 if key in d1 and d1[key] != d2.get(key):
31 diff.append('- %s=%s' % (key, pipes.quote(d1[key])))
32 if key in d2 and d2[key] != d1.get(key):
33 diff.append('+ %s=%s' % (key, pipes.quote(d2[key])))
34 return '\n'.join(diff)
35
36
37 def GetEnvironment(host_obj):
38 init_env = dict(os.environ)
39 init_env['GYP_GENERATORS'] = 'ninja'
40 init_env['GOMA_DIR'] = bb_utils.GOMA_DIR
41 envsetup_cmd = '. build/android/envsetup.sh'
42 if host_obj.target_arch:
43 envsetup_cmd += ' --target_arch=%s' % host_obj.target_arch
44 print 'Running %s' % envsetup_cmd
45 proc = subprocess.Popen(['bash', '-exc',
46 envsetup_cmd + ' >&2; python build/android/buildbot/env_to_json.py'],
47 stdout=subprocess.PIPE, stderr=subprocess.PIPE,
48 cwd=bb_utils.CHROME_SRC, env=init_env)
49 json_env, envsetup_output = proc.communicate()
50 if proc.returncode != 0:
51 print 'FATAL Failure in envsetup.'
52 print envsetup_output
53 sys.exit(1)
54 env = json.loads(json_env)
55 env['GYP_DEFINES'] = env.get('GYP_DEFINES', '') + ' fastbuild=1'
56 extra_gyp = host_obj.extra_gyp_defines
57 if extra_gyp:
58 env['GYP_DEFINES'] += ' %s' % extra_gyp
59 if re.search('(asan|clang)=1', extra_gyp):
60 env.pop('CXX_target', None)
61
62 # Bots checkout chrome in /b/build/slave/<name>/build/src
63 build_internal_android = os.path.abspath(os.path.join(
64 bb_utils.CHROME_SRC, '..', '..', '..', '..', '..', 'build_internal',
65 'scripts', 'slave', 'android'))
66 if os.path.exists(build_internal_android):
67 env['PATH'] = os.pathsep.join([build_internal_android, env['PATH']])
68 return env
33 69
34 70
35 def GetCommands(options, bot_config): 71 def GetCommands(options, bot_config):
36 """Get a formatted list of commands. 72 """Get a formatted list of commands.
37 73
38 Args: 74 Args:
39 options: Options object. 75 options: Options object.
40 bot_config: A BotConfig named tuple. 76 bot_config: A BotConfig named tuple.
41 Returns: 77 Returns:
42 list of Command objects. 78 list of Command objects.
43 """ 79 """
44 slave_props = dict(GLOBAL_SLAVE_PROPS) 80 property_args = bb_utils.EncodeProperties(options)
45 if bot_config.slave_props: 81 commands = [['build/android/buildbot/bb_host_steps.py'] +
46 slave_props.update(bot_config.slave_props) 82 bot_config.host_obj.host_step_args + property_args]
47
48 slave_properties = json.dumps(slave_props)
49 property_args = [
50 '--factory-properties=%s' % json.dumps(options.factory_properties),
51 '--build-properties=%s' % json.dumps(options.build_properties),
52 '--slave-properties=%s' % slave_properties]
53
54 commands = []
55 def WrapWithBash(command):
56 """Wrap a bash command string with envsetup scripts."""
57 return ['bash', '-exc', '; '.join([
58 '. build/android/buildbot/buildbot_functions.sh',
59 'bb_baseline_setup %s --slave-properties=%s' % (
60 CHROME_SRC, pipes.quote(slave_properties)),
61 command])
62 ]
63
64 if bot_config.host_opts:
65 host_cmd = (['build/android/buildbot/bb_host_steps.py'] +
66 bot_config.host_opts + property_args)
67 commands.append(Command(
68 'Host steps',
69 WrapWithBash(' '.join(map(pipes.quote, host_cmd))), host_cmd))
70 83
71 test_obj = bot_config.test_obj 84 test_obj = bot_config.test_obj
72 if test_obj: 85 if test_obj:
73 run_test_cmd = [ 86 run_test_cmd = [
74 'build/android/buildbot/bb_device_steps.py', '--reboot'] + property_args 87 'build/android/buildbot/bb_device_steps.py', '--reboot'] + property_args
75 for test in test_obj.tests: 88 for test in test_obj.tests:
76 run_test_cmd.extend(['-f', test]) 89 run_test_cmd.extend(['-f', test])
77 if test_obj.extra_args: 90 if test_obj.extra_args:
78 run_test_cmd.extend(test_obj.extra_args) 91 run_test_cmd.extend(test_obj.extra_args)
79 commands.append(Command( 92 commands.append(run_test_cmd)
80 'Run tests',
81 WrapWithBash(' '.join(map(pipes.quote, run_test_cmd))), run_test_cmd))
82
83 return commands 93 return commands
84 94
85 95
86 def GetBotStepMap(): 96 def GetBotStepMap():
87 compile_opt = ['--compile'] 97 compile_opt = ['--compile']
88 std_host_tests = ['--host-tests=check_webview_licenses,findbugs'] 98 std_host_tests = ['--host-tests=check_webview_licenses,findbugs']
89 std_build_opts = ['--compile', '--zip-build'] 99 std_build_opts = ['--compile', '--zip-build']
90 std_test_opts = ['--extract-build'] 100 std_test_opts = ['--extract-build']
91 std_tests = ['ui', 'unit'] 101 std_tests = ['ui', 'unit']
92 flakiness_server = '--upload-to-flakiness-server' 102 flakiness_server = '--upload-to-flakiness-server'
93 extra_gyp = 'extra_gyp_defines'
94 103
95 def B(bot_id, bash_funs, test_obj=None, slave_props=None): 104 def B(bot_id, host_object, test_object=None):
96 return BotConfig(bot_id, bash_funs, test_obj, slave_props) 105 return BotConfig(bot_id, host_object, test_object)
97 106
98 def T(tests, extra_args=None): 107 def T(tests, extra_args=None):
99 return TestConfig(tests, extra_args) 108 return TestConfig(tests, extra_args)
100 109
110 def H(host_step_args, extra_gyp=None, target_arch=None):
111 return HostConfig(host_step_args, extra_gyp, target_arch)
112
101 bot_configs = [ 113 bot_configs = [
102 # Main builders 114 # Main builders
103 B('main-builder-dbg', std_build_opts + std_host_tests), 115 B('main-builder-dbg', H(std_build_opts + std_host_tests)),
104 B('main-builder-rel', std_build_opts), 116 B('main-builder-rel', H(std_build_opts)),
105 B('main-clang-builder', compile_opt, slave_props={extra_gyp: 'clang=1'}), 117 B('main-clang-builder', H(compile_opt, 'clang=1')),
106 B('main-clobber', compile_opt), 118 B('main-clobber', H(compile_opt)),
107 B('main-tests', std_test_opts, T(std_tests, [flakiness_server])), 119 B('main-tests', H(std_test_opts), T(std_tests, [flakiness_server])),
108 120
109 # Other waterfalls 121 # Other waterfalls
110 B('asan-builder-tests', compile_opt + ['--update-clang'], 122 B('asan-builder-tests', H(compile_opt, 'asan=1'),
111 T(std_tests, ['--asan']), {extra_gyp: 'asan=1'}), 123 T(std_tests, ['--asan'])),
112 B('chromedriver-fyi-tests-dbg', std_test_opts, 124 B('chromedriver-fyi-tests-dbg', H(std_test_opts),
113 T(['chromedriver'], ['--install=ChromiumTestShell'])), 125 T(['chromedriver'], ['--install=ChromiumTestShell'])),
114 B('fyi-builder-dbg', 126 B('fyi-builder-dbg',
115 std_build_opts + std_host_tests + ['--experimental']), 127 H(std_build_opts + std_host_tests + ['--experimental'])),
116 B('fyi-builder-rel', std_build_opts + ['--experimental']), 128 B('fyi-builder-rel', H(std_build_opts + ['--experimental'])),
117 B('fyi-tests-dbg-ics-gn', compile_opt + [ '--experimental'], 129 B('fyi-tests-dbg-ics-gn', H(compile_opt + [ '--experimental']),
118 T(std_tests, ['--experimental', flakiness_server])), 130 T(std_tests, ['--experimental', flakiness_server])),
119 B('fyi-tests', std_test_opts, 131 B('fyi-tests', H(std_test_opts),
120 T(std_tests, ['--experimental', flakiness_server])), 132 T(std_tests, ['--experimental', flakiness_server])),
121 B('fyi-component-builder-tests-dbg', compile_opt, 133 B('fyi-component-builder-tests-dbg',
122 T(std_tests, ['--experimental', flakiness_server]), 134 H(compile_opt, 'component=shared_library'),
123 {extra_gyp: 'component=shared_library'}), 135 T(std_tests, ['--experimental', flakiness_server])),
124 B('perf-tests-rel', std_test_opts, T([], ['--install=ContentShell'])), 136 B('perf-tests-rel', H(std_test_opts), T([], ['--install=ContentShell'])),
125 B('webkit-latest-webkit-tests', std_test_opts, 137 B('webkit-latest-webkit-tests', H(std_test_opts),
126 T(['webkit_layout', 'webkit'])), 138 T(['webkit_layout', 'webkit'])),
127 B('webkit-latest-contentshell', compile_opt, T(['webkit_layout'])), 139 B('webkit-latest-contentshell', H(compile_opt), T(['webkit_layout'])),
128 B('builder-unit-tests', compile_opt, T(['unit'])), 140 B('builder-unit-tests', H(compile_opt), T(['unit'])),
129 141
130 # Generic builder config (for substring match). 142 # Generic builder config (for substring match).
131 B('builder', std_build_opts), 143 B('builder', H(std_build_opts)),
132 ] 144 ]
133 145
134 bot_map = dict((config.bot_id, config) for config in bot_configs) 146 bot_map = dict((config.bot_id, config) for config in bot_configs)
135 147
136 # These bots have identical configuration to ones defined earlier. 148 # These bots have identical configuration to ones defined earlier.
137 copy_map = [ 149 copy_map = [
138 ('lkgr-clobber', 'main-clobber'), 150 ('lkgr-clobber', 'main-clobber'),
139 ('try-builder-dbg', 'main-builder-dbg'), 151 ('try-builder-dbg', 'main-builder-dbg'),
140 ('try-builder-rel', 'main-builder-rel'), 152 ('try-builder-rel', 'main-builder-rel'),
141 ('try-clang-builder', 'main-clang-builder'), 153 ('try-clang-builder', 'main-clang-builder'),
(...skipping 11 matching lines...) Expand all
153 # identical in configuration to their trunk building counterparts. 165 # identical in configuration to their trunk building counterparts.
154 test_obj = bot_map[to_id].test_obj 166 test_obj = bot_map[to_id].test_obj
155 if to_id.startswith('try') and test_obj: 167 if to_id.startswith('try') and test_obj:
156 extra_args = test_obj.extra_args 168 extra_args = test_obj.extra_args
157 if extra_args and flakiness_server in extra_args: 169 if extra_args and flakiness_server in extra_args:
158 extra_args.remove(flakiness_server) 170 extra_args.remove(flakiness_server)
159 return bot_map 171 return bot_map
160 172
161 173
162 def main(argv): 174 def main(argv):
163 parser = optparse.OptionParser() 175 parser = bb_utils.GetParser()
164
165 def ConvertJson(option, _, value, parser):
166 setattr(parser.values, option.dest, json.loads(value))
167
168 parser.add_option('--build-properties', action='callback',
169 callback=ConvertJson, type='string', default={},
170 help='build properties in JSON format')
171 parser.add_option('--factory-properties', action='callback',
172 callback=ConvertJson, type='string', default={},
173 help='factory properties in JSON format')
174 parser.add_option('--bot-id', help='Specify bot id directly.') 176 parser.add_option('--bot-id', help='Specify bot id directly.')
175 parser.add_option('--TESTING', action='store_true', 177 parser.add_option('--testing', action='store_true',
176 help='For testing: print, but do not run commands') 178 help='For testing: print, but do not run commands')
177 options, args = parser.parse_args(argv[1:]) 179 options, args = parser.parse_args(argv[1:])
178 if args: 180 if args:
179 parser.error('Unused args: %s' % args) 181 parser.error('Unused args: %s' % args)
180 182
181 bot_id = options.bot_id or options.factory_properties.get('android_bot_id') 183 bot_id = options.bot_id or options.factory_properties.get('android_bot_id')
182 if not bot_id: 184 if not bot_id:
183 parser.error('A bot id must be specified through option or factory_props.') 185 parser.error('A bot id must be specified through option or factory_props.')
184 186
185 # Get a BotConfig object looking first for an exact bot-id match. If no exact 187 # Get a BotConfig object looking first for an exact bot-id match. If no exact
186 # match, look for a bot-id which is a substring of the specified id. 188 # match, look for a bot-id which is a substring of the specified id.
187 # This allows similar bots to have unique IDs, but to share config. 189 # This allows similar bots to have unique IDs, but to share config.
188 # If multiple substring matches exist, pick the longest one. 190 # If multiple substring matches exist, pick the longest one.
189 bot_map = GetBotStepMap() 191 bot_map = GetBotStepMap()
190 bot_config = bot_map.get(bot_id) 192 bot_config = bot_map.get(bot_id)
191 if not bot_config: 193 if not bot_config:
192 substring_matches = filter(lambda x: x in bot_id, bot_map.iterkeys()) 194 substring_matches = filter(lambda x: x in bot_id, bot_map.iterkeys())
193 if substring_matches: 195 if substring_matches:
194 max_id = max(substring_matches, key=len) 196 max_id = max(substring_matches, key=len)
195 print 'Using config from id="%s" (substring match).' % max_id 197 print 'Using config from id="%s" (substring match).' % max_id
196 bot_config = bot_map[max_id] 198 bot_config = bot_map[max_id]
197 if not bot_config: 199 if not bot_config:
198 print 'Error: config for id="%s" cannot be inferred.' % bot_id 200 print 'Error: config for id="%s" cannot be inferred.' % bot_id
199 return 1 201 return 1
200 202
201 print 'Using config:', bot_config 203 print 'Using config:', bot_config
202 204
203 command_objs = GetCommands(options, bot_config) 205 commands = GetCommands(options, bot_config)
204 for command_obj in command_objs: 206 for command in commands:
205 print 'Will run:', CommandToString(command_obj.command) 207 print 'Will run: ', bb_utils.CommandToString(command)
206 208
207 for command_obj in command_objs: 209 env = GetEnvironment(bot_config.host_obj)
208 if command_obj.step_name: 210 print 'Environment changes:'
209 buildbot_report.PrintNamedStep(command_obj.step_name) 211 print DictDiff(dict(os.environ), env)
210 command = command_obj.command 212
211 print CommandToString(command) 213 for command in commands:
214 print bb_utils.CommandToString(command)
212 sys.stdout.flush() 215 sys.stdout.flush()
213 env = None 216 if options.testing:
214 if options.TESTING: 217 env['BUILDBOT_TESTING'] = '1'
215 if not command_obj.testing_cmd: 218 return_code = subprocess.call(command, cwd=bb_utils.CHROME_SRC, env=env)
216 continue
217 return_code = subprocess.call(
218 command_obj.testing_cmd,
219 cwd=CHROME_SRC,
220 env=dict(os.environ, BUILDBOT_TESTING='1'))
221 else:
222 return_code = subprocess.call(command, cwd=CHROME_SRC, env=env)
223 if return_code != 0: 219 if return_code != 0:
224 return return_code 220 return return_code
225 221
226 222
227 if __name__ == '__main__': 223 if __name__ == '__main__':
228 sys.exit(main(sys.argv)) 224 sys.exit(main(sys.argv))
OLDNEW
« no previous file with comments | « build/android/buildbot/bb_host_steps.py ('k') | build/android/buildbot/bb_utils.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698