OLD | NEW |
(Empty) | |
| 1 #!/usr/bin/env python |
| 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 |
| 4 # found in the LICENSE file. |
| 5 |
| 6 """Starts bisect try jobs on multiple platforms using known-good configs. |
| 7 |
| 8 The purpose of this script is to serve as an integration test for the |
| 9 auto-bisect project by starting try jobs for various config types and |
| 10 various platforms. |
| 11 |
| 12 The known-good configs are in this same directory as this script. They |
| 13 are expected to all end in ".cfg" and start with the name of the platform |
| 14 followed by a dot. |
| 15 |
| 16 You can specify --full to try running each config on all applicable bots; |
| 17 the default behavior is to try each config on only one bot. |
| 18 """ |
| 19 |
| 20 import argparse |
| 21 import logging |
| 22 import os |
| 23 import subprocess |
| 24 import sys |
| 25 |
| 26 SCRIPT_DIR = os.path.abspath(os.path.dirname(__file__)) |
| 27 BISECT_CONFIG = os.path.join(SCRIPT_DIR, os.path.pardir, 'bisect.cfg') |
| 28 PERF_TEST_CONFIG = os.path.join( |
| 29 SCRIPT_DIR, os.path.pardir, os.path.pardir, 'run-perf-test.cfg') |
| 30 PLATFORM_BOT_MAP = { |
| 31 'linux': ['linux_perf_bot'], |
| 32 'mac': ['mac_perf_bisect', 'mac_10_9_perf_bisect'], |
| 33 'win': ['win_perf_bisect', 'win_8_perf_bisect', 'win_xp_perf_bisect'], |
| 34 'android': [ |
| 35 'android_nexus4_perf_bisect', |
| 36 'android_nexus5_perf_bisect', |
| 37 'android_nexus7_perf_bisect', |
| 38 'android_nexus10_perf_bisect', |
| 39 ], |
| 40 } |
| 41 SVN_URL = 'svn://svn.chromium.org/chrome-try/try-perf' |
| 42 AUTO_COMMIT_MESSAGE = 'Automatic commit for bisect try job.' |
| 43 |
| 44 |
| 45 def main(argv): |
| 46 parser = argparse.ArgumentParser(description=__doc__) |
| 47 parser.add_argument('--full', action='store_true', |
| 48 help='Run each config on all applicable bots.') |
| 49 parser.add_argument('--filter', |
| 50 help='Filter for config filenames to use. Only configs ' |
| 51 'containing the given substring will be tried.') |
| 52 parser.add_argument('--verbose', '-v', action='store_true') |
| 53 args = parser.parse_args(argv[1:]) |
| 54 _SetupLogging(args.verbose) |
| 55 source_configs = _SourceConfigs(args.filter) |
| 56 logging.debug('Source configs: %s', source_configs) |
| 57 try: |
| 58 _StartTryJobs(source_configs, args.full) |
| 59 except subprocess.CalledProcessError as error: |
| 60 print str(error) |
| 61 print error.output |
| 62 |
| 63 |
| 64 def _SetupLogging(verbose): |
| 65 level = logging.INFO |
| 66 if verbose: |
| 67 level = logging.DEBUG |
| 68 logging.basicConfig(level=level) |
| 69 |
| 70 |
| 71 def _SourceConfigs(name_filter): |
| 72 """Gets a list of paths to sample configs to try.""" |
| 73 files = os.listdir(SCRIPT_DIR) |
| 74 files = [os.path.join(SCRIPT_DIR, name) for name in files] |
| 75 files = [name for name in files if name.endswith('.cfg')] |
| 76 if name_filter: |
| 77 files = [name for name in files if name_filter in name] |
| 78 return files |
| 79 |
| 80 |
| 81 def _StartTryJobs(source_configs, full_mode=False): |
| 82 """Tries each of the given sample configs on one or more try bots.""" |
| 83 for source_config in source_configs: |
| 84 dest_config = _DestConfig(source_config) |
| 85 bot_names = _BotNames(source_config, full_mode=full_mode) |
| 86 _StartTry(source_config, dest_config, bot_names) |
| 87 |
| 88 |
| 89 def _DestConfig(source_config): |
| 90 """Returns the path that a sample config should be copied to.""" |
| 91 if 'bisect' in source_config: |
| 92 return BISECT_CONFIG |
| 93 assert 'perf_test' in source_config, source_config |
| 94 return PERF_TEST_CONFIG |
| 95 |
| 96 |
| 97 def _BotNames(source_config, full_mode=False): |
| 98 """Returns try bot names to use for the given config file name.""" |
| 99 platform = os.path.basename(source_config).split('.')[0] |
| 100 assert platform in PLATFORM_BOT_MAP |
| 101 bot_names = PLATFORM_BOT_MAP[platform] |
| 102 if full_mode: |
| 103 return bot_names |
| 104 return [bot_names[0]] |
| 105 |
| 106 |
| 107 def _StartTry(source_config, dest_config, bot_names): |
| 108 """Sends a try job with the given config to the given try bots. |
| 109 |
| 110 Args: |
| 111 source_config: Path of the sample config to copy over. |
| 112 dest_config: Destination path to copy sample to, e.g. "./bisect.cfg". |
| 113 bot_names: List of try bot builder names. |
| 114 """ |
| 115 assert os.path.exists(source_config) |
| 116 assert os.path.exists(dest_config) |
| 117 assert _LastCommitMessage() != AUTO_COMMIT_MESSAGE |
| 118 |
| 119 # Copy the sample config over and commit it. |
| 120 _Run(['cp', source_config, dest_config]) |
| 121 _Run(['git', 'commit', '--all', '-m', AUTO_COMMIT_MESSAGE]) |
| 122 |
| 123 try: |
| 124 # Start the try job. |
| 125 job_name = 'Automatically-started (%s)' % os.path.basename(source_config) |
| 126 try_command = ['git', 'try', '--svn_repo', SVN_URL, '-n', job_name] |
| 127 for bot_name in bot_names: |
| 128 try_command.extend(['-b', bot_name]) |
| 129 print _Run(try_command) |
| 130 finally: |
| 131 # Revert the immediately-previous commit which was made just above. |
| 132 assert _LastCommitMessage() == AUTO_COMMIT_MESSAGE |
| 133 _Run(['git', 'reset', '--hard', 'HEAD~1']) |
| 134 |
| 135 |
| 136 def _LastCommitMessage(): |
| 137 return _Run(['git', 'log', '--format=%s', '-1']).strip() |
| 138 |
| 139 |
| 140 def _Run(command): |
| 141 """Runs a command in a subprocess. |
| 142 |
| 143 Args: |
| 144 command: The command given as an args list. |
| 145 |
| 146 Returns: |
| 147 The output of the command. |
| 148 |
| 149 Raises: |
| 150 subprocess.CalledProcessError: The return-code was non-zero. |
| 151 """ |
| 152 logging.debug('Running %s', command) |
| 153 return subprocess.check_output(command) |
| 154 |
| 155 |
| 156 if __name__ == '__main__': |
| 157 sys.exit(main(sys.argv)) |
OLD | NEW |