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

Side by Side Diff: Tools/TestResultServer/handlers/buildershandler.py

Issue 337433003: Switch buildershandler over to using the json mirror. (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: Created 6 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 | « no previous file | Tools/TestResultServer/handlers/buildershandler_unittest.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 # Copyright (C) 2013 Google Inc. All rights reserved. 1 # Copyright (C) 2013 Google Inc. All rights reserved.
2 # 2 #
3 # Redistribution and use in source and binary forms, with or without 3 # Redistribution and use in source and binary forms, with or without
4 # modification, are permitted provided that the following conditions are 4 # modification, are permitted provided that the following conditions are
5 # met: 5 # met:
6 # 6 #
7 # * Redistributions of source code must retain the above copyright 7 # * Redistributions of source code must retain the above copyright
8 # notice, this list of conditions and the following disclaimer. 8 # notice, this list of conditions and the following disclaimer.
9 # * Redistributions in binary form must reproduce the above 9 # * Redistributions in binary form must reproduce the above
10 # copyright notice, this list of conditions and the following disclaimer 10 # copyright notice, this list of conditions and the following disclaimer
(...skipping 20 matching lines...) Expand all
31 import logging 31 import logging
32 import re 32 import re
33 import sys 33 import sys
34 import traceback 34 import traceback
35 import urllib2 35 import urllib2
36 import webapp2 36 import webapp2
37 37
38 from google.appengine.api import memcache 38 from google.appengine.api import memcache
39 39
40 MASTERS = [ 40 MASTERS = [
41 {'name': 'ChromiumWin', 'url': 'http://build.chromium.org/p/chromium.win', ' groups': ['@ToT Chromium']}, 41 {'name': 'ChromiumWin', 'url_name': 'chromium.win', 'groups': ['@ToT Chromiu m']},
42 {'name': 'ChromiumMac', 'url': 'http://build.chromium.org/p/chromium.mac', ' groups': ['@ToT Chromium']}, 42 {'name': 'ChromiumMac', 'url_name': 'chromium.mac', 'groups': ['@ToT Chromiu m']},
43 {'name': 'ChromiumLinux', 'url': 'http://build.chromium.org/p/chromium.linux ', 'groups': ['@ToT Chromium']}, 43 {'name': 'ChromiumLinux', 'url_name': 'chromium.linux', 'groups': ['@ToT Chr omium']},
44 {'name': 'ChromiumChromiumOS', 'url': 'http://build.chromium.org/p/chromium. chromiumos', 'groups': ['@ToT ChromeOS']}, 44 {'name': 'ChromiumChromiumOS', 'url_name': 'chromium.chromiumos', 'groups': ['@ToT ChromeOS']},
45 {'name': 'ChromiumGPU', 'url': 'http://build.chromium.org/p/chromium.gpu', ' groups': ['@ToT Chromium']}, 45 {'name': 'ChromiumGPU', 'url_name': 'chromium.gpu', 'groups': ['@ToT Chromiu m']},
46 {'name': 'ChromiumGPUFYI', 'url': 'http://build.chromium.org/p/chromium.gpu. fyi', 'groups': ['@ToT Chromium FYI']}, 46 {'name': 'ChromiumGPUFYI', 'url_name': 'chromium.gpu.fyi', 'groups': ['@ToT Chromium FYI']},
47 {'name': 'ChromiumWebkit', 'url': 'http://build.chromium.org/p/chromium.webk it', 'groups': ['@ToT Chromium', '@ToT Blink']}, 47 {'name': 'ChromiumWebkit', 'url_name': 'chromium.webkit', 'groups': ['@ToT C hromium', '@ToT Blink']},
48 {'name': 'ChromiumFYI', 'url': 'http://build.chromium.org/p/chromium.fyi', ' groups': ['@ToT Chromium FYI']}, 48 {'name': 'ChromiumFYI', 'url_name': 'chromium.fyi', 'groups': ['@ToT Chromiu m FYI']},
49 {'name': 'V8', 'url': 'http://build.chromium.org/p/client.v8', 'groups': ['@ ToT V8']}, 49 {'name': 'V8', 'url_name': 'client.v8', 'groups': ['@ToT V8']},
50 ] 50 ]
51 51
52 # Buildbot steps that have test in the name, but don't run tests. 52 # Buildbot steps that have test in the name, but don't run tests.
53 NON_TEST_STEP_NAMES = [ 53 NON_TEST_STEP_NAMES = [
54 'archive', 54 'archive',
55 'Run tests', 55 'Run tests',
56 'find isolated tests', 56 'find isolated tests',
57 'read test spec', 57 'read test spec',
58 'Download latest chromedriver', 58 'Download latest chromedriver',
59 'compile tests', 59 'compile tests',
(...skipping 10 matching lines...) Expand all
70 'python_tests(chrome', 70 'python_tests(chrome',
71 'run_all_tests.py', 71 'run_all_tests.py',
72 'test_report', 72 'test_report',
73 'test CronetSample', 73 'test CronetSample',
74 'test_mini_installer', 74 'test_mini_installer',
75 'telemetry_unittests', 75 'telemetry_unittests',
76 'webkit_python_tests', 76 'webkit_python_tests',
77 'webkit_unit_tests', 77 'webkit_unit_tests',
78 ] 78 ]
79 79
80 class FetchBuildersException(Exception): pass 80 BUILDS_URL = 'http://chrome-build-extract.appspot.com/get_builds?builder=%s&mast er=%s&num_builds=1'
81 MASTER_URL = 'http://chrome-build-extract.appspot.com/get_master/%s'
81 82
82 83
83 def master_json_url(master_url): 84 class FetchBuildersException(Exception):
84 return master_url + '/json/builders' 85 pass
85
86
87 def builder_json_url(master_url, builder):
88 return master_json_url(master_url) + '/' + urllib2.quote(builder)
89
90
91 def cached_build_json_url(master_url, builder, build_number):
92 return builder_json_url(master_url, builder) + '/builds/' + str(build_number )
93 86
94 87
95 def fetch_json(url): 88 def fetch_json(url):
96 logging.debug('Fetching %s' % url) 89 logging.debug('Fetching %s' % url)
97 fetched_json = {} 90 fetched_json = {}
98 try: 91 try:
99 resp = urllib2.urlopen(url) 92 resp = urllib2.urlopen(url)
100 except: 93 except:
101 exc_info = sys.exc_info() 94 exc_info = sys.exc_info()
102 logging.warning('Error while fetching %s: %s', url, exc_info[1]) 95 logging.warning('Error while fetching %s: %s', url, exc_info[1])
103 return fetched_json 96 return fetched_json
104 97
105 try: 98 try:
106 fetched_json = json.load(resp) 99 fetched_json = json.load(resp)
107 except: 100 except:
108 exc_info = sys.exc_info() 101 exc_info = sys.exc_info()
109 logging.warning('Unable to parse JSON response from %s: %s', url, exc_in fo[1]) 102 logging.warning('Unable to parse JSON response from %s: %s', url, exc_in fo[1])
110 103
111 return fetched_json 104 return fetched_json
112 105
113 106
114 def get_latest_build(build_data):
115 cached_builds = []
116 if 'cachedBuilds' in build_data:
117 cached_builds = build_data['cachedBuilds']
118
119 current_builds = build_data['currentBuilds']
120
121 latest_cached_builds = set(cached_builds) - set(current_builds)
122 if len(latest_cached_builds) != 0:
123 latest_cached_builds = sorted(list(latest_cached_builds))
124 latest_build = latest_cached_builds[-1]
125 elif len(current_builds) != 0:
126 latest_build = current_builds[0]
127 else:
128 basedir = build_data['basedir'] if 'basedir' in build_data else 'current builder'
129 logging.info('No cached or current builds for %s', basedir)
130 return None
131
132 return latest_build
133
134
135 def dump_json(data): 107 def dump_json(data):
136 return json.dumps(data, separators=(',', ':'), sort_keys=True) 108 return json.dumps(data, separators=(',', ':'), sort_keys=True)
137 109
138 110
139 def fetch_buildbot_data(masters, force_update=False): 111 def fetch_buildbot_data(masters):
140 if force_update:
141 logging.info('Starting a forced buildbot update. Failure to fetch a mast er\'s data will not abort the fetch.')
142
143 start_time = datetime.datetime.now() 112 start_time = datetime.datetime.now()
144 master_data = masters[:] 113 master_data = masters[:]
145 for master in master_data: 114 for master in master_data:
146 master_url = master['url'] 115 master_url = MASTER_URL % master['url_name']
116 builders = fetch_json(master_url)
117 if not builders:
118 msg = 'Aborting fetch. Could not fetch builders from master "%s": %s .' % (master['name'], master_url)
119 logging.warning(msg)
120 raise FetchBuildersException(msg)
121
147 tests_object = master.setdefault('tests', {}) 122 tests_object = master.setdefault('tests', {})
148 master['tests'] = tests_object
149 123
150 builders = fetch_json(master_json_url(master_url)) 124 for builder in builders['builders'].keys():
151 if not builders: 125 build = fetch_json(BUILDS_URL % (urllib2.quote(builder), master['url _name']))
152 msg = 'Could not fetch builders from master "%s": %s.' % (master['na me'], master_url) 126 if not build:
153 logging.warning(msg) 127 logging.info('Skipping builder %s on master %s due to empty data .', builder, master['url_name'])
154 if force_update:
155 continue
156 else:
157 logging.warning('Aborting fetch.')
158 raise FetchBuildersException(msg)
159
160 for builder in builders:
161 build_data = fetch_json(builder_json_url(master_url, builder))
162
163 latest_build = get_latest_build(build_data)
164 if not latest_build:
165 logging.info('Skipping builder %s because it lacked cached or cu rrent builds.', builder)
166 continue 128 continue
167 129
168 build = fetch_json(cached_build_json_url(master_url, builder, latest _build)) 130 if not build['builds']:
169 if not build: 131 logging.info('Skipping builder %s on master %s due to empty buil ds list.', builder, master['url_name'])
170 logging.info('Skipping build %s on builder %s due to empty data' , latest_build, builder) 132 continue
171 for step in build['steps']: 133
134 for step in build['builds'][0]['steps']:
172 step_name = step['name'] 135 step_name = step['name']
173 136
174 if not 'test' in step_name: 137 if not 'test' in step_name:
175 continue 138 continue
176 139
177 if any(name in step_name for name in NON_TEST_STEP_NAMES): 140 if any(name in step_name for name in NON_TEST_STEP_NAMES):
178 continue 141 continue
179 142
180 if re.search('_only|_ignore|_perf$', step_name): 143 if re.search('_only|_ignore|_perf$', step_name):
181 continue 144 continue
(...skipping 12 matching lines...) Expand all
194 delta = datetime.datetime.now() - start_time 157 delta = datetime.datetime.now() - start_time
195 158
196 logging.info('Fetched buildbot data in %s seconds.', delta.seconds) 159 logging.info('Fetched buildbot data in %s seconds.', delta.seconds)
197 160
198 return dump_json(output_data) 161 return dump_json(output_data)
199 162
200 163
201 class UpdateBuilders(webapp2.RequestHandler): 164 class UpdateBuilders(webapp2.RequestHandler):
202 """Fetch and update the cached buildbot data.""" 165 """Fetch and update the cached buildbot data."""
203 def get(self): 166 def get(self):
204 force_update = True if self.request.get('force') else False
205 try: 167 try:
206 buildbot_data = fetch_buildbot_data(MASTERS, force_update) 168 buildbot_data = fetch_buildbot_data(MASTERS)
207 memcache.set('buildbot_data', buildbot_data) 169 memcache.set('buildbot_data', buildbot_data)
208 self.response.set_status(200) 170 self.response.set_status(200)
209 self.response.out.write("ok") 171 self.response.out.write("ok")
210 except FetchBuildersException, ex: 172 except FetchBuildersException, ex:
211 logging.error('Not updating builders because fetch failed: %s', str( ex)) 173 logging.error('Not updating builders because fetch failed: %s', str( ex))
212 self.response.set_status(500) 174 self.response.set_status(500)
213 self.response.out.write(ex.message) 175 self.response.out.write(ex.message)
214 176
215 177
216
217 class GetBuilders(webapp2.RequestHandler): 178 class GetBuilders(webapp2.RequestHandler):
218 """Return a list of masters mapped to their respective builders, possibly us ing cached data.""" 179 """Return a list of masters mapped to their respective builders, possibly us ing cached data."""
219 def get(self): 180 def get(self):
220 callback = self.request.get('callback')
221
222 buildbot_data = memcache.get('buildbot_data') 181 buildbot_data = memcache.get('buildbot_data')
223 182
224 if not buildbot_data: 183 if not buildbot_data:
225 logging.warning('No buildbot data in memcache. If this message repea ts, something is probably wrong with memcache.') 184 logging.warning('No buildbot data in memcache. If this message repea ts, something is probably wrong with memcache.')
185 try:
186 buildbot_data = fetch_buildbot_data(MASTERS)
187 memcache.set('buildbot_data', buildbot_data)
188 except FetchBuildersException, ex:
189 logging.error('Builders fetch failed: %s', str(ex))
190 self.response.set_status(500)
191 self.response.out.write(ex.message)
192 return
226 193
227 # Since we have no cached buildbot data, we would rather have missin g masters than no data at all. 194 callback = self.request.get('callback')
228 buildbot_data = fetch_buildbot_data(MASTERS, True)
229 try:
230 memcache.set('buildbot_data', buildbot_data)
231 except ValueError, err:
232 logging.error(str(err))
233
234 if callback: 195 if callback:
235 buildbot_data = callback + '(' + buildbot_data + ');' 196 buildbot_data = callback + '(' + buildbot_data + ');'
236 197
237 self.response.out.write(buildbot_data) 198 self.response.out.write(buildbot_data)
OLDNEW
« no previous file with comments | « no previous file | Tools/TestResultServer/handlers/buildershandler_unittest.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698