def OnBuildFailureAnalysisResultRequested(request): """Returns the findings of an analysis for a failed build. Since Findit v2 only supports compile failure on cros builds, this api will simply respond an empty response on other failures. This is to prevent Findit spending too many pixels to tell users many failures are not supported. Args: request(findit_result.BuildFailureAnalysisRequest): request for a build failure. Returns: (findit_result.BuildFailureAnalysisResponseCollection): Analysis results for the requested build. """ build_id = request.build_id build_alternative_id = request.build_alternative_id if build_id: build_entity = LuciFailedBuild.get_by_id(build_id) if not build_entity: logging.debug('No LuciFailedBuild entity for build %d.', request.build_id) return [] else: build_entity = LuciFailedBuild.GetBuildByNumber( build_alternative_id.project, build_alternative_id.bucket, build_alternative_id.builder, build_alternative_id.number) if not build_entity: logging.debug('No LuciFailedBuild entity for build %s/%s/%s/%d.', build_alternative_id.project, build_alternative_id.bucket, build_alternative_id.builder, build_alternative_id.number) return [] if build_entity.build_failure_type == StepTypeEnum.COMPILE: return compile_analysis.OnCompileFailureAnalysisResultRequested( request, build_entity) if build_entity.build_failure_type == StepTypeEnum.TEST: return test_analysis.OnTestFailureAnalysisResultRequested( request, build_entity) logging.debug( 'Findit v2 only supports compile or test failure analysis, ' 'so no results for %d with %s failures.', build_id, build_entity.build_failure_type) return []
def testCreateLuciFailedBuildForCompileFailure(self): build_id = 87654321 commit_position = 65432 legacy_build_number = 12345 build = LuciFailedBuild.Create( luci_project='chromium', luci_bucket='ci', luci_builder='Linux Builder', build_id=build_id, legacy_build_number=legacy_build_number, gitiles_host='chromium.googlesource.com', gitiles_project='chromium/src', gitiles_ref='refs/heads/master', gitiles_id='git_hash', commit_position=commit_position, status=20, create_time=datetime(2019, 3, 28), start_time=datetime(2019, 3, 28, 0, 1), end_time=datetime(2019, 3, 28, 1), build_failure_type=StepTypeEnum.COMPILE) build.put() # Get entity by build_id. build = LuciFailedBuild.get_by_id(build_id) self.assertIsNotNone(build) self.assertEqual(StepTypeEnum.COMPILE, build.build_failure_type) self.assertEqual(commit_position, build.gitiles_commit.commit_position) self.assertEqual('chromium/ci', build.bucket_id) self.assertEqual('chromium/ci/Linux Builder', build.builder_id) # Get entity by build number. res1 = LuciFailedBuild.GetBuildByNumber('chromium', 'ci', 'Linux Builder', legacy_build_number) self.assertEqual(build_id, res1.build_id) # Get entity by commit_position. res2 = LuciFailedBuild.query( ndb.AND( LuciFailedBuild.builder_id == 'chromium/ci/Linux Builder', LuciFailedBuild.gitiles_commit.commit_position == commit_position)).fetch() self.assertEqual(1, len(res2)) self.assertEqual(build_id, res2[0].build_id)
def testSaveCompileFailuresOnlyStepLevelFailures(self, _): detailed_compile_failures = { 'compile': { 'failures': {}, 'first_failed_build': { 'id': 8000000000121, 'number': 121, 'commit_id': 'git_sha' }, 'last_passed_build': { 'id': 8000000000120, 'number': 120, 'commit_id': 'git_sha' }, }, } # Prepares data for first failed build. first_failed_build = self._MockBuild(8000000000121, 121, 'git_sha_121') first_failed_build_entity = luci_build.SaveFailedBuild( self.context, first_failed_build, StepTypeEnum.COMPILE) first_failure = CompileFailure.Create(first_failed_build_entity.key, 'compile', None, 'CXX') first_failure.put() pre_compile_analysis.SaveCompileFailures(self.context, self.build, detailed_compile_failures) build_entity = LuciFailedBuild.get_by_id(self.build_id) self.assertIsNotNone(build_entity) compile_failures = CompileFailure.query( ancestor=build_entity.key).fetch() self.assertEqual(1, len(compile_failures)) self.assertEqual(8000000000121, compile_failures[0].first_failed_build_id) self.assertEqual([], compile_failures[0].output_targets) self.assertEqual(first_failure.key, compile_failures[0].merged_failure_key)
def testGetFirstFailuresInCurrentBuildWithoutGroup(self, *_): build_121_info = { 'id': 8000000000121, 'number': self.build_number - 2, 'commit_id': 'git_sha_121' } first_failures_in_current_build = { 'failures': { 'compile': { 'output_targets': [frozenset(['target1']), frozenset(['target2'])], 'last_passed_build': build_121_info, }, }, 'last_passed_build': build_121_info } # Creates and saves entities of the existing group. detailed_compile_failures = { 'compile': { 'failures': { frozenset(['target1']): { 'rule': 'CXX', 'first_failed_build': self.build_info, 'last_passed_build': build_121_info, }, frozenset(['target2']): { 'rule': 'ACTION', 'first_failed_build': self.build_info, 'last_passed_build': build_121_info, }, }, 'first_failed_build': self.build_info, 'last_passed_build': build_121_info, }, } pre_compile_analysis.SaveCompileFailures(self.context, self.build, detailed_compile_failures) # Prepares data for existing failure group. group_build = self._MockBuild(8000000000134, 12134, 'git_sha_134', builder_name='Mac') group_build_entity = luci_build.SaveFailedBuild( self.context, group_build, StepTypeEnum.COMPILE) group_failure1 = CompileFailure.Create(group_build_entity.key, 'compile', ['target1'], 'CXX') group_failure1.put() group_failure2 = CompileFailure.Create(group_build_entity.key, 'compile', ['target2'], 'ACTION') group_failure2.put() self.assertEqual( { 'failures': {}, 'last_passed_build': None }, pre_compile_analysis.GetFirstFailuresInCurrentBuildWithoutGroup( self.context, self.build, first_failures_in_current_build)) build = LuciFailedBuild.get_by_id(self.build_id) compile_failures = CompileFailure.query(ancestor=build.key).fetch() self.assertEqual(2, len(compile_failures)) for failure in compile_failures: if failure.output_targets == ['target1']: self.assertEqual(group_failure1.key, failure.merged_failure_key) else: self.assertEqual(group_failure2.key, failure.merged_failure_key)
def testSaveCompileFailures(self, _): detailed_compile_failures = { 'compile': { 'failures': { frozenset(['target1', 'target2']): { 'rule': 'CXX', 'first_failed_build': { 'id': 8000000000121, 'number': 121, 'commit_id': 'git_sha_121' }, 'last_passed_build': { 'id': 8000000000120, 'number': 120, 'commit_id': 'git_sha' }, }, }, 'first_failed_build': { 'id': 8000000000121, 'number': 121, 'commit_id': 'git_sha_121' }, 'last_passed_build': { 'id': 8000000000120, 'number': 120, 'commit_id': 'git_sha' }, }, } # Prepares data for existing failure group. group_build = self._MockBuild(8000003400121, 12134, 'git_sha_121', builder_name='Mac') group_build_entity = luci_build.SaveFailedBuild( self.context, group_build, StepTypeEnum.COMPILE) group_failure = CompileFailure.Create(group_build_entity.key, 'compile', ['target1', 'target2'], 'CXX') group_failure.put() # Prepares data for first failed build. first_failed_build = self._MockBuild(8000000000121, 121, 'git_sha_121') first_failed_build_entity = luci_build.SaveFailedBuild( self.context, first_failed_build, StepTypeEnum.COMPILE) first_failure = CompileFailure.Create(first_failed_build_entity.key, 'compile', ['target1', 'target2'], 'CXX') first_failure.merged_failure_key = group_failure.key first_failure.put() pre_compile_analysis.SaveCompileFailures(self.context, self.build, detailed_compile_failures) build = LuciFailedBuild.get_by_id(self.build_id) self.assertIsNotNone(build) compile_failures = CompileFailure.query(ancestor=build.key).fetch() self.assertEqual(1, len(compile_failures)) self.assertEqual(8000000000121, compile_failures[0].first_failed_build_id) self.assertEqual(group_failure.key, compile_failures[0].merged_failure_key)