Simple Scripted Validators
Use the Simple scripted validator to run a simple embedded script that determines whether an issue should be permitted to transition to a particular status within a workflow. This validator allows you to write a Groovy script that can evaluate a wide range of conditions based on issue fields, workflow states, project properties, user permissions, and other contextual data. If validation fails, you can provide a custom error message that explains why the transition is not allowed.
This validator is particularly useful for teams with unique process requirements that need to enforce specific criteria for issue lifecycle management.
Use this validator
- Go to Administration > Issues > Workflows.
- Select Edit on the workflow you want to add this validator to.
- Select the transition you want to add this validator to.
- Under Options, select Validators.
- On the Transition page, select Add validator.
- Select Simple scripted validator.
- Select Add.
Optional: Enter a note that describes the validator. This allows you to identify your workflow validator more easily.
Enter a condition of your choice or enter one of the example scripts displayed further down this page.
If the script returns
true
, the transition is allowed. If it returnsfalse
, the user will not be allowed to perform the transition, and an error message will appear.Enter an error message. This message displays to the user if the condition returns as
false
.Optional: Select the field you want the error message to display against. Leave this option empty if you want the error to display at the top of a transition screen or as a pop-up.
If the transition you are adding this validator to has a screen applied to it, make sure the field you select is on the transition screen.
Select Update.
Select Publish and choose if you want to save a backup copy of the workflow.
You can now test to see if this workflow condition works.
Examples
Each of the examples below is based on specific workflows. Make sure you adjust the examples appropriately to suit your workflow/s.
- Require a fix version if the resolution value is fixed
- Check the resolution value
- Require a comment
- Require a comment when the assignee is changed
- Make sure an option is selected for a custom field
- Make sure no other sub-tasks have the same value for a custom field on issue creation
- Check for attachments
- Check linked issues
- Check the values of a cascading select field
Require a fix version if the resolution value is fixed
You can use the following script to make sure that when a user sets the resolution to Fixed, they also have to add the correct Fix Version:
Make sure the transition includes a Resolve Issue screen (or similar) that includes both the Resolution and Fix version. A step-by-step walkthrough of this example is available on the Validators Tutorial page.
groovyissue.resolution.name != "Fixed" || issue.fixVersions
The above example could be set up as follows:
When a fix version is not provided, the error appears as follows:
Check the resolution value
You can use the following script to validate that a particular resolution value is chosen:
groovyissue.resolution?.name == 'Not an Issue'
You might want to combine this validator with a check on the action name.
The above example could be set up as follows:
When a fix version is not provided, the error appears as follows:
Require a comment
You can use the following script to make sure a comment is added when the resolution of Won’t Fix is selected:
Make sure the transition includes a Resolve Issue screen (or similar) that includes the Resolution. Comments are automatically included in transition screens.
groovyissue.resolution?.name != "Won't Fix" || transientVars["comment"]
The above example could be set up as follows:
When Won't fix is selected, and a comment isn't provided, the error appears as follows:
Require a comment when the assignee is changed
You can check for changed fields by calling methods on originalIssue
. This is the issue as it was before modifications made (during this transition) were applied.
You can use the following script to make sure a comment is added when the assignee is changed during a transition:
Make sure the transition includes a screen that includes the Assignee field. Comments are automatically included in transition screens.
groovyoriginalIssue.assigneeId == issue.assigneeId || transientVars["comment"]
The above example could be set up as follows:
When the assignee is changed and a comment isn't provided, the error appears as follows:
Make sure an option is selected for a custom field
For the following examples, make sure the transition you're applying the validator to includes a screen with the appropriate fields.
- Multiselect values are a collection of
Option
objects. cfValues
is a map-like structure where you can get the value of any custom field on the object. Note that the keys are the field name and not the id.
You can use the following script to make sure a certain option is selected from a multi-select custom field:
groovydef values = cfValues['My Multi Select'] return values && (values*.value as Collection<String>).contains('A field value')
You can use the following script to make sure an option is selected for a single-select or radio button field:
groovycfValues['My Single Select']?.value == "A field value"
You can use the following script as a more complex example, where if the user sets the select-list field Demo to No, you require them to fill in a text field Reason for no demo:
groovycfValues['Demo']?.value != 'No' || cfValues['Reason for No Demo']
You can use the following script to make sure a custom field has a value:
If this condition returns null
or an empty value, it will be evaluated as false
and your chosen error will display.
groovycfValues['Custom Field Name']
Make sure no other sub-tasks have the same value for a custom field on issue creation
You can use the following script to make sure, on the creation of a sub-task, that none of the other sub-tasks of the parent issue have the same value for a particular custom field:
if (!issue.isSubTask()) {
return true
}
def parent = issue.parentObject
def selectedValue = issue.getCustomFieldValue('SelectListA')
!parent.subTaskObjects.any { subtask ->
subtask.getCustomFieldValue('SelectListA') == selectedValue
}
The above example could be set up as follows:
When the option selected is the same as another sub-task for the parent issue, the error appears as follows:
You can put any amount of code in the Condition field. If you don’t explicitly include a return
, the result of the last statement executed defines whether the validator accepts or rejects the transition.
Check for attachments
You can use the following script to check that at least one PDF file is attached:
groovyissue.getAttachments().find { it.filename.endsWith(".pdf") }
The attachment must have existed before the transition was applied to the issue. If you have the Attachments field on the screen, you cannot get newly added attachments in this way.
If your workflow requires specific attachments at certain stages, your validator can either:
tell the user to cancel, add the attachment, and try again (or remove the Attachments field from the screen)
The above example could be set up as follows:
When the transition is attempted without a PDF attachment associated with an issue, the error appears as follows:
Check the status or properties of sub-tasks
The following script examples can be used to check the status or properties of sub-tasks relative to their parent issue during a transition.
Make sure all subtasks are resolved
You can use the following script to make sure that all subtasks of an issue are resolved:
groovyissue.subTaskObjects.every { it.resolution }
Make sure at least one subtask is resolved
You can use the following script to make sure there is at least one subtask is resolved:
groovy!issue.subTaskObjects || issue.subTaskObjects.any { it.resolution }
Make sure the issue has at least one subtask which is In Progress
You can use the following script to make sure the issue has at least one subtask which is In Progress:
groovyissue.subTaskObjects.any { it.status.name == "In Progress" }
To check custom field values of subtasks, cfValues
is not available, so you must use custom field manager to get hold of the custom field object, as shown in Make sure no other sub-tasks have the same value for a custom field on issue creation.
Check properties of the parent issue
For subtasks, you can check properties of the parent by using parentObject
.
You can use the following script to make sure the parent is In Progress:
groovy!issue.isSubTask() || issue.parentObject.status.name == "In Progress"
NullPointerException
if the script is run on an issue that is not a sub-task, as standard issues do not have a parentObject
.Check linked issues
You can use issueLinkManager
to retrieve all outward links. For example, you could use the following to check that the issue has at least one outward Duplicate link:
groovyissueLinkManager.getOutwardLinks(issue.id)*.issueLinkType.name.contains('Duplicate')
You could expand on this example and use it practically. For example, you can use the following script to make sure an issue has at least one outward Duplicate link when the resolution is set to Duplicate:
For the following examples, make sure the transition you're applying the validator to includes a screen with the Resolution field included.
groovyissue.resolution.name != "Duplicate" || issueLinkManager.getOutwardLinks(issue.id)*.issueLinkType.name.contains('Duplicate')
The above example could be set up as follows:
When the transition is resolved as Duplicate and a duplicate issue is not linked, the error appears as follows:
If you have the Issue Links field on a form and want to validate links that occur during this transition, check out the examples on the Validating Attachments/Links in Transitions page.
Check the values of a cascading select field
A cascading select field allows users to select a value from a parent drop-down and a related value from a child drop-down. In the following example scripts, cfValues
is a map-like structure that holds the current values of custom fields.
You can use the following script to check that both drop-downs of a cascading select are filled:
groovycfValues["CascadingSelect"]?.keySet()?.size() == 2
You can use the following script to check that the first dropdown of a cascading select is AAA and the second is a1:
groovyimport com.atlassian.jira.issue.customfields.option.LazyLoadedOption cfValues['CascadingSelect'].values().collect { (it as LazyLoadedOption).value } == ['AAA', 'A1']
You can use the following script to check the first option of the cascading select is AAA:
groovycfValues["CascadingSelect"]?.get(null)?.value == "AAA"
You can use the following script to check the second option of the cascading select is a1:
groovycfValues["CascadingSelect"]?.get("1")?.value == "A1"
The first example above could be set up as follows:
When the transition is attempted and the cascading select does not have both drop-down options filled, the error appears as follows: