| Index: tools/telemetry/telemetry/core/backends/remote/trybot_browser_finder.py
|
| diff --git a/tools/telemetry/telemetry/core/backends/remote/trybot_browser_finder.py b/tools/telemetry/telemetry/core/backends/remote/trybot_browser_finder.py
|
| index 344d1bf5015003bee750cd3808e16d4dde209e3c..cbafc617e62f18d959cfb63049bf67255148b08e 100644
|
| --- a/tools/telemetry/telemetry/core/backends/remote/trybot_browser_finder.py
|
| +++ b/tools/telemetry/telemetry/core/backends/remote/trybot_browser_finder.py
|
| @@ -20,7 +20,21 @@ from telemetry.core.platform import trybot_device
|
| 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', 'linux_perf_tester',
|
| + 'linux_perf_bisector', 'win_perf_bisect_builder',
|
| + 'win_x64_perf_bisect_builder', 'linux_perf_bisect_builder',
|
| + 'mac_perf_bisect_builder', 'android_perf_bisect_builder'
|
| +]
|
|
|
| +INCLUDE_BOTS = ['trybot-all', 'trybot-all-win', 'trybot-all-mac',
|
| + 'trybot-all-linux', 'trybot-all-android'
|
| +]
|
| +
|
| +class TrybotError(Exception):
|
| +
|
| + def __str__(self):
|
| + return '%s\nError running tryjob.' % self.args[0]
|
|
|
|
|
| class PossibleTrybotBrowser(possible_browser.PossibleBrowser):
|
| @@ -28,8 +42,7 @@ class PossibleTrybotBrowser(possible_browser.PossibleBrowser):
|
|
|
| def __init__(self, browser_type, _):
|
| target_os = browser_type.split('-')[1]
|
| - self._buildername = '%s_perf_bisect' % browser_type.replace(
|
| - 'trybot-', '').replace('-', '_')
|
| + self._buildernames = _GetBuilderNames(browser_type)
|
| super(PossibleTrybotBrowser, self).__init__(browser_type, target_os, True)
|
|
|
| def Create(self, finder_options):
|
| @@ -55,13 +68,12 @@ class PossibleTrybotBrowser(possible_browser.PossibleBrowser):
|
| returncode = proc.poll()
|
| return (returncode, out, err)
|
|
|
| - def _AttemptTryjob(self, cfg_file_path):
|
| - """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 _UpdateConfigAndRunTryjob(self, bot_platform, cfg_file_path):
|
| + """Updates perf config file, uploads changes and excutes perf try job.
|
|
|
| Args:
|
| - cfg_file_path: Path to the config file for the try job.
|
| + bot_platform: Name of the platform to be generated.
|
| + cfg_file_path: Perf config file path.
|
|
|
| Returns:
|
| (result, msg) where result is one of:
|
| @@ -69,121 +81,169 @@ class PossibleTrybotBrowser(possible_browser.PossibleBrowser):
|
| 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.
|
| + url if success, otherwise throws TrybotError exception.
|
| """
|
| - returncode, original_branchname, err = self._RunProcess(
|
| - ['git', '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
|
| - return (ERROR, msg)
|
| - original_branchname = original_branchname.strip()
|
| -
|
| - # Check if the tree is dirty: make sure the index is up to date and then
|
| - # run diff-index
|
| - self._RunProcess(['git', 'update-index', '--refresh', '-q'])
|
| - returncode, out, err = self._RunProcess(['git', 'diff-index', 'HEAD'])
|
| - if out:
|
| - msg = 'Cannot send a try job with a dirty tree. Commit locally first.'
|
| + config = self._GetPerfConfig(bot_platform)
|
| + try:
|
| + config_file = open(cfg_file_path, 'w')
|
| + except IOError:
|
| + msg = 'Cannot find %s. Please run from src dir.' % cfg_file_path
|
| return (ERROR, msg)
|
| -
|
| - # Make sure the tree does have local commits.
|
| - returncode, out, err = self._RunProcess(
|
| - ['git', 'log', 'origin/master..HEAD'])
|
| - if not out:
|
| - return (NO_CHANGES, None)
|
| -
|
| - # Create/check out the telemetry-tryjob branch, and edit the configs
|
| - # for the tryjob there.
|
| + config_file.write('config = %s' % json.dumps(
|
| + config, sort_keys=True, indent=2, separators=(',', ': ')))
|
| + config_file.close()
|
| + # Commit the config changes locally.
|
| returncode, out, err = self._RunProcess(
|
| - ['git', 'checkout', '-b', 'telemetry-tryjob'])
|
| + ['git', 'commit', '-a', '-m', 'bisect config: %s' % bot_platform])
|
| if returncode:
|
| - msg = ('Error creating branch telemetry-tryjob. '
|
| - 'Please delete it if it exists.\n%s' % err)
|
| - return (ERROR, msg)
|
| - returncode, out, err = self._RunProcess(
|
| - ['git', 'branch', '--set-upstream-to', 'origin/master'])
|
| + 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 = self._RunProcess([
|
| + 'git', 'cl', 'upload', '-f', '--bypass-hooks', '-m',
|
| + 'CL for perf tryjob on %s' % bot_platform
|
| + ])
|
| + if returncode:
|
| + raise TrybotError('Could 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', 'cl', 'try', '-m', 'tryserver.chromium.perf']
|
| + for bot in self._buildernames[bot_platform]:
|
| + git_try_command.extend(['-b', bot])
|
| + returncode, out, err = self._RunProcess(git_try_command)
|
| if returncode:
|
| - return (ERROR, 'Error in git branch --set-upstream-to: %s' % err)
|
| + raise TrybotError('Could not try CL for %s, error %s' %
|
| + (bot_platform, err))
|
| +
|
| + return (SUCCESS, rietveld_url)
|
| +
|
| + def _GetPerfConfig(self, bot_platform):
|
| + """Generates the perf config for try job.
|
| +
|
| + Args:
|
| + bot_platform: Name of the platform to be generated.
|
|
|
| + Returns:
|
| + Returns a perf config parameters as dictionary.
|
| + """
|
| # Generate the command line for the perf trybots
|
| + target_arch = 'ia32'
|
| arguments = sys.argv
|
| - if self._target_os == 'win':
|
| + if bot_platform in ['win', 'win-x64']:
|
| arguments[0] = 'python tools\\perf\\run_benchmark'
|
| else:
|
| arguments[0] = './tools/perf/run_benchmark'
|
| for index, arg in enumerate(arguments):
|
| if arg.startswith('--browser='):
|
| - if self._target_os == 'android':
|
| + if bot_platform == 'android':
|
| arguments[index] = '--browser=android-chrome-shell'
|
| - elif 'x64' in self._buildername:
|
| + elif any('x64' in bot for bot in self._buildernames[bot_platform]):
|
| arguments[index] = '--browser=release_x64'
|
| + target_arch = 'x64'
|
| else:
|
| arguments[index] = '--browser=release'
|
| command = ' '.join(arguments)
|
|
|
| - # Set target architecture to build 32 or 64 bit binaries.
|
| - target_arch = 'x64' if 'x64' in self._buildername else 'ia32'
|
| -
|
| - # Add the correct command to the config file and commit it.
|
| - config = {
|
| + return {
|
| 'command': command,
|
| 'repeat_count': '1',
|
| 'max_time_minutes': '120',
|
| 'truncate_percent': '0',
|
| 'target_arch': target_arch,
|
| }
|
| - try:
|
| - config_file = open(cfg_file_path, 'w')
|
| - except IOError:
|
| - msg = 'Cannot find %s. Please run from src dir.' % cfg_file_path
|
| - return (ERROR, msg)
|
| - config_file.write('config = %s' % json.dumps(
|
| - config, sort_keys=True, indent=2, separators=(',', ': ')))
|
| - config_file.close()
|
| - returncode, out, err = self._RunProcess(
|
| - ['git', 'commit', '-a', '-m', 'bisect config'])
|
| - if returncode:
|
| - msg = 'Could not commit bisect config change, error %s' % err
|
| - return (ERROR, msg)
|
|
|
| - # Upload the CL to rietveld and run a try job.
|
| - returncode, out, err = self._RunProcess([
|
| - 'git', 'cl', 'upload', '-f', '--bypass-hooks', '-m',
|
| - 'CL for perf tryjob'
|
| - ])
|
| - if returncode:
|
| - msg = 'Could upload to rietveld, error %s' % err
|
| - return (ERROR, msg)
|
| - match = re.search(r'https://codereview.chromium.org/[\d]+', out)
|
| - if not match:
|
| - msg = 'Could not upload CL to rietveld! Output %s' % out
|
| - return (ERROR, msg)
|
| - rietveld_url = match.group(0)
|
| - returncode, out, err = self._RunProcess([
|
| - 'git', 'cl', 'try', '-m', 'tryserver.chromium.perf', '-b',
|
| - self._buildername])
|
| + def _AttemptTryjob(self, cfg_file_path):
|
| + """Attempts to run a tryjob from the current directory.
|
| +
|
| + This is run once for chromium, and if it returns NO_CHANGES, once for blink.
|
| +
|
| + Args:
|
| + cfg_file_path: Path to the config file for the try job.
|
| +
|
| + 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.
|
| + """
|
| + source_repo = 'chromium'
|
| + if cfg_file_path == BLINK_CONFIG_FILENAME:
|
| + source_repo = 'blink'
|
| +
|
| + returncode, original_branchname, err = self._RunProcess(
|
| + ['git', 'rev-parse', '--abbrev-ref', 'HEAD'])
|
| if returncode:
|
| - msg = 'Could not try CL, error %s' % err
|
| - return (ERROR, msg)
|
| + 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()
|
| +
|
| + # Check if the tree is dirty: make sure the index is up to date and then
|
| + # run diff-index
|
| + self._RunProcess(['git', 'update-index', '--refresh', '-q'])
|
| + returncode, out, err = self._RunProcess(['git', 'diff-index', 'HEAD'])
|
| + if out:
|
| + logging.error(
|
| + 'Cannot send a try job with a dirty tree. Commit locally first.')
|
| + return ERROR
|
|
|
| - # Checkout original branch and delete telemetry-tryjob branch.
|
| + # Make sure the tree does have local commits.
|
| returncode, out, err = self._RunProcess(
|
| - ['git', 'checkout', original_branchname])
|
| - if returncode:
|
| - msg = (
|
| - ('Could not check out %s. Please check it out and manually '
|
| - 'delete the telemetry-tryjob branch. Error message: %s') %
|
| - (original_branchname, err))
|
| - return (ERROR, msg)
|
| + ['git', '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 = self._RunProcess(
|
| - ['git', 'branch', '-D', 'telemetry-tryjob'])
|
| + ['git', 'checkout', '-b', 'telemetry-tryjob'])
|
| if returncode:
|
| - msg = (('Could not delete telemetry-tryjob branch. '
|
| - 'Please delete it manually. Error %s') % err)
|
| - return (ERROR, msg)
|
| - return (SUCCESS, rietveld_url)
|
| + logging.error('Error creating branch telemetry-tryjob. '
|
| + 'Please delete it if it exists.\n%s', err)
|
| + return ERROR
|
| + try:
|
| + returncode, out, err = self._RunProcess(
|
| + ['git', '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._buildernames:
|
| + try:
|
| + results, output = self._UpdateConfigAndRunTryjob(
|
| + bot_platform, cfg_file_path)
|
| + if results == ERROR:
|
| + logging.error(output)
|
| + return ERROR
|
| + 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.
|
| + returncode, out, err = self._RunProcess(
|
| + ['git', '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 = self._RunProcess(
|
| + ['git', '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
|
|
|
| def RunRemote(self):
|
| """Sends a tryjob to a perf trybot.
|
| @@ -193,29 +253,17 @@ class PossibleTrybotBrowser(possible_browser.PossibleBrowser):
|
| tryjob on the given bot.
|
| """
|
| # First check if there are chromium changes to upload.
|
| - status, msg = self._AttemptTryjob(CHROMIUM_CONFIG_FILENAME)
|
| - if status == SUCCESS:
|
| - print 'Uploaded chromium try job to rietveld. View progress at %s' % msg
|
| - return
|
| - elif status == ERROR:
|
| - logging.error(msg)
|
| - return
|
| -
|
| - # If we got here, there are no chromium changes to upload. Try blink.
|
| - os.chdir('third_party/WebKit/')
|
| - status, msg = self._AttemptTryjob(BLINK_CONFIG_FILENAME)
|
| - os.chdir('../..')
|
| - if status == SUCCESS:
|
| - print 'Uploaded blink try job to rietveld. View progress at %s' % msg
|
| - return
|
| - elif status == ERROR:
|
| - logging.error(msg)
|
| - return
|
| - else:
|
| - logging.error('No local changes found in chromium or blink trees. '
|
| - 'browser=%s argument sends local changes to the %s '
|
| - 'perf trybot.', self.browser_type, self._buildername)
|
| - return
|
| + status = self._AttemptTryjob(CHROMIUM_CONFIG_FILENAME)
|
| + 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)
|
| + 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.', self.browser_type,
|
| + self._buildernames.values())
|
|
|
| def _InitPlatformIfNeeded(self):
|
| if self._platform:
|
| @@ -240,12 +288,50 @@ def _GetTrybotList():
|
| f = urllib2.urlopen(
|
| 'http://build.chromium.org/p/tryserver.chromium.perf/json')
|
| builders = json.loads(f.read()).get('builders', {}).keys()
|
| - builders = ['trybot-%s' % b.replace('_perf_bisect', '').replace('_', '-')
|
| - for b in builders if not b.endswith('_perf_bisect_builder')]
|
| # Perf try jobs do not work on Windows XP
|
| - if 'trybot-win-xp' in builders:
|
| - builders.remove('trybot-win-xp')
|
| - return builders
|
| + builders = ['trybot-%s' % bot.replace('_perf_bisect', '').replace('_', '-')
|
| + for bot in builders if bot not in EXCLUDED_BOTS]
|
| + builders.extend(INCLUDE_BOTS)
|
| + return sorted(builders)
|
| +
|
| +
|
| +def _GetBuilderNames(browser_type):
|
| + """ Return platform and its available bot name as dictionary."""
|
| + if 'all' not in browser_type:
|
| + bot = ['%s_perf_bisect' % browser_type.replace(
|
| + 'trybot-', '').replace('-', '_')]
|
| + bot_platform = browser_type.split('-')[1]
|
| + if 'x64' in browser_type:
|
| + bot_platform += '-x64'
|
| + return {bot_platform: bot}
|
| +
|
| + f = urllib2.urlopen(
|
| + 'http://build.chromium.org/p/tryserver.chromium.perf/json')
|
| + builders = json.loads(f.read()).get('builders', {}).keys()
|
| + # Exclude unsupported bots like win xp and some dummy bots.
|
| + builders = [bot for bot in builders if bot not in EXCLUDED_BOTS]
|
| +
|
| + platform_and_bots = {}
|
| + for os_name in ['linux', 'android', 'mac', 'win']:
|
| + platform_and_bots[os_name] = [bot for bot in builders if os_name in bot]
|
| +
|
| + # Special case for Windows x64, consider it as separate platform
|
| + # config config should contain target_arch=x64 and --browser=release_x64.
|
| + win_x64_bots = [platform_and_bots['win'].pop(i)
|
| + for i, win_bot in enumerate(platform_and_bots['win']) if 'x64' in win_bot]
|
| + platform_and_bots['win_x64'] = win_x64_bots
|
| +
|
| + if 'all-win' in browser_type:
|
| + return {'win': platform_and_bots['win'],
|
| + 'win_x64': platform_and_bots['win_x64']}
|
| + if 'all-mac' in browser_type:
|
| + return {'mac': platform_and_bots['mac']}
|
| + if 'all-android' in browser_type:
|
| + return {'android': platform_and_bots['android']}
|
| + if 'all-linux' in browser_type:
|
| + return {'linux': platform_and_bots['linux']}
|
| +
|
| + return platform_and_bots
|
|
|
|
|
| def FindAllBrowserTypes(finder_options):
|
|
|