This ScriptRunner code will be useful if your Epic contains more than 100 sub-tasks. Unfortunately, automation JQL rules runs only first 100 issues. Please, find documentation by link Jira automation actions | Cloud automation Cloud | Atlassian Support 'Search for up to 100 issues using an Assets AQL query.'
Fortunately, ScriptRunner can send JQL request with parameters 'startAt'. This parameter allows to iterate the entire JQL results list.
How-to:
//Exclude Epic types
if( issue.fields.issuetype.name == 'Epic'){
logger.info('Ignore Epic type')
return
}
// get custom fields
def customFields = get("/rest/api/2/field")
.asObject(List)
.body
.findAll { (it as Map).custom } as List<Map>
def epicId = customFields.find { it.name == 'Epic Link' }?.id
def storyPointId = customFields.find { it.name == 'Story Points' }?.id
def epicLink = issue.fields[epicId] as String
if (epicLink == null) {
logger.info("No Epic Link for this issue")
return
}
//find all sub-tasks for epic
def jqlEncoded = URLEncoder.encode("\"Epic Link\" = $epicLink", "UTF-8")
def startAt = 0
def maxResults = 100
def total = 0
double totalStoryPoints = 0.0
def firstCycle = true
def checkedSubTasks = 0
// Repat jql search if total count more than 100 issues
while((startAt <= total) || firstCycle ){
firstCycle = false
def jqlResponse = get("/rest/api/2/search?jql=$jqlEncoded&startAt=$startAt&maxResults=$maxResults").asObject(Object).body
total = jqlResponse['total'] as Integer
Double sumStoryPointsSubTasks = 0
try{
def subTasks = jqlResponse['issues']['fields'][storyPointId]?.findAll{ it != null }
sumStoryPointsSubTasks = subTasks?.sum() as Double
checkedSubTasks += subTasks?.size()
}catch(Exception e){
logger.error('Can not get sum ', e)
}
totalStoryPoints += sumStoryPointsSubTasks != null?sumStoryPointsSubTasks:0
startAt += maxResults
}
logger.info('Checked sub-tasks '+checkedSubTasks)
def parentEpicStoryPoints = get("/rest/api/2/issue/$epicLink").asObject(Object).body['fields'][storyPointId] as Double
def originEpicStoryPoints = parentEpicStoryPoints!=null?parentEpicStoryPoints:0
//set new sum if it was changed
if(originEpicStoryPoints != totalStoryPoints){
put("/rest/api/2/issue/$epicLink")
.header("Content-Type", "application/json")
.body([
fields:[
(storyPointId): totalStoryPoints
]
]).asJson()
}
That's all. This listener now updates a Story Points for an Epic as the sum of its linked issues.
P.S.
I've created 122 linked Story issues with the same Epic Link parent.
All sub-tasks have 'Story Points' value equals 1.
The listener set parent issue's value to 122.
I hope the article is helpful.
Regards,
Andrey
Andrew
Senior systems engineer
EPAM Sytems
43 accepted answers
0 comments