Create
cancel
Showing results for 
Search instead for 
Did you mean: 
Sign up Log in

Scriptrunner Post Function failing with a null in loop

Ryan Gillespie January 11, 2022

We have a setup where some issues submitted to a helpdesk create children issues in other helpdesks. Those children are sometimes linked to each other depending on cust req type. This post function is for when a child is completed, it needs to find the parent, find all children of the parent, and then see if all 4 are in one of the completed statuses. If so, leave a comment and transition the parent. However, when going through the children issues, it doesn't get past the first child. It sees the first child, checks its status, and the fails with a null.

Code without the bottom closing tags for brevity:

def linkedIssues = fields.issuelinks as List<Map>
def successStatusByIssueKey = linkedIssues.collectEntries { Map linkedIssue ->
def possibleParent = linkedIssue.inwardIssue as Map
logger.info("linked key is ${possibleParent.key}")
if (((Map) possibleParent.fields.issuetype)?.name == 'Service Request') {
def parentIssue = getIssueByKey(possibleParent.key) as Map
Integer counter = 0
def childIssues = parentIssue.fields.issuelinks as List<Map>
def successStatusByIssueKey = childIssues.collectEntries { Map issueLink ->
def childIssue = issueLink.outwardIssue
logger.info("child key is ${childIssue.key} with status ${childIssue.fields.status.name}")
if (childIssue.fields.status.name == "Completed" || childIssue.fields.status.name == "Closed") {
logger.info ("I actually checked a status!!")

 The error is always: ERROR - null on line 19

Where line 19 is def successStatusByIssueKey = childIssues.collectEntries { Map issueLink ->

The total piece of the log is:

INFO - linked key is <parentissue>
INFO - Serializing object into 'interface java.util.Map'
INFO - GET rest/api/2/issue/<parentissue> asObject Request Duration: 2699ms
INFO - child key is <childissue> with status Completed
INFO - I actually checked a status!!
ERROR - null on line 19

 So there is some code above and below that, but the error has to be in there. I am stumped as to why it gets through once and then dies with something that must not have been a null two seconds ago.

My best guess is there is some difference between "issue" that scriptrunner starts with in a post function and the parentIssue I am pulling back via the getIssueByKey api call. I am still constantly throwing in and out comments trying to narrow it down but why the null? Any help would be greatly appreciated.

2 answers

1 accepted

0 votes
Answer accepted
Ryan Gillespie January 13, 2022

So, for now I got around it by completely rewriting the idea it was based on. Scriptrunner has a built in Condition section now, so I first make sure its the right issue type there. Then I just wrote custom JQL queries that would return very specifically what I am after, and used that. So now it is more of a flat run through with zero loops and zero link connection checks and all that.

 

String commentBody = "All components have been completed. Your request is now done."
final transitionId = ### // Resolve in ____ workflow
Integer counter = 0
def jqlSearch = "issueLink = " + issue.key + " AND issuetype = \"Service Request\""
def parentkey = "X"

post('/rest/api/2/search')
.header('Content-Type', 'application/json')
.body([
jql: jqlSearch,
])
.asObject(Map).body.issues.each { Map ParentIssue ->
logger.info "ParentIssue key: ${ParentIssue.key}"
parentkey = ParentIssue.key
}

jqlSearch = "issueLink = " + parentkey + " AND resolution is not EMPTY"
post('/rest/api/2/search')
.header('Content-Type', 'application/json')
.body([
jql: jqlSearch,
])
.asObject(Map).body.issues.each { Map ChildIssue ->
logger.info "Issue key: ${ChildIssue.key}"
counter = counter + 1
}

if (counter == 4) {
createComment(parentkey, commentBody)
def result = post("/rest/api/2/issue/${parentkey}/transitions")
.header("Content-Type", "application/json")
.body([transition: [id: transitionId]])
.asObject(Map)

// Log out the issues transitioned or which failed to be transitioned
if (result.status == 204) {
logger.info("Transition ${transitionId} performed for the ${parentkey} issue")
} else {
logger.warn("Failed to perform the transition ${transitionId} on the ${parentkey} issue. ${result.status}: ${result.body}")
}
// Collect the success status by issue key to show them as part of the script return value
[(parentkey): (result.status == 204)]
}


void createComment(issueKey, String commentBody) {
def result = post("/rest/api/2/issue/${issueKey}/comment")
.header('Content-Type', 'application/json')
.body([
body: commentBody
])
.asString()
}

0 votes
Ryan Gillespie January 11, 2022

The code is also formatted way better locally, and using indents. Sorry for the appearance here.

Suggest an answer

Log in or Sign up to answer
DEPLOYMENT TYPE
CLOUD
PRODUCT PLAN
PREMIUM Trial
PERMISSIONS LEVEL
Site Admin
TAGS
AUG Leaders

Atlassian Community Events