Forums

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

Sync fixVersion from parent Epic to children stories

helen levich
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.
July 11, 2019

I have ScriptRunner script for custom listener that sets fixVersion on story from parent Epic on a creation of story. It works fine.

I'm wondering if it can be modified to update fixVersion on all stories if fixVersion is changed on Epic?

Any ideas would be greatly appreciated. Thank you

import com.atlassian.jira.ComponentManager
import com.atlassian.jira.issue.CustomFieldManager
import com.atlassian.jira.issue.MutableIssue
import com.atlassian.jira.issue.customfields.CustomFieldType
import com.atlassian.jira.issue.fields.CustomField
import org.apache.log4j.Category
import com.atlassian.jira.component.ComponentAccessor;
import com.atlassian.jira.issue.Issue;
import com.atlassian.jira.issue.ModifiedValue;
import com.atlassian.jira.issue.MutableIssue;
import com.atlassian.jira.issue.fields.layout.field.FieldLayoutItemImpl;
import com.atlassian.jira.issue.util.DefaultIssueChangeHolder;
import com.atlassian.jira.util.ImportUtils;
import com.atlassian.jira.project.version.VersionManager;
import com.atlassian.jira.issue.index.IssueIndexingService;

log.setLevel(org.apache.log4j.Level.INFO);
log.info("Script Runner: On IssueCreated -> TEST JCG");

def issue = event.getIssue();
CustomFieldManager customFieldManager = ComponentAccessor.getCustomFieldManager();
def issueManager = ComponentAccessor.getIssueManager();
def versionManager = ComponentAccessor.getVersionManager();

// Check if Issue Type is Story
if (issue.getIssueType().getName() == "Story" ) {

// Get Custom Field as string (Epic Link)
def epicLinkCf = customFieldManager.getCustomFieldObjectByName("Epic Link")

// Get Custom Field Value as String
CustomField epicLink = customFieldManager.getCustomFieldObjectByName('Epic Link');
String EpicName = issue.getCustomFieldValue(epicLink);

if(EpicName){
// Get Epic from Issue
def epicIssue = issue.getCustomFieldValue(epicLinkCf) as Issue

// Get Fix Version from Epic
def currentValue = epicIssue.getFixVersions()
log.info("Set version to: " + currentValue);
// Set Fix Version to Story
def collection = versionManager.getFixVersionsFor(issue);
log.info("Current fixed versions: " + collection);
versionManager.updateIssueFixVersions(issue, currentValue);
// versionManager.updateIssueAffectsVersions(issue, currentValue);
collection = versionManager.getFixVersionsFor(issue);
log.info("New fixed versions: " + collection);

boolean wasIndexing = ImportUtils.isIndexIssues();
IssueIndexingService indexing = (IssueIndexingService) ComponentAccessor.getComponent(IssueIndexingService.class)
indexing.reIndex(issue)
ImportUtils.setIndexIssues(wasIndexing)
}
}

 

 

I came up with this script that does not give any errors, but does not update fixVersions from epic to story either. :(

import com.atlassian.jira.ComponentManager
import com.atlassian.jira.issue.CustomFieldManager
import com.atlassian.jira.issue.MutableIssue
import com.atlassian.jira.issue.customfields.CustomFieldType
import com.atlassian.jira.issue.fields.CustomField
import org.apache.log4j.Category
import com.atlassian.jira.component.ComponentAccessor;
import com.atlassian.jira.issue.Issue;
import com.atlassian.jira.issue.ModifiedValue
import com.atlassian.jira.issue.MutableIssue
import com.atlassian.jira.issue.fields.layout.field.FieldLayoutItemImpl
import com.atlassian.jira.issue.util.DefaultIssueChangeHolder
import com.atlassian.jira.util.ImportUtils
import com.atlassian.jira.component.ComponentAccessor
import com.atlassian.jira.event.type.EventDispatchOption
import com.atlassian.jira.issue.MutableIssue
import com.atlassian.jira.project.version.VersionManager

def issue = event.issue as MutableIssue
//def issue = event.getIssue() as MutableIssue
//def issue = event.getIssue();
CustomFieldManager customFieldManager = ComponentAccessor.getCustomFieldManager();
def issueManager = ComponentAccessor.getIssueManager();
def versionManager = ComponentAccessor.getVersionManager();

// Check if Issue Type is Story
if (issue.getIssueType().getName() == "Story" ) {

// Get Custom Field as string (Epic Link)
def epicLinkCf = customFieldManager.getCustomFieldObjectByName("Epic Link")

// Get Custom Field Value as String
CustomField epicLink = customFieldManager.getCustomFieldObjectByName('Epic Link');
String EpicName = issue.getCustomFieldValue(epicLink);

if(EpicName){
// Get Epic from Issue
def epicIssue = issue.getCustomFieldValue(epicLinkCf) as Issue

// Get Fix Version from Epic
def currentValue = epicIssue.getFixVersions()
def collection = versionManager.getFixVersionsFor(issue);
log.info("Current fixed versions: " + collection);
versionManager.updateIssueFixVersions(issue, currentValue);
//versionManager.updateIssueAffectsVersions(issue, currentValue);
collection = versionManager.getFixVersionsFor(issue);

// Set Fix Version to Story
issue.setFixVersions(currentValue);

def user = ComponentAccessor.getJiraAuthenticationContext().getLoggedInUser()
issueManager.updateIssue(user, issue, EventDispatchOption.ISSUE_UPDATED, false)

}
}

 

Could you please give a hand?

 

 

2 answers

1 accepted

1 vote
Answer accepted
helen levich
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.
July 25, 2019

With Marc's help, this script runs find in Jira 7. It syncs fixVersions from parent Epic to stories.

import com.atlassian.jira.component.ComponentAccessor;
import com.atlassian.jira.ComponentManager;
import com.atlassian.jira.event.issue.IssueEvent;
import com.atlassian.jira.event.type.EventDispatchOption;
import com.atlassian.jira.issue.CustomFieldManager;
import com.atlassian.jira.issue.customfields.CustomFieldType;
import com.atlassian.jira.issue.fields.CustomField;
import com.atlassian.jira.issue.fields.layout.field.FieldLayoutItemImpl;
import com.atlassian.jira.issue.index.IssueIndexingService;
import com.atlassian.jira.issue.Issue;
import com.atlassian.jira.issue.link.IssueLink;
import com.atlassian.jira.issue.link.IssueLinkManager;
import com.atlassian.jira.issue.ModifiedValue;
import com.atlassian.jira.issue.MutableIssue;
import com.atlassian.jira.issue.util.DefaultIssueChangeHolder;
import com.atlassian.jira.project.version.VersionManager;
import com.atlassian.jira.util.ImportUtils;
import org.apache.log4j.Category;


def issueLinkManager = ComponentAccessor.getIssueLinkManager()
def epicissue = event.issue as MutableIssue

def issueManager = ComponentAccessor.getIssueManager();
def versionManager = ComponentAccessor.getVersionManager();
def user = ComponentAccessor.getJiraAuthenticationContext().getLoggedInUser()

if (epicissue.getIssueType().getName() == "Epic")

issueLinkManager.getOutwardLinks(epicissue.id).each { issueLink ->

if (issueLink.issueLinkType.name == "Epic-Story Link" &&
issueLink.getDestinationObject().getIssueType().name == "Story"
)
{

MutableIssue issue = issueLink.getDestinationObject() as MutableIssue;


def currentValue = epicissue.getFixVersions()


issue.setFixVersions(currentValue);

issueManager.updateIssue(user, issue, EventDispatchOption.ISSUE_UPDATED, false)


boolean wasIndexing = ImportUtils.isIndexIssues();
IssueIndexingService indexing = (IssueIndexingService) ComponentAccessor.getComponent(IssueIndexingService.class)
indexing.reIndex(issue)
ImportUtils.setIndexIssues(wasIndexing)
}
}

Tej
Contributor
September 8, 2020

Hi @helen levich thanks alot for sharing this. 
Mentioned above script only works for update? it is not working at create.

helen levich
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.
September 8, 2020

I used different script on create. Please take a look

import com.atlassian.jira.ComponentManager
import com.atlassian.jira.issue.CustomFieldManager
import com.atlassian.jira.issue.MutableIssue
import com.atlassian.jira.issue.customfields.CustomFieldType
import com.atlassian.jira.issue.fields.CustomField
import org.apache.log4j.Category
import com.atlassian.jira.component.ComponentAccessor;
import com.atlassian.jira.issue.Issue;
import com.atlassian.jira.issue.ModifiedValue;
import com.atlassian.jira.issue.MutableIssue;
import com.atlassian.jira.issue.fields.layout.field.FieldLayoutItemImpl;
import com.atlassian.jira.issue.util.DefaultIssueChangeHolder;
import com.atlassian.jira.util.ImportUtils;
import com.atlassian.jira.project.version.VersionManager;
import com.atlassian.jira.issue.index.IssueIndexingService;

log.setLevel(org.apache.log4j.Level.INFO);
log.info("Script Runner: On IssueCreated -> TEST JCG");

def issue = event.getIssue();
CustomFieldManager customFieldManager = ComponentAccessor.getCustomFieldManager();
def issueManager = ComponentAccessor.getIssueManager();
def versionManager = ComponentAccessor.getVersionManager();

if (issue.getIssueType().getName() == "Story" ) {

// Get Custom Field as string (Epic Link)
def epicLinkCf = customFieldManager.getCustomFieldObjectByName("Epic Link")

// Get Custom Field Value as String
CustomField epicLink = customFieldManager.getCustomFieldObjectByName('Epic Link');
String EpicName = issue.getCustomFieldValue(epicLink);

if(EpicName){
// Get Epic from Issue
def epicIssue = issue.getCustomFieldValue(epicLinkCf) as Issue

// Get Fix Version from Epic
def currentValue = epicIssue.getFixVersions()
log.info("Set version to: " + currentValue);
// Set Fix Version to Story
def collection = versionManager.getFixVersionsFor(issue);
log.info("Current fixed versions: " + collection);
versionManager.updateIssueFixVersions(issue, currentValue);
//versionManager.updateIssueAffectsVersions(issue, currentValue);
collection = versionManager.getFixVersionsFor(issue);
log.info("New fixed versions: " + collection);
// issue.setFixVersions(currentValue);

boolean wasIndexing = ImportUtils.isIndexIssues();
IssueIndexingService indexing = (IssueIndexingService) ComponentAccessor.getComponent(IssueIndexingService.class)
indexing.reIndex(issue)
ImportUtils.setIndexIssues(wasIndexing)
}
}

Tej
Contributor
September 10, 2020

@helen levich I see some errors in above script 

I used this and it worked for create.

import com.atlassian.jira.component.ComponentAccessor
import com.atlassian.jira.issue.CustomFieldManager
import com.atlassian.jira.issue.fields.CustomField
import com.atlassian.jira.issue.Issue;
import com.atlassian.jira.issue.ModifiedValue
import com.atlassian.jira.issue.fields.layout.field.FieldLayoutItemImpl
import com.atlassian.jira.event.type.EventDispatchOption
import com.atlassian.jira.issue.MutableIssue
import com.atlassian.jira.project.version.VersionManager


def issue = event.issue as MutableIssue
CustomFieldManager customFieldManager = ComponentAccessor.getCustomFieldManager();

def issueManager = ComponentAccessor.getIssueManager();
def versionManager = ComponentAccessor.getVersionManager();
def user = ComponentAccessor.getJiraAuthenticationContext().getLoggedInUser()

// Get Custom Field as string (Epic Link)
def epicLinkCf = customFieldManager.getCustomFieldObjectByName("Epic Link")

// Get Custom Field Value as String
CustomField epicLink = customFieldManager.getCustomFieldObjectByName('Epic Link');
String EpicName = issue.getCustomFieldValue(epicLink);

if(EpicName)
{
// Get Epic from Issue
def epicIssue = issue.getCustomFieldValue(epicLinkCf) as Issue

// Get Fix Version from Epic
def currentValue = epicIssue.getFixVersions()
versionManager.updateIssueFixVersions(issue, currentValue);

// Set Fix Version to Story
issue.setFixVersions(currentValue);

issueManager.updateIssue(user, issue, EventDispatchOption.ISSUE_UPDATED, false)
}

0 votes
Bastian Stehmann
Community Champion
July 11, 2019

Hi @helen levich ,

I think this should be possible.

You can check if the version has changed on a epic and if that is the case, get all linked issues and change the version there.

helen levich
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.
July 11, 2019

Thank you, Bastian. 

I'm not sure about syntax of what you are suggesting, could you please give rough idea?

helen levich
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.
July 11, 2019

Thank you, but those links did not help. 

helen levich
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.
July 12, 2019

Came up with following, Still no updates are happening. Could you please help?

 

thank you

 

import com.atlassian.jira.ComponentManager
import com.atlassian.jira.issue.CustomFieldManager
import com.atlassian.jira.issue.MutableIssue
import com.atlassian.jira.issue.customfields.CustomFieldType
import com.atlassian.jira.issue.fields.CustomField
import org.apache.log4j.Category
import com.atlassian.jira.component.ComponentAccessor;
import com.atlassian.jira.issue.Issue;
import com.atlassian.jira.issue.ModifiedValue
import com.atlassian.jira.issue.MutableIssue
import com.atlassian.jira.issue.fields.layout.field.FieldLayoutItemImpl
import com.atlassian.jira.issue.util.DefaultIssueChangeHolder
import com.atlassian.jira.util.ImportUtils
import com.atlassian.jira.component.ComponentAccessor
import com.atlassian.jira.event.type.EventDispatchOption
import com.atlassian.jira.issue.MutableIssue
import com.atlassian.jira.project.version.VersionManager

def issue = event.issue as MutableIssue
//def issue = event.getIssue() as MutableIssue
//def issue = event.getIssue();
CustomFieldManager customFieldManager = ComponentAccessor.getCustomFieldManager();
def issueManager = ComponentAccessor.getIssueManager();
def versionManager = ComponentAccessor.getVersionManager();

// Check if Issue Type is Story
if (issue.getIssueType().getName() == "Story" ) {

// Get Custom Field as string (Epic Link)
def epicLinkCf = customFieldManager.getCustomFieldObjectByName("Epic Link")

// Get Custom Field Value as String
CustomField epicLink = customFieldManager.getCustomFieldObjectByName('Epic Link');
String EpicName = issue.getCustomFieldValue(epicLink);

if(EpicName){
// Get Epic from Issue
def epicIssue = issue.getCustomFieldValue(epicLinkCf) as Issue

// Get Fix Version from Epic
def currentValue = epicIssue.getFixVersions()
def collection = versionManager.getFixVersionsFor(issue);
log.info("Current fixed versions: " + collection);
versionManager.updateIssueFixVersions(issue, currentValue);
//versionManager.updateIssueAffectsVersions(issue, currentValue);
collection = versionManager.getFixVersionsFor(issue);

// Set Fix Version to Story
issue.setFixVersions(currentValue);

def user = ComponentAccessor.getJiraAuthenticationContext().getLoggedInUser()
issueManager.updateIssue(user, issue, EventDispatchOption.ISSUE_UPDATED, false)

}
}

Marc Minten (EVS)
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.
July 16, 2019

I do not really understand you script. You would like to update stories "... if fixVersion is changed on Epic ....". But in your listener script, you validate the issue that changed is... a Story ??? Shouldn't the script listen to EPICs being modified ???

 Next you should use Epic-Story links to find all the Stories in the Epic... And update their FixVersion field.

helen levich
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.
July 16, 2019

Thank you for input Marc. 

The logic is coming from script that is updating fixVersion on story from epic. It works fine on story creation, but not on update. 

import com.atlassian.jira.ComponentManager
import com.atlassian.jira.issue.CustomFieldManager
import com.atlassian.jira.issue.MutableIssue
import com.atlassian.jira.issue.customfields.CustomFieldType
import com.atlassian.jira.issue.fields.CustomField
import org.apache.log4j.Category
import com.atlassian.jira.component.ComponentAccessor;
import com.atlassian.jira.issue.Issue;
import com.atlassian.jira.issue.ModifiedValue;
import com.atlassian.jira.issue.MutableIssue;
import com.atlassian.jira.issue.fields.layout.field.FieldLayoutItemImpl;
import com.atlassian.jira.issue.util.DefaultIssueChangeHolder;
import com.atlassian.jira.util.ImportUtils;
import com.atlassian.jira.project.version.VersionManager;
import com.atlassian.jira.issue.index.IssueIndexingService;

log.setLevel(org.apache.log4j.Level.INFO);
log.info("Script Runner: On IssueCreated -> TEST JCG");

def issue = event.getIssue();
CustomFieldManager customFieldManager = ComponentAccessor.getCustomFieldManager();
def issueManager = ComponentAccessor.getIssueManager();
def versionManager = ComponentAccessor.getVersionManager();

// Check if Issue Type is Story
if (issue.getIssueType().getName() == "Story" ) {

// Get Custom Field as string (Epic Link)
def epicLinkCf = customFieldManager.getCustomFieldObjectByName("Epic Link")

// Get Custom Field Value as String
CustomField epicLink = customFieldManager.getCustomFieldObjectByName('Epic Link');
String EpicName = issue.getCustomFieldValue(epicLink);

if(EpicName){
// Get Epic from Issue
def epicIssue = issue.getCustomFieldValue(epicLinkCf) as Issue

// Get Fix Version from Epic
def currentValue = epicIssue.getFixVersions()
log.info("Set version to: " + currentValue);
// Set Fix Version to Story
def collection = versionManager.getFixVersionsFor(issue);
log.info("Current fixed versions: " + collection);
versionManager.updateIssueFixVersions(issue, currentValue);
// versionManager.updateIssueAffectsVersions(issue, currentValue);
collection = versionManager.getFixVersionsFor(issue);
log.info("New fixed versions: " + collection);

boolean wasIndexing = ImportUtils.isIndexIssues();
IssueIndexingService indexing = (IssueIndexingService) ComponentAccessor.getComponent(IssueIndexingService.class)
indexing.reIndex(issue)
ImportUtils.setIndexIssues(wasIndexing)
}
}

helen levich
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.
July 17, 2019

Hi Marc, I got with this version, but it does not update fixVersions on stories. 

Could you please take a quick look if something what I did not right? Thank you 

import com.atlassian.jira.ComponentManager
import com.atlassian.jira.issue.CustomFieldManager
import com.atlassian.jira.issue.MutableIssue
import com.atlassian.jira.issue.customfields.CustomFieldType
import com.atlassian.jira.issue.fields.CustomField
import org.apache.log4j.Category
import com.atlassian.jira.component.ComponentAccessor;
import com.atlassian.jira.issue.Issue;
import com.atlassian.jira.issue.ModifiedValue;
import com.atlassian.jira.issue.MutableIssue;
import com.atlassian.jira.issue.fields.layout.field.FieldLayoutItemImpl;
import com.atlassian.jira.issue.util.DefaultIssueChangeHolder;
import com.atlassian.jira.util.ImportUtils;
import com.atlassian.jira.project.version.VersionManager;
import com.atlassian.jira.issue.index.IssueIndexingService;
import com.atlassian.jira.event.type.EventDispatchOption
import com.atlassian.jira.issue.link.IssueLink;
import com.atlassian.jira.issue.link.IssueLinkManager;
import com.atlassian.jira.issue.Issue
import com.atlassian.jira.issue.MutableIssue;
import com.atlassian.jira.issue.link.IssueLink;
import com.atlassian.jira.event.issue.IssueEvent;
import com.atlassian.jira.component.ComponentAccessor
//import com.atlassian.jira.event.issue.link.IssueLinkCreatedEvent

def issueLinkManager = ComponentAccessor.getIssueLinkManager()
def epicissue = event.issue

def issueManager = ComponentAccessor.getIssueManager();
def versionManager = ComponentAccessor.getVersionManager();
def user = ComponentAccessor.getJiraAuthenticationContext().getLoggedInUser()

if (epicissue.getIssueType().getName() == "Epic")

issueLinkManager.getOutwardLinks(epicissue.id).each {


if (it.issueLinkType.name == "Epic-Story Link" && it.getDestinationObject().getIssueType().name == "Story") {

def issue = IssueLink.getDestinationObject() as MutableIssue;


def currentValue = epicissue.getFixVersions()
log.info("Set version to: " + currentValue);
// Set Fix Version to Story
def collection = versionManager.getFixVersionsFor(epicissue);
log.info("Current fixed versions: " + collection);
versionManager.updateIssueFixVersions(issue, currentValue);
// versionManager.updateIssueAffectsVersions(issue, currentValue);
collection = versionManager.getFixVersionsFor(issue);
log.info("New fixed versions: " + collection);
//issue.setFixVersions(currentValue);

//issue.setFixVersions(currentValue);

//issueManager.updateIssue(user, issue, EventDispatchOption.ISSUE_UPDATED, false)


boolean wasIndexing = ImportUtils.isIndexIssues();
IssueIndexingService indexing = (IssueIndexingService) ComponentAccessor.getComponent(IssueIndexingService.class)
indexing.reIndex(issue)
ImportUtils.setIndexIssues(wasIndexing)
}
}

Marc Minten (EVS)
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.
July 18, 2019

Hi,

I think your script throws many errors (in your log files), they should help you to fix the issues ! :

In your Epic-Story loop, you refer to "IssueLink" when getting the Story (into "issue"), but IssueLink is not defined!

You should write something like

issueLinkManager.getOutwardLinks(epicissue.id).each {issueLink ->

if (issueLink.issueLinkType.name == "Epic-Story Link" && issueLink.getDestinationObject().getIssueType().name == "Story") {

MutableIssue issue = issueLink.getDestinationObject() as MutableIssue;

...

 I never updated the FixVersions of an issue through the VersionManager neither. No idea what this does (it returns a list of ChangeItemBeans, so I guess you still have to apply them ?).

Better and easier is to work directly on the issue :

issue.setFixVersions(currentValue);

issueManager.updateIssue(user, issue, EventDispatchOption.ISSUE_UPDATED, false)

and remove all the versionManager.getFixVersionsFor() and versionManager.updateIssueFixVersions() stuff...

 

Hope this helps :)

helen levich
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.
July 18, 2019

Hi Marc, 

Thank you very much for your help.  Your suggestions fixed problem. 

helen levich
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.
July 18, 2019

Hi Marc, could you please copy your last reply as an answer not as reply. It seems that I can't accept your post as "Accepted Answer" this way. Thank you for help.

Suggest an answer

Log in or Sign up to answer