Grammar
This page describes the basic grammar, variable declarations, data types and literals that are used in the YouTrack workflow programming language.
Workflow Language Elements | |||
---|---|---|---|
The workflow programming language borrows most of its syntax from JavaScript. If you are familiar with JavaScript, you will quickly recognize the structure that is used to write a workflow rule.
If you're not a programmer, you can find your way around with the code completion feature in the workflow editor. The workflow editor shows you a list of available options for every element in the code. The editor also displays default text that tells you what is expected for each line.
The workflow language is case-sensitive and uses the Unicode character set.
Workflow Rule Syntax
The syntax that is used for each rule is defined by the rule type. The workflow editor applies constraints when you write that help you follow the required syntax.
The syntax for each rule type is as follows:
Literals
The workflow programming language uses the following keywords to represent fixed values.
Keyword | Description | Example |
---|---|---|
loggedInUser | References the user who is currently logged in to YouTrack. | issue.Assignee = loggedInUser |
issue | References the current issue. | when issue.becomesReported() |
now | References the current date and time in UTC. | Due date = now |
true | A Boolean literal value. | var isHandled = true |
false | A Boolean literal value. | var hasChildren = false |
null | A reference literal value. | var number = null |
Use the following formats to reference literal values for specific data types.
Type | Format | Example |
---|---|---|
date | Written in the format year-month-day .
Use the T operation to combine with a time value. | if (created < 2012-Dec-31 && !isResolved()) {
tags.add(project.getUser("root").getSharedTag("obsolete?"));
} |
time | Written in the format hour-minute-second .
Use the T operation to combine with a date value. | daily at 08:00:00 [issue.resolved == null && issue.Priority == {Normal} && issue.created < now - 7 days]{
issue.Priority = {Major};
} |
integer | Unformatted numeric value. | var increaseNumber = Internal number + 1; |
period | Represented by an integer and the time period. The following period constants are supported: | if (updated + 10 months < now) {
project.leader.watchIssue(issue);
} |
string | Set in quotation marks | if (now > created + 3 days && Assignee == null) {
message("Issue is three days old and is still unassigned!");
} |
You can reference literal values for entities with the construction {entity: static_entity_name}
.
Reference | Value |
---|---|
{group: [group_name]} | UserGroup literal. |
{issue: [issueID]} | Issue literal. |
{project: [project_shortName]} | Project literal. |
{savedSearch: [savedSearchName]} | SavedSearch literal. |
{tag: [tagName]} | IssueTag literal. |
{user: [username]} | User literal. |
{[customFieldName]} | CustomField literal. |
The following examples show you how to insert static references to different entities.
Code | Description |
---|---|
{group: QA Engineers}.notifyAllUsers("Test failed!", "Please look at the failed test " + getId()) | References the UserGroup QA Engineers .
|
assert {issue: IDEA-99999}.Type == {Feature}: "It should be the cool feature about the new look and feel!"; | References a single Issue IDEA-99999 . |
for each currency in {project: Business Trips}.valuesFor(Currency) {
if (currency.name == {Dollar}) {
assert currency.colorIndex == 17: "Dollar should be green!";
}
} | References the Project Business Trips . |
for each notMyIssue in loggedInUser.getIssues({savedSearch: Reported by me}, "for: -me") {
notMyIssue.Assignee = loggedInUser;
} | References the SavedSearch Reported by me . |
rule Regression
when State.becomes({Reopened}) {
tags.add({tag: regression});
} | References the IssueTag regression . |
Variables
Variables are declared with the keyword var
, followed by the name of the variable.
You can specify the initial value with the =
sign, as with JavaScript.
var notInitializedVariable;
var initializedVariable = "Hello";
The data type of the variable is inferred from the type that is specified in the initial expression. When a variable has no initial value, its value is inferred from its usages.
Once you have declared a variable, you can refer to it by its name.
notInitializedVar = "World!";
notInitializedVar = initializedVar + ", " + notInitializedVar;
In the following example, the variable user
is used to set the assignee of an issue.
var user;
if (issue.Assignee == null) {
user = issue.project.leader;
} else {
user = issue.Assignee;
}
When you use the createNewIssue
method, an issue is created with the default (or empty) values for each field as configured for the project.
To create an issue with specific values for fields, use variable declarations.
The following sample shows how to create an issue in the project with the ID RM
,
specify values for custom fields, and add a depends on link for the current issue to the issue that is created by the workflow.
var i = loggedInUser.createNewIssue("RM");
i.Assignee = Marketing;
i.Due Date = Due Date - 1 month;
i.summary = "Write text for mailing list";
i.Version = Version;
i.Product = Product;
depends on.add(i);
Comments
You can use comments to add notes to your workflow rules. This can help others understand what a rule does and how it can be implemented. You can also use comments to disable specific lines of code.
To insert a comment, use //
. All of the text that follows on the same line is commented out.
For example:
for each subtask in parent.parent for {
//We can't use subtask.isResolved() here, as this method relies on issue.resolved
//property, which is updated after workflow rules are executed.
if (!subtask.State.isResolved) {
allSubtasksResolved = false;
break;
}
}