Getting Started

JIRA Extension Points

The Script Console is the place for running one-off ad hoc scripts, and for learning and experimenting with the JIRA REST API from ScriptRunner.


Take one of these samples and use it as a starting point for your own needs.

Get JIRA Version

Starting with a very simple script to read the JIRA version and display it in the console. API Reference.

get('/rest/api/2/serverInfo') (1)
        .queryString('doHealthCheck', 'true') (2)
        .asObject(Map) (3)
        .body (4)
        .version (5)
1 This is a get request to the serverInfo resource
2 Just as an example we see how to add a query string parameter of doHeathCheck and set it to true
3 asObject(Map) makes the request and converts the response into a Map
4 Calling .body on the result of asObject(Map) returns a Map representation of the JSON response
5 We now read the version property of the resulting Map

Show Issue Counts for Projects Based on JQL

Now let’s perform a JQL search to find all stories and group them into projects to determine which projects have the most stories

Map<String, Object> searchResult = get('/rest/api/2/search')
        .queryString('jql', 'issuetype = Story')
        .queryString('fields', 'project')
        .body (1)

def issues = (List<Map<String, Object>>) searchResult.issues (2)

issues.groupBy { issue -> (3)
    ((Map<String, Map>) issue.fields).project.key
}.collectEntries { pKey, issueList -> (4)
    [(pKey): issueList.size()]
}.toString() (5)
1 Perform the JQL search, specifying we are interested in the project field from the issue
2 Grab all the issues from the search
3 Take each issue and group them by project key
4 The resulting list can be transformed into pairs of project key and the number of issues with that project key
5 Turn the result into a String for display

Now the display of this isn’t great. It would be nice to output a html table so lets do that using Groovy’s MarkupBuilder.

Map<String, Object> searchResult = get('/rest/api/2/search')
        .queryString('jql', 'issuetype = Story')
        .queryString('fields', 'project')

def issues = (List<Map<String, Object>>) searchResult.issues

def mapping = issues.groupBy { issue -> (1)
    ((Map<String, Map>) issue.fields).project.key
}.collectEntries { pKey, issueList ->
    [(pKey): issueList.size()]

import groovy.xml.MarkupBuilder
def writer = new StringWriter()
def builder = new MarkupBuilder(writer) (2)
builder.table(class: "aui") {
    thead {
        tr {
            th("Project Key")
    tbody {
        mapping.each { projectKey, count ->
            tr {
                td {

return writer.toString()
1 Up until this point everything is the same, except we assign the result to mapping
2 A new MarkupBuild is created, note the import. The markup builder takes advantage of Groovy’s meta-programming so the static type checking will cause errors, this is nothing to be worried about.

Update an issue

Another common task is to update a field of an issue. In this case we set the summary to be a new summary

def issueKey = 'TP-1' (1)
def newSummary = 'Updated by a script'

def result = put('/rest/api/2/issue/' + issueKey) (2)
    .header('Content-Type', 'application/json') (3)
        fields: [
                summary: newSummary
        .asString() (4)
if (result.status == 204) { (5)
    return 'Success'
} else {
    return "${result.status}: ${result.body}"
1 Issue key and new summary to set
2 Create the rest PUT request
3 Important to set the content type of the put, and then the body content as a Groovy Map
4 Calling .asString() executes the put and parses the result as a string
5 Response code of the request can be checked

Adding a User or Group to a Project Role

Say we would like to add a user to a group. This can be quickly achieved using the following assuming that the user, group, project and role all exist

def username = 'charlie'
def groupName = 'awesome-users'
def projectKey = 'TP'
def roleName = 'Developers'

def roles = get("/rest/api/2/project/${projectKey}/role")
        .asObject(Map).body (1)

String developersUrl = roles[roleName] (2)

def result = post(developersUrl)
    .header('Content-Type', 'application/json')
            user: [username], (3)
            group: [groupName]

assert result.status == 200
1 First all the roles for the project are fetched
2 Then the url for the specified role is found to use to post to
3 In this case we have a group and a user to add, user and group must be arrays