Example Scenario

Let’s say you have business logic that dictates that the component lead(s) must be added as watchers if the priority is Blocker.

You ignore the sensible option, just for the purpose of my example, and decide to write a script to add the component leads as watchers on the Start Progress transition.

Your script might look like:

import com.atlassian.jira.component.ComponentAccessor
import com.atlassian.jira.issue.Issue

// this comes to us in the binding... so this line is unnecessary other than to give my IDE "type" information
Issue issue = issue

// get some components we need
def watcherManager = ComponentAccessor.getWatcherManager()
def userUtil = ComponentAccessor.getUserUtil()

// would be better to use componentLead rather than lead, but not available until 6.3
issue.componentObjects*.lead.each {String username ->
    def applicationUser = userUtil.getUserByKey(username)
    watcherManager.startWatching(applicationUser, issue)
}

We will write some tests for the above script, and throw various combinations at it. The test inherits from AbstractWorkflowSpecification which will take care of setting us up a project, workflow and workflow scheme, ready for us to start editing it.

The entire test class can be found here: https://gist.github.com/anonymous/ffd058dbe82a800d80df

Then we write a single test. I used the Spock data table idiom. Whilst initially hard to setup, it’s very easy to add new test combinations.

In testing adding a component that doesn’t have a lead, I got an error from my script, and a test failure…​

ERROR [scriptrunner.jira.workflow.ScriptWorkflowFunction] Script function failed on issue: SRTESTPRJ-3, actionId: 4, file: examples/docs/AddComponentLeadsAsWatchers.groovy
groovy.lang.GroovyRuntimeException: Ambiguous method overloading for method com.atlassian.jira.issue.watchers.DefaultWatcherManager#startWatching.
Cannot resolve which method to invoke for [null, class com.atlassian.jira.issue.IssueImpl] due to overlapping prototypes between:
    [interface com.atlassian.crowd.embedded.api.User, interface com.atlassian.jira.issue.Issue]
    [interface com.atlassian.jira.user.ApplicationUser, interface com.atlassian.jira.issue.Issue]
    at com.atlassian.jira.issue.watchers.WatcherManager$startWatching$1.call(Unknown Source)
    at examples.docs.AddComponentLeadsAsWatchers$_run_closure1.doCall(AddComponentLeadsAsWatchers.groovy:16)

This happened because I was passing null (the component without a lead) to startWatching, and so required a small change to the script to handle the case where the component lead is not set, namely:

...
if (applicationUser) {
    watcherManager.startWatching(applicationUser, issue)
}
...

For how-to questions please ask on Atlassian Answers where there is a very active community. Adaptavist staff are also likely to respond there.

Ask a question about ScriptRunner for JIRA, for for Bitbucket Server, or for Confluence.