def _GetPerfTryConfig(bisect_bot, suite, good_revision, bad_revision, rerun_option=None): """Fills in a JSON response with the filled-in config file. Args: bisect_bot: Bisect bot name. suite: Test suite name. good_revision: Known good revision number. bad_revision: Known bad revision number. rerun_option: Optional rerun command line parameter. Returns: A dictionary with the result; if successful, this will contain "config", which is a config string; if there's an error, this will contain "error". """ command = GuessCommand(bisect_bot, suite, rerun_option=rerun_option) if not command: return {'error': 'Only Telemetry is supported at the moment.'} if not can_bisect.IsValidRevisionForBisect(good_revision): return {'error': 'Invalid "good" revision "%s".' % good_revision} if not can_bisect.IsValidRevisionForBisect(bad_revision): return {'error': 'Invalid "bad" revision "%s".' % bad_revision} config_dict = { 'command': command, 'good_revision': str(good_revision), 'bad_revision': str(bad_revision), 'repeat_count': '1', 'max_time_minutes': '60', } return config_dict
def GetBisectConfig( bisect_bot, master_name, suite, metric, good_revision, bad_revision, repeat_count, max_time_minutes, bug_id, use_archive=None, bisect_mode='mean', bypass_no_repro_check=False): """Fills in a JSON response with the filled-in config file. Args: bisect_bot: Bisect bot name. (This should be either a legacy bisector or a recipe-enabled tester). master_name: Master name of the test being bisected. suite: Test suite name of the test being bisected. metric: Bisect bot "metric" parameter, in the form "chart/trace". good_revision: Known good revision number. bad_revision: Known bad revision number. repeat_count: Number of times to repeat the test. max_time_minutes: Max time to run the test. bug_id: The Chromium issue tracker bug ID. use_archive: Specifies whether to use build archives or not to bisect. If this is not empty or None, then we want to use archived builds. bisect_mode: What aspect of the test run to bisect on; possible options are "mean", "std_dev", and "return_code". Returns: A dictionary with the result; if successful, this will contain "config", which is a config string; if there's an error, this will contain "error". """ command = GuessCommand(bisect_bot, suite, metric=metric) if not command: return {'error': 'Could not guess command for %r.' % suite} try: repeat_count = int(repeat_count) max_time_minutes = int(max_time_minutes) bug_id = int(bug_id) except ValueError: return {'error': 'repeat count, max time and bug_id must be integers.'} if not can_bisect.IsValidRevisionForBisect(good_revision): return {'error': 'Invalid "good" revision "%s".' % good_revision} if not can_bisect.IsValidRevisionForBisect(bad_revision): return {'error': 'Invalid "bad" revision "%s".' % bad_revision} config_dict = { 'command': command, 'good_revision': str(good_revision), 'bad_revision': str(bad_revision), 'metric': metric, 'repeat_count': str(repeat_count), 'max_time_minutes': str(max_time_minutes), 'bug_id': str(bug_id), 'builder_type': _BuilderType(master_name, use_archive), 'target_arch': GuessTargetArch(bisect_bot), 'bisect_mode': bisect_mode, } config_dict['recipe_tester_name'] = bisect_bot if bypass_no_repro_check: config_dict['required_initial_confidence'] = '0' return config_dict
def _MakeBisectTryJob(bug_id, test_anomaly, test): """Tries to automatically select parameters for a bisect job. Args: bug_id: A bug ID which some alerts are associated with. Returns: A TryJob entity, which has not yet been put in the datastore. Raises: NotBisectableError: A valid bisect config could not be created. """ good_revision = _GetRevisionForBisect(test_anomaly.start_revision - 1, test) bad_revision = _GetRevisionForBisect(test_anomaly.end_revision, test) if not can_bisect.IsValidRevisionForBisect(good_revision): raise NotBisectableError('Invalid "good" revision: %s.' % good_revision) if not can_bisect.IsValidRevisionForBisect(bad_revision): raise NotBisectableError('Invalid "bad" revision: %s.' % bad_revision) if test_anomaly.start_revision == test_anomaly.end_revision: raise NotBisectableError('Same "good"/"bad" revisions, bisect skipped') metric = start_try_job.GuessMetric(test.test_path) story_filter = start_try_job.GuessStoryFilter(test.test_path) bisect_bot = start_try_job.GuessBisectBot(test.master_name, test.bot_name) if not bisect_bot: raise NotBisectableError( 'Could not select a bisect bot: %s for (%s, %s)' % (bisect_bot, test.master_name, test.bot_name)) new_bisect_config = start_try_job.GetBisectConfig( bisect_bot=bisect_bot, master_name=test.master_name, suite=test.suite_name, metric=metric, story_filter=story_filter, good_revision=good_revision, bad_revision=bad_revision, repeat_count=10, max_time_minutes=20, bug_id=bug_id) if 'error' in new_bisect_config: raise NotBisectableError('Could not make a valid config.') config_python_string = utils.BisectConfigPythonString(new_bisect_config) bisect_job = try_job.TryJob(bot=bisect_bot, config=config_python_string, bug_id=bug_id, master_name=test.master_name, internal_only=test.internal_only, job_type='bisect') return bisect_job
def GetBisectConfig( bisect_bot, master_name, suite, metric, good_revision, bad_revision, repeat_count, max_time_minutes, bug_id, story_filter=None, bisect_mode='mean', use_staging_bot=False): """Fills in a JSON response with the filled-in config file. Args: bisect_bot: Bisect bot name. (This should be either a legacy bisector or a recipe-enabled tester). master_name: Master name of the test being bisected. suite: Test suite name of the test being bisected. metric: Bisect bot "metric" parameter, in the form "chart/trace". good_revision: Known good revision number. bad_revision: Known bad revision number. repeat_count: Number of times to repeat the test. max_time_minutes: Max time to run the test. bug_id: The Chromium issue tracker bug ID. bisect_mode: What aspect of the test run to bisect on; possible options are "mean", "std_dev", and "return_code". use_staging_bot: Specifies if we should redirect to a staging bot. Returns: A dictionary with the result; if successful, this will contain "config", which is a config string; if there's an error, this will contain "error". """ command = GuessCommand(bisect_bot, suite, story_filter=story_filter) if not command: return {'error': 'Could not guess command for %r.' % suite} try: repeat_count = int(repeat_count) max_time_minutes = int(max_time_minutes) bug_id = int(bug_id) except ValueError: return {'error': 'repeat count, max time and bug_id must be integers.'} if not can_bisect.IsValidRevisionForBisect(good_revision): return {'error': 'Invalid "good" revision "%s".' % good_revision} if not can_bisect.IsValidRevisionForBisect(bad_revision): return {'error': 'Invalid "bad" revision "%s".' % bad_revision} config_dict = { 'command': command, 'good_revision': str(good_revision), 'bad_revision': str(bad_revision), 'metric': metric, 'repeat_count': str(repeat_count), 'max_time_minutes': str(max_time_minutes), 'bug_id': str(bug_id), 'builder_type': _BuilderType(master_name), 'target_arch': GuessTargetArch(bisect_bot), 'bisect_mode': bisect_mode, } # If 'use_staging_bot' was checked, we try to redirect to a staging bot. # Do this here since we need to guess parts of the command line using the # bot's name. if use_staging_bot: bisect_bot = _GuessStagingBot(master_name, bisect_bot) or bisect_bot config_dict['recipe_tester_name'] = bisect_bot return config_dict
def _MakeBisectTryJob(bug_id, run_count=0): """Tries to automatically select parameters for a bisect job. Args: bug_id: A bug ID which some alerts are associated with. run_count: An integer; this is supposed to represent the number of times that a bisect has been tried for this bug; it is used to try different config parameters on different re-try attempts. Returns: A TryJob entity, which has not yet been put in the datastore. Raises: NotBisectableError: A valid bisect config could not be created. """ anomalies = anomaly.Anomaly.query(anomaly.Anomaly.bug_id == bug_id).fetch() if not anomalies: raise NotBisectableError('No Anomaly alerts found for this bug.') good_revision, bad_revision = _ChooseRevisionRange(anomalies) if not can_bisect.IsValidRevisionForBisect(good_revision): raise NotBisectableError('Invalid "good" revision: %s.' % good_revision) if not can_bisect.IsValidRevisionForBisect(bad_revision): raise NotBisectableError('Invalid "bad" revision: %s.' % bad_revision) test = _ChooseTest(anomalies, run_count) if not test or not can_bisect.IsValidTestForBisect(test.test_path): raise NotBisectableError('Could not select a test.') metric = start_try_job.GuessMetric(test.test_path) bisect_bot = start_try_job.GuessBisectBot(test.master_name, test.bot_name) if not bisect_bot or '_' not in bisect_bot: raise NotBisectableError('Could not select a bisect bot.') use_recipe = bool(start_try_job.GetBisectDirectorForTester(bisect_bot)) new_bisect_config = start_try_job.GetBisectConfig( bisect_bot=bisect_bot, master_name=test.master_name, suite=test.suite_name, metric=metric, good_revision=good_revision, bad_revision=bad_revision, repeat_count=10, max_time_minutes=20, bug_id=bug_id, use_archive='true', use_buildbucket=use_recipe) if 'error' in new_bisect_config: raise NotBisectableError('Could not make a valid config.') config_python_string = utils.BisectConfigPythonString(new_bisect_config) bisect_job = try_job.TryJob(bot=bisect_bot, config=config_python_string, bug_id=bug_id, master_name=test.master_name, internal_only=test.internal_only, job_type='bisect', use_buildbucket=use_recipe) return bisect_job