def _ProcessAndSaveRerunBuildResult(context, analyzed_build_id, rerun_build): """Gets results of a completed rerun build and save it in datastore. Args: context (findit_v2.services.context.Context): Scope of the analysis. analyzed_build_id (int): Id of the failed ci/post_submit build that's being analyzed. rerun_build (buildbucket build.proto): ALL info about the rerun build. Returns: True if the rerun build entity is updated, otherwise False. """ project_api = projects.GetProjectAPI(context.luci_project_name) analysis = TestFailureAnalysis.GetVersion(analyzed_build_id) if not analysis: logging.error('TestFailureAnalysis missing for %d.', analyzed_build_id) return False rerun_build_entity = TestRerunBuild.get_by_id( rerun_build.id, parent=analysis.key) if not rerun_build_entity: logging.error('TestRerunBuild entity for build %d missing.', rerun_build.id) return False detailed_test_failures = {} if rerun_build.status == common_pb2.FAILURE: failed_steps = build_util.GetFailedStepsInBuild(context, rerun_build) test_steps = [fs[0] for fs in failed_steps if fs[1] == StepTypeEnum.TEST] detailed_test_failures = project_api.GetTestFailures( rerun_build, test_steps) if test_steps else {} _SaveRerunBuildResults(rerun_build_entity, rerun_build.status, detailed_test_failures, rerun_build.end_time.ToDatetime()) return True
def OnBuildFailure(context, build): """Processes the failed build within the given context. Args: context (findit_v2.services.context.Context): Scope of the analysis. build (buildbucket build.proto): ALL info about the build. Returns: True if the failed build is supported and analyzed; otherwise False. """ logging.info('Context of analysis: %r', context) logging.info('Failed build is: %r', build.id) failed_steps = build_util.GetFailedStepsInBuild(context, build) if not failed_steps: logging.debug('No failed steps found for failed build %d', build.id) return False compile_steps = [ fs[0] for fs in failed_steps if fs[1] == StepTypeEnum.COMPILE ] if compile_steps: logging.info('Compile failure found in build %d.', build.id) return compile_api.AnalyzeCompileFailure(context, build, compile_steps) logging.info('Unsupported failure types: %r', [fs[1] for fs in failed_steps]) return False
def OnBuildFailure(context, build): """Processes the failed build within the given context. If the failures are supported by Findit, an analysis will start. Args: context (findit_v2.services.context.Context): Scope of the analysis. build (buildbucket build.proto): ALL info about the build. Returns: True if the failed build is supported and analyzed; otherwise False. """ logging.info('Context of analysis: %r', context) logging.info('Failed build is: %r', build.id) failed_steps = build_util.GetFailedStepsInBuild(context, build) if not failed_steps: logging.debug('No failed steps found for failed build %d', build.id) return False compile_steps = [ fs[0] for fs in failed_steps if fs[1] == StepTypeEnum.COMPILE ] if compile_steps: logging.info('Compile failure found in build %d.', build.id) return compile_analysis.AnalyzeCompileFailure(context, build, compile_steps) test_steps = [fs[0] for fs in failed_steps if fs[1] == StepTypeEnum.TEST] if test_steps: logging.info('Test failure found in build %d.', build.id) analysis_triggered = test_analysis.AnalyzeTestFailure( context, build, test_steps) # Because of special project settings, some test failures may skip the # analysis, but a later build may actually need those failures to be # analyzed, so Findit has to check back and trigger a new analysis for # those previously skipped failures. # For example, for CrOS, if there are too many failed steps in one build # (b1), Findit will get notified that b1 doesn't need analysis. Later if # b2 completes with just a few failures, b2 will be analyzed. And if some of # the failures in b2 also happened in b1, Findit should analyze those # particular failures in b1. test_analysis.BackfillIfSkippedAnalyses(context, build) return analysis_triggered logging.info('Unsupported failure types: %r', [fs[1] for fs in failed_steps]) return False
def testGetFailedStepsInBuild(self): build_id = 8000000000123 build_number = 123 builder = BuilderID(project='chromium', bucket='try', builder='linux-rel') build = Build(id=build_id, builder=builder, number=build_number, status=common_pb2.FAILURE) step1 = Step(name='s1', status=common_pb2.SUCCESS) step2 = Step(name='compile', status=common_pb2.FAILURE) build.steps.extend([step1, step2]) context = Context(luci_project_name='chromium', gitiles_host='gitiles.host.com', gitiles_project='project/name', gitiles_ref='ref/heads/master', gitiles_id='git_sha') failed_steps = build_util.GetFailedStepsInBuild(context, build) self.assertEqual(1, len(failed_steps)) self.assertEqual('compile', failed_steps[0][0].name) self.assertEqual(StepTypeEnum.COMPILE, failed_steps[0][1])