Ejemplo n.º 1
0
def _IssueTracker():
  """Get a cached IssueTracker instance."""
  # pylint: disable=protected-access
  if not hasattr(_IssueTracker, '_client'):
    _IssueTracker._client = issue_tracker_service.IssueTrackerService(
        utils.ServiceAccountHttp())
  return _IssueTracker._client
Ejemplo n.º 2
0
  def get(self):
    """The get handler method is called from a cron job.

    It expects no parameters and has no output. It checks all current bisect try
    jobs and send comments to an issue on the issue tracker if a bisect job has
    completed.
    """
    issue_tracker = issue_tracker_service.IssueTrackerService(
        utils.ServiceAccountHttp())

    # Set privilege so we can also fetch internal try_job entities.
    datastore_hooks.SetPrivilegedRequest()

    jobs_to_check = try_job.TryJob.query(
        try_job.TryJob.status.IN(['started', 'pending'])).fetch()
    all_successful = True

    for job in jobs_to_check:
      try:
        _CheckJob(job, issue_tracker)
      except Exception as e:  # pylint: disable=broad-except
        logging.error('Caught Exception %s: %s\n%s',
                      type(e).__name__, e, traceback.format_exc())
        all_successful = False

    if all_successful:
      utils.TickMonitoringCustomMetric('UpdateBugWithResults')
Ejemplo n.º 3
0
  def _PostBugComment(self, comment, send_email=True):
    if not self.bug_id:
      return

    issue_tracker = issue_tracker_service.IssueTrackerService(
        utils.ServiceAccountHttp())
    issue_tracker.AddBugComment(self.bug_id, comment, send_email=send_email)
Ejemplo n.º 4
0
  def Start(self):
    self.Schedule()

    comment = 'Pinpoint job started.\n' + self.url
    issue_tracker = issue_tracker_service.IssueTrackerService(
        utils.ServiceAccountHttp())
    issue_tracker.AddBugComment(self.bug_id, comment, send_email=False)
Ejemplo n.º 5
0
    def Fail(self, exception):
        self.exception = str(exception)

        comment = 'Pinpoint job failed!\n' + self.url
        issue_tracker = issue_tracker_service.IssueTrackerService(
            utils.ServiceAccountHttp())
        issue_tracker.AddBugComment(self.bug_id, comment, send_email=False)
Ejemplo n.º 6
0
def _UpdatePostAndMergeDeferred(
    difference_details, commit_infos, authors_deltas, bug_id, tags, url):
  if not bug_id:
    return

  commit_cache_key = _GenerateCommitCacheKey(commit_infos)

  # Bring it all together.
  owner, sheriff, cc_list = _ComputePostOwnerSheriffCCList(commit_infos,
                                                           authors_deltas)
  comment = _FormatComment(difference_details, commit_infos, sheriff, tags, url)

  issue_tracker = issue_tracker_service.IssueTrackerService(
      utils.ServiceAccountHttp())

  merge_details, cc_list = _ComputePostMergeDetails(
      issue_tracker, commit_cache_key, cc_list)

  current_bug_status = _GetBugStatus(issue_tracker, bug_id)
  if not current_bug_status:
    return

  status = None
  bug_owner = None
  if current_bug_status in ['Untriaged', 'Unconfirmed', 'Available']:
    # Set the bug status and owner if this bug is opened and unowned.
    status = 'Assigned'
    bug_owner = owner

  issue_tracker.AddBugComment(bug_id, comment, status=status,
                              cc_list=sorted(cc_list), owner=bug_owner,
                              merge_issue=merge_details.get('id'))

  update_bug_with_results.UpdateMergeIssue(
      commit_cache_key, merge_details, bug_id)
Ejemplo n.º 7
0
def _Request(path, method='GET', body=None, **parameters):
    if parameters:
        for key, value in parameters.iteritems():
            if value is None:
                del parameters[key]
            if isinstance(value, bool):
                parameters[key] = str(value).lower()
        path += '?' + urllib.urlencode(sorted(parameters.iteritems()),
                                       doseq=True)

    http = utils.ServiceAccountHttp()
    url = API_BASE_URL + path
    logging.debug('Swarming request: %s', url)
    if body:
        body = json.dumps(body)
        headers = {'Content-Type': 'application/json'}
        response, content = http.request(url,
                                         method,
                                         body=body,
                                         headers=headers)
    else:
        response, content = http.request(url, method)
    logging.debug('Swarming response: %s', content)

    if not response['status'].startswith('2'):
        raise SwarmingError(content)

    return json.loads(content)
  def MarkAlertAndBugIfRecovered(self, alert_key_urlsafe, bug_id):
    """Checks whether an alert has recovered, and marks it if so.

    An alert will be considered "recovered" if there's a change point in
    the series after it with roughly equal magnitude and opposite direction.

    Args:
      alert_key_urlsafe: The original regression Anomaly.

    Returns:
      True if the Anomaly should be marked as recovered, False otherwise.
    """
    alert_entity = ndb.Key(urlsafe=alert_key_urlsafe).get()
    logging.info('Checking alert %s', alert_entity)
    if not self._IsAlertRecovered(alert_entity):
      return

    logging.info('Recovered')
    alert_entity.recovered = True
    alert_entity.put()
    if bug_id:
      unrecovered, _, _ = anomaly.Anomaly.QueryAsync(
          bug_id=bug_id, recovered=False).get_result()
      if not unrecovered:
        # All alerts recovered! Update bug.
        logging.info('All alerts for bug %s recovered!', bug_id)
        comment = 'Automatic message: All alerts recovered.\nGraphs: %s' % (
            'https://chromeperf.appspot.com/group_report?bug_id=%s' % bug_id)
        issue_tracker = issue_tracker_service.IssueTrackerService(
            utils.ServiceAccountHttp())
        issue_tracker.AddBugComment(
            bug_id, comment, labels='Performance-Regression-Recovered')
Ejemplo n.º 9
0
    def _PostBugComment(self,
                        status,
                        include_differences=False,
                        send_email=True):
        if not self.bug_id:
            return

        title = '%s Pinpoint job %s.' % (_ROUND_PUSHPIN, status)
        header = '\n'.join((title, self.url))

        change_details = []
        if include_differences:
            # Include list of Changes.
            differences = tuple(self.state.Differences())
            if differences:
                if len(differences) == 1:
                    change_details.append(
                        '<b>Found significant differences after 1 commit:</b>')
                else:
                    change_details.append(
                        '<b>Found significant differences after each of %d commits:</b>'
                        % len(differences))
                for _, change in differences:
                    change_details.append(_FormatChangeForBug(change))
            else:
                change_details.append(
                    "<b>Couldn't reproduce a difference.</b>")

        comment = '\n\n'.join([header] + change_details)

        issue_tracker = issue_tracker_service.IssueTrackerService(
            utils.ServiceAccountHttp())
        issue_tracker.AddBugComment(self.bug_id,
                                    comment,
                                    send_email=send_email)
Ejemplo n.º 10
0
def Put(bucket, parameters):
    service = _DiscoverService(utils.ServiceAccountHttp())
    request = service.put(body={
        'bucket': bucket,
        'parameters_json': json.dumps(parameters)
    })
    return request.execute()
Ejemplo n.º 11
0
    def _PostBugComment(self, *args, **kwargs):
        if not self.bug_id:
            return

        issue_tracker = issue_tracker_service.IssueTrackerService(
            utils.ServiceAccountHttp())
        issue_tracker.AddBugComment(self.bug_id, *args, **kwargs)
Ejemplo n.º 12
0
def UpdatePostAndMergeDeferred(bug_update_builder, bug_id, tags, url):
    if not bug_id:
        return
    commit_cache_key = bug_update_builder.GenerateCommitCacheKey()
    bug_update = bug_update_builder.BuildUpdate(tags, url)
    issue_tracker = issue_tracker_service.IssueTrackerService(
        utils.ServiceAccountHttp())
    merge_details, cc_list = _ComputePostMergeDetails(issue_tracker,
                                                      commit_cache_key,
                                                      bug_update.cc_list)
    current_bug_status = _GetBugStatus(issue_tracker, bug_id)
    if not current_bug_status:
        return

    status = None
    bug_owner = None

    if current_bug_status in ['Untriaged', 'Unconfirmed', 'Available']:
        # Set the bug status and owner if this bug is opened and unowned.
        status = 'Assigned'
        bug_owner = bug_update.owner

    issue_tracker.AddBugComment(bug_id,
                                bug_update.comment_text,
                                status=status,
                                cc_list=sorted(cc_list),
                                owner=bug_owner,
                                labels=bug_update.labels,
                                merge_issue=merge_details.get('id'))
    update_bug_with_results.UpdateMergeIssue(commit_cache_key, merge_details,
                                             bug_id)
Ejemplo n.º 13
0
    def _PostBugComment(self, status):
        if not self.bug_id:
            return

        title = '%s Pinpoint job %s.' % (_ROUND_PUSHPIN, status)
        header = '\n'.join((title, self.url))

        # Include list of Changes.
        change_details = []
        for _, change in self.state.Differences():
            # TODO: Store the commit info in the Commit.
            commit = change.last_commit
            commit_info = gitiles_service.CommitInfo(commit.repository_url,
                                                     commit.git_hash)
            subject = commit_info['message'].split('\n', 1)[0]
            author = commit_info['author']['email']
            time = commit_info['committer']['time']

            byline = 'By %s %s %s' % (author, _MIDDLE_DOT, time)
            git_link = commit.repository + '@' + commit.git_hash
            change_details.append('\n'.join((subject, byline, git_link)))

        comment = '\n\n'.join([header] + change_details)

        issue_tracker = issue_tracker_service.IssueTrackerService(
            utils.ServiceAccountHttp())
        issue_tracker.AddBugComment(self.bug_id, comment, send_email=False)
Ejemplo n.º 14
0
    def _GetBugStatus(self):
        if not self.bug_id:
            return None

        issue_tracker = issue_tracker_service.IssueTrackerService(
            utils.ServiceAccountHttp())
        issue_data = issue_tracker.GetIssue(self.bug_id)
        return issue_data.get('status')
 def _FetchOpenBugs(self):
   """Fetches a list of open bugs on all sheriffing labels."""
   issue_tracker = issue_tracker_service.IssueTrackerService(
       utils.ServiceAccountHttp())
   bugs = issue_tracker.List(
       can='open',
       q='Performance=Sheriff OR Performance=Sheriff-V8',
       maxResults=1000)
   return bugs['items']
Ejemplo n.º 16
0
def _RequestAndProcessHttpErrors(*args, **kwargs):
    """Requests a URL, converting HTTP errors to Python exceptions."""
    http = utils.ServiceAccountHttp(timeout=10)
    response, content = http.request(*args, **kwargs)
    if not response['status'].startswith('2'):
        raise httplib.HTTPException('HTTP status code %s: %s' %
                                    (response['status'], content))

    return content
Ejemplo n.º 17
0
 def MakeRequest(self, path, *args, **kwargs):
   """Makes a request to the Rietveld server."""
   if self.internal_only:
     server_url = self.Config().internal_server_url
   else:
     server_url = self.Config().server_url
   url = '%s/%s' % (server_url, path)
   response, content = utils.ServiceAccountHttp().request(url, *args, **kwargs)
   return ResponseObject(response.get('status'), content)
Ejemplo n.º 18
0
 def _ComputePostMergeDetails(self, commit_cache_key, cc_list):
     merge_details = {}
     if commit_cache_key:
         issue_tracker = issue_tracker_service.IssueTrackerService(
             utils.ServiceAccountHttp())
         merge_details = update_bug_with_results.GetMergeIssueDetails(
             issue_tracker, commit_cache_key)
         if merge_details['id']:
             cc_list = []
     return merge_details, cc_list
Ejemplo n.º 19
0
def PutJob(job, bucket=_BUCKET_NAME):
    """Creates a job via buildbucket's API."""
    parameters = job.GetBuildParameters()
    service = _DiscoverService(utils.ServiceAccountHttp())
    request = service.put(body={
        'bucket': bucket,
        'parameters_json': json.dumps(parameters),
    })
    response_content = request.execute()
    job.response_fields = response_content.get('build')
    return job.response_fields.get('id')
Ejemplo n.º 20
0
def _Request(endpoint, params):
    """Sends a request to an endpoint and returns JSON data."""
    assert datastore_hooks.IsUnalteredQueryPermitted()

    http_auth = utils.ServiceAccountHttp()
    _, content = http_auth.request(_PINPOINT_URL + endpoint,
                                   method='POST',
                                   body=urllib.urlencode(params),
                                   headers={'Content-length': 0})

    return json.loads(content)
Ejemplo n.º 21
0
  def _CommentOnRecoveredBug(cls, bug_id):
    """Adds a comment and close the bug on Issue tracker."""
    bug = ndb.Key('Bug', bug_id).get()
    if bug.status != bug_data.BUG_STATUS_OPENED:
      return
    bug.status = bug_data.BUG_STATUS_RECOVERED
    bug.put()
    comment = cls._RecoveredBugComment(bug_id)

    issue_tracker = issue_tracker_service.IssueTrackerService(
        utils.ServiceAccountHttp())
    issue_tracker.AddBugComment(bug_id, comment)
Ejemplo n.º 22
0
  def __init__(self):
    """Initializes an object for retrieving files and directories from RBE-CAS.

    This class makes requests to RBE-CAS

    Args:
      http: A Http object that requests will be made through
    """
    self._service = discovery.build(
        'remotebuildexecution',
        'v2',
        http=utils.ServiceAccountHttp(scope=utils.CLOUD_SCOPE),
    )
Ejemplo n.º 23
0
    def Post(self):
        owner = self.request.get('owner')
        cc = self.request.get('cc')
        summary = self.request.get('summary')
        description = self.request.get('description')
        labels = self.request.get_all('label')
        components = self.request.get_all('component')
        keys = self.request.get_all('key')
        bisect = api_utils.ParseBool(self.request.get('bisect', 'true'))
        http = utils.ServiceAccountHttp()

        return file_bug.FileBug(http, owner, cc, summary, description, labels,
                                components, keys, bisect)
Ejemplo n.º 24
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".

  Raises:
    AssertionError: Bot or config not set as expected.
    request_handler.InvalidInputError: Some property of the bisect job
        is invalid.
  """
    assert bisect_job.bot and bisect_job.config
    if not bisect_job.key:
        bisect_job.put()

    result = _PerformBuildbucketBisect(bisect_job)
    if 'error' in result:
        bisect_job.run_count += 1
        bisect_job.SetFailed()
        comment = 'Bisect job failed to kick off'
    elif result.get('issue_url'):
        comment = 'Started bisect job %s' % result['issue_url']
    else:
        comment = 'Started bisect job: %s' % result

    if not bisect_job.results_data:
        bisect_job.results_data = {'issue_url': 'N/A', 'issue_id': 'N/A'}
    bisect_job.results_data.update(result)
    bisect_job.put()

    if bisect_job.bug_id:
        logging.info('Commenting on bug %s for bisect job', bisect_job.bug_id)
        issue_tracker = issue_tracker_service.IssueTrackerService(
            utils.ServiceAccountHttp())
        issue_tracker.AddBugComment(bisect_job.bug_id,
                                    comment,
                                    send_email=False)
    return result
Ejemplo n.º 25
0
def PerformBisect(bisect_job, alerts=None):
    """Starts the bisect job.

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

  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".

  Raises:
    AssertionError: Bot or config not set as expected.
    request_handler.InvalidInputError: Some property of the bisect job
        is invalid.
  """
    assert bisect_job.bot and bisect_job.config
    if not bisect_job.key:
        bisect_job.put()

    result = _PerformBuildbucketBisect(bisect_job)
    if 'error' in result:
        bisect_job.SetFailed()
        comment = 'Bisect job failed to kick off'
    elif result.get('issue_url'):
        comment = 'Started bisect job %s' % result['issue_url']
    else:
        comment = 'Started bisect job: %s' % result

    if not bisect_job.results_data:
        bisect_job.results_data = {'issue_url': 'N/A', 'issue_id': 'N/A'}
    bisect_job.results_data.update(result)
    bisect_job.put()

    if alerts:
        for a in alerts:
            a.recipe_bisects.append(bisect_job.key)

    if bisect_job.bug_id:
        logging.info('Commenting on bug %s for bisect job', bisect_job.bug_id)
        issue_tracker = issue_tracker_service.IssueTrackerService(
            utils.ServiceAccountHttp())
        issue_tracker.AddBugComment(bisect_job.bug_id,
                                    comment,
                                    send_email=False)
    return result
Ejemplo n.º 26
0
 def testBisectDisabled(self):
     http = utils.ServiceAccountHttp()
     owner = ''
     cc = '*****@*****.**'
     summary = 'test'
     description = 'Test test.'
     labels = []
     components = []
     test_path = 'ChromiumPerf/linux/scrolling/first_paint'
     test_key = utils.TestKey(test_path)
     sheriff_key = sheriff.Sheriff(id='Sheriff', labels=[]).put()
     keys = [self._AddAnomaly(10, 20, test_key, sheriff_key).urlsafe()]
     bisect = False
     result = file_bug.FileBug(http, owner, cc, summary, description,
                               labels, components, keys, bisect)
     self.assertNotIn('bisect_error', result)
     self.assertNotIn('jobId', result)
Ejemplo n.º 27
0
def _RequestAndProcessHttpErrors(url, use_auth, **kwargs):
    """Requests a URL, converting HTTP errors to Python exceptions."""
    if use_auth:
        http = utils.ServiceAccountHttp(timeout=30)
    else:
        http = httplib2.Http(timeout=30)

    response, content = http.request(url, **kwargs)

    if response['status'] == '404':
        raise NotFoundError('HTTP status code %s: %s' %
                            (response['status'], content))
    if not response['status'].startswith('2'):
        raise httplib.HTTPException('HTTP status code %s: %s' %
                                    (response['status'], content))

    return content
Ejemplo n.º 28
0
 def testSupportsCCList(self):
     http = utils.ServiceAccountHttp()
     owner = ''
     cc = '[email protected],[email protected],[email protected],,'
     summary = 'test'
     description = 'Test test.'
     labels = []
     components = []
     test_path = 'ChromiumPerf/linux/scrolling/first_paint'
     test_key = utils.TestKey(test_path)
     subscription = Subscription(name='Sheriff', )
     keys = [self._AddAnomaly(10, 20, test_key, subscription).urlsafe()]
     bisect = False
     result = file_bug.FileBug(http, owner, cc, summary, description,
                               labels, components, keys, bisect)
     self.assertNotIn('bisect_error', result)
     self.assertNotIn('jobId', result)
Ejemplo n.º 29
0
    def Post(self):
        owner = self.request.get('owner')
        cc = self.request.get('cc')
        summary = self.request.get('summary')
        description = self.request.get('description')
        labels = self.request.get_all('label')
        components = self.request.get_all('component')
        keys = self.request.get_all('key')

        # TODO(924228): After v2spa launches, change its client id to something
        # that is whitelisted by the issue tracker service (or have its client id
        # whitelisted), then forward the bearer token from
        # self.request.headers.get('Authorization') to the issue tracker service by
        # overriding httplib2.Http().request.
        http = utils.ServiceAccountHttp()

        return file_bug.FileBug(http, owner, cc, summary, description, labels,
                                components, keys)
Ejemplo n.º 30
0
def _RequestAndProcessHttpErrors(url, use_auth, scope, **kwargs):
  """Requests a URL, converting HTTP errors to Python exceptions."""
  if use_auth:
    http = utils.ServiceAccountHttp(timeout=60, scope=scope)
  else:
    http = httplib2.Http(timeout=60)

  response, content = http.request(url, **kwargs)

  if response['status'] == '404':
    raise NotFoundError(
        'HTTP status code %s: %s' % (response['status'], repr(content[0:100])),
        content)
  if not response['status'].startswith('2'):
    raise RequestError(
        'Failure in request for `%s`; HTTP status code %s: %s' %
        (url, response['status'], repr(content[0:100])), content)

  return content