Forums

Articles
Create
cancel
Showing results for 
Search instead for 
Did you mean: 

Move an Epic to the Resolved status when all its issues, sub-tasks, and linked issues are Closed

Volodymyr
Contributor
October 20, 2022

Please advise how to change the script to make it work. This script is used in the post function, the latest in the queue. 
At the moment, the issues from Epic have the type DocumentIssueImpl. Because of this, the status of the last issue, which goes to the status Closed is always displayed as the previous. That is, issue.statusId shows the status that the issue has moved, and the line search.results.every{it.statusId == "6"} shows that the current issue is still in the previous status.
How to make this selection readable?

The script was edited to the correct version:

import com.atlassian.jira.jql.parser.JqlQueryParser
import com.atlassian.jira.issue.IssueInputParametersImpl
import com.atlassian.jira.web.bean.PagerFilter
import com.atlassian.jira.bc.issue.search.SearchService
import com.atlassian.jira.component.ComponentAccessor

// Stop the script if the issue is Epic
if (issue.issueTypeId == "6") {
    return
}

// ID of "Epic link" field and current user
Long EPICLINK = 14500
def currentUser = ComponentAccessor.getJiraAuthenticationContext().getLoggedInUser()

// Get managers
def issueLinkManager = ComponentAccessor.getIssueLinkManager()
def customfieldManager = ComponentAccessor.getCustomFieldManager()
def jqlQueryParser = ComponentAccessor.getComponent(JqlQueryParser)
def searchService = ComponentAccessor.getComponent(SearchService)
def workflowManager = ComponentAccessor.getWorkflowManager()
def issueService = ComponentAccessor.getIssueService()

// Epic of the current issue
def epicLinkCustomField = customfieldManager.getCustomFieldObject(EPICLINK)
String epicLink = issue.getCustomFieldValue(epicLinkCustomField)
def currentEpic = ComponentAccessor.getIssueManager().getIssueByCurrentKey(epicLink)

// Stop the script If the issue has no Epic
if (!currentEpic) {
    return
}

// JQL to retrieve all issues in the Epic
def query = jqlQueryParser.parseQuery("issueFunction in issuesInEpics(\"key = ${currentEpic.key}\")")
def search = searchService.search(currentUser, query, PagerFilter.getUnlimitedFilter())
def searchResults = search.getResults().findAll{ it.getKey() != issue.getKey() } // Excluding the current issue, which goes to status "Closed"

// Epic's workflow
def workflow = workflowManager.getWorkflow(currentEpic)
int actionID = 21 // Resolved status
def transitionValidationResult = issueService.validateTransition(currentUser, currentEpic.id, actionID, new IssueInputParametersImpl())

// Transition the epic to Resolved status only if all issues in the epic are closed
if (searchResults.every{it.getStatusId() == "6"}) {
    String newComment = "The issue is resolved. Please check all the updates and manually close it."
    issueService.transition(currentUser, transitionValidationResult)
    ComponentAccessor.getCommentManager().create(currentEpic, currentUser, newComment, false)
}

Please specify if there are errors or lines in my code that can be improved. I'd be grateful. (apologies if there are typos)
P.S.
The script is written in a readable form to make it easier for my colleagues to read it. They don't write scripts.

1 answer

1 accepted

0 votes
Answer accepted
Radek Dostál
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
October 20, 2022

When you're iterating over issues, you could exclude your current Issue.

 

If I understand what you're describing, let's say for the purpose of this example the post-function is being executed on a story.

If the parent issue is Epic, you then get issues in the epic.

The transition on the story is to Done - so we know that this story is in the Done status.

However, getting the issues in Epic, the issues return their current status, however this one particular story still shows as previous status - arguably, we could say, because this story has not yet finished transitioning.

 

If that's the case, you could exclude it, I think this should work

search.results.remove(issue).every { .. }

which should remove your current issue from the results, if it is present in it, then you continue as you were

or with a different approach in case the one above doesn't work

boolean areAllIssuesInEpicDone = searchResults.getResults().find {
it.getKey() != issue.getKey() && it.getStatusId() != "6"
} != null

is there any issue which is not the current story, which is not in "Done" status

 

And of course similar for subtasks or linked issues, etc.

Volodymyr
Contributor
October 21, 2022

@Radek Dostál, thank you very much for your reply. I didn't know about the "Remove" method. Your answer was able to point me in the right direction.
For starters, we get all the issues in the epic except the one that goes to Closed status. After that, we iterate through that list. During the tests, I realized that the script logic is wrong because an epic shouldn't have issue links or sub-tasks and child issues should have them, so I changed and tested the script, so I will change my question with the correct script.

Once again, thank you very much, Radek Dostál. Advice from the outside always helps.

Suggest an answer

Log in or Sign up to answer