Workflow Building Blocks for Jira
  • About Workflow Building Blocks for Jira
  • Administrator Guide
    • Setup Conditions and Validators
  • Conditions & Validators
    • 🚀 Ultimate Condition & Validator
    • Linked Issues Condition & Validator
    • Dates Compare Condition & Validator
    • Fields Required Condition & Validator
    • Jira Expression Condition & Validator
  • Writing Jira Expressions
    • Introduction to Jira Expressions
    • Jira expressions library
    • Writing validation messages
  • Testing & Debugging
    • Testing Conditions & Validators
    • Limitiations
  • Support
    • Service Desk
  • Atlassian Marketplace Apps
    • Workflow Building Blocks for Jira
    • Translated Fields for Jira & JSM
    • Field Rules - UI Modifications for Jira
Powered by GitBook
On this page
  • Field conditions
  • Is required
  • Compare different fields
  • Parent value in condition
  • Field mandatory based on
  • Value starts with
  • Match regex
  • Issue in active sprint
  • Original estimate field condition
  • Rich Text
  • Is not empty
  • Description
  • Time Spent
  • Ensure Time has been logged
  • Log time during the transition
  • Original Estimate
  • Check if Original Estimate was changed during transition
  • Check if Original Estimate is greater than 1 hour
  • Fix Versions
  • Cascading Select
  • Comments
  • Require a comment on a transition screen
  • Attachments
  • Force attaching a file on a transition screen
  • Validate filename
  • Validate extension
  • Pull request validation
  • Dates comparison
  • User conditions
  • Only the issue creator can close the issue.
  • Prevent the reporter from transitioning the issue (approval transition)
  • Linked issues
  • Prevent closing an issue if it has an “is blocked by“ issue linked
  • Prevent closing an epic until all its issues are done
  • Request type
  • Restricting issue creation
  • Restricting the creation of certain issue types based on the user's project role
  • Field is required during a workflow transition for certain issue types
  • Jira Service Management
  • Validate fields specific to a request type
  1. Writing Jira Expressions

Jira expressions library

Jira expression examples and use cases

Field conditions

IDs used in following examples vary between Jira instances.

You need to change the ID of the custom fields to a valid one. In the editor, after issue., start typing the name of the field, and you will get suggestions with the correct value.

Is required

Issue must be assigned:

Jira expression
issue.assignee != null

Issue must have work logged:

Jira expression
issue.timeSpent != null

Compare different fields

The issue assignee must be different from the issue reporter:

Jira expression
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":

Jira expression
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:

Jira expression
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.:

Jira expression
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":

Jira expression
issue.resolution != null && issue.resolution.name == 'Fixed' 
  ? issue. != null
  : true

Make the "Fix version" field mandatory only when the resolution is set to "Done":

Jira expression
issue.resolution != null && issue.resolution.name == 'Done' 
  ? issue.fixVersions.length > 0
  : true

Labels

Make a field required if a "LabelA" label is set:

Jira expression
issue.labels.includes('LabelA') ? issue.customfield_12345 != null : true

Value starts with

Summary starts with a string:

Jira expression
issue.summary.indexOf('Test Case') == 0

Summary starts with a string and is minimum 15 characters long:

Jira expression
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).

Jira expression
issue.customfield_12345 == null || issue.customfield_12345.match('^AB[0-9]{5}$')

Issue in active sprint

Jira expression
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:

Jira expression
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:

Jira expression
let plainTextValue = value => typeof value == 'Map' ? new RichText(value).plainText : value ; 

Is not empty

Jira expression
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:

Jira expression
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:

Jira expression
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:

Jira expression
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:

Jira expression
originalIssue.timeSpent == null 
    ? issue.timeSpent != null 
    : issue.timeSpent > originalIssue.timeSpent

Original Estimate

The originalEstimate field holds the original time estimate in seconds.

For advanced scenarios, like detecting changes during a transition, use the Jira Expression Validator.

Check if Original Estimate was changed during transition

Jira expression
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

Jira expression
issue.originalEstimate > 3600

Fix Versions

Block a transition if the Fix Versions contains "-UPDATE""

Jira expression
!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

Jira expression
issue.attachments.length > originalIssue.attachments.length 

Validate filename

Use "issue.attachments[issue.attachments.length-1]" to access the last added file

Jira expression
issue.attachments[issue.attachments.length-1].filename.includes('NDA')

Validate extension

Don't allow .bmp, .exe, .bat, jam.dev file extensions:

Jira expression
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.

Jira expression
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:

Jira expression
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):

Jira expression
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):

Jira expression
user.accountId != issue.reporter.accountId

Linked issues

Prevent closing an issue if it has an “is blocked by“ issue linked

Jira expression
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
  )

Prevent closing an epic until all its issues are done

Jira expression
(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:

Jira expression
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

  1. Edit the workflow of issue type that you want to restrict

  2. In diagram mode, select the Create transition arrow and click Validators in the properties panel.

  3. Select the Validators tab and click on Add validator button

  4. Add Jira Expression Validator (WBB)

Restricting the creation of certain issue types based on the user's project role

Requires a separate workflow for certain issue types

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:

Jira expression
user.getProjectRoles(issue.project).reduce(
  (isAllowed, role) => isAllowed || ["Developers"].includes(role.name),
  false
)
Validation message
"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

Jira expression
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.

Jira expression
["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

Jira expression
customerRequest.requestType.id == 34 ? issue.dueDate != null : true
PreviousIntroduction to Jira ExpressionsNextWriting validation messages

Last updated 13 days ago

For simple checks, such as whether the field is set or above a threshold, consider using the —no expression needed.

A filename property is a string. Check other string methods:

Link type ID may vary between Jira instances. Use the from the Linked Issues Condition to learn how to construct a similar expression.

Ultimate Validator
https://developer.atlassian.com/cloud/jira/software/jira-expressions-type-reference/#string
Jira expression preview