Exemplo n.º 1
0
def _MakeBisectFYITryJob(test_name, bisect_config):
    """Creates a TryJob entity with the bisect config.

  Args:
    test_name: Name of the test case.
    bisect_config: A dictionary of parameters for a bisect job.

  Returns:
    A TryJob entity, which has not yet been put in the datastore.

  Raises:
    NotBisectableError: A valid bisect config could not be created.
  """
    bisect_bot = bisect_config.get('recipe_tester_name')
    if not bisect_bot:
        raise auto_bisect.NotBisectableError('Could not select a bisect bot.')

    config_python_string = utils.BisectConfigPythonString(bisect_config)
    use_recipe = bool(start_try_job.GetBisectDirectorForTester(bisect_bot))
    bisect_job = try_job.TryJob(bot=bisect_bot,
                                config=config_python_string,
                                bug_id=bisect_config.get('bug_id', -1),
                                master_name='ChromiumPerf',
                                job_type='bisect-fyi',
                                use_buildbucket=use_recipe,
                                job_name=test_name)

    return bisect_job
Exemplo n.º 2
0
def _PerformLegacyBisect(bisect_job):
  config_dict = bisect_job.GetConfigDict()
  config = bisect_job.config
  bot = bisect_job.bot
  email = bisect_job.email
  bug_id = bisect_job.bug_id

  # We need to rewrite the metric name for legacy bisect.
  config_dict['metric'] = _RewriteMetricName(config_dict['metric'])
  bisect_job.config = utils.BisectConfigPythonString(config_dict)

  # Get the base config file contents and make a patch.
  base_config = utils.DownloadChromiumFile(_BISECT_CONFIG_PATH)
  if not base_config:
    return {'error': 'Error downloading base config'}
  patch, base_checksum, base_hashes = _CreatePatch(
      base_config, config, _BISECT_CONFIG_PATH)

  # Check if bisect is for internal only tests.
  bisect_internal = _IsBisectInternalOnly(bisect_job)

  # Upload the patch to Rietveld.
  server = rietveld_service.RietveldService(bisect_internal)

  subject = 'Perf bisect for bug %s on behalf of %s' % (bug_id, email)
  issue_id, patchset_id = server.UploadPatch(subject,
                                             patch,
                                             base_checksum,
                                             base_hashes,
                                             base_config,
                                             _BISECT_CONFIG_PATH)

  if not issue_id:
    return {'error': 'Error uploading patch to rietveld_service.'}

  if bisect_internal:
    # Internal server URL has '/bots', that cannot be accessed via browser,
    # therefore strip this path from internal server URL.
    issue_url = '%s/%s' % (server.Config().internal_server_url.strip('/bots'),
                           issue_id)
  else:
    issue_url = '%s/%s' % (server.Config().server_url.strip('/bots'), issue_id)

  # Tell Rietveld to try the patch.
  master = _GetTryServerMaster(bisect_job)
  trypatch_success = server.TryPatch(master, issue_id, patchset_id, bot)
  if trypatch_success:
    # Create TryJob entity.  update_bug_with_results and auto_bisect
    # cron job will be tracking/starting/restarting bisect.
    if bug_id and bug_id > 0:
      bisect_job.rietveld_issue_id = int(issue_id)
      bisect_job.rietveld_patchset_id = int(patchset_id)
      bisect_job.SetStarted()
      bug_comment = ('Bisect started; track progress at '
                     '<a href="%s">%s</a>' % (issue_url, issue_url))
      LogBisectResult(bug_id, bug_comment)
    return {'issue_id': issue_id, 'issue_url': issue_url}

  return {'error': 'Error starting try job. Try to fix at %s' % issue_url}
Exemplo n.º 3
0
def _PerformPerfTryJob(perf_job):
  """Performs the perf try job on the try bot.

  This creates a patch, uploads it, then tells Rietveld to try the patch.

  Args:
    perf_job: TryJob entity with initialized bot name and config.

  Returns:
    A dictionary containing the result; if successful, this dictionary contains
    the field "issue_id", otherwise it contains "error".
  """
  assert perf_job.bot and perf_job.config

  if not perf_job.key:
    perf_job.put()

  bot = perf_job.bot
  email = perf_job.email

  config_dict = perf_job.GetConfigDict()
  config_dict['try_job_id'] = perf_job.key.id()
  perf_job.config = utils.BisectConfigPythonString(config_dict)

  # Get the base config file contents and make a patch.
  base_config = utils.DownloadChromiumFile(_PERF_CONFIG_PATH)
  if not base_config:
    return {'error': 'Error downloading base config'}
  patch, base_checksum, base_hashes = _CreatePatch(
      base_config, perf_job.config, _PERF_CONFIG_PATH)

  # Upload the patch to Rietveld.
  server = rietveld_service.RietveldService()
  subject = 'Perf Try Job on behalf of %s' % email
  issue_id, patchset_id = server.UploadPatch(subject,
                                             patch,
                                             base_checksum,
                                             base_hashes,
                                             base_config,
                                             _PERF_CONFIG_PATH)

  if not issue_id:
    return {'error': 'Error uploading patch to rietveld_service.'}
  url = 'https://codereview.chromium.org/%s/' % issue_id

  # Tell Rietveld to try the patch.
  master = 'tryserver.chromium.perf'
  trypatch_success = server.TryPatch(master, issue_id, patchset_id, bot)
  if trypatch_success:
    # Create TryJob entity. The update_bug_with_results and auto_bisect
    # cron jobs will be tracking, or restarting the job.
    perf_job.rietveld_issue_id = int(issue_id)
    perf_job.rietveld_patchset_id = int(patchset_id)
    perf_job.SetStarted()
    return {'issue_id': issue_id}
  return {'error': 'Error starting try job. Try to fix at %s' % url}
Exemplo n.º 4
0
  def testFYI_Send_No_Email_On_Success(self):
    stored_object.Set(
        bisect_fyi._BISECT_FYI_CONFIGS_KEY,
        bisect_fyi_test.TEST_FYI_CONFIGS)
    test_config = bisect_fyi_test.TEST_FYI_CONFIGS['positive_culprit']
    bisect_config = test_config.get('bisect_config')
    self._AddTryJob(12345, 'started', 'win_perf',
                    results_data=_SAMPLE_BISECT_RESULTS_JSON,
                    internal_only=True,
                    config=utils.BisectConfigPythonString(bisect_config),
                    job_type='bisect-fyi',
                    job_name='positive_culprit',
                    email='*****@*****.**')

    self.testapp.get('/update_bug_with_results')
    messages = self.mail_stub.get_sent_messages()
    self.assertEqual(0, len(messages))
Exemplo n.º 5
0
  def testFYI_Failed_Job_SendEmail_On_Exception(self):
    stored_object.Set(
        bisect_fyi._BISECT_FYI_CONFIGS_KEY,
        bisect_fyi_test.TEST_FYI_CONFIGS)
    test_config = bisect_fyi_test.TEST_FYI_CONFIGS['positive_culprit']
    bisect_config = test_config.get('bisect_config')
    sample_bisect_results = copy.deepcopy(_SAMPLE_BISECT_RESULTS_JSON)
    sample_bisect_results['status'] = 'failed'
    self._AddTryJob(12345, 'started', 'win_perf',
                    results_data=sample_bisect_results,
                    internal_only=True,
                    buildbucket_job_id='12345',
                    config=utils.BisectConfigPythonString(bisect_config),
                    job_type='bisect-fyi',
                    job_name='positive_culprit',
                    email='*****@*****.**')

    self.testapp.get('/update_bug_with_results')
    messages = self.mail_stub.get_sent_messages()
    self.assertEqual(1, len(messages))
Exemplo n.º 6
0
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
Exemplo n.º 7
0
def PerformBisect(bisect_job):
  """Starts the bisect job.

  This creates a patch, uploads it, then tells Rietveld to try the patch.

  TODO(qyearsley): If we want to use other tryservers sometimes in the future,
  then we need to have some way to decide which one to use. This could
  perhaps be passed as part of the bisect bot name, or guessed from the bisect
  bot name.

  Args:
    bisect_job: A TryJob entity.

  Returns:
    A dictionary containing the result; if successful, this dictionary contains
    the field "issue_id" and "issue_url", otherwise it contains "error".
  """
  assert bisect_job.bot and bisect_job.config
  config_dict = bisect_job.GetConfigDict()

  if bisect_job.use_buildbucket:
    if 'recipe_tester_name' not in config_dict:
      logging.error('"recipe_tester_name" required in bisect jobs '
                    'that use buildbucket. Config: %s', config_dict)
      return {'error': 'No "recipe_tester_name" given.'}
    return PerformBuildbucketBisect(bisect_job)

  config = bisect_job.config
  bot = bisect_job.bot
  email = bisect_job.email
  bug_id = bisect_job.bug_id

  # We need to rewrite the metric name for legacy bisect.
  config_dict['metric'] = _RewriteMetricName(config_dict['metric'])
  bisect_job.config = utils.BisectConfigPythonString(config_dict)

  # Get the base config file contents and make a patch.
  base_config = utils.DownloadChromiumFile(_BISECT_CONFIG_PATH)
  if not base_config:
    return {'error': 'Error downloading base config'}
  patch, base_checksum, base_hashes = _CreatePatch(
      base_config, config, _BISECT_CONFIG_PATH)

  # Check if bisect is for internal only tests.
  bisect_internal = _IsBisectInternalOnly(bisect_job)

  # Upload the patch to Rietveld.
  server = rietveld_service.RietveldService(bisect_internal)

  subject = 'Perf bisect for bug %s on behalf of %s' % (bug_id, email)
  issue_id, patchset_id = server.UploadPatch(subject,
                                             patch,
                                             base_checksum,
                                             base_hashes,
                                             base_config,
                                             _BISECT_CONFIG_PATH)

  if not issue_id:
    return {'error': 'Error uploading patch to rietveld_service.'}

  if bisect_internal:
    # Internal server URL has '/bots', that cannot be accessed via browser,
    # therefore strip this path from internal server URL.
    issue_url = '%s/%s' % (server.Config().internal_server_url.strip('/bots'),
                           issue_id)
  else:
    issue_url = '%s/%s' % (server.Config().server_url.strip('/bots'), issue_id)

  # Tell Rietveld to try the patch.
  master = _GetTryServerMaster(bisect_job)
  trypatch_success = server.TryPatch(master, issue_id, patchset_id, bot)
  if trypatch_success:
    # Create TryJob entity.  update_bug_with_results and auto_bisect
    # cron job will be tracking/starting/restarting bisect.
    if bug_id and bug_id > 0:
      bisect_job.rietveld_issue_id = int(issue_id)
      bisect_job.rietveld_patchset_id = int(patchset_id)
      bisect_job.SetStarted()
      bug_comment = ('Bisect started; track progress at '
                     '<a href="%s">%s</a>' % (issue_url, issue_url))
      LogBisectResult(bug_id, bug_comment)
    return {'issue_id': issue_id, 'issue_url': issue_url}
  return {'error': 'Error starting try job. Try to fix at %s' % issue_url}