I am working on a script runner listener script that sums up the values for a field (MT Loaded) in all the issues linked to an epic and places them in the epic MT Loaded field. Working off a script runner example for subtasks I have this:
// Get the parent issue as a Map
def parent = (issue.fields as Map).parent as Map
// Retrieve all the subtasks of this issue's parent
def parentKey = parent.key
// Get the field ids
def fields = get('/rest/api/2/field')
.asObject(List)
.body as List<Map>
// Get the story points custom field to use in the script
def MTLoadedField = fields.find { it.name == "MT Loaded" }.id
logger.info("The id of the MT Loaded field is: $MTLoadedField")
// Note: The search API is limited that to only be able to return a maximum of 50 results
def allSubtasks = get("/rest/api/2/search")
.queryString("jql", "parent=${parentKey}")
.queryString("fields", "parent,$MTLoadedField")
.asObject(Map)
.body
.issues as List<Map>
logger.info("Total subtasks for ${parentKey}: ${allSubtasks.size()}")
// Sum the estimates
def sumMTLoaded = allSubtasks.collect { Map subtask ->
subtask.fields[MTLoadedField] ?: 0
}.sum()
logger.info("Summed MT Loaded: ${sumMTLoaded}")
// Store the summed MT Loaded on the MT Loaded field of the parent issue
def summedMTLoadedField = fields.find { it.name == "MT Loaded" }.id
logger.info("Custom field ID to update: ${summedMTLoadedField}")
// Now update the parent issue
def result = put("/rest/api/2/issue/${parentKey}")
.header('Content-Type', 'application/json')
.body([
fields: [
(summedMTLoadedField): sumMTLoaded
]
])
.asString()
// check that updating the parent issue worked
assert result.status >= 200 && result.status < 300
But I am stuck in modifying the example to look up the linked epic instead of subtask parent.
Can anyone advise?
Hi,
You should work with Epic Link issue custom field instead of parent.
Hi Aleksandr,
I've tweaked my code to look at the Epic Link field instead of parent, and it does seem to work (please excuse the hardcoded ID). However it seems the script is executing twice, the second time with a failure.
// Get the parent issue as a Map
//def parent = (issue.fields as Map).parent as Map
// Retrieve all the subtasks of this issue's parent
//def parentKey1 = parent.key
// Get the field ids
def fields = get('/rest/api/2/field')
.asObject(List)
.body as List<Map>
//Get the Epic
def parentKey = issue.fields.customfield_10013
logger.info("The value of the Epic Link field is: $parentKey")
// Get the MT Loaded custom field to use in the script
def MTLoadedField = fields.find { it.name == "MT Loaded" }.id
logger.info("The id of the MT Loaded field is: $MTLoadedField")
// Note: The search API is limited that to only be able to return a maximum of 50 results
def IssuesInEpic = get("/rest/api/2/search")
.queryString("jql", "'Epic Link'=${parentKey}")
.queryString("fields", "'Epic Link',$MTLoadedField")
.asObject(Map)
.body
.issues as List<Map>
logger.info("Total issues in epic for ${parentKey}: ${IssuesInEpic.size()}")
// Sum the estimates
def sumMTLoaded = IssuesInEpic.collect { Map issue ->
issue.fields[MTLoadedField] ?: 0
}.sum()
logger.info("Summed MT Loaded: ${sumMTLoaded}")
// Store the summed MT Loaded on the MT Loaded field of the parent issue
def summedMTLoadedField = fields.find { it.name == "MT Loaded" }.id
logger.info("Custom field ID to update: ${summedMTLoadedField}")
// Now update the parent issue
def result = put("/rest/api/2/issue/${parentKey}")
.header('Content-Type', 'application/json')
.body([
fields: [
(summedMTLoadedField): sumMTLoaded
]
])
.asString()
// check that updating the parent issue worked
assert result.status >= 200 && result.status < 300
The first log entry is success:
2019-03-13 00:59:50.280 INFO - Serializing object into 'interface java.util.List' 2019-03-13 00:59:50.294 INFO - GET /rest/api/2/field asObject Request Duration: 403ms 2019-03-13 00:59:50.312 INFO - The value of the Epic Link field is: ES-542 2019-03-13 00:59:50.313 INFO - The id of the MT Loaded field is: customfield_10049 2019-03-13 00:59:50.793 INFO - Serializing object into 'interface java.util.Map' 2019-03-13 00:59:50.812 INFO - GET /rest/api/2/search asObject Request Duration: 479ms 2019-03-13 00:59:50.813 INFO - Total issues in epic for ES-542: 6 2019-03-13 00:59:50.814 INFO - Summed MT Loaded: 570.753 2019-03-13 00:59:50.815 INFO - Custom field ID to update: customfield_10049 2019-03-13 00:59:51.542 INFO - PUT /rest/api/2/issue/ES-542 asString Request Duration: 725ms
But there is a second entry with a failure that I don't understand:
2019-03-13 00:59:53.130 INFO - Serializing object into 'interface java.util.List' 2019-03-13 00:59:53.134 INFO - GET /rest/api/2/field asObject Request Duration: 360ms 2019-03-13 00:59:53.135 INFO - The value of the Epic Link field is: null 2019-03-13 00:59:53.136 INFO - The id of the MT Loaded field is: customfield_10049 2019-03-13 00:59:53.564 INFO - Serializing object into 'interface java.util.Map' 2019-03-13 00:59:53.593 INFO - GET /rest/api/2/search asObject Request Duration: 441ms 2019-03-13 00:59:53.632 INFO - Total issues in epic for null: 50 2019-03-13 00:59:53.633 INFO - Summed MT Loaded: 0 2019-03-13 00:59:53.634 INFO - Custom field ID to update: customfield_10049 2019-03-13 00:59:53.861 WARN - PUT request to /rest/api/2/issue/null returned an error code: status: 404 - Not Found body: {"errorMessages":["Issue does not exist or you do not have permission to see it."],"errors":{}} 2019-03-13 00:59:53.863 INFO - PUT /rest/api/2/issue/null asString Request Duration: 224ms 2019-03-13 00:59:53.865 ERROR - assert result.status >= 200 && result.status < 300 | | | | | | | | 404 true | | 404 false | | status: 404 - Not Found | | body: {"errorMessages":["Issue does not exist or you do not have permission to see it."],"errors":{}} | false status: 404 - Not Found body: {"errorMessages":["Issue does not exist or you do not have permission to see it."],"errors":{}} on line 53 2019-03-13 00:59:53.872 ERROR - Class: com.adaptavist.sr.cloud.events.WebhookExecution, Config: null
I have little to no scripting skills and just get by with using example code. Can you advise where my issue is?
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Actually I figured out what's happening. When my script first executes it updates the Epic, which triggers the script to run again. But my script isn't coded to handle a case where the change is in the epic, it's in the issue.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Online forums and learning are now in one easy-to-use experience.
By continuing, you accept the updated Community Terms of Use and acknowledge the Privacy Policy. Your public name, photo, and achievements may be publicly visible and available in search engines.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.