Withdraw Approvals When a Pull Request Changes

By default, a user can push more content to a pull request even after it has been approved, yet the approvals remain. This could interfere with your approvals process. This listener removes any approvals when new content is pushed to an existing pull request, if the condition matches. Using the conditions, you could apply this only when the pull request contains some sensitive code, or for a particular set of developers.

Example: Changed files contain C++ files

You can withdraw the approvals only when changes are made to  C++ files, including creation and deletion.

Click '?' to see a list of available binding variables. Some are ScriptRunner built-in closures while others provide links to Java docs. There are also various snippet examples available via the Show snippets link that can help you understand how to use these variables.

Example: Notify approvers who have been automatically removed

The default behaviour in Bitbucket is that approvers will NOT be automatically notified in the event of a changed Pull Request. In this scenario, we recommend creating an entirely new listener that listens for the PullRequestParticipantUnapprovedEvent and for example sends an email to all Reviewers that had already approved the Pull Request. The following code shows a simple way to send an email after an approval has been removed:

import com.atlassian.sal.api.component.ComponentLocator
import com.atlassian.bitbucket.nav.NavBuilder
import com.onresolve.scriptrunner.canned.ConfiguredObjectMapper
import com.onresolve.scriptrunner.canned.bitbucket.events.BitbucketEventListenerExecutionContext
import com.onresolve.scriptrunner.canned.bitbucket.events.email.StashSendCustomEmailListener
import com.onresolve.scriptrunner.canned.bitbucket.events.model.StashSendCustomEmailListenerCommand
import com.onresolve.scriptrunner.mail.EmailFormat
import com.onresolve.scriptrunner.runner.ScriptRunnerImpl

def pullRequest = event.pullRequest
def navBuilder = ComponentLocator.getComponent(NavBuilder)
def pullRequestUrl = navBuilder.repo(pullRequest.toRef.repository).pullRequest(pullRequest.id).buildAbsolute()

def objectMapper = ScriptRunnerImpl.scriptRunner.getBean(ConfiguredObjectMapper).get()

def subjectTemplate = "Your approval of the Pull Request $pullRequest.title has been removed"
def emailTemplate = "Your approval of the pull request <a href=\"$pullRequestUrl\">$pullRequest.title</a> has been removed," +
    "as the contents of the branch $pullRequest.fromRef.id have been changed"

def params = [
    "FIELD_EMAIL_SUBJECT_TEMPLATE": subjectTemplate.toString(),
    "FIELD_EMAIL_TEMPLATE"        : emailTemplate.toString(),
    "FIELD_TO_ADDRESSES"          : event.participant.user.emailAddress, // <1>
    "FIELD_CC_ADDRESSES"          : null,
    "FIELD_EMAIL_FORMAT"          : EmailFormat.HTML.name(), // <2>

def command = objectMapper.convertValue(params, StashSendCustomEmailListenerCommand)
def executionContext = new BitbucketEventListenerExecutionContext(event: event)

ScriptRunnerImpl.scriptRunner.createBean(StashSendCustomEmailListener).execute(command, executionContext) // <3>

Line 23: Only sends an email to the pull request participant for which the approval has been removed.

Line 25: If you want to send an email with plain text content, change the emailTemplate variable and enter EmailFormat.TEXT.name() instead of EmailFormat.HTML.name().

Line 31: Uses the internal ScriptRunner script to send an email.