Transition all linked Stories to an Epic

Hi folks

I've been trying to find examples of code so I can transition all linked stories to an Epic if the Epic is moved to state "Approved" for example. I use Script Runner and there are plenty of examples the other way around, ie transition the Epic if all linked Stories are completed for example.

Can anyone guide me to how I add a post-function so moving the Epic to state "Approved" will move the Stories to a certain state? Assume the Stories are all in a certain state and I know what the next state is.

I would be very thankful.

5 answers

1 accepted

2 votes
Accepted answer

Hi,

The script below is something I have made to transfer a related issue to a certain state once a bug is resolved. What it does:

  • Check if there is a relation of a certain type to this issue (a lot of hardcoded stuff in here, because I create this relation with another script in workflow)
  • Check if the related issue is in a certain state
  • Transition the related issue to a predefined state
  • Add a comment to the related issue

I think you just have to slightly modify this by looking up the appropriate IDs of your relation, status and workflow.

A tip on those IDs: when I was playing with this script, I was also configuring the Auto Transition Listener. When you edit the configuration of the listener, it displays a list of all workflows, statuses, events, including ID. Nice for lookup.

 

import com.atlassian.jira.component.ComponentAccessor
import com.atlassian.jira.security.JiraAuthenticationContext
import com.atlassian.jira.workflow.WorkflowTransitionUtil;
import com.atlassian.jira.workflow.WorkflowTransitionUtilImpl;
import com.atlassian.jira.util.JiraUtils;
import com.atlassian.jira.issue.link.IssueLinkManager
import com.atlassian.jira.issue.comments.CommentManager
def compAccessor = new ComponentAccessor()
// retrieve the inward links for the issue (Support Request = source, Bug = destination)
def linkManager = compAccessor.getIssueLinkManager()
def links = linkManager.getInwardLinks(issue.getId())
for (link in links) {
    if (link.getIssueLinkType().getId() == 10500 as Long) {
    // since the issue was created by the relatedIssue, simply assume here that the first link is the correct one
        def relatedIssue = link.getSourceObject()
        // check that related issue status is To Dev, otherwise do nothing
        def status = relatedIssue.getStatusObject().getSimpleStatus().getId()
        if (status == "10019") {
            // get the user who resolved the bug
            def authContext = compAccessor.getJiraAuthenticationContext()
            def userKey = authContext.getUser().getKey()
             
            // create the workflow action to Dev Ready
            def workflowTransitionUtil = ( WorkflowTransitionUtil ) JiraUtils.loadComponent( WorkflowTransitionUtilImpl.class )
            workflowTransitionUtil.setIssue(relatedIssue)
            workflowTransitionUtil.setUserkey(userKey)
            workflowTransitionUtil.setAction(81)
         
            // add a comment so support sees what triggered the status change (only visible on Developer [10001] level)
            def commentManager = compAccessor.getCommentManager()
            String comment = "[auto-comment] Bug "+ issue.getKey() +" causing this support request has been resolved."
            commentManager.create(relatedIssue, userKey, comment, null, 10001 as Long, true)
             
            // validate and transition issue
            workflowTransitionUtil.validate()
            workflowTransitionUtil.progress()
        }
    }
}

Hi Geert, finally I'm trying this out. I get quite far but I have to change the InwardLinks to Outwards and SourceObject to DestinationObject since I want to get the Issues in an Epic. This seems to work because if I output text I see the Issue ID's of the right Issues. However when I try the workflowTransitionUtil.progress() it complains about "Issue Type for issue with id '10829' is null". That is strange because the Issue Type is not null. Do you know how to get around this?

Hi Linus, the message does not sound familiar. Is the workflow action correct for the issue that you want to transition?

Yes it should be. I want to go from Open to the next state which is Estimate. The code currently look like this: import com.atlassian.jira.component.ComponentAccessor import com.atlassian.jira.util.JiraUtils; import com.atlassian.jira.issue.link.IssueLinkManager import com.atlassian.jira.issue.comments.CommentManager import com.atlassian.jira.workflow.WorkflowTransitionUtil; import com.atlassian.jira.workflow.WorkflowTransitionUtilImpl; import com.atlassian.jira.security.JiraAuthenticationContext def compAccessor = new ComponentAccessor() def comment = "Test: " // retrieve the Outward links for the issue (Support Request = source, Bug = destination) def linkManager = compAccessor.getIssueLinkManager() def links = linkManager.getOutwardLinks(issue.getId()) for (link in links) { // Get the linked issues in the Epic def relatedIssue = link.getDestinationObject() def status = relatedIssue.getStatusObject().getSimpleStatus().getId() // get the user who work with the Epic def authContext = compAccessor.getJiraAuthenticationContext() def userKey = authContext.getUser().getKey() if (status == "1") { comment = comment + "Open " def workflowTransitionUtil = ( WorkflowTransitionUtil ) JiraUtils.loadComponent( WorkflowTransitionUtilImpl.class ) workflowTransitionUtil.setIssue(relatedIssue) workflowTransitionUtil.setUserkey(userKey) workflowTransitionUtil.setAction(851) // validate and transition issue workflowTransitionUtil.validate() workflowTransitionUtil.progress() } else if (status == "10202") { comment = comment + "Estimate " def workflowTransitionUtil = ( WorkflowTransitionUtil ) JiraUtils.loadComponent( WorkflowTransitionUtilImpl.class ) workflowTransitionUtil.setIssue(relatedIssue) workflowTransitionUtil.setUserkey(userKey) workflowTransitionUtil.setAction(921) // validate and transition issue //workflowTransitionUtil.validate() //workflowTransitionUtil.progress() } comment = comment + " " + relatedIssue + " " + status + " " } return comment

@Geert Graat I saw that workflowTransitionUtil also have a setParams. Could that solve the problem with the error saying That the Issue Type is null? I really need to solve this.

Hi Linus, It is pretty difficult for me to tell what is going wrong as I am not familiar with your workflows, issue types etc. One thing that you should definitely check is that the user that performs the transition is also allowed to do so, I have had problems with that. Could you post the exact error messages and the script that you currently have?

Sure the script is the above one from Nov 27 but suddenly it was working without any code changes but I have removed the screen used for the transition I'm trying. That seems to be the reason. If I add the screen back I get the strange error: "Issue Type for issue with id '16821' is null" Thank you so much for the code and I'm glad I found the issue. I'm not completely sure what the user will become when using the below code, can you clarify? def authContext = compAccessor.getJiraAuthenticationContext() def userKey = authContext.getUser().getKey()

Now I get very confused. I tried the script in a scripted field because it is easy to test towards an issue and see the result. After removing the transition screen it worked well there but when I added it as a scripted post-function it doesn't transition the related issue, only add the comment I have added. Any ideas? @Jamie Echlin [Adaptavist] Do you have a clue why exactly the same code work in a scripted field but not as a post-function? This is the refined script I'm using: {code} import com.atlassian.jira.component.ComponentAccessor import com.atlassian.jira.util.JiraUtils; import com.atlassian.jira.issue.link.IssueLinkManager import com.atlassian.jira.issue.comments.CommentManager import com.atlassian.jira.workflow.WorkflowTransitionUtil; import com.atlassian.jira.workflow.WorkflowTransitionUtilImpl; import com.atlassian.jira.security.JiraAuthenticationContext def compAccessor = new ComponentAccessor() // retrieve the Outward links for the issue (Issues in Epic) def linkManager = compAccessor.getIssueLinkManager() def links = linkManager.getOutwardLinks(issue.getId()) for (link in links) { // Get the linked issues in the Epic def relatedIssue = link.getDestinationObject() // Get corresponding status def status = relatedIssue.getStatusObject().getSimpleStatus().getId() // get the user who work with the Epic def authContext = compAccessor.getJiraAuthenticationContext() def userKey = authContext.getUser().getKey() if (status == "10100") { def workflowTransitionUtil = ( WorkflowTransitionUtil ) JiraUtils.loadComponent( WorkflowTransitionUtilImpl.class ) workflowTransitionUtil.setIssue(relatedIssue) workflowTransitionUtil.setUserkey(userKey) workflowTransitionUtil.setAction(741) workflowTransitionUtil.validate() workflowTransitionUtil.progress() // add a comment so support sees what triggered the status change (only visible on Developer [10001] level) def commentManager = compAccessor.getCommentManager() String comment = "[auto-comment] Approved Epic "+ issue.getKey() +" pushed this issue to Ready for Backlog" commentManager.create(relatedIssue, userKey, comment, null, 10001 as Long, true) } } {code}

Hi Linus, great that you got it working! Makes sense that it does not work when the transition has a screen, although the error message you get does not point into that direction at all. I cannot really say why it does not work as a post function however does as a scripted field, other than that "something must be different". So I would suggest to add some logging on the exact workflow step you are in etc. and debug from there. Regarding the user: you are using the user that is currently logged in, so that is the one that needs to have the permissions to execute the transition. Regards, Geert

I'd say exactly what Geert said almost. Add some logging. Specifically, workflowTransitionUtil.validate returns an ErrorCollection. Print that out and see what's going on there...

Hi Geert and thank you for a quick reply I actually copied the code from the post script into the scripted field so there is no difference in the code. I'm running it on the same Issue as well. The only difference I can think of is if the transition change of the Epic to status "approved" is not quick enough so the post function gets blocked due to a rule saying that the Epic must be in status "approved". Does that make sense? Reason is that I want to prevent the issues in the epic from being moved before the Epic is in the "approved" state but at the same time I want that "approval" to also move the linked issues. Can you think of a way of getting around this? Can you share with me how to add logging that i can see in for example catalina.out or similar?

update: Yes it was the blocking condition and the timing preventing it from transition the issues. If i can set a specific system user to make the transition it would solve the case because I don't want others to be able to do this transition. Do you know how to change the def userKey = authContext.getUser().getKey() and instead specify a specific user? I don't get how to find the proper value for setUserkey() if I want to specify a specific user. Thanks for all help - soon there.

1 vote
Andreas Knecht Community Champion Nov 21, 2016

There's now a very easy to configure way to transition stories when their epic changes (and vice versa) using Automation for JIRA!

You can easily modify related issues (such as parents, stories, sub-tasks, epics, linked issues and even JQL) using our related issues action and condition:

transition-stories.png

(this example moves stories in the epic to "To Do" but that could be changed to anything really)

For more details see https://blog.codebarrel.io/synchronize-parent-and-sub-task-issues-with-automation-for-jira-bdcca6c9d453

Hi Geert and thank you

I will try using your code and adopt it. I let you know how it worked out.

@Jamie Echlin [Adaptavist]: Is there a way of using the script runners Fast-track transition but transition another issue for this? Or a post function using JQL queries?

Hi again

I have still not solved this issue but I'm wondering if there is a way to fire an event for all related issues to an epic? Then I can use the fast-track transistion listener on the related issues.

Suggest an answer

Log in or Sign up to answer
Community showcase
Published Nov 27, 2018 in Portfolio for Jira

Introducing a new planning experience in Portfolio for Jira (Server/DC)

In the past, Portfolio for Jira required a high degree of detail–foresight that was unrealistic for many businesses to   have–in   order to produce a reliable long-term roadmap. We're tur...

2,707 views 17 21
Read article

Atlassian User Groups

Connect with like-minded Atlassian users at free events near you!

Find a group

Connect with like-minded Atlassian users at free events near you!

Find my local user group

Unfortunately there are no AUG chapters near you at the moment.

Start an AUG

You're one step closer to meeting fellow Atlassian users at your local meet up. Learn more about AUGs

Groups near you