OLD | NEW |
---|---|
1 #!/usr/bin/env python | 1 #!/usr/bin/env python |
2 # Copyright 2014 The Chromium Authors. All rights reserved. | 2 # Copyright 2014 The Chromium Authors. All rights reserved. |
3 # Use of this source code is governed by a BSD-style license that can be | 3 # Use of this source code is governed by a BSD-style license that can be |
4 # found in the LICENSE file. | 4 # found in the LICENSE file. |
5 | 5 |
6 """An auto-roller for GN binaries into Chromium. | 6 """An auto-roller for GN binaries into Chromium. |
7 | 7 |
8 This script is used to update the GN binaries that a Chromium | 8 This script is used to update the GN binaries that a Chromium |
9 checkout uses. In order to update the binaries, one must follow | 9 checkout uses. In order to update the binaries, one must follow |
10 four steps in order: | 10 four steps in order: |
(...skipping 168 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
179 with open('DEPS', 'w') as fp: | 179 with open('DEPS', 'w') as fp: |
180 fp.write(new_deps) | 180 fp.write(new_deps) |
181 | 181 |
182 def WaitForBuildToFinish(self): | 182 def WaitForBuildToFinish(self): |
183 ret = self.CheckoutBuildBranch() | 183 ret = self.CheckoutBuildBranch() |
184 if ret: | 184 if ret: |
185 return ret | 185 return ret |
186 | 186 |
187 print('Checking build') | 187 print('Checking build') |
188 results = self.CheckBuild() | 188 results = self.CheckBuild() |
189 while (len(results) < 3 or | 189 while (any(r['state'] in ('pending', 'started') |
190 any(r['state'] in ('pending', 'started') | |
191 for r in results.values())): | 190 for r in results.values())): |
192 print() | 191 print() |
193 print('Sleeping for 30 seconds') | 192 print('Sleeping for 30 seconds') |
194 time.sleep(30) | 193 time.sleep(30) |
195 print('Checking build') | 194 print('Checking build') |
196 results = self.CheckBuild() | 195 results = self.CheckBuild() |
197 | 196 |
198 ret = 0 if all(r['state'] == 'success' for r in results.values()) else 1 | 197 ret = 0 if all(r['state'] == 'success' for r in results.values()) else 1 |
199 if ret: | 198 if ret: |
200 print('Build failed.') | 199 print('Build failed.') |
(...skipping 20 matching lines...) Expand all Loading... | |
221 def CheckBuild(self): | 220 def CheckBuild(self): |
222 _, out, _ = self.Call('git-cl issue') | 221 _, out, _ = self.Call('git-cl issue') |
223 | 222 |
224 issue = int(out.split()[2]) | 223 issue = int(out.split()[2]) |
225 | 224 |
226 _, out, _ = self.Call('git config user.email') | 225 _, out, _ = self.Call('git config user.email') |
227 email = '' | 226 email = '' |
228 rpc_server = upload.GetRpcServer(CODE_REVIEW_SERVER, email) | 227 rpc_server = upload.GetRpcServer(CODE_REVIEW_SERVER, email) |
229 try: | 228 try: |
230 props = json.loads(rpc_server.Send('/api/%d' % issue)) | 229 props = json.loads(rpc_server.Send('/api/%d' % issue)) |
231 except Exception as _e: | 230 except Exception as _e: |
hinoka
2017/04/18 19:04:43
s/_e/e/
Dirk Pranke
2017/04/18 19:21:33
Er, right. Will fix.
| |
232 raise | 231 print('Failed to load patch data: %s' % e) |
232 return {} | |
233 | 233 |
234 patchset = int(props['patchsets'][-1]) | 234 patchset = int(props['patchsets'][-1]) |
235 | 235 |
236 try: | 236 try: |
237 try_job_results = json.loads(rpc_server.Send( | 237 try_job_results = json.loads(rpc_server.Send( |
238 '/api/%d/%d/try_job_results' % (issue, patchset))) | 238 '/api/%d/%d/try_job_results' % (issue, patchset))) |
239 except Exception as _e: | 239 except Exception as _e: |
hinoka
2017/04/18 19:04:43
s/_e/e/
Dirk Pranke
2017/04/18 19:21:33
Ditto.
| |
240 raise | 240 print('Failed to load try job results: %s' % e) |
241 return {} | |
241 | 242 |
242 if not try_job_results: | 243 if not try_job_results: |
243 print('No try jobs found on most recent patchset') | 244 print('No try jobs found on most recent patchset') |
244 return {} | 245 return {} |
245 | 246 |
246 results = {} | 247 results = {} |
247 for job in try_job_results: | 248 for job in try_job_results: |
248 builder = job['builder'] | 249 builder = job['builder'] |
249 if builder == 'linux_chromium_gn_upload': | 250 if builder == 'linux_chromium_gn_upload': |
250 platform = 'linux64' | 251 platform = 'linux64' |
251 elif builder == 'mac_chromium_gn_upload': | 252 elif builder == 'mac_chromium_gn_upload': |
252 platform = 'mac' | 253 platform = 'mac' |
253 elif builder == 'win8_chromium_gn_upload': | 254 elif builder == 'win8_chromium_gn_upload': |
254 platform = 'win' | 255 platform = 'win' |
255 else: | 256 else: |
256 print('Unexpected builder: %s') | 257 print('Unexpected builder: %s') |
257 continue | 258 continue |
258 | 259 |
259 TRY_JOB_RESULT_STATES = ('started', 'success', 'warnings', 'failure', | 260 TRY_JOB_RESULT_STATES = ('started', 'success', 'warnings', 'failure', |
260 'skipped', 'exception', 'retry', 'pending') | 261 'skipped', 'exception', 'retry', 'pending') |
261 state = TRY_JOB_RESULT_STATES[int(job['result']) + 1] | 262 state = TRY_JOB_RESULT_STATES[int(job['result']) + 1] |
262 url_str = ' %s' % job['url'] | 263 url_str = ' %s' % job['url'] |
263 build = url_str.split('/')[-1] | 264 build = url_str.split('/')[-1] |
264 | 265 |
265 sha1 = '-' | 266 sha1 = '-' |
266 results.setdefault(platform, {'build': -1, 'sha1': '', 'url': url_str}) | 267 results.setdefault(platform, {'build': -1, 'sha1': '', 'url': url_str}) |
267 | 268 |
268 if state == 'success': | 269 if state == 'success': |
269 jsurl = url_str.replace('/builders/', '/json/builders/') | 270 jsurl = url_str.replace('http://build.chromium.org/', |
270 fp = urllib2.urlopen(jsurl) | 271 'http://chrome-build-extract.appspot.com/') |
hinoka
2017/04/18 19:04:43
This is for querying a build right? This endpoint
Dirk Pranke
2017/04/18 19:21:33
Yes, this is for querying individual builds. You c
| |
272 jsurl = jsurl + '?json=1' | |
273 try: | |
274 fp = urllib2.urlopen(jsurl) | |
275 except urllib2.HTTPError as e: | |
276 print('Failed to open %s: %s' % (jsurl, e)) | |
277 return {} | |
278 | |
271 js = json.loads(fp.read()) | 279 js = json.loads(fp.read()) |
272 fp.close() | 280 fp.close() |
273 sha1_step_name = 'gn sha1' | 281 sha1_step_name = 'gn sha1' |
274 for step in js['steps']: | 282 for step in js['steps']: |
275 if step['name'] == sha1_step_name: | 283 if step['name'] == sha1_step_name: |
276 # TODO: At some point infra changed the step text to | 284 # TODO: At some point infra changed the step text to |
277 # contain the step name; once all of the masters have been | 285 # contain the step name; once all of the masters have been |
278 # restarted we can probably assert that the step text | 286 # restarted we can probably assert that the step text |
279 # with the step_name. | 287 # with the step_name. |
280 sha1_step_text_prefix = sha1_step_name + '<br>' | 288 sha1_step_text_prefix = sha1_step_name + '<br>' |
(...skipping 172 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
453 def GetGNChanges(self): | 461 def GetGNChanges(self): |
454 _, out, _ = self.Call( | 462 _, out, _ = self.Call( |
455 "git log --pretty=' %h %s' " + | 463 "git log --pretty=' %h %s' " + |
456 "%s..%s tools/gn" % (self.old_gn_commitish, self.new_gn_commitish)) | 464 "%s..%s tools/gn" % (self.old_gn_commitish, self.new_gn_commitish)) |
457 return out | 465 return out |
458 | 466 |
459 def Call(self, cmd, cwd=None): | 467 def Call(self, cmd, cwd=None): |
460 proc = subprocess.Popen(cmd, stdout=subprocess.PIPE, shell=True, | 468 proc = subprocess.Popen(cmd, stdout=subprocess.PIPE, shell=True, |
461 cwd=(cwd or self.chromium_src_dir)) | 469 cwd=(cwd or self.chromium_src_dir)) |
462 out, err = proc.communicate() | 470 out, err = proc.communicate() |
463 return proc.returncode, out, err | 471 return proc.returncode, out or '', err or '' |
464 | 472 |
465 | 473 |
466 if __name__ == '__main__': | 474 if __name__ == '__main__': |
467 roller = GNRoller() | 475 roller = GNRoller() |
468 sys.exit(roller.Roll()) | 476 sys.exit(roller.Roll()) |
OLD | NEW |