Create
cancel
Showing results for 
Search instead for 
Did you mean: 
Sign up Log in
Celebration

Earn badges and make progress

You're on your way to the next level! Join the Kudos program to earn points and save your progress.

Deleted user Avatar
Deleted user

Level 1: Seed

25 / 150 points

Next: Root

Avatar

1 badge earned

Collect

Participate in fun challenges

Challenges come and go, but your rewards stay with you. Do more to earn more!

Challenges
Coins

Gift kudos to your peers

What goes around comes around! Share the love by gifting kudos to your peers.

Recognition
Ribbon

Rise up in the ranks

Keep earning points to reach the top of the leaderboard. It resets every quarter so you always have a chance!

Leaderboard

Come for the products,
stay for the community

The Atlassian Community can help you and your team get more value out of Atlassian products and practices.

Atlassian Community about banner
4,464,962
Community Members
 
Community Events
176
Community Groups

Validator to enforce all linked issues in Epic to be closed before closing the Epic

Hi,
I got the following script (works) that makes sure all the linked issues to epic are closed.
If not the Epic cant get closed.
I want to limit it to a specific link type: ("Issues in Epic").

Does anyone know how to make it happen?

 

The code:

 

import com.atlassian.jira.component.ComponentAccessor
import com.atlassian.jira.issue.link.IssueLink
import com.atlassian.jira.issue.link.IssueLinkManager
import com.opensymphony.workflow.InvalidInputException
     
// Allow logging for debug and tracking purposes
import org.apache.log4j.Level
import org.apache.log4j.Logger
     
// Script code for easy log identification
String scriptCode = "Check all issues in Epics are Done -"
     
// Setup the log and leave a message to show what we're doing
Logger logger = log
logger.setLevel( Level.ERROR )
logger.debug( "$scriptCode Triggered by $issue.key" )

def passesCondition = true
if (issue.issueType.name == 'Epic')
   {
     IssueLinkManager issueLinkManager = ComponentAccessor.issueLinkManager
     def found = issueLinkManager.getOutwardLinks(issue.id).any
       {
       it?.destinationObject?.getStatus().getName() != 'Done' &&
           it?.destinationObject?.getIssueType().getName()  != 'Epic'
       }
       logger.debug( "$scriptCode Found =  $found " )
       if (found) {
           logger.debug( "$scriptCode return false" )
           passesCondition = false
           invalidInputException = new InvalidInputException("Please make sure all linked issues are in 'Done' status")
       } else {
           logger.debug( "$scriptCode return true" )
       passesCondition = true
       }
   }
// Always allow all other issue types to execute this transition
   else
   {
       logger.debug( "$scriptCode Not Epic return true")
       passesCondition = true
   }

 

2 answers

1 accepted

1 vote
Answer accepted

Hi @Etai Leers,

from your last feedback, I think you could try changing in your original code the line:

def found = issueLinkManager.getOutwardLinks(issue.id).any

 with this:

def found = issueLinkManager.getOutwardLinks(issue.id).findAll { it.issueLinkType.name == 'Epic-Story Link' }.any

Unfortunately not working..

Please could you run this in ScriptRunner Console:

import com.atlassian.jira.component.ComponentAccessor

def issue = ComponentAccessor.issueManager.getIssueObject("SAM-36")
ComponentAccessor.issueLinkManager.getOutwardLinks(issue.id).each { log.error it.issueLinkType.name }
and report here the logs?
Thanks

Hi @Etai Leers,

you could try changing this code:

{
it?.destinationObject?.getStatus().getName() != 'Done' &&
it?.destinationObject?.getIssueType().getName() != 'Epic'
}

with the following:

{
it?.destinationObject?.status.name != 'Done' &&
it?.destinationObject?.issueType.name != 'Epic' &&
it?.destinationObject?.description == 'Issues in Epic'
}

 

Now its not working it all :) 
(When I replace between the code snippets).

Ok, and what happens if you replace with this:

{
it?.destinationObject?.status.name != 'Done' &&
it?.destinationObject?.issueType.name != 'Epic' &&
it?.sourceObject?.description == 'Issues in Epic'
}

?

Still not doing the desired behavior.

Ok, I need more elements to help you.

Please, could you report what you see in the Issue Linking page (YOUR_JIRA_BASE_URL/secure/admin/ViewLinkTypes!default.jspa)?

In particular, the rows where you see 'Issues in Epic' (better if you attach an image).

Thanks

Actually, I don't see the link type in the Jira Issue Linking page.

Its that one:

image.png

@Andrea Pannitti knows how to make it works for "Issues in Epic"?

@Etai Leers , yes, it's an outwardlink of type: 'Epic-Story Link'; for this reason, I asked you to report here the result of this script:

import com.atlassian.jira.component.ComponentAccessor

def issue = ComponentAccessor.issueManager.getIssueObject("SAM-36")
ComponentAccessor.issueLinkManager.getOutwardLinks(issue.id).each { log.error it.issueLinkType.name }

 

2022-06-28 13:06:52,046 DEBUG [support.DefaultListableBeanFactory]: Creating instance of bean 'com.onresolve.scriptrunner.canned.jira.workflow.validators.CustomScriptValidator'

2022-06-28 13:06:52,046 DEBUG [support.DefaultListableBeanFactory]: Returning cached instance of singleton bean 'scriptRunnerImpl'

2022-06-28 13:06:52,046 DEBUG [support.DefaultListableBeanFactory]: Returning cached instance of singleton bean 'configuredValidatorFactory' 2022-06-28 13:06:52,046 DEBUG [support.DefaultListableBeanFactory]: Returning cached instance of singleton bean 'configuredObjectMapper'

2022-06-28 13:06:52,046 DEBUG [support.DefaultListableBeanFactory]: Autowiring by type from bean name 'com.onresolve.scriptrunner.canned.jira.workflow.validators.CustomScriptValidator' via constructor to bean named 'scriptRunnerImpl'

2022-06-28 13:06:52,046 DEBUG [support.DefaultListableBeanFactory]: Autowiring by type from bean name 'com.onresolve.scriptrunner.canned.jira.workflow.validators.CustomScriptValidator' via constructor to bean named 'configuredValidatorFactory'

2022-06-28 13:06:52,046 DEBUG [support.DefaultListableBeanFactory]: Autowiring by type from bean name 'com.onresolve.scriptrunner.canned.jira.workflow.validators.CustomScriptValidator' via constructor to bean named 'configuredObjectMapper'

2022-06-28 13:06:52,046 DEBUG [support.DefaultListableBeanFactory]: Finished creating instance of bean 'com.onresolve.scriptrunner.canned.jira.workflow.validators.CustomScriptValidator'

2022-06-28 13:06:52,069 DEBUG [acme.ListLinks]: TEST

Payload:

@Andrea Pannitti 

{"canned-script""com.onresolve.scriptrunner.canned.jira.workflow.validators.CustomScriptValidator (java.lang.String)", "class.name": "com.onresolve.jira.groovy.GroovyValidator (java.lang.String)", "issue": "SAM-35 (com.atlassian.jira.issue.IssueImpl)", "transientVars": { "issue": "SAM-35 (com.atlassian.jira.issue.IssueImpl)", "configuration": "com.opensymphony.workflow.config.DefaultConfiguration@66b1b2fb", "proj": "Project: SAM (com.atlassian.jira.project.ProjectImpl)", "project": "[GenericEntity:Project][name,Sample][assigneetype,3][description,][projecttype,software][id,10600][counter,26][avatar,10324][originalkey,SAM][url,null][lead,automation4jira][key,SAM] (org.ofbiz.core.entity.GenericValue)", "currentSteps": "[SimpleStep@6[owner=, actionId=0, status=Done]] (java.util.ArrayList)", "store": "com.opensymphony.workflow.spi.ofbiz.OfbizWorkflowStore@e97f036", "descriptor": "com.atlassian.jira.workflow.ImmutableWorkflowDescriptor@48aede84", "userKey": "etai.leers (java.lang.String)", "originalAssigneeId": "null (org.codehaus.groovy.runtime.NullObject)", "entry": "com.opensymphony.workflow.spi.SimpleWorkflowEntry@20490f0c", "context": "com.opensymphony.workflow.basic.BasicWorkflowContext@d83d385", "originalissueobject": "SAM-35 (com.atlassian.jira.issue.IssueImpl)", "actionId": "31 (java.lang.Integer)", "pkey": "SAM (java.lang.String)", "transaction": "com.atlassian.jira.transaction.TransactionSupportImpl$TransactionImpl@7a95eec6" }, "log": "org.apache.log4j.Logger@2c8b3cf0", "originalIssue": "SAM-35 (com.atlassian.jira.issue.IssueImpl)", "invalidInputException": "null (org.codehaus.groovy.runtime.NullObject)", "\u00a3beanContext": "com.onresolve.scriptrunner.beans.BeanFactoryBackedBeanContext@698c9822" }

@Etai Leers,

sorry, I meant what the reported script prints, once run from Script console?

Nope it runs from a workflow validator.
Once trying to make a transition from "In progress" status to "Done" status. 😊

@Andrea Pannitti 

@Etai Leers,

The test I proposed above was to understand whether or not an issuelinktype called Epic-Story Link is present on the issue you try to validate.

Suggest an answer

Log in or Sign up to answer
TAGS

Atlassian Community Events