Jira Expressions Library: Examples & Use Cases
This Jira expressions library provides practical examples and real-world use cases for using Jira expressions in workflow conditions and validators.
In this library youβll find ready-to-use Jira expressions for common workflow conditions and validators. Each example below illustrates a practical use case, such as making a field required or restricting transitions based on roles. These Jira expressions can be plugged into your Workflow Validator to enforce custom rules.
Field Conditions
Is required
Condition example: Require an assignee.
issue.assignee != null
Issue must have work logged:
issue.timeSpent != null
Compare Two Field Values
The issue assignee must be different from the issue reporter:
issue.reporter != issue.assignee
Parent value in condition
Assuming that you have a separate workflow for sub-tasks and want to allow a transition in sub-tasks only when the field in its parent has the value "SAP":
issue.parent.customfield_12345 == "SAP"
It depends what kind of field you are referring. If it is of the Select type, then you need to use .value suffix:
issue.parent.customfield_12345.value == "SAP"
It is up to you to find out the id and type of your custom field. In Jira expression field, after issue.parent. start typing the name of your field, you will get suggestion, which you can click and id of the field will be entered for you. You will also get a syntax error in case a type of the field is incorrect, which will help you make it right.
Finally, if you don't have a separate workflow, then you can make the condition to be checked only for subtasks, i.e. if parent != null. e.g.:
issue.parent != null
? issue.parent.customfield_12345?.value == "SAP"
: true
Field mandatory based on
Resolution
Make the "Root Cause" field required if the resolution is set to "Fixed":
issue.resolution != null && issue.resolution.name == 'Fixed'
? issue. != null
: true
Make the "Fix version" field mandatory only when the resolution is set to "Done":
issue.resolution != null && issue.resolution.name == 'Done'
? issue.fixVersions.length > 0
: true
Labels
Make a field required if a "LabelA" label is set:
issue.labels.includes('LabelA') ? issue.customfield_12345 != null : true
Value starts with
Summary starts with a string:
issue.summary.indexOf('Test Case') == 0
Summary starts with a string and is minimum 15 characters long:
issue.summary.indexOf('Test Case') == 0 && issue.summary.length >= 15
Match regex
A custom field with only serial numbers, can be empty. The serial number format should consist of two letters followed by a sequence of five numbers (e.g., AB12345).
issue.customfield_12345 == null || issue.customfield_12345.match('^AB[0-9]{5}$')
Issue in active sprint
issue.sprint?.state == 'active'
Original estimate field condition
The Original estimate field is stored as a number of seconds, e.g.: 4h = 4x60x60 = 14400.
Original estimate must be less than 4h:
issue.originalEstimate < 14400
Rich Text
The content of a multi-line text field in Jira can be represented either as a string or an ADF (Atlassian Document Format) object, depending on the field's renderer or view context. To handle the field content consistently, regardless of its type, you can declare a helper function as follows:
let plainTextValue = value => typeof value == 'Map' ? new RichText(value).plainText : value ;
Is not empty
let plainTextValue = value => typeof value == 'Map' ? new RichText(value).plainText : value ;
issue.customfield_12345 != null && plainTextValue(issue.customfield_12345) != ''
Description
The description field is an exception, as it is always represented as an ADF (Atlassian Document Format) object. To check if it is not empty, use the plainText
property:
issue.description.plainText != ''
Time Spent
Ensure Time has been logged
The following expression requires that the issue has some time logged before the transition can be completed:
issue.timeSpent != null
In order to check if at least 1 hour has been logged in the issue, compare the value against the number of seconds stored in timeSpent:
issue.timeSpent != null && issue.timeSpent >= 3600
Log time during the transition
if you want to ensure that time is logged during the transition (if you have a dedicated screen with the Log Work field), you can check against originalIssue
βwhich is a snapshot of the issue before the transition screen was opened:
originalIssue.timeSpent == null
? issue.timeSpent != null
: issue.timeSpent > originalIssue.timeSpent
Original Estimate
The originalEstimate field holds the original time estimate in seconds.
For simple checks, such as whether the field is set or above a threshold, consider using the Ultimate Validatorβno expression needed.
For advanced scenarios, like detecting changes during a transition, use the Jira Expression Condition & Validator.
Check if Original Estimate was changed during transition
issue.originalEstimate != null
&& issue.originalEstimate != originalIssue.originalEstimate
This expression ensures the field is set and was modified during the current transition.
Check if Original Estimate is greater than 1 hour
issue.originalEstimate > 3600
Fix Versions
Block a transition if the Fix Versions contains "-UPDATE""
!issue.fixVersions.some(version => version.name.includes('-UPDATE'))
Cascading Select
Allow a transition if the parent option is equal to A:
issue.customfield_12345 != null && issue.customfield_12345.value == 'ParentA'
In order to check the child option, you can use the following:
issue.customfield_12345?.child?.value == 'ChildA'
Allow transition if any of the parent's options is selected:
['ParentA', 'ParentB'].includes(issue.customfield_12345?.value)
Comments
Require a comment on a transition screen
If a user selects "No" in a Radio Button field, then require a comment on the transition screen:
issue.customfield_12345?.value == "No"
? issue.comments.length > originalIssue.comments.length
: true
Attachments
Force attaching a file on a transition screen
issue.attachments.length > originalIssue.attachments.length
Validate filename
Use "issue.attachments[issue.attachments.length-1]" to access the last added file
issue.attachments[issue.attachments.length-1].filename.includes('NDA')
A filename property is a string. Check other string methods: https://developer.atlassian.com/cloud/jira/software/jira-expressions-type-reference/#string
Validate extension
Don't allow .bmp, .exe, .bat, jam.dev file extensions:
issue.attachments.every(item => !item.filename.match('(bmp|exe|bat|jam.dev)$'))
Pull request validation
Information about commits and pull requests is stored in the Development field. The value of the field is a string with format as follows:
"{pullrequest={dataType=pullrequest, state=OPEN, stateCount=1},
json={\"cachedValue\":{\"errors\":[],\"summary\":{\"pullrequest\":{\"overall\":{\"count\":1,\"lastUpdated\":\"2024-05-28T10:24:34.912+0200\",\"stateCount\":1,\"state\":\"OPEN\",\"dataType\":\"pullrequest\",\"open\":true},\"byInstanceType\":{\"bitbucket\":{\"count\":1,\"name\":\"Bitbucket Cloud\"}}}}},\"isStale\":false}}"
Use the includes method or any other available function that operates on strings to validate the state of the field.
issue.customfield_10000.includes('state=OPEN') ? true : false
When a pull request is open, the value should contain state=OPEN
; when it is merged, the value should contain state=MERGED
.
Dates comparison
Due date is approaching in 2 days from now:
issue.dueDate != null
&& issue.dueDate < new Date().toCalendarDate().plusDays(2)
User conditions
Only the issue creator can close the issue.
In the Close transition add Jira Expression Condition or Validator (WBB):
user.accountId == issue.creator.accountId
Prevent the reporter from transitioning the issue (approval transition)
In the Approval transition add Jira Expression Condition or Validator (WBB):
user.accountId != issue.reporter.accountId
Linked issues
Prevent closing an issue if it has an βis blocked byβ issue linked
issue.links
.filter(link => link.type.id == && link.direction == 'inward')
.map(link => link.linkedIssue)
.reduce(
(pass, issue) => pass && ['done'].includes(issue.status.category.key),
true
)
Link type ID may vary between Jira instances. Use the Jira expression preview from the Linked Issues Condition to learn how to construct a similar expression.
Prevent closing an epic until all its issues are done
(issue.isEpic ? issue.stories : []).reduce(
(pass, issue) => pass && ['done'].includes(issue.status.category.key),
true
)
Request type
Use following expression to allow only the Service Desk Team to submit tickets without a request type:
let hasRole = user.getProjectRoles(issue.project).reduce(
(isAllowed, role) => isAllowed || ["Service Desk Team"].includes(role.name),
false
);
!hasRole ? issue.customfield_10010 != null : true
In the editor, after typing issue.
, start typing 'Request Type,' and you will receive a valid custom field ID suggestion.
Restricting issue creation
Edit the workflow of issue type that you want to restrict
In diagram mode, select the Create transition arrow and click Validators in the properties panel.
Select the Validators tab and click on Add validator button
Add Jira Expression Validator (WBB)
Restricting the creation of certain issue types based on the user's project role
For example, if you want only users with the 'Developers' project role to be able to create Story issues, add Jira Expression Validator to the Create transition with following settings:
user.getProjectRoles(issue.project).reduce(
(isAllowed, role) => isAllowed || ["Developers"].includes(role.name),
false
)
"You must have the Developer project role to create Story issues, but got: "
+ user.getProjectRoles(issue.project).map(projectRole => projectRole.name)
Version without separate workflows
issue.issueType.name == "Story"
? user.getProjectRoles(issue.project).reduce(
(isAllowed, role) => isAllowed || ["Developers"].includes(role.name),
false
)
: true
Field is required during a workflow transition for certain issue types
For example, to make the Story Points field required during creation only for the Story issue type, use the following expression. If you press Ctrl + Space after typing issue.
, start typing "story" to get suggestions about the Story Points field key.
["Story"].includes(issue.issueType.name)
? issue.customfield_10036 != null
: true
Note that thanks to our validator, there's no need to create separate workflows for each issue type.
Jira Service Management
Validate fields specific to a request type
You can find the request type ID by looking at the URL of the request type form settings page.
Go to: Project settings -> Request types -> Click on a chosen request type; the URL contains the ID, e.g.:
https://example.atlassian.net/jira/servicedesk/projects/KEY/settings/request-types/request-type/34/request-form
customerRequest.requestType.id == 34 ? issue.dueDate != null : true
Last updated