def testUpdateSuspectedCLPartially(self):
    suspected_cl = WfSuspectedCL.Create(self.repo_name, self.revision_1,
                                        self.commit_position)

    suspected_cl.builds = {
        self.build_key_1: {
            'failure_type':
                'test',
            'failures': {
                's1': ['t1', 't2']
            },
            'status':
                None,
            'approaches': [
                analysis_approach_type.HEURISTIC, analysis_approach_type.TRY_JOB
            ],
            'top_score':
                None,
            'Confidence':
                80.0
        },
        self.build_key_2: {
            'failure_type':
                'test',
            'failures': {
                's1': ['t1', 't2']
            },
            'status':
                None,
            'approaches': [
                analysis_approach_type.HEURISTIC, analysis_approach_type.TRY_JOB
            ],
            'top_score':
                None,
            'Confidence':
                80.0
        }
    }
    suspected_cl.put()

    triage_suspected_cl._UpdateSuspectedCL(self.repo_name, self.revision_1,
                                           self.build_key_1,
                                           suspected_cl_status.CORRECT)

    suspected_cl = WfSuspectedCL.Get(self.repo_name, self.revision_1)

    self.assertEqual(suspected_cl.builds[self.build_key_1]['status'],
                     suspected_cl_status.CORRECT)
    self.assertEqual(suspected_cl.status, suspected_cl_status.PARTIALLY_TRIAGED)

    triage_suspected_cl._UpdateSuspectedCL(self.repo_name, self.revision_1,
                                           self.build_key_2,
                                           suspected_cl_status.INCORRECT)

    suspected_cl = WfSuspectedCL.Get(self.repo_name, self.revision_1)

    self.assertEqual(suspected_cl.builds[self.build_key_2]['status'],
                     suspected_cl_status.INCORRECT)
    self.assertEqual(suspected_cl.status, suspected_cl_status.PARTIALLY_CORRECT)
 def testShouldSendNotificationForSecondFailedBuild(self):
   culprit = WfSuspectedCL.Create('chromium', 'r3', 1)
   culprit.builds['m/b31/31'] = {}
   culprit.put()
   self.assertFalse(
       send_notification_for_culprit_pipeline._ShouldSendNotification(
           'chromium', 'r3', 2, False))
   culprit = WfSuspectedCL.Get('chromium', 'r3')
   culprit.builds['m/b32/32'] = {}
   culprit.put()
   self.assertTrue(
       send_notification_for_culprit_pipeline._ShouldSendNotification(
           'chromium', 'r3', 2, False))
   culprit = WfSuspectedCL.Get('chromium', 'r3')
   self.assertEqual(status.RUNNING, culprit.cr_notification_status)
Esempio n. 3
0
def _ShouldSendNotification(repo_name, revision, build_num_threshold,
                            force_notify):
    """Returns True if a notification for the culprit should be sent.

  Send notification only when:
    1. It was not processed yet.
    2. The culprit is for multiple failures in different builds to avoid false
      positive due to flakiness.

  Any new criteria for deciding when to notify should be implemented within this
  function.

  Args:
    repo_name, revision (str): Uniquely identify the revision to notify about.
    build_num_threshold (int): The number of builds the culprit needs to cause
        to fail before we notify. (To avoid false notifications for flake)
    force_notify (bool): If we should skip the fail number threshold check.

  Returns:
    A boolean indicating whether we should send the notification.

  """
    # TODO (chanli): Add check for if confidence for the culprit is
    # over threshold.
    culprit = WfSuspectedCL.Get(repo_name, revision)
    assert culprit

    if culprit.cr_notification_processed:
        return False

    if force_notify or len(culprit.builds) >= build_num_threshold:
        culprit.cr_notification_status = status.RUNNING
        culprit.put()
        return True
    return False
Esempio n. 4
0
def _SendNotificationForCulprit(repo_name, revision, commit_position,
                                review_server_host, change_id, revert_status):
    code_review_settings = FinditConfig().Get().code_review_settings
    codereview = codereview_util.GetCodeReviewForReview(
        review_server_host, code_review_settings)
    sent = False
    if codereview and change_id:
        # Occasionally, a commit was not uploaded for code-review.
        culprit = WfSuspectedCL.Get(repo_name, revision)

        action = 'identified'
        if revert_status == create_revert_cl_pipeline.CREATED_BY_SHERIFF:
            action = 'confirmed'

        message = textwrap.dedent("""
    Findit (https://goo.gl/kROfz5) %s this CL at revision %s as the culprit for
    failures in the build cycles as shown on:
    https://findit-for-me.appspot.com/waterfall/culprit?key=%s""") % (
            action, commit_position or revision, culprit.key.urlsafe())
        sent = codereview.PostMessage(change_id, message)
    else:
        logging.error('No code-review url for %s/%s', repo_name, revision)

    _UpdateNotificationStatus(repo_name, revision,
                              status.COMPLETED if sent else status.ERROR)
    return sent
Esempio n. 5
0
  def _GetAdditionalInformationForCL(
      self, repo_name, revision, confidences, build, reference_build_key):
    """Gets additional information for a cl.

    Currently additional information contains:
        confidence of the result;
        approaches that found this cl: HEURISTIC, TRY_JOB or both;
        revert_cl_url if the cl has been reverted by Findit.
    """
    additional_info = {}

    cl = WfSuspectedCL.Get(repo_name, revision)
    if not cl:
      return additional_info

    master_name = buildbot.GetMasterNameFromUrl(build.master_url)
    builder_name = build.builder_name
    current_build = build.build_number

    # If the CL is found by a try job, only the first failure will be recorded.
    # So we might need to go to the first failure to get CL information.
    build_info = cl.GetBuildInfo(master_name, builder_name, current_build)
    first_build_info = None if not reference_build_key else cl.GetBuildInfo(
        *build_util.GetBuildInfoFromId(reference_build_key))
    additional_info['confidence'], additional_info['cl_approach'] = (
        suspected_cl_util.GetSuspectedCLConfidenceScoreAndApproach(
            confidences, build_info, first_build_info))

    # Gets the revert_cl_url for the CL if there is one.
    if cl.revert_cl_url:
      additional_info['revert_cl_url'] = cl.revert_cl_url

    return additional_info
Esempio n. 6
0
 def testShouldSendNotificationForSecondFailedBuild(self):
     culprit = WfSuspectedCL.Create('chromium', 'r3', 1)
     culprit.builds['m/b31/31'] = {}
     culprit.put()
     self.assertFalse(
         culprit_action._ShouldSendNotification('chromium', 'r3', False,
                                                None, 2))
     culprit = WfSuspectedCL.Get('chromium', 'r3')
     culprit.builds['m/b32/32'] = {}
     culprit.put()
     self.assertTrue(
         culprit_action._ShouldSendNotification('chromium', 'r3', False,
                                                None, 2))
     culprit = WfSuspectedCL.Get('chromium', 'r3')
     self.assertEqual(analysis_status.RUNNING,
                      culprit.cr_notification_status)
Esempio n. 7
0
    def testLatestBuildSucceeded(self, mock_fn, *_):
        repo_name = 'chromium'
        revision = 'rev1'

        cl_info = ClInfo(self.review_server_host, self.review_change_id)
        cl_info.owner_email = '*****@*****.**'
        cl_info.commits.append(
            Commit('20001', 'rev1', datetime(2017, 2, 1, 0, 0, 0)))
        revert_cl = ClInfo('revert_review_host', '123V3127')
        revert_cl.url = 'https://codereview.chromium.org/54321'
        cl_info.reverts.append(
            Revert('20001', revert_cl, constants.DEFAULT_SERVICE_ACCOUNT,
                   datetime(2017, 2, 1, 1, 0, 0)))
        mock_fn.return_value = cl_info

        culprit = WfSuspectedCL.Create(repo_name, revision, 123)
        culprit.revert_cl = RevertCL()
        culprit.revert_status = status.RUNNING
        culprit.put()
        pipeline = CreateRevertCLPipeline('m', 'b', 123, repo_name, revision)
        revert_status = pipeline.run('m', 'b', 123, repo_name, revision)

        self.assertEquals(revert_status, create_revert_cl_pipeline.SKIPPED)

        culprit = WfSuspectedCL.Get(repo_name, revision)
        self.assertEqual(culprit.revert_status, status.SKIPPED)
        self.assertIsNotNone(culprit.revert_cl)
        self.assertEqual(culprit.skip_revert_reason,
                         create_revert_cl_pipeline.NEWEST_BUILD_GREEN)
Esempio n. 8
0
    def testRevertCLNotSaved(self, mock_fn, *_):
        repo_name = 'chromium'
        revision = 'rev1'

        cl_info = ClInfo(self.review_server_host, self.review_change_id)
        cl_info.commits.append(
            Commit('20001', 'rev1', datetime(2017, 2, 1, 0, 0, 0)))
        cl_info.owner_email = '*****@*****.**'
        revert_cl = ClInfo('revert_review_host', '123V3127')
        revert_cl.url = 'https://codereview.chromium.org/54321'
        cl_info.reverts.append(
            Revert('20001', revert_cl, constants.DEFAULT_SERVICE_ACCOUNT,
                   datetime(2017, 2, 1, 1, 0, 0)))
        mock_fn.return_value = cl_info

        WfSuspectedCL.Create(repo_name, revision, 123).put()
        pipeline = CreateRevertCLPipeline('m', 'b', 123, repo_name, revision)
        revert_status = pipeline.run('m', 'b', 123, repo_name, revision)

        self.assertEquals(revert_status,
                          create_revert_cl_pipeline.CREATED_BY_FINDIT)

        culprit = WfSuspectedCL.Get(repo_name, revision)
        self.assertEqual(culprit.revert_status, status.COMPLETED)
        self.assertIsNotNone(culprit.revert_cl)
Esempio n. 9
0
def UpdateSuspectedCL(repo_name, revision, commit_position, approach,
                      master_name, builder_name, build_number, cl_failure_type,
                      failures, top_score):

  suspected_cl = (
      WfSuspectedCL.Get(repo_name, revision) or
      WfSuspectedCL.Create(repo_name, revision, commit_position))

  if not suspected_cl.identified_time:  # pragma: no cover.
    suspected_cl.identified_time = time_util.GetUTCNow()

  suspected_cl.updated_time = time_util.GetUTCNow()

  if approach not in suspected_cl.approaches:
    suspected_cl.approaches.append(approach)
  if cl_failure_type not in suspected_cl.failure_type:
    suspected_cl.failure_type.append(cl_failure_type)

  build_key = BaseBuildModel.CreateBuildKey(master_name, builder_name,
                                            build_number)
  if build_key not in suspected_cl.builds:
    suspected_cl.builds[build_key] = {
        'approaches': [approach],
        'failure_type': cl_failure_type,
        'failures': failures,
        'status': _GetsStatusFromSameFailure(suspected_cl.builds, failures),
        'top_score': top_score
    }
  else:
    build = suspected_cl.builds[build_key]
    if approach not in build['approaches']:
      build['approaches'].append(approach)

  suspected_cl.put()
Esempio n. 10
0
def _GetAllSuspectedCLsAndCheckStatus(master_name, builder_name, build_number,
                                      analysis):
    build_key = build_util.CreateBuildId(master_name, builder_name,
                                         build_number)
    suspected_cls = copy.deepcopy(analysis.suspected_cls)
    if not suspected_cls:
        return []

    confidences = SuspectedCLConfidence.Get()

    for cl in suspected_cls:
        cl['status'] = _ANALYSIS_CL_STATUS_MAP.get(analysis.result_status,
                                                   None)
        cl['confidence'] = None

        suspected_cl = WfSuspectedCL.Get(cl['repo_name'], cl['revision'])
        if not suspected_cl:
            continue

        build = suspected_cl.builds.get(build_key)
        if build:
            cl['status'] = build['status']
            cl['confidence'] = '%d%%' % (
                suspected_cl_util.GetSuspectedCLConfidenceScore(
                    confidences, build))

    return suspected_cls
Esempio n. 11
0
    def testRevertCulprit(self, mock_revert, *_):
        repo_name = 'chromium'
        revision = 'rev1'
        build_key = 'm/b/123'

        revert_cl = RevertCL()
        revert_cl.revert_cl_url = 'url'
        revert_cl.created_time = datetime.datetime(2018, 6, 20, 0, 0, 0)

        mock_revert.return_value = (constants.CREATED_BY_FINDIT, revert_cl,
                                    None)

        culprit = WfSuspectedCL.Create(repo_name, revision, 1)
        culprit.put()

        pipeline_input = CreateRevertCLParameters(
            cl_key=culprit.key.urlsafe(),
            build_key=build_key,
            failure_type=failure_type.COMPILE)
        self.assertEqual(
            constants.CREATED_BY_FINDIT,
            culprit_action.RevertCulprit(pipeline_input, 'pipeline_id'))
        culprit = WfSuspectedCL.Get(repo_name, revision)
        self.assertEqual(revert_cl, culprit.revert_cl)
        self.assertEqual(analysis_status.COMPLETED, culprit.revert_status)
    def testSubmitRevertSucceed(self, mock_fn, mock_commit, *_):
        repo_name = 'chromium'
        revision = 'rev1'
        commit_position = 123

        cl_info = ClInfo(self.review_server_host, self.review_change_id)
        cl_info.commits.append(
            Commit('20001', 'rev1', [], datetime(2017, 2, 1, 0, 0, 0)))
        mock_fn.return_value = cl_info
        mock_commit.return_value = True

        culprit = WfSuspectedCL.Create(repo_name, revision, commit_position)
        revert = RevertCL()
        revert_change_id = '54321'
        revert.revert_cl_url = 'https://%s/q/%s' % (self.review_server_host,
                                                    revert_change_id)
        culprit.revert_cl = revert
        culprit.revert_status = status.COMPLETED
        culprit.put()
        revert_status = constants.CREATED_BY_FINDIT
        pipeline_input = SubmitRevertCLParameters(
            cl_key=culprit.key.urlsafe(),
            revert_status=revert_status,
            failure_type=failure_type.COMPILE)
        pipeline = SubmitRevertCLPipeline(pipeline_input)
        self.assertEqual(constants.COMMITTED, pipeline.run(pipeline_input))

        culprit = WfSuspectedCL.Get(repo_name, revision)
        self.assertEqual(culprit.revert_submission_status, status.COMPLETED)

        mock_commit.assert_called_with(revert_change_id)
Esempio n. 13
0
def GetWfSuspectedClKeysFromCLInfo(cl_info):
  """Get a dict of urlsafe keys object from result of GetCLInfo."""
  cl_keys = DictOfBasestring()
  for revision, info in cl_info.iteritems():
    culprit = WfSuspectedCL.Get(info['repo_name'], info['revision'])
    if not culprit:
      continue
    cl_keys[revision] = culprit.key.urlsafe()
  return cl_keys
    def _LogUnexpectedAborting(self, was_aborted):
        if not was_aborted:  # pragma: no cover
            return

        culprit = WfSuspectedCL.Get(self.repo_name, self.revision)

        if culprit.revert_status and culprit.revert_status != status.COMPLETED:
            culprit.revert_status = status.ERROR
            culprit.put()
Esempio n. 15
0
    def testCreateWfSuspectedCL(self):
        approach = analysis_approach_type.HEURISTIC
        master_name = 'm'
        builder_name = 'b'
        build_number = 123
        compile_failure_type = failure_type.COMPILE
        repo_name = 'chromium'
        revision = 'r1'
        commit_position = 1
        failures = {'compile': []}
        top_score = 5

        mocked_utcnow = datetime.datetime(2016, 10, 4, 0, 0, 0)
        self.MockUTCNow(mocked_utcnow)

        self.assertIsNone(WfSuspectedCL.Get(repo_name, revision))

        suspected_cl_util.UpdateSuspectedCL(repo_name, revision,
                                            commit_position, approach,
                                            master_name, builder_name,
                                            build_number, compile_failure_type,
                                            failures, top_score)

        expected_builds = {
            build_util.CreateBuildId(master_name, builder_name, build_number):
            {
                'approaches': [approach],
                'failure_type': compile_failure_type,
                'failures': failures,
                'status': None,
                'top_score': top_score
            }
        }

        suspected_cl = WfSuspectedCL.Get(repo_name, revision)

        self.assertIsNotNone(suspected_cl)
        self.assertEqual([analysis_approach_type.HEURISTIC],
                         suspected_cl.approaches)
        self.assertEqual([compile_failure_type], suspected_cl.failure_type)
        self.assertEqual(expected_builds, suspected_cl.builds)
        self.assertEqual(mocked_utcnow, suspected_cl.identified_time)
        self.assertEqual(mocked_utcnow, suspected_cl.updated_time)
Esempio n. 16
0
    def testLogUnexpectedAbortingNoChange(self):
        repo_name = 'chromium'
        revision = 'rev1'
        culprit = WfSuspectedCL.Create(repo_name, revision, 123)
        culprit.put()

        CreateRevertCLPipeline('m', 'b', 123, repo_name,
                               revision)._LogUnexpectedAborting(True)
        culprit = WfSuspectedCL.Get(repo_name, revision)
        self.assertIsNone(culprit.revert_status)
Esempio n. 17
0
    def testLogUnexpectedAborting(self):
        repo_name = 'chromium'
        revision = 'rev1'
        culprit = WfSuspectedCL.Create(repo_name, revision, 123)
        culprit.revert_status = status.RUNNING
        culprit.put()

        CreateRevertCLPipeline('m', 'b', 123, repo_name,
                               revision)._LogUnexpectedAborting(True)
        culprit = WfSuspectedCL.Get(repo_name, revision)
        self.assertEquals(culprit.revert_status, status.ERROR)
Esempio n. 18
0
    def testUpdateWfSuspectedCLAddSameBuild(self):
        approach = analysis_approach_type.HEURISTIC
        master_name = 'm'
        builder_name = 'b'
        build_number = 122
        test_failure_type = failure_type.TEST
        repo_name = 'chromium'
        revision = 'r2'
        commit_position = 2
        failures = {'step_1': ['test1', 'test2']}
        top_score = 4

        suspected_cl = WfSuspectedCL.Create(repo_name, revision,
                                            commit_position)
        suspected_cl.approaches = [analysis_approach_type.HEURISTIC]
        suspected_cl.builds = {
            build_util.CreateBuildId(master_name, builder_name, build_number):
            {
                'approaches': [analysis_approach_type.HEURISTIC],
                'failure_type': test_failure_type,
                'failures': failures,
                'status': None,
                'top_score': 4
            }
        }
        suspected_cl.failure_type = [test_failure_type]
        suspected_cl.put()

        suspected_cl_util.UpdateSuspectedCL(repo_name, revision,
                                            commit_position, approach,
                                            master_name, builder_name,
                                            build_number, test_failure_type,
                                            failures, top_score)

        expected_builds = {
            build_util.CreateBuildId(master_name, builder_name, build_number):
            {
                'approaches': [analysis_approach_type.HEURISTIC],
                'failure_type': test_failure_type,
                'failures': failures,
                'status': None,
                'top_score': 4
            }
        }

        expected_approaches = [analysis_approach_type.HEURISTIC]

        suspected_cl = WfSuspectedCL.Get(repo_name, revision)

        self.assertIsNotNone(suspected_cl)
        self.assertEqual(expected_approaches, suspected_cl.approaches)
        self.assertEqual([test_failure_type], suspected_cl.failure_type)
        self.assertEqual(expected_builds, suspected_cl.builds)
Esempio n. 19
0
 def testShouldNotSendNotificationForSameFailedBuild(self):
     culprit = WfSuspectedCL.Create('chromium', 'r2', 1)
     culprit.builds['m/b2/2'] = {}
     culprit.put()
     self.assertTrue(
         culprit_action._ShouldSendNotification(
             'chromium', 'r2', True, constants.CREATED_BY_SHERIFF, 2))
     self.assertFalse(
         culprit_action._ShouldSendNotification(
             'chromium', 'r2', True, constants.CREATED_BY_SHERIFF, 2))
     culprit = WfSuspectedCL.Get('chromium', 'r2')
     self.assertEqual(analysis_status.RUNNING,
                      culprit.cr_notification_status)
    def testLogUnexpectedAbortingNoChange(self):
        repo_name = 'chromium'
        revision = 'rev1'
        build_key = 'm/b/123'
        culprit = WfSuspectedCL.Create(repo_name, revision, 123)
        culprit.put()

        pipeline_input = CreateRevertCLParameters(
            cl_key=culprit.key.urlsafe(),
            build_key=build_key,
            failure_type=failure_type.COMPILE)
        CreateRevertCLPipeline(pipeline_input).OnAbort(pipeline_input)
        culprit = WfSuspectedCL.Get(repo_name, revision)
        self.assertIsNone(culprit.revert_status)
 def testLogUnexpectedAborting(self):
     repo_name = 'chromium'
     revision = 'rev1'
     culprit = WfSuspectedCL.Create(repo_name, revision, 123)
     culprit.revert_submission_status = status.RUNNING
     culprit.put()
     revert_status = constants.CREATED_BY_FINDIT
     pipeline_input = SubmitRevertCLParameters(
         cl_key=culprit.key.urlsafe(),
         revert_status=revert_status,
         failure_type=failure_type.COMPILE)
     SubmitRevertCLPipeline(pipeline_input).OnAbort(pipeline_input)
     culprit = WfSuspectedCL.Get(repo_name, revision)
     self.assertEquals(culprit.revert_submission_status, status.ERROR)
    def testRevertCLSucceed(self, mock_fn, mock_revert, *_):
        repo_name = 'chromium'
        revision = 'rev1'
        commit_position = 123
        build_key = 'm/b/123'

        cl_info = ClInfo(self.review_server_host, self.review_change_id)
        cl_info.commits.append(
            Commit('20001', 'rev1', ['rev0'], datetime(2017, 2, 1, 0, 0, 0)))
        cl_info.owner_email = '*****@*****.**'
        mock_fn.return_value = cl_info
        mock_revert.return_value = '54321'

        culprit = WfSuspectedCL.Create(repo_name, revision, commit_position)
        culprit.builds = {
            build_key: {
                'status': None,
                'failures': {
                    'step': ['test1']
                }
            }
        }
        culprit.put()

        pipeline_input = CreateRevertCLParameters(
            cl_key=culprit.key.urlsafe(),
            build_key=build_key,
            failure_type=failure_type.COMPILE)
        pipeline = CreateRevertCLPipeline(pipeline_input)
        revert_status = pipeline.run(pipeline_input)

        self.assertEquals(revert_status, constants.CREATED_BY_FINDIT)

        culprit = WfSuspectedCL.Get(repo_name, revision)
        self.assertEqual(culprit.revert_status, status.COMPLETED)
        self.assertIsNotNone(culprit.revert_cl)

        reason = textwrap.dedent("""
        Findit (https://goo.gl/kROfz5) identified CL at revision %s as the
        culprit for failures in the build cycles as shown on:
        https://analysis.chromium.org/waterfall/culprit?key=%s\n
        Sample Failed Build: %s\n
        Sample Failed Step: %s""") % (commit_position, culprit.key.urlsafe(),
                                      buildbot.CreateBuildUrl('m', 'b',
                                                              '123'), 'step')
        mock_revert.assert_called_with(reason,
                                       self.review_change_id,
                                       '20001',
                                       bug_id=None)
Esempio n. 23
0
def GetHeuristicSuspectedCLs(master_name, builder_name, build_number):
    """Gets revisions of suspected cls found by heuristic approach."""
    analysis = WfAnalysis.Get(master_name, builder_name, build_number)
    suspects = ListOfBasestring()
    if analysis and analysis.suspected_cls:
        for cl in analysis.suspected_cls:
            culprit = WfSuspectedCL.Get(cl['repo_name'], cl['revision'])
            if not culprit:  # pragma: no cover
                logging.warning(
                    'No culprit found for repo_name %s and revision %s',
                    cl['repo_name'], cl['revision'])
                continue
            suspects.append(culprit.key.urlsafe())

    return suspects
Esempio n. 24
0
    def testCommit(self, *_):
        culprit = WfSuspectedCL.Create('chromium', 'rev1', 1)
        culprit.put()

        pipeline_input = SubmitRevertCLParameters(
            cl_key=culprit.key.urlsafe(),
            revert_status=constants.CREATED_BY_FINDIT,
            failure_type=failure_type.COMPILE)

        self.assertEqual(
            constants.COMMITTED,
            culprit_action.CommitRevert(pipeline_input, 'pipeline_id'))

        culprit = WfSuspectedCL.Get('chromium', 'rev1')
        self.assertEqual(analysis_status.COMPLETED,
                         culprit.revert_submission_status)
Esempio n. 25
0
def GetSampleFailedStepName(repo_name, revision, build_id):
    culprit = WfSuspectedCL.Get(repo_name, revision)

    if culprit and culprit.builds:
        if (culprit.builds.get(build_id)
                and culprit.builds[build_id].get('failures')):
            failures = culprit.builds[build_id]['failures']
        else:
            logging.warning(
                '%s is not found in culprit %s/%s\'s build,'
                ' using another build to get a sample failed step.', build_id,
                repo_name, revision)
            failures = culprit.builds.values()[0]['failures']
        return failures.keys()[0]
    logging.error('Cannot get a sample failed step for culprit %s/%s.',
                  repo_name, revision)
    return ''
Esempio n. 26
0
def _UpdateSuspectedCL(repo_name,
                       revision,
                       build_key,
                       cl_status,
                       updated_time=None):
    suspected_cl = WfSuspectedCL.Get(repo_name, revision)
    if (not suspected_cl or not suspected_cl.builds):
        return False

    if not suspected_cl.builds.get(build_key):
        # The failure is not a first time failure.
        # Will not update suspected_cl but will update analysis.
        return True

    suspected_cl.builds[build_key]['status'] = cl_status

    cl_correct = True
    cl_incorrect = True
    partial_triaged = False
    # Checks if all the builds have been triaged and checks the status of the cl
    # on each build.
    # If all the builds are  correct, the cl is correct;
    # If all the builds are incorrect, the cl is incorrect;
    # If some builds are correct while others aren't, the cl is partially correct;
    # If not all the builds have been triaged, the cl is partially triaged.
    for build in suspected_cl.builds.values():
        if build['status'] is None:
            partial_triaged = True
        elif build['status'] == suspected_cl_status.CORRECT:
            cl_incorrect = False
        else:
            cl_correct = False

    if partial_triaged:
        suspected_cl.status = suspected_cl_status.PARTIALLY_TRIAGED
    elif cl_correct:
        suspected_cl.status = suspected_cl_status.CORRECT
    elif cl_incorrect:
        suspected_cl.status = suspected_cl_status.INCORRECT
    else:
        suspected_cl.status = suspected_cl_status.PARTIALLY_CORRECT

    suspected_cl.updated_time = updated_time or time_util.GetUTCNow()

    suspected_cl.put()
    return True
    def testLogUnexpectedAbortingPipelineIdNotMatch(self):
        repo_name = 'chromium'
        revision = 'rev1'
        culprit = WfSuspectedCL.Create(repo_name, revision, 123)
        culprit.submit_revert_pipeline_id = 'pipeline_id'
        culprit.put()

        revert_status = constants.CREATED_BY_FINDIT
        pipeline_input = SubmitRevertCLParameters(
            cl_key=culprit.key.urlsafe(),
            revert_status=revert_status,
            failure_type=failure_type.COMPILE)
        pipeline = SubmitRevertCLPipeline(pipeline_input)
        pipeline.start_test()
        pipeline.OnAbort(pipeline_input)
        culprit = WfSuspectedCL.Get(repo_name, revision)
        self.assertEqual(culprit.submit_revert_pipeline_id, 'pipeline_id')
Esempio n. 28
0
def _ShouldSendNotification(repo_name, revision, force_notify, revert_status,
                            build_num_threshold):
    """Returns True if a notification for the culprit should be sent.

  Send notification only when:
    1. The culprit is not reverted.
    2. It was not processed yet.
    3. The culprit is for multiple failures in different builds to avoid false
      positive due to flakiness.

  Any new criteria for deciding when to notify should be implemented within this
  function.

  Args:
    repo_name, revision (str): Uniquely identify the revision to notify about.
    force_notify (bool): If we should skip the fail number threshold check.
    revert_status (int): Status of revert if exists.
    build_num_threshold (int): Threshold for the number of builds the culprit is
      responsible for. A notification should be sent when number of builds
      exceeds the threshold.

  Returns:
    A boolean indicating whether we should send the notification.

  """
    if revert_status == constants.CREATED_BY_FINDIT:
        # Already notified when revert, bail out.
        return False

    if revert_status == constants.CREATED_BY_SHERIFF:
        force_notify = True

    # TODO (chanli): Add check for if confidence for the culprit is
    # over threshold.
    culprit = WfSuspectedCL.Get(repo_name, revision)
    assert culprit

    if culprit.cr_notification_processed:
        return False

    if force_notify or len(culprit.builds) >= build_num_threshold:
        culprit.cr_notification_status = analysis_status.RUNNING
        culprit.put()
        return True
    return False
    def testLogUnexpectedAbortingPipelineIdNotMatch(self):
        repo_name = 'chromium'
        revision = 'rev1'
        build_key = 'm/b/123'

        culprit = WfSuspectedCL.Create(repo_name, revision, 123)
        culprit.revert_pipeline_id = 'pipeline_id'
        culprit.put()

        pipeline_input = CreateRevertCLParameters(
            cl_key=culprit.key.urlsafe(),
            build_key=build_key,
            failure_type=failure_type.COMPILE)
        pipeline = CreateRevertCLPipeline(pipeline_input)
        pipeline.start()
        pipeline.OnAbort(pipeline_input)
        culprit = WfSuspectedCL.Get(repo_name, revision)
        self.assertEqual(culprit.revert_pipeline_id, 'pipeline_id')
Esempio n. 30
0
def _SetActionsForEvent(event):
    """Sets the actions for an analysis event.

  Args:
    (*AnalysisCompletionEventProto): Event proto to be written to.
  """
    if event.analysis_info.culprit.host:
        # If there's a culprit.host, then the SuspectedCL exists.
        culprit_cl = WfSuspectedCL.Get(event.analysis_info.culprit.project,
                                       event.analysis_info.culprit.revision)
        assert culprit_cl
        if culprit_cl.revert_submission_status == analysis_status.COMPLETED:
            event.analysis_info.actions.append(findit_pb2.REVERT_SUBMITTED)

        if culprit_cl.revert_status == analysis_status.COMPLETED:
            event.analysis_info.actions.append(findit_pb2.REVERT_CREATED)

        if culprit_cl.cr_notification_status == analysis_status.COMPLETED:
            event.analysis_info.actions.append(findit_pb2.CL_COMMENTED)