/src/main/java/com/atlassian/stash/unapprove/UnapproveReviewersHook.java
https://bitbucket.org/markmielke/stash-unapprove-reviewers-hook · Java · 82 lines · 57 code · 9 blank · 16 comment · 5 complexity · af2f8a2cdd850e76534f6db23891e1ab MD5 · raw file
- package com.atlassian.stash.unapprove;
- import com.atlassian.sal.api.transaction.TransactionCallback;
- import com.atlassian.sal.api.transaction.TransactionTemplate;
- import com.atlassian.stash.hook.repository.AsyncPostReceiveRepositoryHook;
- import com.atlassian.stash.hook.repository.RepositoryHookContext;
- import com.atlassian.stash.pull.*;
- import com.atlassian.stash.repository.RefChange;
- import com.atlassian.stash.repository.RefChangeType;
- import com.atlassian.stash.user.SecurityService;
- import com.atlassian.stash.util.*;
- import javax.annotation.Nonnull;
- import java.util.Collection;
- /**
- * A simple repository hook for automatically marking reviewers as unapproved when a pull request is updated.
- */
- public class UnapproveReviewersHook implements AsyncPostReceiveRepositoryHook {
- private static final PageRequestImpl ALL = new PageRequestImpl(0, 10000);
- private final PullRequestService pullRequestService;
- private final SecurityService securityService;
- private final TransactionTemplate txTemplate;
- public UnapproveReviewersHook(PullRequestService pullRequestService, SecurityService securityService,
- TransactionTemplate txTemplate) {
- this.pullRequestService = pullRequestService;
- this.securityService = securityService;
- this.txTemplate = txTemplate;
- }
- /**
- * Withdraw approval for all reviewers on any outgoing Pull Request from this repository where the source ref has
- * been updated.
- */
- @Override
- public void postReceive(@Nonnull final RepositoryHookContext hookContext, @Nonnull Collection<RefChange> refChanges) {
- // iterate through refs that have been updated with this push
- for (RefChange change : refChanges) {
- if (change.getType() == RefChangeType.UPDATE) {
- // iterate through all pull requests 'pulling' this branch into another
- for (final PullRequest pr : iterateOutgoingOpenPullRequests(hookContext, change)) {
- // batch withdrawal of approval per pull request
- txTemplate.execute(new TransactionCallback<Void>() {
- @Override
- public Void doInTransaction() {
- for (PullRequestParticipant participant : pr.getReviewers()) {
- // the withdrawApproval method withdraws approval for the currently authenticated user,
- // so use SecurityService to impersonate the reviewer we are withdrawing approval for
- securityService.doAsUser("Unapproving pull-request on behalf of user", participant.getUser().getName(), new Operation<Object, RuntimeException>() {
- @Override
- public Object perform() {
- return pullRequestService.withdrawApproval(hookContext.getRepository().getId(), pr.getId());
- }
- });
- }
- return null;
- }
- });
- }
- }
- }
- }
- /**
- * Use {@link PagedIterable} to wrap the paging behaviour of {@link PullRequestService}, giving us an exhaustive
- * {@link Iterable} of all open pull requests from the specified updated ref.
- */
- private Iterable<PullRequest> iterateOutgoingOpenPullRequests(final RepositoryHookContext hookContext, final RefChange change) {
- return new PagedIterable<PullRequest>(new PageProvider<PullRequest>() {
- @Override
- public Page<PullRequest> get(PageRequest pageRequest) {
- return pullRequestService.findInDirection(PullRequestDirection.OUTGOING,
- hookContext.getRepository().getId(), change.getRefId(), PullRequestState.OPEN, null,
- pageRequest);
- }
- }, ALL);
- }
- }