How to synchronize fields between epics and issues in Jira with Scriptrunner?

550 Views Asked by At

Let us assume a typical software project in Jira that uses Issues, Subtasks and Epics, with a custom field called "Customer" that can be set on any issue or the Epic. I want to have this field synchronized, so that its value for any tickets get automatically set to the highest parent of the hierarchy, up to the epics. How to achieve that with ScriptRunner for Jira?

1

There are 1 best solutions below

0
On

This can be done with the following listener:

import com.atlassian.jira.component.ComponentAccessor
import com.atlassian.jira.event.type.EventDispatchOption
import com.atlassian.jira.issue.Issue
import com.atlassian.jira.issue.MutableIssue
import com.atlassian.jira.issue.link.IssueLink

def issue = event.issue as MutableIssue

def customFieldManager = ComponentAccessor.customFieldManager
def issueManager = ComponentAccessor.issueManager
def issueLinkManager = ComponentAccessor.issueLinkManager
def customField = customFieldManager.getCustomFieldObjectsByName('Customer').first()
def epicLink = customFieldManager.getCustomFieldObjectsByName('Epic Link').first()
def EPIC_STORY_LINK = "Epic-Story Link"

def issuesToUpdate = [] as ArrayList<Issue>

def valueFromTop = null
if (issue.issueType.name == 'Epic') {
    // The issue is an epic. Propagate the custom field value down
    valueFromTop = issue.getCustomFieldValue(customField)
    issueLinkManager.getOutwardLinks(issue.id).find {
            it.issueLinkType.name == EPIC_STORY_LINK
        }.each { IssueLink it1 ->
        issuesToUpdate.addAll(it1.destinationObject)
        it1.destinationObject.subTaskObjects.findAll { it2 ->
            issuesToUpdate.addAll(it2)
        }
    }
}
else {
    // Normal issue. Look up to find the reference issue to get the value from.
    def issueIterator = issue
    while ( true ) {
        def value = issueIterator.getCustomFieldValue(customField)
        if ( value ) {
            valueFromTop = value
        }
        issuesToUpdate.addAll(issueIterator)
        if ( issueIterator.parentObject ) {
            issueIterator = issueIterator.parentObject
        }
        else {
            break
        }
    }
    // Check if the parent issue is an Epic.
    issueLinkManager.getInwardLinks(issueIterator.id).find {
            it.issueLinkType.name == EPIC_STORY_LINK
        }.each { IssueLink epicIssueLink ->
        // Get the value from the Epic
            valueFromTop = epicIssueLink.sourceObject.getCustomFieldValue(customField)
    }
    // Add child issues to list
    issue.subTaskObjects.findAll {
        issuesToUpdate.addAll(it)
    }
}

def loggedInUser = ComponentAccessor.jiraAuthenticationContext.loggedInUser
issuesToUpdate.each {
    def mutableTicket = it as MutableIssue
    mutableTicket.setCustomFieldValue(customField, valueFromTop)
    ComponentAccessor.issueManager.updateIssue(loggedInUser, mutableTicket, EventDispatchOption.DO_NOT_DISPATCH, false)
}