Using Scriptrunner, I want to use the workflow condition "Linked issues condition" to transition an issue based on the resolution of linked issues. The problem is that that built-in capability doesn't specific by issue type or by project.
For context, we have Feature issue types in project ABC, that uses link type "derivation". So a Feature can have an inward direction called "derivation is", and that's where all the child issues are under. But our Feature can have that same link type for different issue types and some to different projects.
We want so that if a Feature has derived issue types Story or Spike, within the same project as the Feature, and if those child issues are Done, then the Feature can be done.
I'm trying to use Custom script condition. And this goes under the Feature workflow in project ABC.
import com.atlassian.jira.component.ComponentAccessor
import com.atlassian.jira.issue.link.IssueLink
def issueTypes = ["Story","Spike"]
def projectABC = ComponentAccessor.getProjectManager().getProjectObjByKey("ABC")
def issueLinkManager = ComponentAccessor.getIssueLinkManager()
def parentLink = "derivation is"
def done = ["Done","OBE"]
for(IssueLink derivedLink in issueLinkManager.getOutwardLinks(issue.id)) {
if (derivedLink.getIssueLinkType().getName() == parentLink) {
def linkedIssue = derivedLink.getSourceObject()
def linkType = linkedIssue.getIssueType().getName()
if(linkedIssue.issueType.name == issueTypes && linkedIssue == projectABC && linkedIssue.getStatus().name != done) {
passesCondition = false
}
}
I tried switch Inward and Outward direction, and tried grouping conditions and still doesn't work. I test it by viewing this:
BEOFRE
Feature-123
>parent link "derivation is"
-Story << not done, so Feature cannot transition to done
-Spike << is done
-Bug << different issue type, so ignore
-Story << under different project, so ignore
AFTER
Feature-123
>parent link "derivation is"
-Story << now is done, so Feature can transition to done
-Spike << is done
-Bug << different issue type, so ignore
-Story << under different project, so ignore
Hi @Diana Gorv
The clause
linkedIssue.issueType.name == issueTypes
is trying to compare a single string to an array of strings and this will always fail to match.
Try using
issueTypes.contains(linkedIssue.issueType.name)
Similarly
linkedIssue == projectABC
seems to be comparing an issue to a project object. You will need to compare to the issues project. I don't have the exact syntax to hand. It will something linkedIssue.getProjectObject()
Hi @Tom Lister so far I've been unlucky.
I've tried
if(issueTypes.contains(linkedIssue.issueType.name) &&
issueTypes.contains(linkedIssue.getProjectObject().key == projectABC) &&
linkedIssue.getStatus().name != done)
and I've tried
if(linkedIssue.getComponents().contains(issueTypes) &&
linkedIssue.getComponents().contains(projectABC) &&
linkedIssue.status.name !=done)
But I still can't get it to work. Is it possible this kind of mapping requirements might be better in listeners?
p.s. i meant to type this under "reply". the first comment i had typed accidentally under "suggest an answer"
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Hi @Diana Gorv
in the first example
if(issueTypes.contains(linkedIssue.issueType.name) &&
issueTypes.contains(linkedIssue.getProjectObject().key == projectABC) &&
linkedIssue.getStatus().name != done)
will fail because you are asking if the issue types list contain the boolean result of linkedIssue.getProjectObject().key == projectABC
and
linkedIssue.getStatus().name != done
Would compare the name to an array of status names which will fail
In the second sample
if(linkedIssue.getComponents().contains(issueTypes) &&
linkedIssue.getComponents().contains(projectABC) &&
linkedIssue.status.name !=done)
you comparing the list of components to a project object. This fail.
This is difficult to debug by question and answer. I would definitely recommend adding log statements until you are sure of the output. This will confirm the values you are passing and whether the compares are correct e.g.
log.info("***IssueType: " + linked.issueType.name + " " + issueTypes.contains(linkedIssue.issueType.name)
I think the form you are trying to get to is
if (
issueTypes.contains(linkedIssue.issueType.name) &&
linkedIssue.getProjectObject().key == projectABC.key &&
done.contains(linkedIssue.getStatus().name)
)
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Hi @Tom Lister
I think what I was aiming for was something similar to this https://community.atlassian.com/t5/Jira-questions/Validator-script-to-check-status-of-all-linked-issues-before/qaq-p/427966
For some reason the logging wouldn't show in Conditions so I tried on Validators to test the logging at the debug level. I've tried as suggested, using all my conditions under 1 IF statement, and I even tried multi IF statements. The debug logs would tell me the issue types are correct, and its under the right link name, so it possible I'm trying to put too many condition criteria.
I'll mark this as answered, or really obe, but I'll discuss with my team. I appreciate your help!
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Hi @Diana Gorv
Thanks for the answer brownie point :-)
debugging scriptrunner is quite difficult. If you have access to the server log files you should be able to find the log output. I always put some tag at the front so I can find them
log.info("***...
I have often changed to log4j.properties to redirect logs to a separate files. I can post some info on doing that.
A simpler way to test small pieces of script is in the console although you will not see the same inbuilt variables.
Try this as an example to play around with this case and get logging output. I've used logit.warn as I could see that was the logging level set on my server.
import com.atlassian.jira.component.ComponentAccessor
import com.atlassian.jira.issue.link.IssueLink
import org.apache.log4j.Logger
import org.apache.log4j.Level
Logger logit = Logger.getRootLogger()
logit.warn logit.getLevel()
def issueManager = ComponentAccessor.issueManager
def issueKey = 'SCR-1'
def issue = issueManager.getIssueObject(issueKey)
assert issue: "Could not find issue with key $issueKey"
def issueTypes = ["Story","Spike"]
def projectABC = ComponentAccessor.getProjectManager().getProjectObjByKey("ABC")
def issueLinkManager = ComponentAccessor.getIssueLinkManager()
def parentLink = "derivation is"
def done = ["Done","OBE"]
logit.warn("*** link: " + issueLinkManager.getOutwardLinks(issue.id))
for(IssueLink derivedLink in issueLinkManager.getOutwardLinks(issue.id)) {
if (derivedLink.getIssueLinkType().getName() == parentLink) {
def linkedIssue = derivedLink.getSourceObject()
def linkType = linkedIssue.getIssueType().getName()
if(linkedIssue.issueType.name == issueTypes && linkedIssue == projectABC && linkedIssue.getStatus().name != done) {
logit.warn false
}
}
}
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
I've tried
if(issueTypes.contains(linkedIssue.issueType.name) &&
issueTypes.contains(linkedIssue.getProjectObject().key == projectABC) &&
linkedIssue.getStatus().name != done)
and I've tried
if(linkedIssue.getComponents().contains(issueTypes) &&
linkedIssue.getComponents().contains(projectABC) &&
linkedIssue.status.name !=done)
But I still can't get it to work. Is it possible this kind of mapping requirements might be better in listeners?
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.