def testUpdateIssueWithIssueGeneratorReopen(self, mock_create_bug_fn, mock_update_bug_fn, mock_get_merged_issue): issue_id = 12345 issue = Issue({ 'status': 'Fixed', 'summary': 'summary', 'description': 'description', 'projectId': 'chromium', 'labels': [], 'fieldValues': [], 'state': 'open', 'owner': { 'name': '*****@*****.**' } }) mock_get_merged_issue.return_value = issue test_issue_generator = TestIssueGenerator() monorail_util.UpdateIssueWithIssueGenerator( issue_id=issue_id, issue_generator=test_issue_generator, reopen=True) self.assertFalse(mock_create_bug_fn.called) mock_update_bug_fn.assert_called_once_with( issue, 'comment without previous tracking bug id.', 'chromium') issue = mock_update_bug_fn.call_args_list[0][0][0] self.assertEqual(['label1'], issue.labels) self.assertEqual(1, len(issue.field_values)) self.assertEqual('Flaky-Test', issue.field_values[0].to_dict()['fieldName']) self.assertEqual('suite.test', issue.field_values[0].to_dict()['fieldValue']) self.assertEqual('Assigned', issue.status)
def _CreateIssueForFlake(issue_generator, target_flake, create_or_update_bug): """Creates a monorail bug for a single flake. This function is used to create bugs for detected flakes and flake analysis results. Args: create_or_update_bug (bool): True to create or update monorail bug, otherwise False. Should always look for existing bugs for flakes, even if cannot update the bug. """ monorail_project = issue_generator.GetMonorailProject() # Re-uses an existing open bug if possible. issue_id = SearchOpenIssueIdForFlakyTest(target_flake.normalized_test_name, monorail_project) if not issue_id: # Reopens a recently closed bug if possible. issue_id = SearchRecentlyClosedIssueIdForFlakyTest( target_flake.normalized_test_name, monorail_project) if issue_id: logging.info('An existing issue %s was found, attach it to flake: %s.', FlakeIssue.GetLinkForIssue(monorail_project, issue_id), target_flake.key) _AssignIssueToFlake(issue_id, target_flake) if create_or_update_bug: monorail_util.UpdateIssueWithIssueGenerator( issue_id=issue_id, issue_generator=issue_generator, reopen=True) return issue_id if not create_or_update_bug: # No existing bug found, and cannot create bug, bail out. return None logging.info('No existing open issue was found, create a new one.') issue_id = monorail_util.CreateIssueWithIssueGenerator( issue_generator=issue_generator) if not issue_id: logging.warning('Failed to create monorail bug for flake: %s.', target_flake.key) return None logging.info('%s was created for flake: %s.', FlakeIssue.GetLinkForIssue(monorail_project, issue_id), target_flake.key) _AssignIssueToFlake(issue_id, target_flake) return issue_id
def testUpdateIssueWithIssueGeneratorAndRestoreSheriffLabel( self, mock_create_bug_fn, mock_update_bug_fn, mock_get_merged_issue, _): issue_id = 12345 issue = Issue({ 'status': 'Available', 'summary': 'summary', 'description': 'description', 'projectId': 'chromium', 'labels': [], 'fieldValues': [], 'state': 'open', }) mock_get_merged_issue.return_value = issue test_issue_generator = TestIssueGenerator() monorail_util.UpdateIssueWithIssueGenerator( issue_id=issue_id, issue_generator=test_issue_generator) self.assertFalse(mock_create_bug_fn.called) self.assertTrue(mock_update_bug_fn.called) self.assertEqual(['label1', 'Sheriff-Chromium'], issue.labels)
def _UpdateIssuesForFlakes(flake_groups_to_update_issue): """Updates monorail bugs. The issues have been updated when generating flake groups, so in this function directly updates the issues. Args: flake_groups_to_update_issue ([FlakeGroupByFlakeIssue]): A list of flake groups with bugs. """ for flake_group in flake_groups_to_update_issue: try: if len(flake_group.flakes) == 1: # A single flake in group, updates the bug using this flake's info. issue_generator = FlakeDetectionIssueGenerator( flake_group.flakes[0], flake_group.num_occurrences) issue_generator.SetPreviousTrackingBugId( flake_group.previous_issue_id) monorail_util.UpdateIssueWithIssueGenerator( issue_id=flake_group.flake_issue.issue_id, issue_generator=issue_generator, reopen=True) else: _UpdateFlakeIssueForFlakeGroup(flake_group) # Update FlakeIssue's last_updated_time_by_flake_detection property. This # property is only applicable to Flake Detection because Flake Detection # can update an issue at most once every 24 hours. flake_issue = flake_group.flake_issue flake_issue.last_updated_time_by_flake_detection = time_util.GetUTCNow( ) flake_issue.last_updated_time_in_monorail = time_util.GetUTCNow() flake_issue.put() except HttpError as error: # Benign exceptions (HttpError 403) may happen when FindIt tries to # update an issue that it doesn't have permission to. Do not raise # exception so that the for loop can move on to create or update next # issues. logging.warning( 'Failed to create or update issue due to error: %s', error)
def testUpdateIssueWithIssueGeneratorWithPreviousTrackingId( self, mock_create_bug_fn, mock_update_bug_fn, mock_get_merged_issue): issue_id = 12345 issue = Issue({ 'status': 'Available', 'summary': 'summary', 'description': 'description', 'projectId': 'chromium', 'labels': [], 'fieldValues': [], 'state': 'open', }) mock_get_merged_issue.return_value = issue test_issue_generator = TestIssueGenerator() test_issue_generator.SetPreviousTrackingBugId(56789) monorail_util.UpdateIssueWithIssueGenerator( issue_id=issue_id, issue_generator=test_issue_generator) self.assertFalse(mock_create_bug_fn.called) mock_update_bug_fn.assert_called_once_with( issue, 'comment with previous tracking bug id: 56789.', 'chromium')
def _UpdateFlakeIssueForFlakeGroup(flake_group): """Updates an issue for a flake group. Args: flake_group (FlakeGroupByFlakeIssue): A flake group with an issue. Returns: Id of the issue that was eventually created or linked. """ assert isinstance(flake_group, FlakeGroupByFlakeIssue), ( 'flake_group is not a FlakeGroupByFlakeIssue instance.') issue_generator = FlakeDetectionGroupIssueGenerator( flake_group.flakes, flake_group.num_occurrences, flake_issue=flake_group.flake_issue, flakes_with_same_occurrences=flake_group.flakes_with_same_occurrences) flake_issue = flake_group.flake_issue monorail_util.UpdateIssueWithIssueGenerator( issue_id=flake_issue.issue_id, issue_generator=issue_generator, reopen=True) return flake_issue.issue_id
def UpdateMonorailBugWithCulprit(analysis_urlsafe_key): """Updates a bug in monorail with the culprit of a MasterFlakeAnalsyis""" analysis = entity_util.GetEntityFromUrlsafeKey(analysis_urlsafe_key) assert analysis, 'Analysis {} missing unexpectedly!'.format( analysis_urlsafe_key) if not analysis.flake_key: # pragma: no cover. logging.warning( 'Analysis %s has no flake key. Bug updates should only be ' 'routed through Flake and FlakeIssue', analysis_urlsafe_key) return flake = analysis.flake_key.get() assert flake, 'Analysis\' associated Flake {} missing unexpectedly!'.format( analysis.flake_key) flake_urlsafe_key = flake.key.urlsafe() if flake.archived: logging.info( 'Flake %s has been archived when flake analysis %s completes.', flake_urlsafe_key, analysis_urlsafe_key) return if not flake.flake_issue_key: # pragma: no cover. logging.warning( 'Flake %s has no flake_issue_key. Bug updates should only' ' be routed through Flake and FlakeIssue', flake_urlsafe_key) return flake_issue = flake.flake_issue_key.get() assert flake_issue, 'Flake issue {} missing unexpectedly!'.format( flake.flake_issue_key) # Only comment on the latest flake issue. flake_issue_to_update = flake_issue.GetMostUpdatedIssue() issue_link = FlakeIssue.GetLinkForIssue( flake_issue_to_update.monorail_project, flake_issue_to_update.issue_id) # Don't comment if the issue is closed. latest_merged_monorail_issue = monorail_util.GetMonorailIssueForIssueId( flake_issue_to_update.issue_id) if not latest_merged_monorail_issue or not latest_merged_monorail_issue.open: logging.info( 'Skipping updating issue %s which is not accessible or closed', issue_link) return # Don't comment if there are existing updates by Findit to prevent spamming. if flake_issue_to_update.last_updated_time_with_analysis_results: logging.info( 'Skipping updating issue %s as it has already been updated', issue_link) return # Don't comment if Findit has filled the daily quota of monorail updates. if flake_issue_util.GetRemainingPostAnalysisDailyBugUpdatesCount() <= 0: logging.info( 'Skipping updating issue %s due to maximum daily bug limit being ' 'reached', issue_link) return # Comment with link to FlakeCulprit. monorail_util.UpdateIssueWithIssueGenerator( flake_issue_to_update.issue_id, issue_generator.FlakeAnalysisIssueGenerator(analysis)) flake_issue_to_update.last_updated_time_with_analysis_results = ( time_util.GetUTCNow()) flake_issue_to_update.last_updated_time_in_monorail = time_util.GetUTCNow() flake_issue_to_update.put() monitoring.flake_analyses.increment({ 'result': 'culprit-identified', 'action_taken': 'bug-updated', 'reason': '' })