How to use cyle? Edited

Using Adaptavist ScriptRuner

I need to check all opens issues(add value(from parent epic) to the "Deadline" field if it is null) in all open epics in project "BUIS".

I think, this can to use cycle(find epics), but i dont know how. Please, write solution or examples.

2 answers

Hey Andrey!

I am unsure of the "cicle" method that you are referring to, but I believe the easiest way to do this would actually be to just run a stand-alone script in the ScriptRunner Script Console.  

As far as the script goes, you can pick one of two options for traversing the project's issues. Either you run through all of the issues in a project and check their Epic Link custom field to obtain the linked epic. Or you go through and find every epic in a project and then look at all of that epic's linked issues. I've gone ahead and coded up the two variants for you and will paste them below:

Traverse all issues and look at Epic Link field

import com.atlassian.jira.component.ComponentAccessor

//Get necessary managers
def projectManager = ComponentAccessor.projectManager
def issueManager = ComponentAccessor.issueManager
def cfm = ComponentAccessor.customFieldManager

//Get issues in specified project
def project = projectManager.getProjectByCurrentKey("BUIS")
def issueIdsInProject = issueManager.getIssueIdsForProject(project.id)

//Traverse all issues in aforementioned project
issueIdsInProject.each{
def currentIssue = issueManager.getIssueObject(it)

//Check that issue is in status "Open"
if(currentIssue.status.name == "Open")
{
//Get the Deadline and Epic Link as well as their values for the current issue
def deadlineCF = cfm.getCustomFieldObjectByName("Deadline")
def epicLink = cfm.getCustomFieldObjectByName("Epic Link")

def deadlineValue = currentIssue.getCustomFieldValue(deadlineCF)
def epicLinkValue = currentIssue.getCustomFieldValue(epicLink)

//If the issue is linked to an epic and does not have a Deadline value
if(!(deadlineValue) && epicLinkValue)
{
//Set the issues Deadline value to it's epic's
def epicDeadline = epicLinkValue.getCustomFieldValue(deadlineCF)
currentIssue.setCustomFieldValue(epicDeadline)
}
}
}

Traverse Epics and get linked issues

import com.atlassian.jira.component.ComponentAccessor

//Get necessary managers
def projectManager = ComponentAccessor.projectManager
def issueManager = ComponentAccessor.issueManager
def issueLinkManager = ComponentAccessor.issueLinkManager
def cfm = ComponentAccessor.customFieldManager

//Get issues in specified project
def project = projectManager.getProjectByCurrentKey("BUIS")
def issueIdsInProject = issueManager.getIssueIdsForProject(project.id)

//Traverse all issues in aforementioned project
issueIdsInProject.each{
def currentIssue = issueManager.getIssueObject(it)

//Check that issue is an Open Epic
if(currentIssue.issueType.name == "Epic" && currentIssue.status.name == "Open")
{
//Get all of the Epic's Epic-Story Links
issueLinkManager.getOutwardLinks(it).each{
if(it.issueLinkType.name == "Epic-Story Link")
{
//Get the linked mutable issue object and check that it is Open as well
def linkedIssue = issueManager.getIssueObject(it.destinationObject.id)

if(linkedIssue.status.name == "Open")
{
def deadlineCF = cfm.getCustomFieldObjectByName("Deadline")
//Check if the linked issue has a set Deadline
if(!(linkedIssue.getCustomFieldValue(deadlineCF)))
{
//If no set Deadline is found, set the linked issue's Deadline to that of the Epic's
def epicDeadlineValue = currentIssue.getCustomFieldValue(deadlineCF)
linkedIssue.setCustomFieldValue(epicDeadlineValue)
}
}
}
}
}
}

Let me know if everything I've included in this answer makes sense and if you need me help figuring anything out! And when running the scripts in the console, ignore any errors by the static type checker. :D

Aidan

 Hi, Aidan.

I have question(upload image in next message)

Whiсh class i need to add in import in first script?

Hey again Andrey!

I believe you can ignore the errors that you are getting in the below screenshot. Those are errors thrown by the static type checker, as it is unable to discern the returned type of the epicLinkValue variable.

Try running the script regardless of the errors and see if it still works for you.

Aidan :)

Thank you, Aidan, its working.. But only if issues in project(BUIS), what to do if in differents(epics in BUIS and issues in others )?

Please, give me new consult, how to do conditions correct - If issue not containt component  "Поддержка" and not have other components.

No problem!

If you want to execute the script on a different project, all you need to do is change this line of code to contain a different project's key:

def project = projectManager.getProjectByCurrentKey("BUIS")

As far as your other request, where are you wanting to put those conditions? What is the condition meant to do? Are you saying to only copy the Deadline field from the Epic if the issue contains on that component? (I'm just asking for context)

Aidan :D

Hi, Aidan

I got new extra conditions for thise script, from busines. :(

All conditions:

1. Epics in one project(BUIS), issues in others projects.

2. Add component "Сопровождение", if in issue not writed component "Поддержка".

3. "Due Date" field from Epic  will be copied to all issues in the Epic , if it have "null"

4."Заказчик" field from Epic  will be copied to all issues in the Epic, if it have "null"

5. "Deadline" field from Epic will be copied to all issues in the Epic, if it have "null"

Can help?

Hey again Andrey!

With all of those conditions you may have better luck using the first script that I provided you. If you use the first script, the first condition that you've listed will be irrelevant because all of the issues will be accessed via the Epic's links (so you won't need to specify the issue's projects).

Conditions 2-4 are basically the same as 5, which I added in my first reply. So to add those conditions, you'll follow the same process.

I'll go head and make some changes to the script to reflect conditions 2-4. However, it's difficult for me to test these scripts on my own instance because of how specific they are, so I cannot be sure that they will work the first time around. So let me know if you get any errors. Read through the code to make sure everything looks how you expect or how you'd like it to:

import com.atlassian.jira.component.ComponentAccessor

//Get necessary managers
def projectManager = ComponentAccessor.projectManager
def issueManager = ComponentAccessor.issueManager
def issueLinkManager = ComponentAccessor.issueLinkManager
def cfm = ComponentAccessor.customFieldManager
def pcm = ComponentAccessor.projectComponentManager

//Get issues in specified project
def project = projectManager.getProjectByCurrentKey("BUIS")
def issueIdsInProject = issueManager.getIssueIdsForProject(project.id)

//Traverse all issues in aforementioned project
issueIdsInProject.each{
def currentIssue = issueManager.getIssueObject(it)

//Check that issue is an Open Epic
if(currentIssue.issueType.name == "Epic" && currentIssue.status.name == "Open")
{
//Get all of the Epic's Epic-Story Links
issueLinkManager.getOutwardLinks(it).each{
if(it.issueLinkType.name == "Epic-Story Link")
{
//Get the linked mutable issue object and check that it is Open as well
def linkedIssue = issueManager.getIssueObject(it.destinationObject.id)
def projectComponents = pcm.findAllForProject(linkedIssue.projectId)

if(linkedIssue.status.name == "Open")
{
def componentsOfIssue = linkedIssue.components
def componentNames = componentsOfIssue.collect{it.name}
if(!("Поддержка" in componentNames))
{
def componentToAdd = componentsOfIssue.find{it.name == "Сопровождение"}
componentsOfIssue << componentToAdd
linkedIssue.setComponent(componentsOfIssue)
}

def deadlineCF = cfm.getCustomFieldObjectByName("Deadline")
//Check if the linked issue has a set Deadline
if(!(linkedIssue.getCustomFieldValue(deadlineCF)))
{
//If no set Deadline is found, set the linked issue's Deadline to that of the Epic's
def epicDeadlineValue = currentIssue.getCustomFieldValue(deadlineCF)
if(epicDeadlineValue)
{
linkedIssue.setCustomFieldValue(deadlineCF, epicDeadlineValue)
}
}

//If there is no due date on the linked issue, set it from the Epic's
if(!(linkedIssue.dueDate))
{
if(currentIssue.dueDate)
{
linkedIssue.setDueDate(currentIssue.dueDate)
}
}

//Check if Заказчик CF is present on the linked issue and set from the Epic's if it is not
def customField = cfm.getCustomFieldObjectByName("Заказчик")
if(!(linkedIssue.getCustomFieldValue(customField)))
{
def customFieldValue = currentIssue.getCustomFieldValue(customField)
if(customFieldValue)
{
linkedIssue.setCustomFieldValue(customField, customFieldValue)
}
}
}
}
}
}
}

Adian, script working without errors.

But issues in other projects(not BUIS) not changing. (

DueDate, Заказчик(user) still empty.

Hey again,

Could you give me a bit more detail on how all of these issues are connect/linked? Are all of the issues that you are wanting to change in epics? And if so, what are the ways in which they are linked?

For example - epic from AFT, issues from CC. I started script before

Снимок2.PNGСнимок1.PNGСнимок.PNG

AH yes! Ok sooooooo the script that I provided you with will ONLY access epics that are in the specified project and all of the issues attached to those epics. Were you wanting to execute this script on a set of projects or all of them? 

If you'd like to operate on a set of projects, you only need to add a couple of lines of code. You need to wrap everything after the managers in an "each" loop that loops over a list of project keys:

import com.atlassian.jira.component.ComponentAccessor

//Get necessary managers
def projectManager = ComponentAccessor.projectManager
def issueManager = ComponentAccessor.issueManager
def issueLinkManager = ComponentAccessor.issueLinkManager
def cfm = ComponentAccessor.customFieldManager
def pcm = ComponentAccessor.projectComponentManager

def projectKeys = ["BUIS","Other project key","Other project key","Other project key"] //SET THE PROJECT KEYS HERE

projectKeys.each{
//Get issues in specified project
def project = projectManager.getProjectByCurrentKey(it)
def issueIdsInProject = issueManager.getIssueIdsForProject(project.id)

//Traverse all issues in aforementioned project
issueIdsInProject.each{
def currentIssue = issueManager.getIssueObject(it)

//Check that issue is an Open Epic
if(currentIssue.issueType.name == "Epic" && currentIssue.status.name == "Open")
{
//Get all of the Epic's Epic-Story Links
issueLinkManager.getOutwardLinks(it).each{
if(it.issueLinkType.name == "Epic-Story Link")
{
//Get the linked mutable issue object and check that it is Open as well
def linkedIssue = issueManager.getIssueObject(it.destinationObject.id)
def projectComponents = pcm.findAllForProject(linkedIssue.projectId)

if(linkedIssue.status.name == "Open")
{
def componentsOfIssue = linkedIssue.components
def componentNames = componentsOfIssue.collect{it.name}
if(!("Поддержка" in componentNames))
{
def componentToAdd = componentsOfIssue.find{it.name == "Сопровождение"}
componentsOfIssue << componentToAdd
linkedIssue.setComponent(componentsOfIssue)
}

def deadlineCF = cfm.getCustomFieldObjectByName("Deadline")
//Check if the linked issue has a set Deadline
if(!(linkedIssue.getCustomFieldValue(deadlineCF)))
{
//If no set Deadline is found, set the linked issue's Deadline to that of the Epic's
def epicDeadlineValue = currentIssue.getCustomFieldValue(deadlineCF)
if(epicDeadlineValue)
{
linkedIssue.setCustomFieldValue(deadlineCF, epicDeadlineValue)
}
}

//If there is no due date on the linked issue, set it from the Epic's
if(!(linkedIssue.dueDate))
{
if(currentIssue.dueDate)
{
linkedIssue.setDueDate(currentIssue.dueDate)
}
}

//Check if Заказчик CF is present on the linked issue and set from the Epic's if it is not
def customField = cfm.getCustomFieldObjectByName("Заказчик")
if(!(linkedIssue.getCustomFieldValue(customField)))
{
def customFieldValue = currentIssue.getCustomFieldValue(customField)
if(customFieldValue)
{
linkedIssue.setCustomFieldValue(customField, customFieldValue)
}
}
}
}
}
}
}
}

If instead you'd like to run over ALL project, you would only need to change one line. Instead of initializing the projectKeys variable to be a list of keys, you would just get all of the project keys via the ProjectManager:

def projectKeys = projectManager.getProjects().collect{it.key}

Try whichever one of those out that you feel is appropriate and let me know if that does it for you! :)

Aidan (Thanks for being so patient with me) 

Hi, Aidan.

When i choose all projects - get timeout error.

When i choose projects, it still not working ..

We have one project(BUIS) with analitics issues and epics, from thises epics we add issues in programmers project(CC). And i dont to change issues in CC, wich not have parent epics in BUIS

 

Thank you for help. It working correct.

Suggest an answer

Log in or Sign up to answer
Atlassian Community Anniversary

Happy Anniversary, Atlassian Community!

This community is celebrating its one-year anniversary and Atlassian co-founder Mike Cannon-Brookes has all the feels.

Read more
Community showcase
Bridget Sauer
Published Thursday in Marketplace Apps

Calling all developers––You're invited to Atlas Camp 2018

 Atlas Camp   is our developer event which will take place in Barcelona, Spain  from the 6th -7th of   September . This is a great opportunity to meet other developers and get n...

78 views 0 5
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