Workflow Enhancer for JIRA Documentation
This page contains old documentation. The new documentation can be found here: https://tngtech.atlassian.net/wiki/spaces/WORKFLOW
This is the documentation for the JWFE 2.0 onwards. You can find a documentation for older versions here.
Content
Validators and Conditions
To enter a validator or a condition provided by JWFE, edit your workflow and in any transition add a new "universal validator" or a "universal condition". You will be prompted with entering a Boolean expression as explained below. In the case of the universal validator, you will be prompted to enter a message as well.
Post Functions
As of JWFE 3.0, you have the possibility of executing any post function depending on if a Boolean expression (see the rest of this documentation) evaluates to true or false, respectively. When adding a "Universal Post Function", you will not only be prompted for a Boolean expression, but also for another post function to be executed and any values that post function might take.
Note that some of the inbuild post functions of JIRA have unintuitive functionality:
- Create a comment: If in the transition screen a comment was added, it will be added again
- Update Issue Status: Will update the issue status after transition, although it was already changed
- Create Issue: Recreates the issue, e.g. previously there is an issue " TEST-4 - access task", but after post function transition it becomes " TEST-5 - access task"
In the future we might decide to hide these post functions.
Fields
Name | Type | Explanation | Example | Annotation |
---|---|---|---|---|
Reporter, Assignee | String | User field containing a username, e.g. {Reporter} represents the username of the issue's reporter | {Reporter} = "admin" | Attention: In the old JWFE (until version 1.5.1) it represented the reporter's fullname Anonymous is in JIRA and JWFE represented by "" |
Environment, Description, Summary | String | Text field, e.g. {Summary} contains the text entered in the issue's summary | {Summary} = "Issue1" | |
Due Date, Created, Updated | Date | Date field, e.g. {Due Date} contains the date entered in the issue's Due Date field | {Due Date} = 24.12.2012 | |
Original Estimate, Remaining Estimate, Time Spent | Timespan | Time span field, e.g. {Original Estimate} contains the time span entered in the issue's Original Estimate field | {Original Estimate} = 4w 5d 6h | if nothing is entered in the field, JWFE gives back 0min ( i.e. {...} = 0min ) |
Σ Original Estimate, Σ Remaining Estimate, Σ Time Spent | Timespan | Time span field, e.g. {Σ Original Estimate} contains the sum of the Original Estimates of the issue's subtasks | {Σ Original Estimate} = 1w 7d 3h | if nothing is entered in the field, JWFE gives back 0min ( i.e. {...} = 0min ) |
Project | String | {Project} contains the issue's project name | {Project} = "Rocket" | |
Priority | String | {Priority} contains the (name of the) priority of the issue | {Priority} = "Major" | |
Status | String | {Status} = "In Progress" | ||
Resolution | String | {Resolution} == "Resolved" | ||
Issue Type | String | {Issue Type} = "Bug" | ||
Key | String | {Key} contains the key of the issue which is of the form PROJECTKEY-IssueId | {Key} = "ROCKET-1" | |
Issue Links | String | {Linked Issues} <=> "Passive: LinkType % IssueKey $ ... $ LinkType % IssueKey Aktive: LinkType % IssueKey $ ...$ LinkType % IssueKey" |
| JIRA default LinkTypes are Blocks, Cloners and Duplicate. Note the space before ¨Aktive¨ and the spelling of ¨Aktive¨ Set the log level to Debug and check in the logs, this syntax is not really easy to handle. |
Labels | String | Gives back the Array of labels as String in alphabetical order; e.g. [label1, label2, label3] | {labels} = "[aLabel]" for exactly one specific label, or {labels} == "[]" for none | Use regular expressions to check for one label among several, e.g. {labels} = /.*mylabel.*/ |
Fix Version/s, Affects Version/s | String | Gives back the Array of versions as String in alphabetical order; e.g. [version1, version2, version3] |
| Use regular expressions to check for one version among several |
Components | String | Gives back the Array of components as String in alphabetical order; e.g. [component1, component2, component3] |
| Use regular expressions to check for one version among several |
Transition Comment | String | Gives back the comment added in the transition as a string. | Is only useful for post functions and validators and if a screen is shown during the transition |
JIRA fields (written as `{field_id}`) may themselves contain a special value. Therefore if a field contains a value such as `1h 30min`, it will automatically be parsed as a timespan. This also allows for example a chain of field identifiers (by putting the identifier of another field in a field). An application may be that the first element of the chain is set as a post-function to dynamically change the behavior of the condition / validator depending on the steps in the workflow we have visited).
However, we are currently exploring the idea of not evaluating the field values or making it possible for the user to define which fields should be evaluated.
Please compare JIRA-Fields always with English field values e.g. {Resolution} == "Resolved"
Important: The fields of type String only allow string comparisons. So especially the order operations <, <=, >=, > often don't make sense, for example in the case of priority {Priority} > "a string which begins with the letter a" always evaluates to "True".
You can use both field names in your local language as well as english lower-case names, e.g. in German {resolution} and {Lösung} both refer to the resolution while {Resolution} tries to evaluate a customfield.
Custom Fields
Type | Explanation | Annotation |
---|---|---|
Date Picker | {Date Picker} represents the picked date as a date value | e.g. {Date Picker} = 25.09.2012 00:00, if you picked 25/Sep/2012 in the issue's Date Picker field or {Date Picker} = "" if you want to check that the date picker is not set. |
Version Picker | {Single Version Picker} represents all picked versions of the issue as a comma and space separated string | |
Single Version Picker | {Version Picker} represents the picked version as a string | |
Project Picker | {Project Picker} represents the picked projectname as a string | Projectname is a unique value |
User Picker | {User Picker} represents the picked user's username | |
Multi User Picker | {Multi User Picker} represents all picked user's username in a comma and space separated string | e.g. {Multi User Picker} = "username1, username2", if you picked user1 and user2 in the issue's Multi User Picker field |
Group Picker | {Group Picker} represents the picked groupname in a string | |
Multi Group Picker | {Multi Group Picker} represents all picked groups groupname in a comma and space separaded string | e.g. {Multi Group Picker} = "jira-developers, jira-users, jira-tester", if you picked these three groups in the issue's Multi Group Picker field. |
Number Field | {Number Field} represents the entered number as a float value | e.g. {Number Field } = "3.14", if you entered in the issue's Number Field field 3.14 |
Free Text Field | {Free Text Field} represents the entered text as a string | e.g. {Free Text Field} = "all work and no play makes Jack a dull boy" if you entered all work and no play makes Jack a dull boy in the issue's Free Text Field |
Text Field | see Free Text Field above | |
Label | {Labels} represents all labels, which are affixed to the issue, as a string | e.g. {Label} = "label1, label2, label3" if you affixed this labels to the issue. Note that: JIRA sorts the labels so "label1, label2" = "label2, label1" |
Date Time | {Date Time} represents the picked point in time as a date value | e.g. {Date Time} = 24.12.2012 15:45 if you picked this moment in the issue's Date Time field. See Values/Date |
URL Field | {URL Field} represents the entered URL as a string | e.g. {URL Field} = "http://en.wikipedia.org/wiki/Uniform_Resource_Locator" |
Import Id | not supported | |
Read only Text Field | not supported | |
Cascading Select | {Cascading Select} reprensents the selected options as as String in the same format as Atlassian´s
| e.g. {Cascading Select} = /null=.*, 1=.*/ to ensure both values are set |
Bug Import ID | not supported | |
Multi Select | {Multi Select} represents the selected options as a comma and space separated string | |
Radio Buttons | {Radio Button Field} represents the selected option as a string | |
(Multi) Checkboxes | {Checkbox} represents the selected options as a comma and space separated string | |
Select List | {Select List} represents the selected option as a string | |
Hidden Job Switch | not supported |
In version 2.0.5 we added better logging. Now every boolean evaluation (equation and comparison) is logged. If you are not sure, to which value JWFE evaluates your custom field, just do the following:
- Administration -> Logging & Profiling
- Configure new logger:
com.tng.jira.workflowenhancer.evaluator.types.AbstractGenericValue
- Set logging level to debug or below
- Now one can see every evaluation and its result in the logs.
Note that JWFE can change left and right side of the equation/comparison!
Macros
Type | Description | Example | |
---|---|---|---|
[user] | String | username of the current user | |
[groups] | String | comma-separated list of the groups the user belongs to | |
[roles] | String | comma-separated list of the project roles the user belongs to | [roles]=/.*role_name_1.*/ |
[now] | Date value | current date and time | |
[subtasks#field] | String | comma-separated list of the values in the subtasks | [subtasks#Summary]=/.*Test.*/ Checks if any Subtaks has a summary that contains "Test" [subtasks#Status]=/\0133(Done(, Done)*)?\0135/ Checks if all subtasks are in the status "Done". \0133 and \0135 are encoded "[" and "]", as you can't use them in the regex as a literal String |
Values
String
Example | |
---|---|
Any String has to be enclosed by " (quotation marks) | "String", "another String" |
RegEx
Example | |
---|---|
Any regular expression has to be enclosed by / (forward slashes) | /ab/ |
* matches the preceding element zero or more times | /a*/ = {ε,a,aa,aaa,aaaa,...} |
+ matches the preceding element one or more times | /a+/ = {a,aa,aaa,aaaa,...} |
? matches the preceding element zero or one time | /a?/ = {ε,a} |
( ) defines subexpression | /(ab)+/ = {ab,abab,abab,ababab,...} |
{n} matches the precending element exactly n times | /a{3}/ = {aaab} |
{min, max} matches the precending element at least min and at most max times | /a{2,4}/ = {aa,aaa,aaaa} /a{1,}/ = /a+/ = {a,aa,aaa,...} /a{ ,5}/ = {ε,a,aa,aaa,aaaa,aaaaa} |
In the examples above ε always stands for the empty word. For example in the case of /a?/ that means that there can be either one "a" or no "a".
Date
Example | |
---|---|
Pattern: dd.mm.yyyy hh:mm | 24.12.2012 15:30 |
Time is optional | 24.12.2012 |
The maximal date value is 31.12.2099 23:59.
Timespan
Example | |
---|---|
Labor timespan pattern: n1w n2d n3h n4min , where n1, n2, n3, n4 are non negative integers | 12w 13d 5h 3min means 12 labor weeks 13 labor days 5 hours and 3 minutes |
Real timespan pattern: n1W n2D n3H n4MIN , where n1, n2, n3, n4 are non negative integers | 12W 13D 5H 3 MIN means 12weeks 13day 5 hours and 3minutes |
If a component is 0 it can be omitted | 0w 5d 3h 0min = 5d 3h |
It is not possible to change the order | Wrong: 5d 8w Right: 8w 5d |
JWFE works with the TimeTracker settings of your JIRA such that a timespan of JIRA is automatically a labor timespan. This also means that a date and a timespan field cannot be added!
If the TimeTracker is disabled, 1 day = 8 hours, 1 week = 5 days.
So if your JIRA TimeTracker settings are 1 labour day = 24h and 1 labor week = 7 labor days, labor timespan and real timespans are the same.
Float
Example | |
---|---|
Pattern: d+(.d*)? or d*(.d+)?, where d is an integer | 3.14, 1.61803, 42 |
Insert negative numbers as a term: | 0 - 3.14, 0 - 5.24 |
The JWFE intern float data type works with negative values. But the parser does not support unary operations.
Operators
Boolean operators
Description | Operator |
---|---|
AND | & (alternatively && or AND) |
OR | | (alternatively || or OR) |
NOT | ! |
( ) |
Order operators
Description | Operator |
---|---|
Equals | = (alternatively ==) |
Not equal | != |
Greater | > |
Greaterequals | >= |
Less | < |
Lessequals | <= |
Arithmetic Operators
Description | Operator |
---|---|
Plus | + |
Minus | - |
Order Operations
The following matrix shows between which values order operations are possible and how they are defined:
String | Float | Date | Real Timespan | Labor timespan | RegEx | |
---|---|---|---|---|---|---|
String | s | default | default | default | default | r |
Float | default | f | ||||
Date | default | d | ||||
Real Timespan | default | t | t | |||
Labor Timespan | default | t | t | |||
RegEx | r |
Order operations are possible if the field at the crossing point is not empty. The type of the operation is explained in the legend.
Type | Explanation | Example |
s | lexicographical comparison based on the Unicode value of each character in the strings | "zoo" >= "a much longer string but with an a at the beginning" "2 test strings" < "a test string without a number at the beginning" |
---|---|---|
f | usual comparison of numbers | 4.5 < 42, 7.77 >= 2.2222, |
d | the time is considered if and only if both values match the pattern dd.mm.yyyy hh:mm | 24.12.2012 15:30 = 24.12.2012 24.12.2012 15:30 < 24.12.2012 16:00 |
t | number comparison of the timespan values converted to minutes | 1w > 1min, 1h <= 61min, 1d 1h = 1d 1h |
r | equal if and only if the string matches the regular expression the other operations are defined as default (see below) | "Bar"= /Ba[a,r]/ /Ba[a,r]/ > "A" |
default | lexicographical comparison after both values have been converted to string | 10.10.2000 = "10.10.2000", 10.10.2000 < "a string" 42 = "42.0", "0 a string with a zero at the beginning" < 42 "1w 0d 0h 0min" = 1w, 1w >= "1w 0d 0h 0min" |
Arithmetic Operations
Addition
The following matrix shows between which values additions are possible and how they are defined:
String | Float | Date | Real Timespan | Labor Timespan | RegEx | |
---|---|---|---|---|---|---|
String | s | |||||
Float | f | |||||
Date | d | |||||
Real Timespan | d | t | t | |||
Labor Timespan | t | t | ||||
RegEx |
Additions are possible if the field at the crossing point is not empty.
Type | Explanation | Example |
s | string concatenation | "An" + "na" = "Anna" |
---|---|---|
f | usual addition of numbers | 1.5 + 3 = 4.5 |
t | usual addition of timespans based on minutes If the the timespan values don't have the same type (i.e. not both real or both labor) the result has the type of the first operand. | 1w 2d 3h + 2w 2d 2h = 3w 4d 5h 1D + 1h = 1D 1H |
d | The timespan value is added to the date. If the date has no entered time, hours and minutes don't matter | (12.10.2016 + 14H) + 12H = 12.10.2016, 12.10.2016 + 1W 3D = 22.10.2016 |
Subtraction
The following matrix shows between which values subtractions are possible and how they are defined:
String | Float | Date | Real Timespan | Labour Timespan | RegEx | |
---|---|---|---|---|---|---|
String | ||||||
Float | f | |||||
Date | d | |||||
Real Timespan | d | t | t | |||
Labor Timespan | t | t | ||||
RegEx |
Subtractions are possible if the field at the crossing point is not empty.
Note that substraction of dates is not supported. Use e.g. {Date A} < {Date B} + 1W
instead of comparing the difference of the dates to a week.
Type | Explanation | Example |
f | usual subtraction of numbers | |
t | the subtraction of two timespans gives back the absolute difference based on minutes. If the the timespan values don't have the same type (i.e. not both real or both labor) the result has the type of the first operand. | 8w 1d 3h - 8w 2d 4h 9min = 1d 1h 9min 2h - 1H = 1h |
d | the timespan value is subtracted from the date. If the date has no entered time, hours and minutes don't matter | (29.05.2015 - 12H 5MIN) - 12H 5MIN = 29.05.2015, 29.11.2019 - 6D = 23.11.2019 |