Chromium Code Reviews| 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 |