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

Unified Diff: tools/perf/core/trybot_command.py

Issue 2245333003: CL for perf tryjob on linux Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: CL for src perf tryjob Created 4 years, 4 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | tools/perf/core/trybot_command_unittest.py » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: tools/perf/core/trybot_command.py
diff --git a/tools/perf/core/trybot_command.py b/tools/perf/core/trybot_command.py
index 7d97fb52bb5b21ea088649783e34716cd7766bd4..af44a808c529a321eae753836904f56e596d6cad 100644
--- a/tools/perf/core/trybot_command.py
+++ b/tools/perf/core/trybot_command.py
@@ -3,13 +3,15 @@
# found in the LICENSE file.
import argparse
-import os
+import json
import logging
+import os
import platform
import re
import subprocess
+import sys
import urllib2
-import json
+
from core import path_util
@@ -20,9 +22,6 @@ from telemetry.util import command_line
from telemetry.util import matching
-CHROMIUM_CONFIG_FILENAME = 'tools/run-perf-test.cfg'
-BLINK_CONFIG_FILENAME = 'Tools/run-perf-test.cfg'
-SUCCESS, NO_CHANGES, ERROR = range(3)
# Unsupported Perf bisect bots.
EXCLUDED_BOTS = {
'win_xp_perf_bisect', # Goma issues: crbug.com/330900
@@ -57,20 +56,41 @@ INCLUDE_BOTS = [
]
# Default try bot to use incase builbot is unreachable.
-DEFAULT_TRYBOTS = [
+DEFAULT_TRYBOTS = [
'linux_perf_bisect',
'mac_10_11_perf_bisect',
'winx64_10_perf_bisect',
'android_s5_perf_bisect',
]
-assert not set(DEFAULT_TRYBOTS) & set(EXCLUDED_BOTS), ( 'A trybot cannot '
- 'present in both Default as well as Excluded bots lists.')
+CHROMIUM_SRC_PATH = path_util.GetChromiumSrcDir()
+REPO_INFO_MAP = {
+ 'src': {
+ 'src': 'src',
+ 'url': 'https://chromium.googlesource.com/chromium/src.git',
+ },
+ 'v8': {
+ 'src': 'src/v8',
+ 'url': 'https://chromium.googlesource.com/v8/v8.git',
+ },
+ 'skia': {
+ 'src': 'src/third_party/skia',
+ 'url': 'https://chromium.googlesource.com/skia.git',
+ },
+ 'angle': {
+ 'src': 'src/third_party/angle',
+ 'url': 'https://chromium.googlesource.com/angle/angle.git',
+ }
+}
+
+assert not set(DEFAULT_TRYBOTS) & set(EXCLUDED_BOTS), (
+ 'A trybot cannot present in both Default as well as Excluded bots lists.')
+
class TrybotError(Exception):
def __str__(self):
- return '%s\nError running tryjob.' % self.args[0]
+ return '(ERROR) Perf Try Job: %s' % self.args[0]
def _GetTrybotList(builders):
@@ -89,7 +109,7 @@ def _GetBotPlatformFromTrybotName(trybot_name):
def _GetBuilderNames(trybot_name, builders):
- """ Return platform and its available bot name as dictionary."""
+ """Return platform and its available bot name as dictionary."""
os_names = ['linux', 'android', 'mac', 'win']
if 'all' not in trybot_name:
bot = ['%s_perf_bisect' % trybot_name.replace('-', '_')]
@@ -125,6 +145,14 @@ def _GetBuilderNames(trybot_name, builders):
return platform_and_bots
+_GIT_CMD = 'git'
+
+
+if platform.system() == 'Windows':
+ # On windows, the git command is installed as 'git.bat'
+ _GIT_CMD = 'git.bat'
+
+
def _RunProcess(cmd):
logging.debug('Running process: "%s"', ' '.join(cmd))
proc = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
@@ -133,14 +161,19 @@ def _RunProcess(cmd):
return (returncode, out, err)
-_GIT_CMD = 'git'
-if platform.system() == 'Windows':
- # On windows, the git command is installed as 'git.bat'
- _GIT_CMD = 'git.bat'
+def RunGit(cmd, msg_on_error='', ignore_return_code=False):
+ try:
+ output = subprocess.check_output([_GIT_CMD] + cmd, stderr=subprocess.STDOUT)
+ return output.decode(sys.stdout.encoding).strip()
+ except subprocess.CalledProcessError as e:
+ if ignore_return_code:
+ return None
+ raise TrybotError('%s. \n%s' % (
+ msg_on_error, e.output.decode(sys.stdout.encoding)))
class Trybot(command_line.ArgParseCommand):
- """ Run telemetry perf benchmark on trybot """
+ """Run telemetry perf benchmark on trybot."""
usage = 'botname benchmark_name [<benchmark run options>]'
_builders = None
@@ -159,10 +192,10 @@ class Trybot(command_line.ArgParseCommand):
# In case of any kind of exception, allow tryjobs to use default trybots.
# Possible exception are ssl.SSLError, urllib2.URLError,
# socket.timeout, socket.error.
- except Exception:
+ except Exception: # pylint: disable=broad-except
# Incase of any exception return default trybots.
print ('WARNING: Unable to reach builbot to retrieve trybot '
- 'information, tryjob will use default trybots.')
+ 'information, tryjob will use default trybots.')
cls._builders = DEFAULT_TRYBOTS
else:
builders = json.loads(f.read()).keys()
@@ -189,9 +222,9 @@ class Trybot(command_line.ArgParseCommand):
if arg == '--browser' or arg.startswith('--browser='):
parser.error('--browser=... is not allowed when running trybot.')
all_benchmarks = discover.DiscoverClasses(
- start_dir=path_util.GetPerfBenchmarksDir(),
- top_level_dir=path_util.GetPerfDir(),
- base_class=benchmark.Benchmark).values()
+ start_dir=path_util.GetPerfBenchmarksDir(),
+ top_level_dir=path_util.GetPerfDir(),
+ base_class=benchmark.Benchmark).values()
all_benchmark_names = [b.Name() for b in all_benchmarks]
all_benchmarks_by_names = {b.Name(): b for b in all_benchmarks}
benchmark_class = all_benchmarks_by_names.get(options.benchmark_name, None)
@@ -199,9 +232,9 @@ class Trybot(command_line.ArgParseCommand):
possible_benchmark_names = matching.GetMostLikelyMatchedObject(
all_benchmark_names, options.benchmark_name)
parser.error(
- 'No benchmark named "%s". Do you mean any of those benchmarks '
- 'below?\n%s' %
- (options.benchmark_name, '\n'.join(possible_benchmark_names)))
+ 'No benchmark named "%s". Do you mean any of those benchmarks '
+ 'below?\n%s' % (
+ options.benchmark_name, '\n'.join(possible_benchmark_names)))
is_benchmark_disabled, reason = cls.IsBenchmarkDisabledOnTrybotPlatform(
benchmark_class, options.trybot)
also_run_disabled_option = '--also-run-disabled-tests'
@@ -211,7 +244,7 @@ class Trybot(command_line.ArgParseCommand):
@classmethod
def IsBenchmarkDisabledOnTrybotPlatform(cls, benchmark_class, trybot_name):
- """ Return whether benchmark will be disabled on trybot platform.
+ """Return whether benchmark will be disabled on trybot platform.
Note that we cannot tell with certainty whether the benchmark will be
disabled on the trybot platform since the disable logic in ShouldDisable()
@@ -271,6 +304,15 @@ class Trybot(command_line.ArgParseCommand):
help=('specify which benchmark to run. To see all available benchmarks,'
' run `run_benchmark list`'),
metavar='<benchmark name>')
+ parser.add_argument(
+ '--repo_path', type=str, default=CHROMIUM_SRC_PATH,
+ help='specify which repo path to use for perf try job\n',
+ metavar='<repo name>')
+ parser.add_argument(
+ '--deps_revision', type=str, default=None,
+ help='specify DEPS revision to be used by Chromium.\n',
+ metavar='<repo name>')
+
def Run(self, options, extra_args=None):
"""Sends a tryjob to a perf trybot.
@@ -283,88 +325,30 @@ class Trybot(command_line.ArgParseCommand):
extra_args = []
self._InitializeBuilderNames(options.trybot)
- arguments = [options.benchmark_name] + extra_args
-
- # First check if there are chromium changes to upload.
- status = self._AttemptTryjob(CHROMIUM_CONFIG_FILENAME, arguments)
- if status not in [SUCCESS, ERROR]:
- # If we got here, there are no chromium changes to upload. Try blink.
- os.chdir('third_party/WebKit/')
- status = self._AttemptTryjob(BLINK_CONFIG_FILENAME, arguments)
- os.chdir('../..')
- if status not in [SUCCESS, ERROR]:
- logging.error('No local changes found in chromium or blink trees. '
- 'browser=%s argument sends local changes to the '
- 'perf trybot(s): %s.', options.trybot,
- self._builder_names.values())
- return 1
- return 0
-
- def _UpdateConfigAndRunTryjob(self, bot_platform, cfg_file_path, arguments):
- """Updates perf config file, uploads changes and excutes perf try job.
-
- Args:
- bot_platform: Name of the platform to be generated.
- cfg_file_path: Perf config file path.
-
- Returns:
- (result, msg) where result is one of:
- SUCCESS if a tryjob was sent
- NO_CHANGES if there was nothing to try,
- ERROR if a tryjob was attempted but an error encountered
- and msg is an error message if an error was encountered, or rietveld
- url if success, otherwise throws TrybotError exception.
- """
- config = self._GetPerfConfig(bot_platform, arguments)
- config_to_write = 'config = %s' % json.dumps(
- config, sort_keys=True, indent=2, separators=(',', ': '))
-
+ original_workdir = os.getcwd()
+ repo_path = os.path.abspath(options.repo_path)
try:
- with open(cfg_file_path, 'r') as config_file:
- if config_to_write == config_file.read():
- return NO_CHANGES, ''
- except IOError:
- msg = 'Cannot find %s. Please run from src dir.' % cfg_file_path
- return (ERROR, msg)
-
- with open(cfg_file_path, 'w') as config_file:
- config_file.write(config_to_write)
- # Commit the config changes locally.
- returncode, out, err = _RunProcess(
- [_GIT_CMD, 'commit', '-a', '-m', 'bisect config: %s' % bot_platform])
- if returncode:
- raise TrybotError('Could not commit bisect config change for %s,'
- ' error %s' % (bot_platform, err))
- # Upload the CL to rietveld and run a try job.
- returncode, out, err = _RunProcess([
- _GIT_CMD, 'cl', 'upload', '-f', '--bypass-hooks', '-m',
- 'CL for perf tryjob on %s' % bot_platform
- ])
- if returncode:
- raise TrybotError('Could not upload to rietveld for %s, error %s' %
- (bot_platform, err))
-
- match = re.search(r'https://codereview.chromium.org/[\d]+', out)
- if not match:
- raise TrybotError('Could not upload CL to rietveld for %s! Output %s' %
- (bot_platform, out))
- rietveld_url = match.group(0)
- # Generate git try command for available bots.
- git_try_command = [_GIT_CMD, 'cl', 'try', '-m', 'tryserver.chromium.perf']
- for bot in self._builder_names[bot_platform]:
- git_try_command.extend(['-b', bot])
- returncode, out, err = _RunProcess(git_try_command)
- if returncode:
- raise TrybotError('Could not try CL for %s, error %s' %
- (bot_platform, err))
-
- return (SUCCESS, rietveld_url)
+ # Check the existence of repo path.
+ if not os.path.exists(repo_path):
+ raise TrybotError('Repository path "%s" does not exists, please check '
+ 'the value of <repo_path> argument.' % repo_path)
+ # Change to the repo directory.
+ os.chdir(repo_path)
+ self._AttemptTryjob(repo_path, options, extra_args)
+ except TrybotError, error:
+ print error
+ return 1
+ finally:
+ # Restore to original working directory.
+ os.chdir(original_workdir)
+ return 0
def _GetPerfConfig(self, bot_platform, arguments):
"""Generates the perf config for try job.
Args:
bot_platform: Name of the platform to be generated.
+ arguments: Command line arguments.
Returns:
A dictionary with perf config parameters.
@@ -374,7 +358,7 @@ class Trybot(command_line.ArgParseCommand):
# Always set verbose logging for later debugging
if '-v' not in arguments and '--verbose' not in arguments:
- arguments.append('--verbose')
+ arguments.append('--verbose')
# Generate the command line for the perf trybots
target_arch = 'ia32'
@@ -384,10 +368,8 @@ class Trybot(command_line.ArgParseCommand):
'Trybot does not suport --chrome-root option set directly '
'through command line since it may contain references to your local '
'directory')
- if bot_platform in ['win', 'win-x64']:
- arguments.insert(0, 'python tools\\perf\\run_benchmark')
- else:
- arguments.insert(0, './tools/perf/run_benchmark')
+
+ arguments.insert(0, 'src/tools/perf/run_benchmark')
if bot_platform == 'android':
arguments.insert(1, '--browser=android-chromium')
@@ -407,100 +389,152 @@ class Trybot(command_line.ArgParseCommand):
'target_arch': target_arch,
}
- def _AttemptTryjob(self, cfg_file_path, arguments):
- """Attempts to run a tryjob from the current directory.
-
- This is run once for chromium, and if it returns NO_CHANGES, once for blink.
+ def _GetRepoAndBranchName(self, repo_path):
+ """Gets the repository name and working branch name.
Args:
- cfg_file_path: Path to the config file for the try job.
+ repo_path: Path to the repository.
Returns:
- Returns SUCCESS if a tryjob was sent, NO_CHANGES if there was nothing to
- try, ERROR if a tryjob was attempted but an error encountered.
+ Repository name and branch name as tuple.
+
+ Raises:
+ TrybotError: This exception is raised for the following cases,
+ 1. Try job is for non-git repository or in invalid branch.
+ 2. Un-committed changes in the current branch.
+ 3. No local commits in the current branch.
"""
- source_repo = 'chromium'
- if cfg_file_path == BLINK_CONFIG_FILENAME:
- source_repo = 'blink'
-
- # TODO(prasadv): This method is quite long, we should consider refactor
- # this by extracting to helper methods.
- returncode, original_branchname, err = _RunProcess(
- [_GIT_CMD, 'rev-parse', '--abbrev-ref', 'HEAD'])
- if returncode:
- msg = 'Must be in a git repository to send changes to trybots.'
- if err:
- msg += '\nGit error: %s' % err
- logging.error(msg)
- return ERROR
-
- original_branchname = original_branchname.strip()
+ # If command runs successfully, then the output will be repo root path.
+ # and current branch name.
+ output = RunGit(['rev-parse', '--abbrev-ref', '--show-toplevel', 'HEAD'],
+ ('%s is not a git repository, must be in a git repository '
+ 'to send changes to trybots' % os.getcwd()))
+
+ repo_info = output.split()
+ # Assuming the base directory name is same as repo project name set in
+ # codereviews.settings file.
+ repo_name = os.path.basename(repo_info[0]).strip()
+ branch_name = repo_info[1].strip()
+
+ if branch_name == 'HEAD':
+ raise TrybotError('Not on a valid branch, looks like branch '
+ 'is dettached. [branch:%s]' % branch_name)
# Check if the tree is dirty: make sure the index is up to date and then
# run diff-index
- _RunProcess([_GIT_CMD, 'update-index', '--refresh', '-q'])
- returncode, out, err = _RunProcess([_GIT_CMD, 'diff-index', 'HEAD'])
- if out:
- logging.error(
- 'Cannot send a try job with a dirty tree. Commit locally first.')
- return ERROR
+ RunGit(['update-index', '--refresh', '-q'], ignore_return_code=True)
+ output = RunGit(['diff-index', 'HEAD'])
+ if output:
+ raise TrybotError(
+ 'Cannot send a try job with a dirty tree. Please commit '
+ 'your changes locally first in %s repository.' % repo_path)
# Make sure the tree does have local commits.
- returncode, out, err = _RunProcess(
- [_GIT_CMD, 'log', 'origin/master..HEAD'])
- if not out:
- return NO_CHANGES
-
- # Create/check out the telemetry-tryjob branch, and edit the configs
- # for the tryjob there.
- returncode, out, err = _RunProcess(
- [_GIT_CMD, 'checkout', '-b', 'telemetry-tryjob'])
- if returncode:
- logging.error('Error creating branch telemetry-tryjob. '
- 'Please delete it if it exists.\n%s', err)
- return ERROR
- try:
- returncode, out, err = _RunProcess(
- [_GIT_CMD, 'branch', '--set-upstream-to', 'origin/master'])
- if returncode:
- logging.error('Error in git branch --set-upstream-to: %s', err)
- return ERROR
- for bot_platform in self._builder_names:
- if not self._builder_names[bot_platform]:
- logging.warning('No builder is found for %s', bot_platform)
- continue
- try:
- results, output = self._UpdateConfigAndRunTryjob(
- bot_platform, cfg_file_path, arguments)
- if results == ERROR:
- logging.error(output)
- return ERROR
- elif results == NO_CHANGES:
- print ('Skip the try job run on %s because it has been tried in '
- 'previous try job run. ' % bot_platform)
- else:
- print ('Uploaded %s try job to rietveld for %s platform. '
- 'View progress at %s' % (source_repo, bot_platform, output))
- except TrybotError, err:
- print err
- logging.error(err)
- finally:
- # Checkout original branch and delete telemetry-tryjob branch.
- # TODO(prasadv): This finally block could be extracted out to be a
- # separate function called _CleanupBranch.
- returncode, out, err = _RunProcess(
- [_GIT_CMD, 'checkout', original_branchname])
- if returncode:
- logging.error('Could not check out %s. Please check it out and '
- 'manually delete the telemetry-tryjob branch. '
- ': %s', original_branchname, err)
- return ERROR # pylint: disable=lost-exception
- logging.info('Checked out original branch: %s', original_branchname)
- returncode, out, err = _RunProcess(
- [_GIT_CMD, 'branch', '-D', 'telemetry-tryjob'])
- if returncode:
- logging.error('Could not delete telemetry-tryjob branch. '
- 'Please delete it manually: %s', err)
- return ERROR # pylint: disable=lost-exception
- logging.info('Deleted temp branch: telemetry-tryjob')
- return SUCCESS
+ output = RunGit(['footers', 'HEAD'])
+ if output:
+ raise TrybotError('No local changes found in %s repository.' % repo_path)
+
+ return (repo_name, branch_name)
+
+ def _GetBaseGitHashForRepo(self, branch_name, git_url):
+ """Gets the base revision for the repo on which local changes are made."""
+ while not self._IsRepoSupported(branch_name, git_url):
+ branch_name = RunGit([
+ 'rev-parse', '--abbrev-ref', '%s@{upstream}' % branch_name])
+ return RunGit(['rev-parse', '%s@{upstream}' % branch_name])
+
+ def _IsRepoSupported(self, current_branch, repo_git_url):
+ cur_remote = RunGit(['config', 'branch.%s.remote'% current_branch])
+ if cur_remote == '.':
+ return False
+ cur_remote_url= RunGit(['config', 'remote.%s.url' % cur_remote])
+ if cur_remote_url.lower() == repo_git_url:
+ return True
+ raise TrybotError('Remote url on remote %s is not recognized '
+ 'on branch: %s' % (cur_remote, cur_remote_url))
+
+ def _AttemptTryjob(self, repo_path, options, extra_args):
+ """Attempts to run a tryjob from a repo directory.
+
+ Args:
+ repo_path: Path to the repository.
+ options: Command line arguments to run benchmark.
+ extra_args: Extra arugments to run benchmark.
+ """
+ repo_name, branch_name = self._GetRepoAndBranchName(repo_path)
+
+ repo_info = REPO_INFO_MAP.get(repo_name, None)
+ if not repo_info:
+ raise TrybotError('Unsupported repository %s' % repo_name)
+
+ rietveld_url = self._UploadPatchToRietveld(repo_name)
+ print ('\nUploaded patch to rietveld.'
+ '\n\tRepo Name: %s\n\tPath: %s\n\tBranch: %s' % (
+ repo_name, repo_path, branch_name))
+
+ deps_override = None
+ if repo_name != 'src':
+ if not options.deps_revision:
+ options.deps_revision = self._GetBaseGitHashForRepo(
+ branch_name, repo_info.get('url'))
+ deps_override = {repo_info.get('src'): options.deps_revision}
+
+ arguments = [options.benchmark_name] + extra_args
+
+ rietveld_url = self._UploadPatchToRietveld(repo_name)
+ print ('\nUploaded try job to rietveld.\n'
+ 'view progress here %s.\n\tRepo Name: %s\n\tPath: %s\n\tBranch: %s' % (
+ rietveld_url, repo_name, repo_path, branch_name))
+
+ for bot_platform in self._builder_names:
+ if not self._builder_names[bot_platform]:
+ logging.warning('No builder is found for %s', bot_platform)
+ continue
+ try:
+ self._RunTryJob(bot_platform, arguments, deps_override)
+ print ('Perf Try job sent to rietveld for %s platform.\n' %
+ bot_platform)
+ except TrybotError, err:
+ print err
+
+ def _UploadPatchToRietveld(self, repo_name):
+ # Upload the CL to rietveld and run a try job.
+ output = RunGit(['cl', 'upload', '-f', '--bypass-hooks', '-m',
+ 'CL for %s perf tryjob' % repo_name],
+ 'Could not upload to rietveld for %s' % repo_name)
+
+ match = re.search(r'https://codereview.chromium.org/[\d]+', output)
+ if not match:
+ raise TrybotError('Could not upload CL to rietveld for %s! Output %s' %
+ (repo_name, output))
+ return match.group(0)
+
+
+ def _RunTryJob(self, bot_platform, arguments, deps_override):
+ """Generates perf try config, uploads changes and excutes perf try job.
+
+ Args:
+ bot_platform: Name of the platform to be generated.
+ arguments: Command line arguments.
+ deps_override: DEPS revision if needs to be overridden.
+
+ Raises:
+ TrybotError: When trybot fails to upload CL or run git try.
+ """
+ config = self._GetPerfConfig(bot_platform, arguments)
+
+ # Generate git try command for available bots.
+ git_try_command = ['cl', 'try', '-m', 'tryserver.chromium.perf']
+
+ # Add Perf Test config to git try --properties arg.
+ git_try_command.extend(['-p', 'perf_try_config=%s' % json.dumps(config)])
+
+ # Add deps overrides to git try --properties arg.
+ if deps_override:
+ git_try_command.extend([
+ '-p', 'deps_revision_overrides=%s' % json.dumps(deps_override)])
+
+ for bot in self._builder_names[bot_platform]:
+ git_try_command.extend(['-b', bot])
+
+ RunGit(git_try_command, 'Could not try CL for %s' % bot_platform)
« no previous file with comments | « no previous file | tools/perf/core/trybot_command_unittest.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698