Keep Issue Open Until Everything Blocking It Is Closed

This custom subroutine can be used to not allow users to transition an issue which is linked via linktype 'Blocking' to issues not in a user specified state. (you could easily extend this routine to allow the linktype to be user-specified as well)

When using the condition in a JIRA workflow the user must supply a single parameter 'closedstate' which contains the 'id' primary key value (1 or more, comma separated) of the issue state(s) the linked issues must be in to allow the workflow transition.

One big shortcoming to this simple task - no overriding of the condition is possible. In itself this is ok as you can just have it in a 'or' clause with an additional check for the groups the user is a member of. If however you wish to have more complicated logic - i.e.:

if (the user is a member of project-admin group AND all subtasks are closed) OR (user is a jira-administrator)

you have to create a 'meta-condition' class which contains the logic for the 'and' conditions. There is supposed to be a supported syntax with the JIRA 3.0.3 opensymphony osworkflow library but I haven't determined what this is yet.

How to use

Every transition that used this condition required complex if/else logic so I had to create a 'meta-condition' which contained calls to multiple conditionals. You environment might differ. Regardless, to use this condition call it from a java class as shown in the skeleton at the linked page shown below.

Custom Workflow Condition Skeleton -> go here to get frame to use below subroutine.

blockingLinksClosed subroutine
    public boolean blockingLinksClosed( GenericValue issue
                                       , String linkValidStates )
    {
        try
        {
            // Inward links are links made from other issues to the passed 'issue'
            List inwardLinks = ComponentManager.getInstance().getIssueLinkManager().getInwardLinks(issue.getLong("id"));

            // Make sure all linked issues of link type equal to passed link name
            for (int i = 0; i < inwardLinks.size(); i++)
            {
                IssueLink link = (IssueLink) inwardLinks.get(i);
                //log.error("issueLinkName: " + link.getIssueLinkType().getName());
                if("Blocking".equals(link.getIssueLinkType().getName()))
                {
                    String issueStatus = ((GenericValue ) link.getSource()).getString("status");
                    //log.error("issueStatus: " + issueStatus);

                    boolean isClosed = false;
                    String[] validStates = linkValidStates.split(",");
                    for (int j = 0; j < validStates.length; j++)
                    {
                        String validState = validStates[j];
                        if(issueStatus.equals(validState))
                        {
                            //log.error("  validState: " + validState);
                            isClosed = true;
                            break;
                        }
                    }
                    //log.error("  returning: " + isClosed);
                    return isClosed;
                }
            }
            return true;
        }
        catch(Exception e)
        {
            log.error("Exception verifying all blockingLinks are closed: " + e, e);
            return false;
        }
    }

Install Instructions

You can deploy this subroutine into your instance by wrapping it in a custom workflow element plugin.

Was this page helpful?

Have a question about this article?

See questions about this article

Powered by Confluence and Scroll Viewport