I share in this post how to implement a suspect mechanism in Jira using a ScriptRunner listener.
Challenge description
It is common wish for ALM tools to want to flag issues if a parent linked issue was modified, so that you can later make a change impact analysis; this mechanism is called "suspect link or flagging".
R4J Limitations
R4J Jira Add-On for DataCenter/Server provides also a suspect functionality.
Unfortunately, it is a bit hard to customize. For example you can not distinguish between different types of Suspection (like one for reuse, another one for changed after approval)
Also, you can not define a global (=valid for all projects) suspect configuration i.e. you have to duplicate configurations across multiple projects if you need to.
For the cloud version as for now (2022-12-08), you also need to use such an automation. Documentation recommends using Jira Automation.
I present in the next section how to use ScriptRunner for this purpose.
ScriptRunner Solution
You can implement such a mechanism with ScriptRunner using a Listener.
Create a listener for the event 'Issue Updated'.
Script
This script will be triggered if a list of fields was changed (listed in the variable suspectFieldNames).
It will then go through the issues linked via the Reuse link (type inward) and flag/ label these issues with 'suspect_reuse'. The link type and direction as well as the label name are here hard-coded: you might want to adapt them for your need.
A nice comment with references to the parent issue and changed fields will also be written documenting the suspect flagging.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import com.atlassian.jira.component.ComponentAccessor | |
import com.atlassian.jira.issue.Issue | |
import com.atlassian.jira.issue.MutableIssue | |
import com.atlassian.jira.event.type.EventDispatchOption | |
import com.atlassian.jira.issue.label.LabelManager | |
def issue = event.issue | |
// Set Log Level | |
import org.apache.log4j.Logger | |
import org.apache.log4j.Level | |
def log = Logger.getLogger("com.thda.suspect") | |
log.setLevel(Level.DEBUG) | |
// check for IssueType requirement - if no requirement, exit | |
if (!issue.issueType.name.toLowerCase().contains("requirement")) { | |
log.info(issue.key + ": Nothing to suspect: No requirement type. -> exit") | |
return | |
} | |
def suspectFieldNames = ["description","summary"] | |
def commentBody = "" | |
suspectFieldNames.each{ fn-> | |
def change = event?.getChangeLog()?.getRelated("ChildChangeItem")?.find {it.field == fn} | |
if (change) { | |
log.debug "New value for ${fn} : ${change.newstring}" | |
commentBody = commentBody + """ | |
Field '${fn}' changed to: | |
{quote} | |
${change.newstring} | |
{quote} | |
""" | |
} | |
} // end loop on fields | |
//if fields have no change history, exit | |
if (commentBody.isEmpty()) { | |
log.info(issue.key + ": Nothing to suspect: no Suspected Field changed. -> exit") | |
return | |
} | |
commentBody = "Listener labelled the issue with 'suspect_reuse' because it reuses ${issue.key} which had following fields changed:" + commentBody | |
log.info("${issue.key}: Suspect flagging triggered because a suspected Field was changed.") | |
// Loop over linked Reuse: is reused by | |
LabelManager labelManager = ComponentAccessor.getComponent(LabelManager.class) | |
def commentManager = ComponentAccessor.getCommentManager() | |
def issueLinkManager = ComponentAccessor.getIssueLinkManager() | |
def user = ComponentAccessor.jiraAuthenticationContext.loggedInUser | |
// Loop on Links Reuse: is reused by (Inward) | |
def Links = issueLinkManager.getInwardLinks(issue.id) | |
Links.each { | |
if (!it.issueLinkType.name == "Reuse") { return } | |
def linkedIssue = it.sourceObject as MutableIssue | |
// Add Label 'suspect_reuse' to Reusing issue | |
log.info("Sel label 'suspect_reuse' to reused issue ${linkedIssue.key}") | |
labelManager.addLabel(user, linkedIssue.id, 'suspect_reuse', false) | |
// Add a comment | |
commentManager.create(linkedIssue, user, commentBody, true) | |
} // loop on Links |