Some customers and some partners may be using ScriptRunner in order to automate some tasks and even extend the features provided by Jira.

You can also do some automation related with Xray, specially because we use Jira entities and concepts.

ScriptRunner may be used in order to access existing features or even to extend the built-in features.

Let us know if you're using also ScriptRunner and your use cases so we can improve and share them with other users.


Please note

The following scripts are provided as-is, no warranties attached. Use these scripts carefully.

Please feel free to adapt them to your needs. 

Note: We don't provide support for ScriptRunner; if you have doubts concerning its usage, please contact ScriptRunner's support.



Examples

Validate coverable issues upon making a transition

Sometimes you may need to assure that the coverable issue (e.g. requirement) is covered before transitioning it to some status, or before resolving it.

The following script validates the requirement based on the directly linked tests to it.


Please note

This solution is not perfect for several reasons, so please take the following notes into consideration:

  1. this should be implemented as a workflow condition (currently it's not possible with ScriptRunner on Jira Cloud)
  2. the tests association should be validated properly, based on all the direct linked tests and on the ones linked to "sub-requirements"


You need to:

  1. edit the workflow transition of the "coverable issue" (e.g. story, requirement), by editing the related workflow
  2. add a ScriptRunner Post Function, in the Post Functions tab  




Script content
Map<String, Object> searchResult = get('/rest/api/2/search')
        .queryString('jql', "key = ${issue.key} and hasLinks = 'is tested by'")
        .asObject(Map)
        .body 

// if no Tests linked, then force a certain transition (i.e. rollback it)
if (searchResult.issues.size == 0) {
    def res = post("/rest/api/2/issue/" + issue.key + "/transitions")
    .header("Content-Type", "application/json")
    .body([
        "transition": [
            "id": "301"
        ]
    ])
    .asString()
    //assert res.status == 204    
}


Reopen/transition linked Tests to a covered issue

Whenever you change the specification of a requirement, for example, you most probably will need to review the Tests that you have already specified.

The following script tries to make a transition on all linked Tests to a requirement. You can hook it to a post-function on the transition of the covered issue.


Please note

This solution is not perfect because the tests association should be validated properly, based on all the direcly and indirectly linked tests.

Script content
import org.apache.log4j.Logger
import org.apache.log4j.Level

def transitionIssue(issueKey, transitionId){
    def res = post("/rest/api/2/issue/" + issueKey + "/transitions")
    .header("Content-Type", "application/json")
    .body([
        "transition": [
            "id": transitionId
        ]
    ])
    .asString()
}

def log = Logger.getLogger("com.example.script")
log.setLevel(org.apache.log4j.Level.DEBUG)


def result = get('/rest/api/2/issue/' + issue.key)
        .header('Content-Type', 'application/json')
        .asObject(Map)
if (result.status == 200){
    def issueLinks = (List<Map<String, Object>>) result.body.fields.issuelinks
    
    def mapping = issueLinks.groupBy { issueLink -> 
        ((Map<String, Map>) issueLink).type.inward
    }.collectEntries { linkName, linkItem ->
        [(linkName): linkItem.inwardIssue.key]
    }
    
    log.debug mapping['is tested by']
    def transitionId = 11 // Done=>TODO
    mapping['is tested by'].each { testKey ->
        transitionIssue(testKey, transitionId)
    }
} else {
    return "Failed to find issue: Status: ${result.status} ${result.body}"
}


You need to:

  1. edit the workflow transition of the "coverable issue" (e.g. story, requirement), by editing the related workflow
  2. add a ScriptRunner Post Function, in the Post Functions tab  



Show Tests Count for a requirement

In the following example, we'll create a text custom field to show the total amount of directly linked Tests to a given coverable issue.


Please note

ScriptRunner for Jira Cloud does not provide scripted field; thus, we have to create a standard text (single line) custom field and we'll update it periodically. For the later, we'll use a periodic job.



Script content
import org.apache.log4j.Logger
import org.apache.log4j.Level

def transitionIssue(issueKey, transitionId){
    def res = post("/rest/api/2/issue/" + issue.key + "/transitions")
    .header("Content-Type", "application/json")
    .body([
        "transition": [
            "id": transitionId
        ]
    ])
    .asString()
}

def log = Logger.getLogger("com.example.script")

log.setLevel(org.apache.log4j.Level.DEBUG)

def issueKey = 'CALC-1'

def result = get('/rest/api/2/issue/' + issue.key)
        .header('Content-Type', 'application/json')
        .asObject(Map)
if (result.status == 200){    
    def issueLinks = (List<Map<String, Object>>) result.body.fields.issuelinks
    
    def mapping = issueLinks.groupBy { issueLink -> 
        ((Map<String, Map>) issueLink).type.inward
    }.collectEntries { linkName, linkList ->
        [(linkName): linkList.size()]
    }
    
        log.debug mapping['is tested by']
        
    def testsCountCF = "customfield_10027"
    def res = put("/rest/api/2/issue/${issue.key}") 
     .header("Content-Type", "application/json")
     .body([
         fields:[
         (testsCountCF): mapping['is tested by'].toString()
         ]
     ])
     .asString()
 

} else {
    return "Failed to find issue: Status: ${result.status} ${result.body}"
}


You need to:

  1. create a text (single line) custom field (e.g. "Tests Count")
  2. create a ScriptRunner scheduled job



References