def testFindMatchingWaterfallStepCheckAllShards(self, mock_object, *_): mock_object.side_effect = [ WebkitLayoutTestResults({}, partial_result=True), WebkitLayoutTestResults({}, partial_result=True) ] step_mapper.FindMatchingWaterfallStep(self.wf_build_step, 'webkit_layout_tests') self.assertTrue(self.wf_build_step.swarmed) self.assertTrue(self.wf_build_step.supported)
def ScheduleAnalysisForFlake(request, user_email, is_admin, triggering_source, rerun=False): """Schedules an analysis on the flake in the given request if needed. Args: request (FlakeAnalysisRequest): The request to analyze a flake. user_email (str): The email of the requester. is_admin (bool): Whether the requester is an admin. triggering_source (int): Where the request is coming from, either Findit UI (check flake page), pipeline (from analysis) or Findit API. rerun (bool): This is a rerun, so force it to be run. Returns: True if an analysis was scheduled; False if a new analysis is not needed; None if the user has no permission to. """ # TODO(crbug.com/853325): Refactor rerun logic. assert len(request.build_steps), 'At least 1 build step is needed!' if not IsAuthorizedUser(user_email, is_admin): logging.info( 'Schedule failed because user is not authorized. user:%s, admin:%s', user_email, is_admin) return None request.bug_reported_by = triggering_source request.user_emails = [user_email] manually_triggered = user_email.endswith('@google.com') trigger_action = 'manual' if manually_triggered else 'auto' flake_source = 'cq' if request.on_cq else 'waterfall' build_steps = [] for build_step in request.build_steps: step_mapper.FindMatchingWaterfallStep(build_step, request.name) # crbug.com/844516: temporarily bail out for fuchsia and Win7. if build_step.has_matching_waterfall_step and ( build_step.wf_builder_name == 'Win10 Tests x64 (dbg)' or 'fuchsia' in build_step.wf_builder_name.lower()): continue build_steps.append(build_step) request.build_steps = build_steps if not request.build_steps: logging.info('Flake %s on android/fuchsia temporarily unsupported.', request.name) return None canonical_step_name = 'unknown' isolate_target_name = 'unknown' if request.build_steps[0].step_metadata: # Tries to use step_metadata from request.build_steps as default. canonical_step_name = request.build_steps[0].step_metadata.get( 'canonical_step_name') or canonical_step_name isolate_target_name = request.build_steps[0].step_metadata.get( 'isolate_target_name') or isolate_target_name version_number, build_step = _CheckForNewAnalysis(request, rerun) if build_step and build_step.step_metadata: # Uses the step_metadata from the step that the analysis will actually # run for. canonical_step_name = ( build_step.step_metadata.get('canonical_step_name') or canonical_step_name) isolate_target_name = ( build_step.step_metadata.get('isolate_target_name') or isolate_target_name) if version_number and build_step: # A new analysis is needed. logging.info('A new analysis is needed for: %s', build_step) normalized_test = TestInfo(build_step.wf_master_name, build_step.wf_builder_name, build_step.wf_build_number, build_step.wf_step_name, request.name) original_test = TestInfo(build_step.master_name, build_step.builder_name, build_step.build_number, build_step.step_name, request.name) analysis = initialize_flake_pipeline.ScheduleAnalysisIfNeeded( normalized_test, original_test, request.flake_key, bug_id=request.bug_id, allow_new_analysis=True, manually_triggered=manually_triggered, user_email=user_email, triggering_source=triggering_source, queue_name=constants.WATERFALL_ANALYSIS_QUEUE, force=rerun) if analysis: # TODO: put this in a transaction. request = FlakeAnalysisRequest.GetVersion(key=request.name, version=version_number) request.analyses.append(analysis.key) request.put() logging.info( 'A new analysis was triggered successfully with key: %s', analysis.key) monitoring.OnFlakeAnalysisTriggered( source=flake_source, operation='analyze', trigger=trigger_action, canonical_step_name=canonical_step_name, isolate_target_name=isolate_target_name) return True else: logging.error('But new analysis was not triggered!') monitoring.OnFlakeAnalysisTriggered( source=flake_source, operation='error', trigger=trigger_action, canonical_step_name=canonical_step_name, isolate_target_name=isolate_target_name) else: logging.info('No new analysis is needed: %s', request) monitoring.OnFlakeAnalysisTriggered( source=flake_source, operation='skip', trigger=trigger_action, canonical_step_name=canonical_step_name, isolate_target_name=isolate_target_name) return False
def ScheduleAnalysisForFlake(request, user_email, is_admin, triggering_source): """Schedules an analysis on the flake in the given request if needed. Args: request (FlakeAnalysisRequest): The request to analyze a flake. user_email (str): The email of the requester. is_admin (bool): Whether the requester is an admin. triggering_source (int): Where the request is coming from, either Findit UI (check flake page), pipeline (from analysis) or Findit API. Returns: True if an analysis was scheduled; False if a new analysis is not needed; None if the user has no permission to. """ assert len(request.build_steps), 'At least 1 build step is needed!' if not IsAuthorizedUser(user_email, is_admin): logging.info('user:%s, admin:%s', user_email, is_admin) return None request.user_emails = [user_email] manually_triggered = user_email.endswith('@google.com') trigger_action = 'manual' if manually_triggered else 'auto' flake_source = 'cq' if request.on_cq else 'waterfall' for build_step in request.build_steps: step_mapper.FindMatchingWaterfallStep(build_step, request.name) version_number, build_step = _CheckForNewAnalysis(request) if version_number and build_step: # A new analysis is needed. # TODO(lijeffrey): Add support for the force flag to trigger a rerun. logging.info('A new analysis is needed for: %s', build_step) normalized_test = TestInfo(build_step.wf_master_name, build_step.wf_builder_name, build_step.wf_build_number, build_step.wf_step_name, request.name) original_test = TestInfo(build_step.master_name, build_step.builder_name, build_step.build_number, build_step.step_name, request.name) analysis = initialize_flake_pipeline.ScheduleAnalysisIfNeeded( normalized_test, original_test, bug_id=request.bug_id, allow_new_analysis=True, manually_triggered=manually_triggered, user_email=user_email, triggering_source=triggering_source, queue_name=constants.WATERFALL_ANALYSIS_QUEUE) if analysis: # TODO: put this in a transaction. request = FlakeAnalysisRequest.GetVersion(key=request.name, version=version_number) request.analyses.append(analysis.key) request.put() logging.info('A new analysis was triggered successfully: %s', analysis.key) monitoring.flakes.increment({ 'operation': 'analyze', 'trigger': trigger_action, 'source': flake_source, }) return True else: logging.error('But new analysis was not triggered!') else: logging.info('No new analysis is needed: %s', request) monitoring.flakes.increment({ 'operation': 'skip', 'trigger': trigger_action, 'source': flake_source, }) return False
def testFindMatchingWaterfallStepNoOutput(self, *_): step_mapper.FindMatchingWaterfallStep(self.build_step, 'test1') self.assertTrue(self.build_step.swarmed) self.assertFalse(self.build_step.supported)
def testFindMatchingWaterfallStepNotSwarmed(self, _): step_mapper.FindMatchingWaterfallStep(self.build_step, 'test1') self.assertFalse(self.build_step.swarmed)
def testFindMatchingWaterfallStepNoMatch(self, _): step_mapper.FindMatchingWaterfallStep(self.build_step, 'test1') self.assertFalse(self.build_step.swarmed) self.assertIsNone(self.build_step.wf_builder_name)
def testFindMatchingWaterfallStepNoTestResultObject(self, *_): step_mapper.FindMatchingWaterfallStep(self.wf_build_step, 'webkit_layout_tests') self.assertTrue(self.wf_build_step.swarmed) self.assertFalse(self.wf_build_step.supported)
def testFindMatchingWaterfallStepNotSupportOtherIsolatedScriptTests( self, mock_object, *_): mock_object.return_value = WebkitLayoutTestResults(None) step_mapper.FindMatchingWaterfallStep(self.wf_build_step, 'test1') self.assertTrue(self.wf_build_step.swarmed) self.assertFalse(self.wf_build_step.supported)
def testFindMatchingWaterfallStepForWfStep(self, *_): step_mapper.FindMatchingWaterfallStep(self.wf_build_step, 'test1') self.assertTrue(self.wf_build_step.swarmed) self.assertTrue(self.wf_build_step.supported)
def testFindMatchingWaterfallStepForWfStepNoStepMetadata(self, _): step_mapper.FindMatchingWaterfallStep(self.wf_build_step, 'test1') self.assertEqual(self.wf_build_step.wf_build_number, self.wf_build_step.build_number) self.assertFalse(self.wf_build_step.swarmed) self.assertFalse(self.wf_build_step.supported)