
Workflow validators and conditions for Jira Cloud, built on Jira expressions. Pick a rule from the template library, fill in a short form, and click "Test against issue" to see the result before you publish the workflow. Advanced admins can write their own Jira expression.
Built on Atlassian Forge. Rules are evaluated by Jira itself, so the app sends no data outside Atlassian.
Each template is available as a validator, which blocks the transition and shows an error message, and as a condition, which hides the transition.
| Template | What it checks | Settings |
|---|---|---|
| Fields are required | Chosen fields have a value (all of them, or at least one) | Fields; all / at least one |
| Field required when… | A field is required only when work type, priority, resolution, a label, a component or a select field has one of the listed values | Required field; trigger; values |
| Sub-tasks or child issues are done | Every sub-task (or child issue) is in a Done-category status, or in the listed statuses | Sub-tasks / child issues; statuses (optional) |
| Linked issues are done | Issues linked with a chosen link type and direction (for example "is blocked by") are done, or in the listed statuses | Link; statuses (optional); require at least one link |
| Parent is in status | The parent issue is in one of the listed statuses | Statuses; allow or block issues without a parent |
| Attachment required | At least N attachments, optionally of given file types | Minimum; extensions |
| Text field matches pattern | A text field matches a regular expression | Field; pattern; allow empty |
| Due date is valid | A due date is set, not in the past, and at most N days ahead | Each check can be turned on or off |
| Time logged | At least N minutes of logged work | Minutes |
| Custom Jira expression | Your own expression (advanced) | Expression; short description |
Validators can show your own error message. If you leave it empty, a message is written for you from the settings (for example "Fill in these fields before this transition: Components, Story Points."). The generated message is written again each time you save the rule, so it follows changes to the settings. A message you typed yourself is kept as you wrote it.
| You want | Use | ||
|---|---|---|---|
| Bugs need a component | Field required when… → Components, when Work type is Bug | ||
| Critical incidents need release notes | Field required when… → Release notes, when select field Severity is Critical | ||
| Story points before "In Progress" | Fields are required → Story Points | ||
| A fix version or a component | Fields are required → Fix versions, Components; at least one | ||
| No closing a story with open sub-tasks | Sub-tasks or child issues are done → Sub-tasks | ||
| No closing an epic with open stories | Sub-tasks or child issues are done → All child issues | ||
| No starting work while blocked | Linked issues are done → "Blocks: is blocked by" | ||
| Every release task links a done QA ticket | Linked issues are done → "Relates: relates to" (either direction); require at least one link | ||
| Sub-tasks start only when the parent is in progress | Parent is in status → In Progress | ||
| Evidence before approval | Attachment required → 1, pdf, png | ||
Summary starts with a tag such as [API] | Text field matches pattern → Summary, ^\[.+\] | ||
Ticket reference in the format OPS-123 | Text field matches pattern → your field, ^[A-Z]+-\d+$ | ||
| Due date within the sprint | Due date is valid → not in past, at most 14 days ahead | ||
| Time logged before resolving | Time logged → 15 minutes | ||
| Anything else | Custom Jira expression, for example `issue.labels.includes('approved') \ | \ | user.groups.includes('release-managers')` |
Story Points or customfield_10010) and suggest fields as you type.The test runs the rule now, as you, against the issue as it is saved (POST /rest/api/3/expression/evaluate, with the rule settings passed as config). A real transition can give a different result, for these reasons.
transition, workflow, originalIssue and groupOperator exist only during a real transition, so custom expressions that use them cannot be fully tested.Status, work type, priority, resolution, label and option values are compared exactly, and the comparison is case-sensitive (Done is not done). Run "Test against issue" to check.
Separate list values with commas or new lines. A value that contains a comma goes in double quotes, for example "Yes, approved", No. The form shows each value it read as a separate chip.
The "Select field" trigger takes only option-type custom fields. These are single select, radio buttons, multi-select, checkboxes and cascading select. For a cascading select, the first-level value is compared. Number, text, date and user fields are refused, because they have no option value to compare.
The field boxes list at most 2,000 fields on very large sites. The cap keeps every supported system field, then custom fields in name order. The box itself lists fields by name, with system and custom fields mixed. If a site has more, the form says so and names the last listed field. You can't pick fields after it, but fields a rule already uses are kept, so you can still edit and save that rule.
If the field list can't be loaded, the fields already saved in a rule are kept and the rule can be saved again. You can choose other fields only after a reload.
Symmetric link types such as Relates ("relates to" in both directions) are offered only as "either direction", because a link made from the other issue has the opposite direction. A rule saved earlier with one direction keeps it, and the picker labels it as such.
"Linked issues are done" fails for a link when Jira returns that link without its issue. We expect Jira to do this when the user who transitions can't view the linked issue, but this isn't confirmed on a live site yet. Sub-tasks and child issues that user can't see may be skipped. Jira's documentation doesn't say whether it leaves them out of the list, and if it does, "Sub-tasks or child issues are done" doesn't check them.
Jira caps how much data one expression may load. Rules that read many linked issues or child issues can hit this cap on very large issues, and Jira then treats the rule as failed.
Jira runs the pattern with its own regular-expression engine, not your browser's. When you save, the form checks the syntax in the browser. It also refuses common constructs that the two engines read differently. These are [], [^], [ or && inside a class, an unescaped { that is not a repeat count, \u/\x without the full hex digits, group names with _, inline flags such as (?i), and Unicode classes such as \p{Lu}. For a case-insensitive letter, use a class such as [Aa].
A backslash before a letter is accepted only for \d \D \s \S \w \W \b \B \n \r \t \f, \u and \x with their hex digits, \c with a control letter and \k<name>. Any other letter is refused. That covers escapes that Java-style engines refuse, such as \y, and escapes they read differently from the browser, such as \A, \z and \Q…\E. We haven't confirmed which engine Jira uses, so this check is cautious. Use ^ and $ instead of \A and \z.
Other rare differences can remain. So run "Test against issue" after you change a pattern, and if Jira rejects it, the test shows Jira's error. "Matches" means the pattern is found anywhere in the text. Use ^ and $ to match the whole value.
Custom expressions use the expression override that Atlassian documents for Forge workflow rules (expression in the saved configuration). If Jira ever ignores the override, the rule blocks the transition with a message that says so, and a custom condition hides it. It never silently lets transitions through.
Jira evaluates the rules on Atlassian's cloud. If the app is uninstalled, Jira treats its rules as failed, so validators block and conditions hide transitions. Remove the rules from your workflows before you uninstall.
| Scope | Why |
|---|---|
manage:jira-configuration | Required by Forge to save workflow rule settings. |
read:jira-work | Field list, issue link types, and the Test button. |
read:jira-user | Recommended by Atlassian for expression evaluation (expressions can read users). |
All Jira calls are made as the signed-in admin. The app has no scope that writes issues, stores no data of its own, and makes no calls outside Atlassian.
Zovo builds and maintains this app. If it saves you time, you can support the work on GitHub Sponsors. Sponsorship is optional, and the tool works the same without it.
Zovo is made by theluckystrike on GitHub.
MIT. See LICENSE.
If this app saves you time, you can support the work on GitHub Sponsors. Monthly tiers start at $5, and one-time tiers start at $15. Sponsorship is optional, and the tool works the same without it.