def ReviveOrCreateTryJobEntity(master_name, builder_name, build_number, force_try_job): """Checks try job entity to further determine if need a new try job. * If there is an entity for a running or completed try job, no need for new job. * If there is an entity for a failed try job, revive the entity and start a new job. * If there is no entity, create one. Returns: A bool to indicate if a try job entity is revived or created. The try job entities' key. """ try_job_entity_revived_or_created = True try_job = WfTryJob.Get(master_name, builder_name, build_number) if try_job: if try_job.failed or force_try_job: try_job.status = analysis_status.PENDING try_job.put() else: try_job_entity_revived_or_created = False else: try_job = WfTryJob.Create(master_name, builder_name, build_number) try_job.put() return try_job_entity_revived_or_created, try_job.key.urlsafe()
def _GetAllTryJobs(self, failure_result_map): """Returns all try jobs related to one build. Args: A dict to map each step/test with the key to the build when it failed the first time. { 'step1': 'm/b/1', 'step2': { 'test1': 'm/b/1', 'test2': 'm/b/2' } } Returns: A dict of try jobs like below: { 'm/b/1': WfTryJob( key=Key('WfBuild', 'm/b/1'),...) ... } """ if not failure_result_map: return {} try_jobs = {} for step_map in failure_result_map.values(): if isinstance(step_map, basestring): try_jobs[step_map] = WfTryJob.Get(*step_map.split('/')) else: for task_key in step_map.values(): if not try_jobs.get(task_key): try_jobs[task_key] = WfTryJob.Get(*task_key.split('/')) return try_jobs
def testReturnNoneIfNoTryJob(self): master_name = 'm' builder_name = 'b' build_number = 8 WfTryJob.Create(master_name, builder_name, build_number).put() self.MockGeneratorPipeline( pipeline_class=RevertAndNotifyTestCulpritPipeline, expected_input=CulpritActionParameters( build_key=BuildKey(master_name=master_name, builder_name=builder_name, build_number=build_number), culprits=DictOfBasestring(), heuristic_cls=ListOfBasestring(), failure_to_culprit_map=None), mocked_output=False) parameters = IdentifyTestTryJobCulpritParameters(build_key=BuildKey( master_name=master_name, builder_name=builder_name, build_number=build_number), result=None) pipeline = IdentifyTestTryJobCulpritPipeline(parameters) pipeline.start() self.execute_queued_tasks() try_job = WfTryJob.Get(master_name, builder_name, build_number) self.assertEqual(try_job.test_results, []) self.assertEqual(try_job.status, analysis_status.COMPLETED)
def testSuccessfullyScheduleNewTryJobForCompileWithSuspectedRevisions( self, mock_module): master_name = 'm' builder_name = 'b' build_number = 223 good_revision = 'rev1' bad_revision = 'rev2' build_id = '1' url = 'url' build = WfBuild.Create(master_name, builder_name, build_number) build.data = { 'properties': { 'parent_mastername': 'pm', 'parent_buildername': 'pb' } } build.put() response = { 'build': { 'id': build_id, 'url': url, 'status': 'SCHEDULED', } } results = [(None, buildbucket_client.BuildbucketBuild(response['build']))] mock_module.TriggerTryJobs.return_value = results WfTryJob.Create(master_name, builder_name, build_number).put() try_job_pipeline = ScheduleCompileTryJobPipeline() try_job_id = try_job_pipeline.run(master_name, builder_name, build_number, good_revision, bad_revision, failure_type.COMPILE, None, ['r5'], None, None) try_job = WfTryJob.Get(master_name, builder_name, build_number) try_job_data = WfTryJobData.Get(build_id) expected_try_job_id = '1' self.assertEqual(expected_try_job_id, try_job_id) self.assertEqual(expected_try_job_id, try_job.compile_results[-1]['try_job_id']) self.assertTrue(expected_try_job_id in try_job.try_job_ids) self.assertIsNotNone(try_job_data) self.assertEqual(try_job_data.master_name, master_name) self.assertEqual(try_job_data.builder_name, builder_name) self.assertEqual(try_job_data.build_number, build_number) self.assertEqual( try_job_data.try_job_type, failure_type.GetDescriptionForFailureType(failure_type.COMPILE)) self.assertFalse(try_job_data.has_compile_targets) self.assertTrue(try_job_data.has_heuristic_results)
def testGet(self): master_name = 'm' builder_name = 'b' build_number = 123 try_job_id = 'try_job_id' try_job_before = WfTryJob.Create(master_name, builder_name, build_number) try_job_before.try_job_ids = [try_job_id] try_job_before.put() try_job_after = WfTryJob.Get(master_name, builder_name, build_number) self.assertEqual([try_job_id], try_job_after.try_job_ids)
def testUpdateTryJobResultAnalyzing(self): master_name = 'm' builder_name = 'b' build_number = 1 try_job_id = '3' try_job = WfTryJob.Create(master_name, builder_name, build_number) try_job.put() pipeline = MonitorTryJobPipeline() pipeline._UpdateTryJobResult( try_job.key.urlsafe(), failure_type.TEST, try_job_id, 'url', buildbucket_client.BuildbucketBuild.STARTED) try_job = WfTryJob.Get(master_name, builder_name, build_number) self.assertEqual(analysis_status.RUNNING, try_job.status)
def testNotNeedANewWaterfallTryJobForOtherType(self, mock_fn): master_name = 'm' builder_name = 'b' build_number = 223 failure_info = { 'master_name': master_name, 'builder_name': builder_name, 'build_number': build_number, 'failed_steps': {}, 'builds': { '222': { 'blame_list': ['222-1'], 'chromium_revision': '222-1' }, '223': { 'blame_list': ['223-1', '223-2', '223-3'], 'chromium_revision': '223-3' } }, 'failure_type': failure_type.UNKNOWN } mock_fn.return_value = False expected_try_job_key = WfTryJob.Create(master_name, builder_name, build_number).key need_try_job, try_job_key = try_job_util.NeedANewWaterfallTryJob( master_name, builder_name, build_number, failure_info, None, None) self.assertFalse(need_try_job) self.assertEqual(expected_try_job_key, try_job_key)
def testNotNeedANewWaterfallTryJobIfNoNewFailure(self, mock_fn): master_name = 'm' builder_name = 'b' build_number = 223 failure_info = { 'failed_steps': { 'a': { 'current_failure': 223, 'first_failure': 222, 'last_pass': 221, 'tests': { 'a.t2': { 'current_failure': 223, 'first_failure': 222, 'last_pass': 221 } } } }, 'failure_type': failure_type.TEST } analysis = WfAnalysis.Create(master_name, builder_name, build_number) analysis.failure_result_map = {'a': {'a.t2': 'm/b/222'}} analysis.put() mock_fn.return_value = False expected_try_job_key = WfTryJob.Create(master_name, builder_name, build_number).key need_try_job, try_job_key = try_job_util.NeedANewWaterfallTryJob( master_name, builder_name, build_number, failure_info, None, None) self.assertFalse(need_try_job) self.assertEqual(expected_try_job_key, try_job_key)
def testGetWaterfallTryJobs(self): try_job_completed = WfTryJobData.Create(3) try_job_completed.try_job_key = WfTryJob.Create('m', 'b', 3).key try_job_completed.try_job_type = 'compile' try_job_completed.start_time = datetime(2016, 5, 4, 0, 0, 1) try_job_completed.request_time = datetime(2016, 5, 4, 0, 0, 0) try_job_completed.created_time = datetime(2016, 5, 4, 0, 0, 0) try_job_completed.end_time = datetime(2016, 5, 4, 0, 0, 2) try_job_completed.try_job_url = 'url3' try_job_completed.culprits = {'compile': {'12345': 'failed'}} try_job_completed.last_buildbucket_response = {'status': 'COMPLETED'} try_job_completed.put() expected_try_job_completed_display_data = { 'master_name': 'm', 'builder_name': 'b', 'build_number': 3, 'try_job_type': 'compile', 'request_time': '2016-05-04 00:00:00 UTC', 'try_job_url': 'url3', 'culprit_found': True, 'last_buildbucket_response': '{"status": "COMPLETED"}' } response = self.test_app.get( ('/try-job-dashboard?format=json&start_date=2016-05-03&' 'category=waterfall')) response_data = response.json_body successfully_completed_try_jobs = response_data.get( 'successfully_completed_try_jobs') self.assertEqual(response.status_int, 200) self.validateTryJobDisplayData( [expected_try_job_completed_display_data], successfully_completed_try_jobs)
def ScheduleCompileTryJob(parameters, runner_id): master_name, builder_name, build_number = (parameters.build_key.GetParts()) properties = GetBuildProperties(parameters) tryserver_mastername, tryserver_buildername = try_job_service.GetTrybot() build_id, error = try_job_service.TriggerTryJob( master_name, builder_name, tryserver_mastername, tryserver_buildername, properties, failure_type.GetDescriptionForFailureType(failure_type.COMPILE), parameters.cache_name, parameters.dimensions, runner_id) if error: raise exceptions.RetryException(error.reason, error.message) try_job = WfTryJob.Get(master_name, builder_name, build_number) try_job.compile_results.append({'try_job_id': build_id}) try_job.try_job_ids.append(build_id) try_job.put() try_job = try_job_service.UpdateTryJob(master_name, builder_name, build_number, build_id, failure_type.COMPILE) # Create a corresponding WfTryJobData entity to capture as much metadata as # early as possible. try_job_service.CreateTryJobData(build_id, try_job.key, bool(parameters.compile_targets), bool(parameters.suspected_revisions), failure_type.COMPILE, runner_id=runner_id) return build_id
def CreateTestFailureAnalysisCompletionEvent(analysis): """Transforms a test failure analysis into an event proto. Args: analysis (WfAnalysis): The analysis to be transformed. Returns: ([TestAnalysisCompletionEvent]) Proto used to report to BQ table. """ events = [] for step in analysis.failure_info.get('failed_steps', {}): for test in analysis.failure_info['failed_steps'][step].get( 'tests') or {}: if analysis.flaky_tests and test in analysis.flaky_tests.get( step, []): # The test is flaky, should report it in flake analysis. continue # If the failure result mapping isn't there, then bailout since it # contains required information. if (not analysis.failure_result_map or not analysis.failure_result_map.get(step) or not analysis.failure_result_map[step].get(test)): continue event = TestAnalysisCompletionEvent() event.flake = False _ExtractGeneralAnalysisInfo(analysis, event) event.analysis_info.step_name = step event.test_name = test # Extract master/builder/build_number from failure_result_Map. master, builder, build_number = ( analysis.failure_result_map[step][test].split('/')) event.analysis_info.culprit_build_number = int(build_number) # Culprit. try_job = WfTryJob.Get(master, builder, build_number) if (try_job and try_job.test_results and try_job.test_results[-1].get('culprit') and try_job.test_results[-1]['culprit'].get(step) and try_job.test_results[-1]['culprit'][step].get('tests') and try_job.test_results[-1]['culprit'][step]['tests'].get( test)): _ExtractCulpritForDict( try_job.test_results[-1]['culprit'][step]['tests'][test], event) event = _ExtractSuspectsForWfAnalysis(analysis, event) # Outcomes. _SetOutcomesForEvent(event) # Actions. _SetActionsForEvent(event) events.append(event) return events
def testProperties(self): master_name = 'm' builder_name = 'b' try_job = WfTryJob.Create(master_name, builder_name, 123) self.assertEqual(master_name, try_job.master_name) self.assertEqual(builder_name, try_job.builder_name)
def _ReviveOrCreateTryJobEntity(master_name, builder_name, build_number, force_try_job): try_job_entity_revived_or_created = True try_job = WfTryJob.Get(master_name, builder_name, build_number) if try_job: if try_job.failed or force_try_job: try_job.status = analysis_status.PENDING try_job.put() else: try_job_entity_revived_or_created = False else: try_job = WfTryJob.Create(master_name, builder_name, build_number) try_job.put() return try_job_entity_revived_or_created, try_job.key
def testIdentifyCulpritForCompileTryJobNoCulprit(self): master_name = 'm' builder_name = 'b' build_number = 1 try_job_id = '1' self._CreateEntities(master_name, builder_name, build_number, try_job_id) analysis = WfAnalysis.Create(master_name, builder_name, build_number) analysis.put() self.MockPipeline(RevertAndNotifyCulpritPipeline, None, expected_args=[master_name, builder_name, build_number, None, [], failure_type.COMPILE]) pipeline = IdentifyTryJobCulpritPipeline( master_name, builder_name, build_number, failure_type.COMPILE, '1', None) pipeline.start() self.execute_queued_tasks() try_job = WfTryJob.Get(master_name, builder_name, build_number) try_job_data = WfTryJobData.Get(try_job_id) self.assertEqual(analysis_status.COMPLETED, try_job.status) self.assertEqual([], try_job.compile_results) self.assertIsNone(try_job_data.culprits) self.assertIsNone(analysis.result_status) self.assertIsNone(analysis.suspected_cls)
def testNoCompileTryJobBecauseNoGoodRevision(self, mock_pipeline, mock_parameter, mock_fn): mock_parameter.return_value = RunCompileTryJobParameters( good_revision=None) try_job = WfTryJob.Create('m', 'b', 1) try_job.put() mock_fn.return_value = (True, try_job.key.urlsafe()) failure_info = {'failure_type': failure_type.COMPILE} heuristic_result = { 'failure_info': failure_info, 'signals': {}, 'heuristic_result': {} } start_try_job_params = StartCompileTryJobInput( build_key=BuildKey(master_name='m', builder_name='b', build_number=1), heuristic_result=CompileHeuristicAnalysisOutput.FromSerializable( heuristic_result), build_completed=True, force=False) pipeline = StartCompileTryJobPipeline(start_try_job_params) result = pipeline.RunImpl(start_try_job_params) self.assertEqual(list(result), []) self.assertFalse(mock_pipeline.called)
def _CreateRunTestTryJobParameters(self): master_name = 'm' builder_name = 'b' build_number = 1 try_job_id = '1' job = WfTryJob.Create(master_name, builder_name, build_number) try_job_data = WfTryJobData.Create(try_job_id) try_job_data.try_job_key = job.key try_job_data.try_job_url = ( 'https://build.chromium.org/p/m/builders/b/builds/1234') try_job_data.put() job.test_results = [{ 'report': None, 'url': 'https://build.chromium.org/p/m/builders/b/builds/1234', 'try_job_id': '1', }] job.status = analysis_status.RUNNING job.put() return RunTestTryJobParameters(build_key=BuildKey( master_name=master_name, builder_name=builder_name, build_number=build_number), good_revision='rev1', bad_revision='rev2', suspected_revisions=['r5'], cache_name=None, dimensions=[], targeted_tests={}, urlsafe_try_job_key=job.key.urlsafe())
def testGetTryJobResultForCompileNonBuildbot(self): try_job = WfTryJob.Create(self.master_name, self.builder_name, self.build_number) try_job.status = analysis_status.RUNNING try_job.compile_results = [{ 'result': None, 'url': 'https://luci-milo.appspot.com/swarming/task/3639e', 'try_job_id': '12341234' }] try_job.put() result = handlers_util._GetTryJobResultForCompile( {'compile': 'm/b/121'}) expected_result = { 'compile': { 'try_jobs': [{ 'try_job_key': 'm/b/121', 'status': analysis_status.RUNNING, 'try_job_build_number': '12341234', 'try_job_url': 'https://luci-milo.appspot.com/swarming/task/3639e', }] } } self.assertEqual(expected_result, result)
def testGetTryJobResultForCompileOnlyReturnUrlIfStarts(self): try_job = WfTryJob.Create(self.master_name, self.builder_name, self.build_number) try_job.status = analysis_status.RUNNING try_job.compile_results = [{ 'result': None, 'url': ('http://build.chromium.org/p/tryserver.chromium.linux/' 'builders/linux_chromium_variable/builds/121') }] try_job.put() result = handlers_util._GetTryJobResultForCompile( {'compile': 'm/b/121'}) expected_result = { 'compile': { 'try_jobs': [{ 'try_job_key': 'm/b/121', 'status': analysis_status.RUNNING, 'try_job_build_number': 121, 'try_job_url': ('http://build.chromium.org/p/tryserver.chromium.' 'linux/builders/linux_chromium_variable/builds/121') }] } } self.assertEqual(expected_result, result)
def testGetCulpritInfoForTryJobResultForTestTryJobNoResult(self): try_job_key = 'm/b/119' culprits_info = { 'step1 on platform': { 'try_jobs': [{ 'ref_name': 'step1', 'try_job_key': try_job_key, 'tests': ['test2', 'test3'] }] } } WfTryJob.Create('m', 'b', '119').put() handlers_util._GetCulpritInfoForTryJobResultForTest( try_job_key, culprits_info) expected_culprits_info = { 'step1 on platform': { 'try_jobs': [{ 'ref_name': 'step1', 'try_job_key': try_job_key, 'tests': ['test2', 'test3'], 'status': analysis_status.PENDING }] } } self.assertEqual(expected_culprits_info, culprits_info)
def testGetStatusAndCulpritFromTryJobTryJobFailed(self): try_job = WfTryJob.Create('m', 'b', 123) try_job.status = analysis_status.ERROR try_job.put() status, culprit = findit_api.FindItApi( )._GetStatusAndCulpritFromTryJob(try_job, None, None, None, None) self.assertEqual(status, findit_api._TryJobStatus.FINISHED) self.assertIsNone(culprit)
def testIdentifyCulpritForFlakyCompile(self): master_name = 'm' builder_name = 'b' build_number = 1 try_job_id = '1' compile_result = { 'report': { 'result': { 'rev1': 'failed', 'rev2': 'failed' }, 'metadata': { 'sub_ranges': [ [ None, 'rev2' ] ] } }, 'url': 'url', 'try_job_id': try_job_id, } self._CreateEntities(master_name, builder_name, build_number, try_job_id) analysis = WfAnalysis.Create(master_name, builder_name, build_number) analysis.result = { 'failures': [ { 'step_name': 'compile', 'suspected_cls': [] } ] } analysis.put() self.MockPipeline(RevertAndNotifyCulpritPipeline, None, expected_args=[master_name, builder_name, build_number, {}, [], failure_type.COMPILE]) pipeline = IdentifyTryJobCulpritPipeline( master_name, builder_name, build_number, failure_type.COMPILE, '1', compile_result) pipeline.start() self.execute_queued_tasks() try_job = WfTryJob.Get(master_name, builder_name, build_number) self.assertEqual(analysis_status.COMPLETED, try_job.status) try_job_data = WfTryJobData.Get(try_job_id) self.assertIsNone(try_job_data.culprits) analysis = WfAnalysis.Get(master_name, builder_name, build_number) self.assertEqual(result_status.FLAKY, analysis.result_status) self.assertEqual([], analysis.suspected_cls)
def testCompileTryJob(self, mock_module): master_name = 'm' builder_name = 'b' build_number = 1 try_job_type = failure_type.COMPILE failure_info = { 'failure_type': try_job_type, 'builds': { '0': { 'blame_list': ['r0', 'r1'], 'chromium_revision': 'r1' }, '1': { 'blame_list': ['r2'], 'chromium_revision': 'r2' } }, 'failed_steps': { 'compile': { 'first_failure': 1, 'last_pass': 0 } } } good_revision = 'r1' bad_revision = 'r2' try_job = WfTryJob.Create('m', 'b', 1) try_job.put() mock_module.NeedANewWaterfallTryJob.return_value = True, try_job.key mock_module.GetFailedTargetsFromSignals.return_value = {} self.MockPipeline( start_try_job_on_demand_pipeline.ScheduleCompileTryJobPipeline, 'try_job_id', expected_args=[ master_name, builder_name, build_number, good_revision, bad_revision, try_job_type, {}, [] ], expected_kwargs={}) self.MockPipeline( start_try_job_on_demand_pipeline.MonitorTryJobPipeline, 'try_job_result', expected_args=[try_job.key.urlsafe(), try_job_type, 'try_job_id'], expected_kwargs={}) self.MockPipeline( start_try_job_on_demand_pipeline.IdentifyTryJobCulpritPipeline, 'final_result', expected_args=[ master_name, builder_name, build_number, ['r2'], try_job_type, 'try_job_id', 'try_job_result' ], expected_kwargs={}) pipeline = StartTryJobOnDemandPipeline() result = pipeline.run('m', 'b', 1, failure_info, {}, {}, True, False) self.assertNotEqual(list(result), [])
def testSuccessfullyScheduleNewTryJobForTest(self, mock_module): master_name = 'm' builder_name = 'b' build_number = 223 good_revision = 'rev1' bad_revision = 'rev2' targeted_tests = ['a on platform', ['a', ['test1', 'test2']]] build_id = '1' build = WfBuild.Create(master_name, builder_name, build_number) build.data = {'properties': {'parent_mastername': 'pm', 'parent_buildername': 'pb'}} build.put() response = { 'build': { 'id': build_id, 'url': 'url', 'status': 'SCHEDULED', } } results = [(None, buildbucket_client.BuildbucketBuild(response['build']))] mock_module.TriggerTryJobs.return_value = results WfTryJob.Create(master_name, builder_name, build_number).put() try_job_pipeline = ScheduleTestTryJobPipeline() try_job_id = try_job_pipeline.run( master_name, builder_name, build_number, good_revision, bad_revision, failure_type.TEST, None, None, None, targeted_tests) try_job = WfTryJob.Get(master_name, builder_name, build_number) self.assertEqual(try_job_id, build_id) self.assertEqual(try_job.test_results[-1]['try_job_id'], build_id) try_job_data = WfTryJobData.Get(try_job_id) self.assertIsNotNone(try_job_data) self.assertEqual(try_job_data.master_name, master_name) self.assertEqual(try_job_data.builder_name, builder_name) self.assertEqual(try_job_data.build_number, build_number) self.assertEqual( try_job_data.try_job_type, failure_type.GetDescriptionForFailureType(failure_type.TEST)) self.assertFalse(try_job_data.has_compile_targets) self.assertFalse(try_job_data.has_heuristic_results)
def testGetTryJobResultWhenTryJobCompleted(self): analysis = WfAnalysis.Create(self.master_name, self.builder_name, self.build_number) analysis.failure_result_map = {'compile': 'm/b/121'} analysis.put() try_job = WfTryJob.Create(self.master_name, self.builder_name, self.build_number) try_job.status = analysis_status.COMPLETED try_job.compile_results = [{ 'report': { 'result': { 'rev1': 'passed', 'rev2': 'failed' } }, 'try_job_id': 'm/b/121', 'url': ('http://build.chromium.org/p/tryserver.chromium.' 'linux/builders/linux_chromium_variable/builds/121'), 'culprit': { 'compile': { 'revision': 'rev2', 'commit_position': '2', 'review_url': 'url_2' } } }] try_job.put() result = handlers_util.GetAllTryJobResults(self.master_name, self.builder_name, self.build_number) expected_result = { 'compile': { 'try_jobs': [{ 'try_job_key': 'm/b/121', 'status': analysis_status.COMPLETED, 'try_job_build_number': 121, 'try_job_url': ('http://build.chromium.org/p/tryserver.chromium.' 'linux/builders/linux_chromium_variable/builds/121'), 'culprit': { 'revision': 'rev2', 'commit_position': '2', 'review_url': 'url_2' } }] } } self.assertEqual(expected_result, result)
def testUpdateTryJobMetadataForBuildError(self): error_data = {'reason': 'BUILD_NOT_FOUND', 'message': 'message'} error = buildbucket_client.BuildbucketError(error_data) try_job_data = WfTryJobData.Create('1') try_job_data.try_job_key = WfTryJob.Create('m', 'b', 123).key monitor_try_job_pipeline._UpdateTryJobMetadata(try_job_data, failure_type.COMPILE, None, error, False) self.assertEqual(try_job_data.error, error_data)
def UpdateTryJobResult(parameters, culprits): master_name, builder_name, build_number = parameters.build_key.GetParts() try_job = WfTryJob.Get(master_name, builder_name, build_number) new_result = parameters.result.ToSerializable( ) if parameters.result else {} try_job_id = parameters.result.try_job_id if parameters.result else None if culprits: try_job_service.UpdateTryJobResult(try_job.compile_results, new_result, try_job_id) try_job.status = analysis_status.COMPLETED try_job.put()
def testReturnNoneIfNoTryJob(self): master_name = 'm' builder_name = 'b' build_number = 8 WfTryJob.Create(master_name, builder_name, build_number).put() self.MockPipeline(RevertAndNotifyCulpritPipeline, None, expected_args=[master_name, builder_name, build_number, None, [], failure_type.TEST]) pipeline = IdentifyTryJobCulpritPipeline( master_name, builder_name, build_number, failure_type.TEST, None, None) pipeline.start() self.execute_queued_tasks() try_job = WfTryJob.Get(master_name, builder_name, build_number) self.assertEqual(try_job.test_results, []) self.assertEqual(try_job.status, analysis_status.COMPLETED)
def UpdateTryJob(master_name, builder_name, build_number, build_id, try_job_type): try_job = WfTryJob.Get(master_name, builder_name, build_number) if try_job_type == failure_type.COMPILE: try_job.compile_results.append({'try_job_id': build_id}) else: try_job.test_results.append({'try_job_id': build_id}) try_job.try_job_ids.append(build_id) try_job.put() return try_job
def testProperties(self): master_name = 'm' builder_name = 'b' build_number = 123 try_job_id = 'try_job_id' try_job = WfTryJob.Create(master_name, builder_name, build_number) try_job_data = WfTryJobData.Create(try_job_id) try_job_data.try_job_key = try_job.key self.assertEqual(master_name, try_job_data.master_name) self.assertEqual(builder_name, try_job_data.builder_name) self.assertEqual(build_number, try_job_data.build_number)
def run(self, master_name, builder_name, build_number, good_revision, bad_revision, try_job_type, suspected_revisions, cache_name, dimensions, *task_results): """ Args: master_name (str): the master name of a build. builder_name (str): the builder name of a build. build_number (int): the build number of a build. good_revision (str): the revision of the last passed build. bad__revision (str): the revision of the first failed build. try_job_type (int): type of the try job: TEST in this case. suspected_revisions (list): a list of suspected revisions from heuristic. cache_name (str): A string to identify separate directories for different waterfall bots on the trybots. dimensions (list): A list of strings in the format ["key1:value1", "key2:value2"]. task_results (list): a list of reliable failed tests. Returns: build_id (str): id of the triggered try job. """ properties = self._GetBuildProperties(master_name, builder_name, build_number, good_revision, bad_revision, try_job_type, suspected_revisions) targeted_tests = _GetTargetedTests(dict(task_results)) if not targeted_tests: # pragma: no cover logging.info('All tests are flaky, no try job will be triggered.') return additional_parameters = {'tests': targeted_tests} build_id = self._TriggerTryJob( master_name, builder_name, properties, additional_parameters, failure_type.GetDescriptionForFailureType(failure_type.TEST), cache_name, dimensions) try_job = WfTryJob.Get(master_name, builder_name, build_number) try_job.test_results.append({'try_job_id': build_id}) try_job.try_job_ids.append(build_id) try_job.put() # Create a corresponding WfTryJobData entity to capture as much metadata as # early as possible. self._CreateTryJobData(build_id, try_job.key, bool(suspected_revisions)) return build_id