<commit_before># Copyright 2015 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

"""URL endpoint for a cron job to automatically run bisects."""

import datetime
import logging

from dashboard import can_bisect
from dashboard import datastore_hooks
from dashboard import request_handler
from dashboard import start_try_job
from dashboard import utils
from dashboard.models import anomaly
from dashboard.models import graph_data
from dashboard.models import try_job

# Days between successive bisect restarts.
_BISECT_RESTART_PERIOD_DAYS = [0, 1, 7, 14]


class AutoBisectHandler(request_handler.RequestHandler):
  """URL endpoint for a cron job to automatically run bisects."""

  def get(self):
    """A get request is the same a post request for this endpoint."""
    self.post()

  def post(self):
    """Runs auto bisects."""
    if 'stats' in self.request.query_string:
      self.RenderHtml('result.html', _PrintStartedAndFailedBisectJobs())
      return
    datastore_hooks.SetPrivilegedRequest()
    if _RestartFailedBisectJobs():
      utils.TickMonitoringCustomMetric('RestartFailedBisectJobs')


class NotBisectableError(Exception):
  """An error indicating that a bisect couldn't be automatically started."""
  pass


def _RestartFailedBisectJobs():
  """Restarts failed bisect jobs.

  Bisect jobs that ran out of retries will be deleted.

  Returns:
    True if all bisect jobs that were retried were successfully triggered,
    and False otherwise.
  """
  bisect_jobs = try_job.TryJob.query(try_job.TryJob.status == 'failed').fetch()
  all_successful = True
  for job in bisect_jobs:
    if job.run_count > 0:
      if job.run_count <= len(_BISECT_RESTART_PERIOD_DAYS):
        if _IsBisectJobDueForRestart(job):
          # Start bisect right away if this is the first retry. Otherwise,
          # try bisect with different config.
          if job.run_count == 1:
            try:
              start_try_job.PerformBisect(job)
            except request_handler.InvalidInputError as e:
              logging.error(e.message)
              all_successful = False
          elif job.bug_id:
            restart_successful = _RestartBisect(job)
            if not restart_successful:
              all_successful = False
      else:
        if job.bug_id:
          comment = ('Failed to run bisect %s times.'
                     'Stopping automatic restart for this job.' %
                     job.run_count)
          start_try_job.LogBisectResult(job.bug_id, comment)
        job.key.delete()
  return all_successful


def _RestartBisect(bisect_job):
  """Re-starts a bisect-job after modifying it's config based on run count.

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

  Returns:
    True if the bisect was successfully triggered and False otherwise.
  """
  try:
    new_bisect_job = _MakeBisectTryJob(
        bisect_job.bug_id, bisect_job.run_count)
  except NotBisectableError:
    return False
  bisect_job.config = new_bisect_job.config
  bisect_job.bot = new_bisect_job.bot
  bisect_job.put()
  try:<commit_msg>Switch legacy pending bisect jobs to recipe based jobs.<commit_after># Copyright 2015 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

"""URL endpoint for a cron job to automatically run bisects."""

import datetime
import logging

from dashboard import can_bisect
from dashboard import datastore_hooks
from dashboard import request_handler
from dashboard import start_try_job
from dashboard import utils
from dashboard.models import anomaly
from dashboard.models import graph_data
from dashboard.models import try_job

# Days between successive bisect restarts.
_BISECT_RESTART_PERIOD_DAYS = [0, 1, 7, 14]


class AutoBisectHandler(request_handler.RequestHandler):
  """URL endpoint for a cron job to automatically run bisects."""

  def get(self):
    """A get request is the same a post request for this endpoint."""
    self.post()

  def post(self):
    """Runs auto bisects."""
    if 'stats' in self.request.query_string:
      self.RenderHtml('result.html', _PrintStartedAndFailedBisectJobs())
      return
    datastore_hooks.SetPrivilegedRequest()
    if _RestartFailedBisectJobs():
      utils.TickMonitoringCustomMetric('RestartFailedBisectJobs')


class NotBisectableError(Exception):
  """An error indicating that a bisect couldn't be automatically started."""
  pass


def _RestartFailedBisectJobs():
  """Restarts failed bisect jobs.

  Bisect jobs that ran out of retries will be deleted.

  Returns:
    True if all bisect jobs that were retried were successfully triggered,
    and False otherwise.
  """
  bisect_jobs = try_job.TryJob.query(try_job.TryJob.status == 'failed').fetch()
  all_successful = True
  for job in bisect_jobs:
    if job.run_count > 0:
      if job.run_count <= len(_BISECT_RESTART_PERIOD_DAYS):
        if _IsBisectJobDueForRestart(job):
          # Start bisect right away if this is the first retry. Otherwise,
          # try bisect with different config.
          if job.run_count == 1:
            try:
              start_try_job.PerformBisect(job)
            except request_handler.InvalidInputError as e:
              logging.error(e.message)
              all_successful = False
          elif job.bug_id:
            restart_successful = _RestartBisect(job)
            if not restart_successful:
              all_successful = False
      else:
        if job.bug_id:
          comment = ('Failed to run bisect %s times.'
                     'Stopping automatic restart for this job.' %
                     job.run_count)
          start_try_job.LogBisectResult(job.bug_id, comment)
        job.key.delete()
  return all_successful


def _RestartBisect(bisect_job):
  """Re-starts a bisect-job after modifying it's config based on run count.

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

  Returns:
    True if the bisect was successfully triggered and False otherwise.
  """
  try:
    new_bisect_job = _MakeBisectTryJob(
        bisect_job.bug_id, bisect_job.run_count)
  except NotBisectableError:
    return False
  bisect_job.config = new_bisect_job.config
  bisect_job.bot = new_bisect_job.bot
  bisect_job.use_buildbucket = new_bisect_job.use_buildbucket
  bisect_job.put()
  try:
{'fraction_non_alphanumeric': 0.07100775193798449, 'fraction_numerical': 0.0034108527131782944, 'mean_word_length': 3.1971372804163956, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 5, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6868167', 'n_tokens_mistral': 1959, 'n_tokens_neox': 1898, 'n_words': 601}