Transition issue when all linked issues are resolved

Jason Plumhoff
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.
April 29, 2013

What is the best method for automatically transitioning an issue when all linked issues are closed? Example: Our support team has their own JIRA instance. When a issue in the support project requires development, they open another issue in the appropriate development project and link it to the original support issue. They would like to then push their support issue into a "waiting for dev" state, and have it automatically pop into a "dev complete" state when the developers close the development issue.

I've seen similar requests for sub-tasks, but since a sub-task has to be in the same project as the parent task, this won't work for us. Any recommendations for scripts/plugins/methodologies that would address our needs would be greatly appreciated!

Thanks,

Jason

3 answers

1 accepted

0 votes
Answer accepted
Ramiro Pointis
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.
April 29, 2013

Hi Jason, the Script Runner plugin has this option called:

Allows the transition if this query matches a JQL query

But this works when it's in the same JIRA instance, than know if it would work between two instances.

And there's listener you can create: Fast-track transition an issue

Jason Plumhoff
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.
April 30, 2013

OK - I've looked at the script runner. If I understand the way this works, then I'd want a post function script to fire on the CLOSE transition for a development issue. That script should:

1. Get a list (list1) of all linked issues where:

a) link type = "Blocks"

b) linked issue is in the Support project

c) linked issue is in state "Awaiting Development".

2. For each Blocked issue in list1:

a. Get a list (list2) of all issue links of type "Blocked By" (minus originating issue)

b. If all issues in list2 are closed, transition the Blocked issue to the "Dev Complete" state

Does the logic sound right? Or am I missing something obvious? I am trying to handle the case where a support issue may be blocked by multiple dev issues, as well as the case where a single dev issue might block multiple support issues...

Thanks,

Jason

2 votes
Jason Plumhoff
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.
May 1, 2013

I followed Ramiro's advice and installed the script runner plugin. I cobbled together a Groovy script from various examples that did what I wanted. This is my first ever Groovy script, so it may have significant problems I just haven't seen yet. If you see any places to clean it up, please let me know.

//Post-function script for transitioning a linked issue in another project when this issue is closed
//Jason Plumhoff
//May 2, 2013
import org.apache.log4j.Category
import com.atlassian.jira.ComponentManager 
import com.atlassian.jira.issue.Issue
import com.atlassian.jira.project.Project
import com.atlassian.jira.issue.link.IssueLink
import com.atlassian.jira.component.ComponentAccessor
import com.atlassian.jira.bc.issue.IssueService
import com.atlassian.jira.bc.issue.IssueService.TransitionValidationResult
import com.atlassian.crowd.embedded.api.User

def Category log = Category.getInstance("com.onresolve.jira.groovy.TransitionToDevComplete")

User currentUserObj = ComponentAccessor.getJiraAuthenticationContext().getLoggedInUser()

issueManager = ComponentAccessor.getIssueManager()
linkMgr = ComponentAccessor.getIssueLinkManager()
projectMgr = ComponentAccessor.getProjectManager()
issueIndexMgr = ComponentAccessor.getIssueIndexManager()
log.debug ("Current issue ID: " + issue.id)
log.debug ("Looking for Links...")

//Iterate through the dev issue's links
for (IssueLink link in linkMgr.getOutwardLinks(issue.id)) {
    def issueLinkTypeName = link.issueLinkType.name
    def linkedIssue = link.getDestinationObject()
    def linkProjectName = linkedIssue.getProjectObject().getName()
    def linkedIssueKey = linkedIssue.getKey()
    def linkedIssueID = linkedIssue.getId()
    def linkedIssueStatus = linkedIssue.getStatusObject().getName()
 
    //look for a link that blocks an In Dev Tech Support issue
    if (issueLinkTypeName == "Blocks" && linkProjectName == "Technical Support" && linkedIssueStatus == "In Development") {
        log.debug ("issue "+ issue.getKey() + " blocks " + linkProjectName + " issue " + linkedIssueKey)
        def allClosed = true
 
        //go to tech support issue and see if it has other open blockers
        for (IssueLink parentIssueLink in linkMgr.getInwardLinks(linkedIssueID)) {
            def parentIssue = parentIssueLink.getSourceObject()
            def parentIssueKey = parentIssue.getKey()
            def parentIssueID = parentIssue.getId()
            def parentIssueLinkType = parentIssueLink.issueLinkType.name
            def parentIssueStatusName = parentIssue.getStatusObject().name
            log.debug ("parentIssueLinkType = " + parentIssueLinkType)
            if (issue.getKey() != parentIssueKey  && parentIssueLinkType == "Blocks") {
                if (parentIssueStatusName == "Closed") {
                    log.debug ("Issue " + parentIssueKey + " is closed")
                } else {
                    log.debug ("Issue " + parentIssueKey + " is still open")
                    allClosed = false
                }
            }
        }
        log.debug ("All issues closed? " + allClosed)
        
        //if no other blockers remain open, try to transition the issue
        if (allClosed) {
            def actionID = 201 //CHANGE THIS TO THE APPROPRIATE VALUE FOR YOUR TRANSITION
            log.debug ("Transition issue " + linkedIssueKey)
            issueService = ComponentAccessor.getIssueService()
            issueInputParameters = issueService.newIssueInputParameters()
            TransitionValidationResult validationResult = issueService.validateTransition(currentUserObj, linkedIssue.getId(), actionID, issueInputParameters)
            if (validationResult.isValid()) {
            // Transition linked issue to status = "Closed"
                issueService.transition(currentUserObj, validationResult)
                log.debug ("Transitioned")
                // Re-index issue
                issueIndexMgr.reIndex(validationResult.getIssue())
                log.debug ("Reindexed")
            } else {
                Collection<String> errors = validationResult.getErrorCollection().getErrorMessages()
                for (errmsg in errors) {
                    log.debug ("[ERROR] - Error message:" + errmsg)
                }
            }
        }
    }
}

Deepali Bagul June 2, 2016

This works like charm. Thanks !

Mithil October 2, 2020

Does it also works if multiple issues are linked?

I want to setup auto close original issues when all linked issues are closed.

1 vote
MB June 11, 2015

Hy guys, is this solution valid for JIRA 6? I'm getting no errors, but the issue remains in the same state...

sk February 19, 2016

We have the same problem on our Jira 6 instance.

MB June 2, 2016

I was missing this line:

issueInputParameters.setSkipScreenCheck(true);

Suggest an answer

Log in or Sign up to answer