def merge_proposal_modified(merge_proposal, event): """Notify branch subscribers when merge proposals are updated.""" # Check the user. if event.user is None: return if isinstance(event.user, UnauthenticatedPrincipal): from_person = None else: from_person = IPerson(event.user) # If the merge proposal was work in progress, then we don't want to send # out an email as the needs review email will cover that. old_status = event.object_before_modification.queue_status if old_status == BranchMergeProposalStatus.WORK_IN_PROGRESS: # Unless the new status is merged. If this occurs we really should # send out an email. if merge_proposal.queue_status != BranchMergeProposalStatus.MERGED: return # Create a delta of the changes. If there are no changes to report, then # we're done. delta = BranchMergeProposalNoPreviewDiffDelta.construct( event.object_before_modification, merge_proposal) if delta is None: return changes = text_delta( delta, delta.delta_values, delta.new_values, delta.interface) # Now create the job to send the email. getUtility(IMergeProposalUpdatedEmailJobSource).create( merge_proposal, changes, from_person)
def merge_proposal_modified(merge_proposal, event): """Notify branch subscribers when merge proposals are updated.""" # Check the user. if event.user is None: return if isinstance(event.user, UnauthenticatedPrincipal): from_person = None else: from_person = IPerson(event.user) # If the merge proposal was work in progress, then we don't want to send # out an email as the needs review email will cover that. old_status = event.object_before_modification.queue_status if old_status == BranchMergeProposalStatus.WORK_IN_PROGRESS: # Unless the new status is merged. If this occurs we really should # send out an email. if merge_proposal.queue_status != BranchMergeProposalStatus.MERGED: return # Create a delta of the changes. If there are no changes to report, then # we're done. delta = BranchMergeProposalNoPreviewDiffDelta.construct( event.object_before_modification, merge_proposal) if delta is None: return changes = text_delta(delta, delta.delta_values, delta.new_values, delta.interface) # Now create the job to send the email. getUtility(IMergeProposalUpdatedEmailJobSource).create( merge_proposal, changes, from_person)
def test_rejectedCodeReview(self): # Rejecting a code review is also a significant event, and as such # gets its own karma event. proposal = self.factory.makeBranchMergeProposal() reviewer = proposal.target_branch.owner self.karma_events = [] login_person(reviewer) with BranchMergeProposalNoPreviewDiffDelta.monitor(proposal): proposal.rejectBranch(reviewer, "A rev id.") self.assertOneKarmaEvent(reviewer, 'branchmergerejected')
def test_approvingOwnCodeReview(self): # Approving your own merge proposal isn't such a significant event. reviewer = self.factory.makePerson() target_branch = self.factory.makeProductBranch(owner=reviewer) proposal = self.factory.makeBranchMergeProposal( target_branch=target_branch, registrant=reviewer) self.karma_events = [] login_person(reviewer) with BranchMergeProposalNoPreviewDiffDelta.monitor(proposal): proposal.approveBranch(reviewer, "A rev id.") self.assertOneKarmaEvent(reviewer, 'branchmergeapprovedown')
def test_rejectedOwnCodeReview(self): # Rejecting your own merge proposal isn't such a significant event # either, and I don't know why someone would, but hey, people are # strange. reviewer = self.factory.makePerson() target_branch = self.factory.makeProductBranch(owner=reviewer) proposal = self.factory.makeBranchMergeProposal( target_branch=target_branch, registrant=reviewer) self.karma_events = [] login_person(reviewer) with BranchMergeProposalNoPreviewDiffDelta.monitor(proposal): proposal.rejectBranch(reviewer, "A rev id.") self.assertOneKarmaEvent(reviewer, 'branchmergerejectedown')
def test_iterReady_supports_updated_emails(self): # iterReady will also return pending MergeProposalUpdatedEmailJob. bmp = self.makeBranchMergeProposal( set_state=BranchMergeProposalStatus.NEEDS_REVIEW) self.completePendingJobs() old_merge_proposal = ( BranchMergeProposalNoPreviewDiffDelta.snapshot(bmp)) bmp.commit_message = 'new commit message' event = ObjectModifiedEvent( bmp, old_merge_proposal, [], bmp.registrant) merge_proposal_modified(bmp, event) [job] = self.job_source.iterReady() self.assertEqual(job.branch_merge_proposal, bmp) self.assertIsInstance(job, MergeProposalUpdatedEmailJob)
def notify_modified(proposal, func, *args, **kwargs): """Call func, then notify about the changes it made. :param proposal: the merge proposal to notify about. :param func: The callable that will modify the merge proposal. :param args: Additional arguments for the method. :param kwargs: Keyword arguments for the method. :return: The return value of the method. """ from lp.code.adapters.branch import BranchMergeProposalNoPreviewDiffDelta snapshot = BranchMergeProposalNoPreviewDiffDelta.snapshot(proposal) result = func(*args, **kwargs) notify(ObjectModifiedEvent(proposal, snapshot, [])) return result
def processCommands(self, context, commands): """Process the various merge proposal commands against the context.""" processing_errors = [] with BranchMergeProposalNoPreviewDiffDelta.monitor( context.merge_proposal): for command in commands: try: command.execute(context) except EmailProcessingError as error: processing_errors.append((error, command)) if len(processing_errors) > 0: errors, commands = zip(*processing_errors) raise IncomingEmailError('\n'.join(str(error) for error in errors), list(commands)) return len(commands)
def merge_proposal_modified(merge_proposal, event): """Notify branch subscribers when merge proposals are updated.""" # Check the user. if event.user is None: return if isinstance(event.user, UnauthenticatedPrincipal): from_person = None else: from_person = IPerson(event.user) old_status = event.object_before_modification.queue_status new_status = merge_proposal.queue_status in_progress_states = (BranchMergeProposalStatus.WORK_IN_PROGRESS, BranchMergeProposalStatus.NEEDS_REVIEW) # If the merge proposal was work in progress and is now needs review, # then we don't want to send out an email as the needs review email will # cover that. if (old_status != BranchMergeProposalStatus.WORK_IN_PROGRESS or new_status not in in_progress_states): # Create a delta of the changes. If there are no changes to report, # then we're done. delta = BranchMergeProposalNoPreviewDiffDelta.construct( event.object_before_modification, merge_proposal) if delta is not None: changes = text_delta(delta, delta.delta_values, delta.new_values, delta.interface) # Now create the job to send the email. getUtility(IMergeProposalUpdatedEmailJobSource).create( merge_proposal, changes, from_person) if getFeatureFlag(BRANCH_MERGE_PROPOSAL_WEBHOOKS_FEATURE_FLAG): payload = { "action": "modified", "old": _compose_merge_proposal_webhook_payload( event.object_before_modification), "new": _compose_merge_proposal_webhook_payload(merge_proposal), } # Some fields may not be in the before-modification snapshot; take # values for these from the new object instead. for field in payload["old"]: if not hasattr(event.object_before_modification, field): payload["old"][field] = payload["new"][field] _trigger_webhook(merge_proposal, payload)
def merge_detected(logger, source, target, proposal=None, merge_revno=None): """Handle the merge of source into target.""" # If the target branch is not the development focus, then don't update # the status of the source branch. logger.info( 'Merge detected: %s => %s', source.bzr_identity, target.bzr_identity) if proposal is None: # If there's no explicit merge proposal, only change the branch's # status when it has been merged into the development focus. if is_development_focus(target): mark_branch_merged(logger, source) else: with BranchMergeProposalNoPreviewDiffDelta.monitor(proposal): proposal.markAsMerged(merge_revno) # If there is an explicit merge proposal, change the branch's # status when it's been merged into a development focus or any # other series branch. if is_series_branch(proposal.target_branch): mark_branch_merged(logger, proposal.source_branch)