def testCurrentSheriffsMissingDate(self): response = json.dumps({ 'calendar': [ {'date': '2016-12-31', 'participants': [[], ['foo', 'bar']]}, ], 'rotations': ['dummy1', 'dummy2'] }) self.http_client.SetResponse(rotations.ROTATIONS_URL, (200, response)) with self.assertRaises(Exception): rotations.current_sheriffs('dummy2')
def testCurrentSheriffs(self): response = json.dumps({ 'calendar': [ { 'date': '2016-12-31', 'participants': [[], ['foo', 'bar']] }, { 'date': '2017-01-01', 'participants': [['ham', 'eggs', '*****@*****.**'], []] }, ], 'rotations': ['dummy1', 'dummy2'] }) self.http_client.SetResponse(rotations._ROTATIONS_URL, (200, response)) self.assertIn('*****@*****.**', rotations.current_sheriffs('dummy1')) self.assertIn('*****@*****.**', rotations.current_sheriffs('dummy1'))
def testCurrentSheriffsBadRotationName(self): response = json.dumps({ 'calendar': [ {'date': '2016-12-31', 'participants': [[], ['foo', 'bar']]}, {'date': '2017-01-01', 'participants': [['ham', 'eggs'], []]}, ], 'rotations': ['dummy1', 'dummy2'] }) self.http_client.SetResponse(rotations.ROTATIONS_URL, (200, response)) self.assertFalse(rotations.current_sheriffs('memegen-rotation'))
def _AddReviewers(revision, culprit, codereview, revert_change_id, submitted): """Adds sheriffs to reviewers and sends messages. Based on the status of the revert - submitted or not, sends different messages to reviewers. Args: culprit (FlakeCulprit or WfSuspectedCL): the culprit entity. revert_change_id (str): Id of the revert change. submitted (bool): If the revert is submitted or not. """ culprit_link = culprit.GetCulpritLink() if not culprit_link: # pragma: no cover. logging.error('Failed to get culprit link for culprit %s', culprit.key.urlsafe() if culprit else '') return false_positive_bug_link = CreateFinditWrongBugLink( FINDIT_BUILD_FAILURE_COMPONENT, culprit_link, revision) auto_revert_bug_query = urllib.urlencode({ 'status': 'Available', 'components': 'Tools>Test>FindIt>Autorevert', 'summary': 'Auto Revert failed on %s' % revision, 'comment': 'Detail is %s' % culprit_link }) auto_revert_bug_link = ( 'https://bugs.chromium.org/p/chromium/issues/entry?%s') % ( auto_revert_bug_query) new_reviewers = rotations.current_sheriffs() if not submitted: # Findit only creates the revert but doesn't intend to submit it. # This should only be used when auto_commit is disabled. message = textwrap.dedent(""" Sheriffs, CL owner or CL reviewers: Please submit this revert if it is correct. If it is a false positive, please abandon and report it at %s. If failed to submit the revert, please abandon it and report the failure at %s. For more information about Findit auto-revert: %s. Sheriffs, it'll be much appreciated if you could take a couple minutes to fill out this survey: %s.""") % (false_positive_bug_link, auto_revert_bug_link, _MANUAL_LINK, _SURVEY_LINK) else: # Findit submits the revert successfully. Add sheriffs to confirm the # revert is correct. message = textwrap.dedent(""" Sheriffs, CL owner or CL reviewers: Please confirm this revert if it is correct. If it is a false positive, please reland the original CL and report this false positive at %s. For more information about Findit auto-revert: %s. Sheriffs, it'll be much appreciated if you could take a couple minutes to fill out this survey: %s.""") % (false_positive_bug_link, _MANUAL_LINK, _SURVEY_LINK) # Original CL owner and reviewers are already reviewers when creating the # revert, add sheriffs or Findit members to reviewers as well. return codereview.AddReviewers(revert_change_id, new_reviewers, message)
def testCurrentSheriffsBadHttp(self): self.http_client.SetResponse(rotations.ROTATIONS_URL, (403, 'forbidden')) with self.assertRaises(Exception): rotations.current_sheriffs('dummy2')
def _RevertCulprit(master_name, builder_name, build_number, repo_name, revision): culprit = _UpdateCulprit(repo_name, revision) if culprit.revert_cl and culprit.revert_status == status.COMPLETED: return CREATED_BY_FINDIT # 0. Gets information about this culprit. culprit_info = (suspected_cl_util.GetCulpritInfo(repo_name, revision)) culprit_commit_position = culprit_info['commit_position'] culprit_change_id = culprit_info['review_change_id'] culprit_host = culprit_info['review_server_host'] codereview = codereview_util.GetCodeReviewForReview(culprit_host) if not codereview or not culprit_change_id: # pragma: no cover logging.error('Failed to get change id for %s/%s' % (repo_name, revision)) return ERROR culprit_cl_info = codereview.GetClDetails(culprit_change_id) if not culprit_cl_info: # pragma: no cover logging.error('Failed to get cl_info for %s/%s' % (repo_name, revision)) return ERROR # Checks if the culprit is a revert created by Findit. If yes, bail out. if _IsOwnerFindit(culprit_cl_info.owner_email): _UpdateCulprit(repo_name, revision, status.SKIPPED, skip_revert_reason=CULPRIT_OWNED_BY_FINDIT) return SKIPPED if culprit_cl_info.auto_revert_off: _UpdateCulprit(repo_name, revision, status.SKIPPED, skip_revert_reason=AUTO_REVERT_OFF) return SKIPPED # 1. Checks if a revert CL by sheriff has been created. reverts = culprit_cl_info.GetRevertCLsByRevision(revision) if reverts is None: # pragma: no cover # if no reverts, reverts should be [], only when some error happens it will # be None. logging.error('Failed to find patchset_id for %s/%s' % (repo_name, revision)) return ERROR findit_revert = None for revert in reverts: if _IsOwnerFindit(revert.reverting_user_email): findit_revert = revert break if reverts and not findit_revert: # Sheriff(s) created the revert CL(s). return CREATED_BY_SHERIFF # 2. Reverts the culprit. if not _LatestBuildFailed(master_name, builder_name, build_number): # The latest build didn't fail, skip. _UpdateCulprit(repo_name, revision, status.SKIPPED, skip_revert_reason=NEWEST_BUILD_GREEN) return SKIPPED revert_change_id = None if findit_revert: revert_change_id = findit_revert.reverting_cl.change_id # TODO (chanli): Better handle cases where 2 analyses are trying to revert # at the same time. if not revert_change_id: _UpdateCulprit(repo_name, revision, status.RUNNING) revert_reason = textwrap.dedent(""" Findit (https://goo.gl/kROfz5) identified CL at revision %s as the culprit for failures in the build cycles as shown on: https://findit-for-me.appspot.com/waterfall/culprit?key=%s""") % ( culprit_commit_position or revision, culprit.key.urlsafe()) revert_change_id = codereview.CreateRevert( revert_reason, culprit_change_id, culprit_cl_info.GetPatchsetIdByRevision(revision)) if not revert_change_id: # pragma: no cover _UpdateCulprit(repo_name, revision, status.ERROR) logging.error('Revert for culprit %s/%s failed.' % (repo_name, revision)) culprit.put() return ERROR # Save revert CL info and notification info to culprit. if not culprit.revert_cl: revert_cl = RevertCL() revert_cl.revert_cl_url = codereview.GetCodeReviewUrl(revert_change_id) revert_cl.created_time = time_util.GetUTCNow() _UpdateCulprit(repo_name, revision, None, revert_cl=revert_cl) # 3. Add reviewers. sheriffs = rotations.current_sheriffs() message = textwrap.dedent(""" Sheriffs: Please confirm and "Quick L-G-T-M & CQ" this revert if it is correct. If it is a false positive, please close it. Findit (https://goo.gl/kROfz5) identified the original CL as the culprit for failures in the build cycles as shown on: https://findit-for-me.appspot.com/waterfall/culprit?key=%s""") % ( culprit.key.urlsafe()) success = codereview.AddReviewers(revert_change_id, sheriffs, message) if not success: # pragma: no cover _UpdateCulprit(repo_name, revision, status.ERROR) logging.error('Failed to add reviewers for revert of culprit %s/%s' % (repo_name, revision)) return ERROR _UpdateCulprit(repo_name, revision, revert_status=status.COMPLETED) return CREATED_BY_FINDIT