Send email using ScriptRunner when sensitive files are involved in a pull request

Michael McKinstry September 26, 2016

We would like send an email using ScriptRunner when certain sensitive files are included in a pull request. This request is similar to the questions raised and answered in my earlier question here: https://answers.atlassian.com/questions/39441445 How can we adapt this solution as an event handler for a PullRequestOpenedEvent that sends an email to certain users which would include a list of files changed?  When I use pathsMatch, I see the same issue as was raised in previous question. 

1 answer

1 accepted

2 votes
Answer accepted
adammarkham
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
September 26, 2016

The example in the other answer you have linked to can easily be adapted to work for an event handler, so a lot of this will be familiar. To make this easier you can use the built-in send mail event handler which will send the email if you listen for the PullRequestOpenedEvent.

You can find the event handler under Admin -> ScriptRunner -> Script Event Handlers -> Send mail.

The documentation for this can be found here. Your condition should be the following code which will stream the changes in the pull request and return true if sensitive files are detected.

import com.atlassian.bitbucket.content.AbstractChangeCallback
import com.atlassian.bitbucket.content.Change
import com.atlassian.bitbucket.event.pull.PullRequestOpenedEvent
import com.atlassian.bitbucket.pull.PullRequestChangesRequest
import com.atlassian.bitbucket.pull.PullRequestService
import com.atlassian.sal.api.component.ComponentLocator

import javax.annotation.Nonnull

def event =  event as PullRequestOpenedEvent
def pullRequestService = ComponentLocator.getComponent(PullRequestService)
// get pull request from event
def pullRequest = event.pullRequest

def senstiveFilePatterns = ["README.md", "basic_branching/file.txt"]

def fileChangeFinder = new FileChangeFinder(senstiveFilePatterns)
pullRequestService.streamChanges(new PullRequestChangesRequest.Builder(pullRequest).build(), fileChangeFinder)

// return true if sensitive files detected
return fileChangeFinder.fileFound

class FileChangeFinder extends AbstractChangeCallback {

    private boolean fileFound = false
    private List<String> files

    FileChangeFinder(List<String> files) {
        this.files = files
    }

    @Override
    boolean onChange(@Nonnull Change change) throws IOException {

        if (change.path.toString() in files) {
            fileFound = true
        }

        return true
    }
}

 

Additionally if you want to check the files in all commits on the pull request (not just the diff changes) you can instead use as your condition: 

pathsMatchExcludingDeletes('regex:.*\\.css$|.*\\.js$')
 
OR
 
pathsMatch('glob:**.cpp')

The first one will ignore deleted files too, more about that here.

Hope this helps. Let me know if you have trouble getting it to work.

Michael McKinstry September 27, 2016

Hi Adam,

Thank you for the information.  I am seeing this in my logs when it runs:

2016-09-27 17:38:03,007 ERROR [AtlassianEvent::thread-1] user @17HNHIKx1058x1738562x1 w7lfwf <IP ADDRESS> "POST /projects/SANDBOX/repos/pr-build-test/pull-requests HTTP/1.1" c.o.s.bitbucket.InnerListener Event handler failed: event: com.atlassian.bitbucket.event.pull.PullRequestOpenedEvent file: null

groovy.lang.MissingPropertyException: No such property: pullRequest for class: groovy.lang.Binding

 at com.onresolve.scriptrunner.canned.bitbucket.events.StashSendCustomEmail$_doScript_closure3.doCall(StashSendCustomEmail.groovy:173) ~[na:na]

 at com.onresolve.scriptrunner.canned.bitbucket.events.StashSendCustomEmail.doScript(StashSendCustomEmail.groovy:167) ~[na:na]

 at com.onresolve.scriptrunner.canned.CannedScript$doScript$2.call(Unknown Source) ~[na:na]

 at com.onresolve.scriptrunner.canned.CannedScript$doScript$2.call(Unknown Source) ~[na:na]

 at com.onresolve.scriptrunner.runner.ScriptRunnerImpl.validateAndRunCannedInternal(ScriptRunnerImpl.groovy:402) ~[na:na]

 at com.onresolve.scriptrunner.runner.ScriptRunnerImpl.runCanned(ScriptRunnerImpl.groovy:361) ~[na:na]

 at com.onresolve.scriptrunner.runner.ScriptRunner$runCanned$4.call(Unknown Source) ~[na:na]

 at com.onresolve.scriptrunner.bitbucket.InnerListener.receiveEvent(BitbucketEventListener.groovy:202) ~[na:na]

 at com.atlassian.event.internal.SingleParameterMethodListenerInvoker.invoke(SingleParameterMethodListenerInvoker.java:36) ~[atlassian-event-3.0.0.jar:na]

 at com.atlassian.stash.internal.event.AsyncBatchingInvokersTransformer$AsyncInvokerBatch.invoke(AsyncBatchingInvokersTransformer.java:109) ~[bitbucket-platform-4.9.0.jar:na]

 at com.atlassian.event.internal.AsynchronousAbleEventDispatcher$1$1.run(AsynchronousAbleEventDispatcher.java:46) ~[atlassian-event-3.0.0.jar:na]

 at com.atlassian.sal.core.executor.ThreadLocalDelegateRunnable.run(ThreadLocalDelegateRunnable.java:34) ~[sal-core-3.0.6.jar:na]

Any ideas?

Michael

adammarkham
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
September 27, 2016

I do not get the same error as you.

Did you modify the script I added in any way? It seems to be trying to get the pullRequest from the binding. Are you using:

def event =  event as PullRequestOpenedEvent
def pullRequest = event.pullRequest

to get the pull request from the event in your condition? Event is in the binding but pull request is not.

Failing that what version of ScriptRunner and Bitbucket are you using?

Michael McKinstry September 28, 2016

Hi Adam,

No, I did not modify the script.  I created a new Script Event Handler, gave it a name, a repository, and under events I added PullRequestOpenedEvent (the form did not let me leave this field blank).  I added the script under Condition, added a Subject template and Email template, chose HTML as Email format and added my email address.

Yes, those 2 lines are in the condition.

I am running Bitbucket version 4.9.0 and ScriptRunner version 4.3.4

adammarkham
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
September 29, 2016

Hi Michael,

I could not reproduce the same error as you even with those versions. Could you try upgrading your version of ScriptRunner and seeing if that resolves the issue?

I've attached my screenshots of the send mail event handler below for you to check you have a similar configuration.

For the condition I just copied and pasted the code I provided in my answer here.

Screen Shot 2016-09-29 at 13.40.22.png

 

Screen Shot 2016-09-29 at 13.40.40.png

Michael McKinstry September 29, 2016

Hi Adam,

Thanks, I upgraded the plugin and I removed some variables from the Subject template and Email template fields and now it works. I guess I need some help with what is possible in the templates.  Is there some documentation on that? Specifically, I would like to add the user who created the pull request, the file(s) changed and a link to the pull request.

I appreciate all the help!

Michael

Suggest an answer

Log in or Sign up to answer
TAGS
AUG Leaders

Atlassian Community Events