OLD | NEW |
---|---|
1 # Copyright 2015 The Chromium Authors. All rights reserved. | 1 # Copyright 2015 The Chromium Authors. All rights reserved. |
2 # Use of this source code is governed by a BSD-style license that can be | 2 # Use of this source code is governed by a BSD-style license that can be |
3 # found in the LICENSE file. | 3 # found in the LICENSE file. |
4 | 4 |
5 import argparse | 5 import argparse |
6 import json | 6 import json |
7 import logging | 7 import logging |
8 import os | 8 import os |
9 import platform | 9 import platform |
10 import re | 10 import re |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
56 | 56 |
57 # Default try bot to use incase builbot is unreachable. | 57 # Default try bot to use incase builbot is unreachable. |
58 DEFAULT_TRYBOTS = [ | 58 DEFAULT_TRYBOTS = [ |
59 'linux_perf_bisect', | 59 'linux_perf_bisect', |
60 'mac_10_11_perf_bisect', | 60 'mac_10_11_perf_bisect', |
61 'winx64_10_perf_bisect', | 61 'winx64_10_perf_bisect', |
62 'android_s5_perf_bisect', | 62 'android_s5_perf_bisect', |
63 ] | 63 ] |
64 | 64 |
65 CHROMIUM_SRC_PATH = path_util.GetChromiumSrcDir() | 65 CHROMIUM_SRC_PATH = path_util.GetChromiumSrcDir() |
66 # Mapping of repo to its root path and git remote URL. | |
67 REPO_INFO_MAP = { | |
68 'src': { | |
69 'src': 'src', | |
70 'url': 'https://chromium.googlesource.com/chromium/src.git', | |
71 }, | |
72 'v8': { | |
73 'src': 'src/v8', | |
74 'url': 'https://chromium.googlesource.com/v8/v8.git', | |
75 }, | |
76 'skia': { | |
77 'src': 'src/third_party/skia', | |
78 'url': 'https://chromium.googlesource.com/skia.git', | |
79 }, | |
80 'angle': { | |
81 'src': 'src/third_party/angle', | |
82 'url': 'https://chromium.googlesource.com/angle/angle.git', | |
83 } | |
84 } | |
sullivan
2016/09/08 03:22:59
Any reason not to add catapult here as well?
prasadv
2016/09/08 19:03:32
I added support for catapult too.
| |
66 | 85 |
67 assert not set(DEFAULT_TRYBOTS) & set(EXCLUDED_BOTS), ( | 86 assert not set(DEFAULT_TRYBOTS) & set(EXCLUDED_BOTS), ( |
68 'A trybot cannot present in both Default as well as Excluded bots lists.') | 87 'A trybot cannot present in both Default as well as Excluded bots lists.') |
69 | 88 |
70 | 89 |
71 class TrybotError(Exception): | 90 class TrybotError(Exception): |
72 | 91 |
73 def __str__(self): | 92 def __str__(self): |
74 return '(ERROR) Perf Try Job: %s' % self.args[0] | 93 return '(ERROR) Perf Try Job: %s' % self.args[0] |
75 | 94 |
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
150 """ | 169 """ |
151 proc = subprocess.Popen( | 170 proc = subprocess.Popen( |
152 [_GIT_CMD] + cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE) | 171 [_GIT_CMD] + cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE) |
153 output, err = proc.communicate() | 172 output, err = proc.communicate() |
154 returncode = proc.poll() | 173 returncode = proc.poll() |
155 if returncode: | 174 if returncode: |
156 if ignore_return_code: | 175 if ignore_return_code: |
157 return None | 176 return None |
158 raise TrybotError('%s. \n%s' % (msg_on_error, err)) | 177 raise TrybotError('%s. \n%s' % (msg_on_error, err)) |
159 | 178 |
160 return output | 179 return output.strip() |
161 | |
162 | 180 |
163 class Trybot(command_line.ArgParseCommand): | 181 class Trybot(command_line.ArgParseCommand): |
164 """Run telemetry perf benchmark on trybot.""" | 182 """Run telemetry perf benchmark on trybot.""" |
165 | 183 |
166 usage = 'botname benchmark_name [<benchmark run options>]' | 184 usage = 'botname benchmark_name [<benchmark run options>]' |
167 _builders = None | 185 _builders = None |
168 | 186 |
169 def __init__(self): | 187 def __init__(self): |
170 self._builder_names = None | 188 self._builder_names = None |
171 | 189 |
(...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
285 parser.add_argument( | 303 parser.add_argument( |
286 'trybot', choices=available_bots, | 304 'trybot', choices=available_bots, |
287 help=('specify which bots to run telemetry benchmarks on. ' | 305 help=('specify which bots to run telemetry benchmarks on. ' |
288 ' Allowed values are:\n' + '\n'.join(available_bots)), | 306 ' Allowed values are:\n' + '\n'.join(available_bots)), |
289 metavar='<trybot name>') | 307 metavar='<trybot name>') |
290 parser.add_argument( | 308 parser.add_argument( |
291 'benchmark_name', type=str, | 309 'benchmark_name', type=str, |
292 help=('specify which benchmark to run. To see all available benchmarks,' | 310 help=('specify which benchmark to run. To see all available benchmarks,' |
293 ' run `run_benchmark list`'), | 311 ' run `run_benchmark list`'), |
294 metavar='<benchmark name>') | 312 metavar='<benchmark name>') |
313 parser.add_argument( | |
314 '--repo_path', type=str, default=CHROMIUM_SRC_PATH, | |
315 help='specify which repo path to use for perf try job\n', | |
316 metavar='<repo path>') | |
sullivan
2016/09/08 03:22:59
This is supposed to be specified relative to cwd?
prasadv
2016/09/08 19:03:32
No, this is the complete path to the directory whe
sullivan
2016/09/08 20:43:57
I think the documentation needs to be clearer, esp
prasadv
2016/09/08 23:44:36
Please note that the path info in REPO_INFO_MAP is
| |
317 parser.add_argument( | |
318 '--deps_revision', type=str, default=None, | |
319 help='specify DEPS revision to be used by Chromium.\n', | |
sullivan
2016/09/08 03:22:59
Would be great to clarify what this argument does
prasadv
2016/09/08 19:03:32
This is used when we want to modify DEPS entry in
| |
320 metavar='<deps revision>') | |
295 | 321 |
296 def Run(self, options, extra_args=None): | 322 def Run(self, options, extra_args=None): |
297 """Sends a tryjob to a perf trybot. | 323 """Sends a tryjob to a perf trybot. |
298 | 324 |
299 This creates a branch, telemetry-tryjob, switches to that branch, edits | 325 This creates a branch, telemetry-tryjob, switches to that branch, edits |
300 the bisect config, commits it, uploads the CL to rietveld, and runs a | 326 the bisect config, commits it, uploads the CL to rietveld, and runs a |
301 tryjob on the given bot. | 327 tryjob on the given bot. |
302 """ | 328 """ |
303 if extra_args is None: | 329 if extra_args is None: |
304 extra_args = [] | 330 extra_args = [] |
305 self._InitializeBuilderNames(options.trybot) | 331 self._InitializeBuilderNames(options.trybot) |
332 | |
333 original_workdir = os.getcwd() | |
334 repo_path = os.path.abspath(options.repo_path) | |
306 try: | 335 try: |
307 self._AttemptTryjob(CHROMIUM_SRC_PATH, options, extra_args) | 336 # Check the existence of repo path. |
337 if not os.path.exists(repo_path): | |
338 raise TrybotError('Repository path "%s" does not exists, please check ' | |
sullivan
2016/09/08 03:22:59
s/does not exists/does not exist/
prasadv
2016/09/08 19:03:33
Done.
| |
339 'the value of <repo_path> argument.' % repo_path) | |
340 # Change to the repo directory. | |
341 os.chdir(repo_path) | |
sullivan
2016/09/08 03:22:59
Why the need for os.chdir here?
prasadv
2016/09/08 19:03:32
As mentioned in the previous comments, repo_path i
sullivan
2016/09/08 20:43:56
So it looks like _AttemptTryJob requires you to be
prasadv
2016/09/08 23:44:36
Done.
| |
342 self._AttemptTryjob(repo_path, options, extra_args) | |
308 except TrybotError, error: | 343 except TrybotError, error: |
309 print error | 344 print error |
310 return 1 | 345 return 1 |
346 finally: | |
347 # Restore to original working directory. | |
348 os.chdir(original_workdir) | |
311 return 0 | 349 return 0 |
312 | 350 |
313 def _GetPerfConfig(self, bot_platform, arguments): | 351 def _GetPerfConfig(self, bot_platform, arguments): |
314 """Generates the perf config for try job. | 352 """Generates the perf config for try job. |
315 | 353 |
316 Args: | 354 Args: |
317 bot_platform: Name of the platform to be generated. | 355 bot_platform: Name of the platform to be generated. |
318 arguments: Command line arguments. | 356 arguments: Command line arguments. |
319 | 357 |
320 Returns: | 358 Returns: |
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
396 'Cannot send a try job with a dirty tree. Please commit ' | 434 'Cannot send a try job with a dirty tree. Please commit ' |
397 'your changes locally first in %s repository.' % repo_path) | 435 'your changes locally first in %s repository.' % repo_path) |
398 | 436 |
399 # Make sure the tree does have local commits. | 437 # Make sure the tree does have local commits. |
400 output = RunGit(['footers', 'HEAD']) | 438 output = RunGit(['footers', 'HEAD']) |
401 if output: | 439 if output: |
402 raise TrybotError('No local changes found in %s repository.' % repo_path) | 440 raise TrybotError('No local changes found in %s repository.' % repo_path) |
403 | 441 |
404 return (repo_name, branch_name) | 442 return (repo_name, branch_name) |
405 | 443 |
444 def _GetBaseGitHashForRepo(self, branch_name, git_url): | |
445 """Gets the base revision for the repo on which local changes are made. | |
446 | |
447 Finds the upstream of the current branch that it is set to and gets | |
448 the HEAD revision from upstream. This also checks if the remote URL on | |
449 the upstream is supported by Perf Try job. | |
450 | |
451 Args: | |
452 branch_name: Current working branch name. | |
453 git_url: Remote URL of the repo. | |
454 | |
455 Returns: | |
456 Git hash of the HEAD revision from the upstream branch. | |
457 | |
458 Raises: | |
459 TrybotError: This exception is raised when a GIT command fails or if the | |
460 remote URL of the repo found is not supported. | |
461 """ | |
462 while not self._IsRepoSupported(branch_name, git_url): | |
463 branch_name = RunGit( | |
464 ['rev-parse', '--abbrev-ref', '%s@{upstream}' % branch_name], | |
465 'Failed to get upstream branch name.') | |
sullivan
2016/09/08 03:22:59
Isn't this an infinite loop?
prasadv
2016/09/08 19:03:33
I don't think so, because every time we enter the
sullivan
2016/09/08 20:43:57
I think adding a high-level comment to explain wha
prasadv
2016/09/08 23:44:36
Done.
| |
466 | |
467 return RunGit( | |
468 ['rev-parse', '%s@{upstream}' % branch_name], | |
469 'Failed to get base revision hash on upstream.') | |
470 | |
471 def _IsRepoSupported(self, current_branch, repo_git_url): | |
472 cur_remote = RunGit( | |
473 ['config', 'branch.%s.remote'% current_branch], | |
474 'Failed to get branch.%s.remote from git config' % current_branch) | |
475 cur_remote = cur_remote.strip() | |
476 if cur_remote == '.': | |
477 return False | |
478 cur_remote_url = RunGit( | |
479 ['config', 'remote.%s.url' % cur_remote], | |
480 'Failed to get remote.%s.url from git config' % cur_remote) | |
481 if cur_remote_url.lower() == repo_git_url: | |
482 return True | |
483 raise TrybotError('URL %s on remote %s is not recognized on branch.'% ( | |
484 cur_remote_url, cur_remote)) | |
485 | |
406 def _AttemptTryjob(self, repo_path, options, extra_args): | 486 def _AttemptTryjob(self, repo_path, options, extra_args): |
407 """Attempts to run a tryjob from a repo directory. | 487 """Attempts to run a tryjob from a repo directory. |
408 | 488 |
409 Args: | 489 Args: |
410 repo_path: Path to the repository. | 490 repo_path: Path to the repository. |
411 options: Command line arguments to run benchmark. | 491 options: Command line arguments to run benchmark. |
412 extra_args: Extra arugments to run benchmark. | 492 extra_args: Extra arugments to run benchmark. |
413 """ | 493 """ |
414 repo_name, branch_name = self._GetRepoAndBranchName(repo_path) | 494 repo_name, branch_name = self._GetRepoAndBranchName(repo_path) |
415 | 495 |
496 repo_info = REPO_INFO_MAP.get(repo_name, None) | |
497 if not repo_info: | |
498 raise TrybotError('Unsupported repository %s' % repo_name) | |
sullivan
2016/09/08 03:22:59
Here the error would be clearer if users specified
| |
499 | |
500 deps_override = None | |
501 if repo_name != 'src': | |
502 if not options.deps_revision: | |
503 options.deps_revision = self._GetBaseGitHashForRepo( | |
504 branch_name, repo_info.get('url')) | |
505 deps_override = {repo_info.get('src'): options.deps_revision} | |
506 | |
416 arguments = [options.benchmark_name] + extra_args | 507 arguments = [options.benchmark_name] + extra_args |
417 | 508 |
418 rietveld_url = self._UploadPatchToRietveld(repo_name, options) | 509 rietveld_url = self._UploadPatchToRietveld(repo_name, options) |
419 print ('\nUploaded try job to rietveld.\nview progress here %s.' | 510 print ('\nUploaded try job to rietveld.\nview progress here %s.' |
420 '\n\tRepo Name: %s\n\tPath: %s\n\tBranch: %s' % ( | 511 '\n\tRepo Name: %s\n\tPath: %s\n\tBranch: %s' % ( |
421 rietveld_url, repo_name, repo_path, branch_name)) | 512 rietveld_url, repo_name, repo_path, branch_name)) |
422 | 513 |
423 for bot_platform in self._builder_names: | 514 for bot_platform in self._builder_names: |
424 if not self._builder_names[bot_platform]: | 515 if not self._builder_names[bot_platform]: |
425 logging.warning('No builder is found for %s', bot_platform) | 516 logging.warning('No builder is found for %s', bot_platform) |
426 continue | 517 continue |
427 try: | 518 try: |
428 self._RunTryJob(bot_platform, arguments) | 519 self._RunTryJob(bot_platform, arguments, deps_override) |
429 except TrybotError, err: | 520 except TrybotError, err: |
430 print err | 521 print err |
431 | 522 |
432 def _UploadPatchToRietveld(self, repo_name, options): | 523 def _UploadPatchToRietveld(self, repo_name, options): |
433 """Uploads the patch to rietveld and returns rietveld URL.""" | 524 """Uploads the patch to rietveld and returns rietveld URL.""" |
434 output = RunGit(['cl', 'upload', '-f', '--bypass-hooks', '-m', | 525 output = RunGit(['cl', 'upload', '-f', '--bypass-hooks', '-m', |
435 ('CL for %s perf tryjob to run %s benchmark ' | 526 ('CL for %s perf tryjob to run %s benchmark ' |
436 'on %s platform(s)' % ( | 527 'on %s platform(s)' % ( |
437 repo_name, options.benchmark_name, options.trybot))], | 528 repo_name, options.benchmark_name, options.trybot))], |
438 'Could not upload to rietveld for %s' % repo_name) | 529 'Could not upload to rietveld for %s' % repo_name) |
439 | 530 |
440 match = re.search(r'https://codereview.chromium.org/[\d]+', output) | 531 match = re.search(r'https://codereview.chromium.org/[\d]+', output) |
441 if not match: | 532 if not match: |
442 raise TrybotError('Could not upload CL to rietveld for %s! Output %s' % | 533 raise TrybotError('Could not upload CL to rietveld for %s! Output %s' % |
443 (repo_name, output)) | 534 (repo_name, output)) |
444 return match.group(0) | 535 return match.group(0) |
445 | 536 |
446 def _RunTryJob(self, bot_platform, arguments): | 537 def _RunTryJob(self, bot_platform, arguments, deps_override): |
447 """Executes perf try job with benchmark test properties. | 538 """Executes perf try job with benchmark test properties. |
448 | 539 |
449 Args: | 540 Args: |
450 bot_platform: Name of the platform to be generated. | 541 bot_platform: Name of the platform to be generated. |
451 arguments: Command line arguments. | 542 arguments: Command line arguments. |
543 deps_override: DEPS revision if needs to be overridden. | |
452 | 544 |
453 Raises: | 545 Raises: |
454 TrybotError: When trybot fails to upload CL or run git try. | 546 TrybotError: When trybot fails to upload CL or run git try. |
455 """ | 547 """ |
456 config = self._GetPerfConfig(bot_platform, arguments) | 548 config = self._GetPerfConfig(bot_platform, arguments) |
457 | 549 |
458 # Generate git try command for available bots. | 550 # Generate git try command for available bots. |
459 git_try_command = ['cl', 'try', '-m', 'tryserver.chromium.perf'] | 551 git_try_command = ['cl', 'try', '-m', 'tryserver.chromium.perf'] |
460 | 552 |
461 # Add Perf Test config to git try --properties arg. | 553 # Add Perf Test config to git try --properties arg. |
462 git_try_command.extend(['-p', 'perf_try_config=%s' % json.dumps(config)]) | 554 git_try_command.extend(['-p', 'perf_try_config=%s' % json.dumps(config)]) |
463 | 555 |
556 # Add deps overrides to git try --properties arg. | |
557 if deps_override: | |
558 git_try_command.extend([ | |
559 '-p', 'deps_revision_overrides=%s' % json.dumps(deps_override)]) | |
464 for bot in self._builder_names[bot_platform]: | 560 for bot in self._builder_names[bot_platform]: |
465 git_try_command.extend(['-b', bot]) | 561 git_try_command.extend(['-b', bot]) |
466 | 562 |
467 RunGit(git_try_command, 'Could not try CL for %s' % bot_platform) | 563 RunGit(git_try_command, 'Could not try CL for %s' % bot_platform) |
468 print 'Perf Try job sent to rietveld for %s platform.' % bot_platform | 564 print 'Perf Try job sent to rietveld for %s platform.' % bot_platform |
OLD | NEW |