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)
예제 #3
0
 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')
예제 #4
0
 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')
예제 #5
0
 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')
예제 #6
0
 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
예제 #8
0
    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)
예제 #9
0
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)
예제 #10
0
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)