Exemple #1
0
 def testGetSheriffForAutorollCommit_AutoRoll_ReturnsSheriff(self):
     self.assertEqual(
         '*****@*****.**',
         utils.GetSheriffForAutorollCommit(
             '*****@*****.**',
             'This is a roll.\n\[email protected],[email protected]\n\n'))
     self.assertEqual(
         '*****@*****.**',
         utils.GetSheriffForAutorollCommit(
             'v8-ci-autoroll-builder@'
             'chops-service-accounts.iam.gserviceaccount.com',
             '[email protected]'))
     # Some alternative spellings for TBR.
     self.assertEqual(
         '*****@*****.**',
         utils.GetSheriffForAutorollCommit(
             'v8-ci-autoroll-builder@'
             'chops-service-accounts.iam.gserviceaccount.com',
             'TBR: [email protected]'))
     self.assertEqual(
         '*****@*****.**',
         utils.GetSheriffForAutorollCommit(
             'v8-ci-autoroll-builder@'
             'chops-service-accounts.iam.gserviceaccount.com',
             'Tbr: [email protected]'))
     self.assertEqual(
         '*****@*****.**',
         utils.GetSheriffForAutorollCommit(
             'v8-ci-autoroll-builder@'
             'chops-service-accounts.iam.gserviceaccount.com',
             'TBR= [email protected]'))
Exemple #2
0
 def testGetSheriffForAutorollCommit_NotAutoroll_ReturnsNone(self):
     self.assertIsNone(
         utils.GetSheriffForAutorollCommit('*****@*****.**',
                                           '[email protected]'))
     self.assertIsNone(
         utils.GetSheriffForAutorollCommit('*****@*****.**',
                                           '[email protected]'))
Exemple #3
0
 def testGetSheriffForAutorollCommit_NotAutoroll_ReturnsNone(self):
   self.assertIsNone(utils.GetSheriffForAutorollCommit({
       'author': {'email': '*****@*****.**'},
       'message': '[email protected]',
   }))
   self.assertIsNone(utils.GetSheriffForAutorollCommit({
       'author': {'email': '*****@*****.**'},
       'message': '[email protected]',
   }))
    def _PeopleToNotify(self):
        """Return the people to notify for these differences.

    This looks at the top commits (by absolute change), and returns a tuple of:
      * owner (str, will be ignored if the bug is already assigned)
      * cc_list (list, authors of the top 2 commits)
      * why_text (str, text explaining why this owner was chosen)
    """
        ordered_commits = [
            diff.commit_info for diff in self._OrderedDifferencesByDelta()
        ]

        # CC the folks in the top N commits.  N is scaled by the number of commits
        # (fewer than 10 means N=1, fewer than 100 means N=2, etc.)
        commits_cap = int(math.floor(math.log10(len(ordered_commits)))) + 1
        cc_list = set()
        for commit in ordered_commits[:commits_cap]:
            cc_list.add(commit['author'])

        # Assign to the author of the top commit.  If that is an autoroll, assign to
        # a sheriff instead.
        why_text = ''
        top_commit = ordered_commits[0]
        owner = top_commit['author']
        sheriff = utils.GetSheriffForAutorollCommit(owner,
                                                    top_commit['message'])
        if sheriff:
            owner = sheriff
            why_text = 'Assigning to sheriff %s because "%s" is a roll.' % (
                sheriff, top_commit['subject'])

        return owner, cc_list, why_text
Exemple #5
0
 def testGetSheriffForAutorollCommit_AutoRoll_ReturnsSheriff(self):
   self.assertEqual(
       '*****@*****.**',
       utils.GetSheriffForAutorollCommit({
           'author': {
               'email': '*****@*****.**',
           },
           'message': 'This is a roll.\n\[email protected],[email protected]\n\n',
       }))
   self.assertEqual(
       '*****@*****.**',
       utils.GetSheriffForAutorollCommit({
           'author': {
               'email': '*****@*****.**',
           },
           'message': '[email protected]',
       }))
   self.assertEqual(
       '*****@*****.**',
       utils.GetSheriffForAutorollCommit({'tbr': '*****@*****.**'}))
Exemple #6
0
 def _ComputePostOwnerSheriffCCList(self, commit_infos):
   owner = None
   sheriff = None
   cc_list = set()
   for cur_commit in commit_infos:
     # TODO: Assign the largest difference, not the last one.
     owner = cur_commit['author']
     sheriff = utils.GetSheriffForAutorollCommit(owner, cur_commit['message'])
     cc_list.add(cur_commit['author'])
     if sheriff:
       owner = sheriff
   return owner, sheriff, cc_list
Exemple #7
0
 def testGetSheriffForAutorollCommit_AutoRoll_ReturnsSheriff(self):
     self.assertEqual(
         '*****@*****.**',
         utils.GetSheriffForAutorollCommit({
             'author': {
                 'email':
                 '*****@*****.**',
             },
             'message':
             'This is a roll.\n\[email protected],[email protected]\n\n',
         }))
     self.assertEqual(
         '*****@*****.**',
         utils.GetSheriffForAutorollCommit({
             'author': {
                 'email':
                 'v8-ci-autoroll-builder@'
                 'chops-service-accounts.iam.gserviceaccount.com',
             },
             'message': '[email protected]',
         }))
     self.assertEqual(
         '*****@*****.**',
         utils.GetSheriffForAutorollCommit({'tbr': '*****@*****.**'}))
Exemple #8
0
def _ComputePostOwnerSheriffCCList(commit_infos, authors_with_deltas):
  owner = None
  sheriff = None
  cc_list = set()

  if authors_with_deltas:
    owner, _ = max(authors_with_deltas.items(), key=lambda i: abs(i[1]))

  for cur_commit in commit_infos:
    if not owner:
      owner = cur_commit['author']
    sheriff = utils.GetSheriffForAutorollCommit(owner, cur_commit['message'])
    cc_list.add(cur_commit['author'])
    if sheriff:
      owner = sheriff
  return owner, sheriff, cc_list
Exemple #9
0
def _AssignBugToCLAuthor(bug_id, alert, service):
    """Assigns the bug to the author of the given revision."""
    repository_url = None
    repositories = namespaced_stored_object.Get('repositories')
    test_path = utils.TestPath(alert.test)
    if test_path.startswith('ChromiumPerf'):
        repository_url = repositories['chromium']['repository_url']
    elif test_path.startswith('ClankInternal'):
        repository_url = repositories['clank']['repository_url']
    if not repository_url:
        # Can't get committer info from this repository.
        return

    rev = str(auto_bisect.GetRevisionForBisect(alert.end_revision, alert.test))
    # TODO(sullivan, dtu): merge this with similar pinoint code.
    if (re.match(r'^[0-9]{5,7}$', rev)
            and repository_url == repositories['chromium']['repository_url']):
        # This is a commit position, need the git hash.
        result = crrev_service.GetNumbering(
            number=rev,
            numbering_identifier='refs/heads/master',
            numbering_type='COMMIT_POSITION',
            project='chromium',
            repo='chromium/src')
        rev = result['git_sha']
    if not re.match(r'[a-fA-F0-9]{40}$', rev):
        # This still isn't a git hash; can't assign bug.
        return

    commit_info = gitiles_service.CommitInfo(repository_url, rev)
    author = commit_info['author']['email']
    message = commit_info['message']
    sheriff = utils.GetSheriffForAutorollCommit(author, message)
    if sheriff:
        service.AddBugComment(
            bug_id,
            ('Assigning to sheriff %s because this autoroll is '
             'the only CL in range:\n%s') % (sheriff, message),
            status='Assigned',
            owner=sheriff)
    else:
        service.AddBugComment(
            bug_id,
            'Assigning to %s because this is the only CL in range:\n%s' %
            (author, message),
            status='Assigned',
            owner=author)
Exemple #10
0
def _ComputePostOwnerSheriffCCList(commits_with_deltas):
    owner = None
    sheriff = None
    cc_list = set()

    # First, we sort the list of commits by absolute change.
    ordered_commits_by_delta = [
        commit for _, commit in sorted(
            commits_with_deltas, key=lambda i: abs(i[0]), reverse=True)
    ]

    # We assign the issue to the author of the CL at the head of the ordered list.
    # Then we only CC the folks in the top two commits.
    for commit in ordered_commits_by_delta[:2]:
        if not owner:
            owner = commit['author']
        sheriff = utils.GetSheriffForAutorollCommit(owner, commit['message'])
        cc_list.add(commit['author'])
        if sheriff:
            owner = sheriff

    return owner, sheriff, cc_list
Exemple #11
0
  def _FormatAndPostBugCommentOnComplete(self):
    if not self.comparison_mode:
      # There is no comparison metric.
      title = "<b>%s Job complete. See results below.</b>" % _ROUND_PUSHPIN
      self._PostBugComment('\n'.join((title, self.url)))
      return

    # There is a comparison metric.
    differences = self.state.Differences()

    if not differences:
      title = "<b>%s Couldn't reproduce a difference.</b>" % _ROUND_PUSHPIN
      self._PostBugComment('\n'.join((title, self.url)))
      return

    # Include list of Changes.
    owner = None
    sheriff = None
    cc_list = set()
    difference_details = []
    for change_a, change_b in differences:
      if change_b.patch:
        commit_info = change_b.patch.AsDict()
      else:
        commit_info = change_b.last_commit.AsDict()

      # TODO: Assign the largest difference, not the last one.
      owner = commit_info['author']
      sheriff = utils.GetSheriffForAutorollCommit(
          commit_info['author'], commit_info['message'])
      cc_list.add(commit_info['author'])

      values_a = self.state.ResultValues(change_a)
      values_b = self.state.ResultValues(change_b)
      difference = _FormatDifferenceForBug(commit_info, values_a, values_b,
                                           self.state.metric)
      difference_details.append(difference)

    # Header.
    if len(differences) == 1:
      status = 'Found a significant difference after 1 commit.'
    else:
      status = ('Found significant differences after each of %d commits.' %
                len(differences))

    title = '<b>%s %s</b>' % (_ROUND_PUSHPIN, status)
    header = '\n'.join((title, self.url))

    # Body.
    body = '\n\n'.join(difference_details)
    if sheriff:
      owner = sheriff
      body += '\n\nAssigning to sheriff %s because "%s" is a roll.' % (
          sheriff, commit_info['subject'])

    # Footer.
    footer = ('Understanding performance regressions:\n'
              '  http://g.co/ChromePerformanceRegressions')

    if differences:
      footer += self._FormatDocumentationUrls()

    # Bring it all together.
    comment = '\n\n'.join((header, body, footer))
    current_bug_status = self._GetBugStatus()
    if (not current_bug_status or
        current_bug_status in ['Untriaged', 'Unconfirmed', 'Available']):
      # Set the bug status and owner if this bug is opened and unowned.
      self._PostBugComment(comment, status='Assigned',
                           cc_list=sorted(cc_list), owner=owner)
    else:
      # Only update the comment and cc list if this bug is assigned or closed.
      self._PostBugComment(comment, cc_list=sorted(cc_list))
Exemple #12
0
def FileBug(http,
            owner,
            cc,
            summary,
            description,
            labels,
            components,
            urlsafe_keys,
            needs_bisect=True):
    alert_keys = [ndb.Key(urlsafe=k) for k in urlsafe_keys]
    alerts = ndb.get_multi(alert_keys)

    if not description:
        description = 'See the link to graphs below.'

    milestone_label = _MilestoneLabel(alerts)
    if milestone_label:
        labels.append(milestone_label)

    user_issue_tracker_service = issue_tracker_service.IssueTrackerService(
        http)

    new_bug_response = user_issue_tracker_service.NewBug(
        summary,
        description,
        labels=labels,
        components=components,
        owner=owner,
        cc=[email for email in cc.split(',') if email.strip()])
    if 'error' in new_bug_response:
        return {'error': new_bug_response['error']}

    bug_id = new_bug_response['bug_id']
    bug_data.Bug(id=bug_id).put()

    for a in alerts:
        a.bug_id = bug_id

    ndb.put_multi(alerts)

    comment_body = _AdditionalDetails(bug_id, alerts)
    # Add the bug comment with the service account, so that there are no
    # permissions issues.
    dashboard_issue_tracker_service = issue_tracker_service.IssueTrackerService(
        utils.ServiceAccountHttp())
    dashboard_issue_tracker_service.AddBugComment(bug_id, comment_body)

    template_params = {'bug_id': bug_id}
    if all(k.kind() == 'Anomaly' for k in alert_keys):
        logging.info('Kicking bisect for bug ' + str(bug_id))
        culprit_rev = _GetSingleCLForAnomalies(alerts)

        if culprit_rev is not None:
            commit_info = _GetCommitInfoForAlert(alerts[0])
            if commit_info:
                author = commit_info['author']['email']
                message = commit_info['message']
                if not utils.GetSheriffForAutorollCommit(author, message):
                    needs_bisect = False
                    _AssignBugToCLAuthor(bug_id, commit_info,
                                         dashboard_issue_tracker_service)

        if needs_bisect:
            bisect_result = auto_bisect.StartNewBisectForBug(bug_id)
            if 'error' in bisect_result:
                logging.info('Failed to kick bisect for ' + str(bug_id))
                template_params['bisect_error'] = bisect_result['error']
            else:
                logging.info('Successfully kicked bisect for ' + str(bug_id))
                template_params.update(bisect_result)

    else:
        kinds = set()
        for k in alert_keys:
            kinds.add(k.kind())
        logging.info(
            'Didn\'t kick bisect for bug id %s because alerts had kinds %s',
            bug_id, list(kinds))
    return template_params
Exemple #13
0
  def _Complete(self):
    try:
      results2.ScheduleResults2Generation(self)
    except taskqueue.Error:
      pass

    # Format bug comment.

    if not self.auto_explore:
      # There is no comparison metric.
      title = "<b>%s Job complete. See results below.</b>" % _ROUND_PUSHPIN
      self._PostBugComment('\n'.join((title, self.url)))
      return

    # There is a comparison metric.
    differences = tuple(self.state.Differences())

    if not differences:
      title = "<b>%s Couldn't reproduce a difference.</b>" % _ROUND_PUSHPIN
      self._PostBugComment('\n'.join((title, self.url)))
      return

    # Include list of Changes.
    owner = None
    sheriff = None
    cc_list = set()
    commit_details = []
    for _, change in differences:
      if change.patch:
        commit_info = change.patch.AsDict()
      else:
        commit_info = change.last_commit.AsDict()

      # TODO: Assign the largest difference, not the last one.
      owner = commit_info['author']
      sheriff = utils.GetSheriffForAutorollCommit(commit_info)
      cc_list.add(commit_info['author'])
      commit_details.append(_FormatCommitForBug(commit_info))

    # Header.
    if len(differences) == 1:
      status = 'Found a significant difference after 1 commit.'
    else:
      status = ('Found significant differences after each of %d commits.' %
                len(differences))

    title = '<b>%s %s</b>' % (_ROUND_PUSHPIN, status)
    header = '\n'.join((title, self.url))

    # Body.
    body = '\n\n'.join(commit_details)
    if sheriff:
      owner = sheriff
      body += '\n\nAssigning to sheriff %s because "%s" is a roll.' % (
          sheriff, commit_info['subject'])

    # Footer.
    footer = ('Understanding performance regressions:\n'
              '  http://g.co/ChromePerformanceRegressions')

    # Bring it all together.
    comment = '\n\n'.join((header, body, footer))
    current_bug_status = self._GetBugStatus()
    if (not current_bug_status or
        current_bug_status in ['Untriaged', 'Unconfirmed', 'Available']):
      # Set the bug status and owner if this bug is opened and unowned.
      self._PostBugComment(comment, status='Assigned',
                           cc_list=sorted(cc_list), owner=owner)
    else:
      # Only update the comment and cc list if this bug is assigned or closed.
      self._PostBugComment(comment, cc_list=sorted(cc_list))
Exemple #14
0
 def testGetSheriffForAutorollCommit_InvalidCommit_ReturnsNone(self):
     self.assertIsNone(utils.GetSheriffForAutorollCommit(None))
     self.assertIsNone(utils.GetSheriffForAutorollCommit({}))
     self.assertIsNone(utils.GetSheriffForAutorollCommit({'author': {}}))