Hello Brothers and Sisters, I know that this topic is old as world but I AM JIRA SERVER....
and I have seen 100 articles regarding this but all of them are Cloud oriented.
Simple scenario:
1. I have 1 EPIC
2. EPIC has 20 CHILD Stories and 3 BUGS
3. EPIC has 10 LINKED Stories and 5 BUGS
I need transition validator before EPIC goes to status DONE all
CHILD STORIES, LINKES STORIES
CHILD BUGS, LINKED BUGS
must be resolved/ (Or in particual status i.e. DONE)
If there are orther issueTypes as Child or Link we can ignore their status.
I use JMWE app as well.
Hello @Mateusz Janus
If you review the documentation for JMWE:
https://appfire.atlassian.net/wiki/spaces/JMWE/overview
...and look specifically at the Workflow Extensions > Workflow Validators section
https://appfire.atlassian.net/wiki/spaces/JMWE/pages/462127423/Workflow+Validators
...you will find the Related Issues Status Validator and Linked Issues Status Validator.
https://appfire.atlassian.net/wiki/spaces/JMWE/pages/461406396/Related+Issues+Status+Validator
https://appfire.atlassian.net/wiki/spaces/JMWE/pages/462062626/Linked+Issues+Status+Validator
You can use those to fulfill your requirements.
I encourage you to review the documentation for your apps to see if they provide functions that will meet your needs when questions like this come up.
thanks I found including groovy validator condition <3 appreciate. All works perfect
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Hi, @Mateusz Janus
Since you are on Jira Server, the built-in workflow validators won't cover both child issues and linked issues in a single check. If you have ScriptRunner for Jira Server, you can add a Script Validator to the transition leading to your DONE status in the workflow editor.
The approach is straightforward. In the validator script (Groovy), you grab all issues in the epic using the Epic Link field, then grab all linked issues via the IssueLinkManager. For each collection, you check whether every issue sits in a resolved status (or your specific DONE status). If any issue fails the check, you throw an InvalidInputException with a clear message telling the user which issues still need work.
Here is the core logic. Use ComponentAccessor to get the IssueLinkManager and CustomFieldManager. Find the Epic Link custom field, then query all issues where that field equals your epic key. Loop through them and collect any that are not in a resolved state. Next, iterate through issue.getInwardLinks() and issue.getOutwardLinks() from the IssueLinkManager, filtering by the link types you care about (for example, blocks, relates to, or whatever your project uses). Collect unresolved ones the same way. If either collection is non-empty, throw the InvalidInputException listing the blocking issue keys.
The ScriptRunner documentation covers this pattern in detail under workflow validators, and the Stack Overflow thread linked below has a working Groovy example you can adapt directly to your setup.
https://stackoverflow.com/questions/72161639/jira-custom-script-validator-check-if-linked-issues-in-epic-are-done
// Source - https://stackoverflow.com/a/72201278
// Posted by User1
// Retrieved 2026-02-14, License - CC BY-SA 4.0
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() != null
}
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
}
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.