Hi,
I have a custom field in my JIRA environment named "Technical Thrust" and it is in all epic, task, and story issues. I've written two custom listeners with the goal of ensuring the Technical Thrust field matches between an epic and the stories/tasks linked to that epic.
The goal of the first listener is to copy the Technical Thrust labels (1 or more) from an epic to any task or story that is linked to the epic. This listener executes on an Issue Update event and has a check to see if the issue is an Epic before copying anything.
The goal of the second is to copy labels from an Epic Link in the event that a user updates a child task or story. The idea here is that someone might link an already created story to an epic, and the Technical Thrust would need to be copied from the new Epic Link. Or a user might accidentally delete a Technical Thrust label and the code would automatically replace it.
The problem arises when I make the second listener execute on event: Issue Updated. Currently the code works just fine if the second listener only executes on event: Issue Created. When I add the second event, then go to a task that has an epic link, the JIRA environment locks up and the script remains hanging. Furthermore, when I check the Script Listener log, I see that the script has been called multiple times (with multiple failures). This leads me to believe that I am creating a loop when the second listener executes on an issue update it causes an update that triggers the script to run multiple times.
Any help would be much appreciated.
Thanks.
The first listener executes on event: Issue Updated
import com.atlassian.jira.issue.Issue
import com.atlassian.jira.ComponentManager;
import com.atlassian.jira.issue.link.IssueLink;
import com.atlassian.jira.component.ComponentAccessor;
import com.atlassian.jira.issue.label.LabelManager;
import com.atlassian.jira.issue.IssueManager;
import com.atlassian.jira.issue.util.DefaultIssueChangeHolder
import com.atlassian.jira.issue.ModifiedValue
def issueManager = ComponentAccessor.getIssueManager()
def issue = event.issue
// execute following code if in an EPIC
if (issue.issueType.name == "Epic"){
def customFieldManager = ComponentAccessor.getCustomFieldManager()
def currentUser = ComponentAccessor.getJiraAuthenticationContext().getLoggedInUser()
def labelMgr = ComponentAccessor.getComponent(LabelManager)
// custom field name is Technical Thrust and its ID is 10300
def cfname = "Technical Thrust"
def cf = customFieldManager.getCustomFieldObjects(issue).find {it.name == cfname}
def cfValue = cf.getValue(issue) // return a collection from the epic custom field for technical thrust
if (!cf) {return} // escape if cf does not exist
List<IssueLink> allOutIssueLink = ComponentAccessor.getIssueLinkManager().getOutwardLinks(issue.getId());
for (Iterator<IssueLink> outIterator = allOutIssueLink.iterator(); outIterator.hasNext();) {
IssueLink issueLink = (IssueLink) outIterator.next();
def linkedIssue = issueLink.getDestinationId()
def child = issueManager.getIssueObject(linkedIssue) //as Issue
if (!child) {return} // if null, escape
// clear any labels from the child before updating the labels
def dummy = "" as Set
def childCF = customFieldManager.getCustomFieldObjects(child).find {it.name == cfname}
def changeHolder = new DefaultIssueChangeHolder()
childCF.updateValue(null,child, new ModifiedValue(child.getCustomFieldValue(childCF),dummy),changeHolder)
// loop through each string in cfValue (in the event of multiple labels)
for (String s : cfValue) {
labelMgr.addLabel(currentUser, child.getId(), 10300L, s, false);
}
}
}
The second listener executes on event: Issue Created
import com.atlassian.jira.component.ComponentAccessor
import com.atlassian.jira.issue.Issue
import com.atlassian.jira.issue.MutableIssue
import com.atlassian.jira.issue.label.LabelManager
import com.atlassian.jira.issue.util.DefaultIssueChangeHolder
import com.atlassian.jira.issue.ModifiedValue
def customFieldManager = ComponentAccessor.getCustomFieldManager()
def issue = event.issue as MutableIssue
// execute following code if issue type is task or story
if (issue.issueType.name == "Task" || issue.issueType.name == "Story"){
def currentUser = ComponentAccessor.getJiraAuthenticationContext().getLoggedInUser()
def labelMgr = ComponentAccessor.getComponent(LabelManager)
// custom field name is Technical Thrust and its ID is 10300
def cfname = "Technical Thrust"
def cf = customFieldManager.getCustomFieldObjects(issue).find {it.name == cfname}
def epicCf = customFieldManager.getCustomFieldObjects(issue).find {it.name == 'Epic Link'}
if (!cf || !epicCf) {return} // escape if cf or epicCf do not exist
def epic = issue.getCustomFieldValue(epicCf) as Issue
if (!epic) {return} // escape if epic does not exist
def cfValue = cf.getValue(epic) // return a collection from the epic custom field
// clear any existing labels before updating
def dummy = "" as Set
def changeHolder = new DefaultIssueChangeHolder()
cf.updateValue(null,issue, new ModifiedValue(issue.getCustomFieldValue(cf),dummy),changeHolder)
// loop through each string in cfValue (in the event of multiple labels)
for (String s : cfValue) {
labelMgr.addLabel(currentUser, event.issue.getId(), 10300L, s, false);
}
}