YouTrack Standalone 7.0 Help

Methods and Operations

This page provides a list of the methods and operations that are supported the workflow programming language. The syntax for each method or operation is presented in the format: [name]([data type] parameter): [data type].

The methods and operations that are described on this page are grouped by the object type that they are related to.

ObjectMethods and Operations
IssuegetId, getUrl, applyCommand, createCopy, getEditedComments, addComment, clearAttachments, hasTag, isStarred, addTag, removeTag, getDuplicateRoot, isReported, becomesReported, isResolved, becomesResolved, becomesUnresolved, getNotificationEmail, sendMail, wikify
Fieldbecomes, canBeReadBy, canBeUpdatedBy, changed, oldValue, required
CustomFieldgetPresentation
ProjectFieldgetValuePresentation, getBackgroundColor, getForegroundColor
IssueTaggetShareGroup, getUpdateShareGroup
SavedQuerygetOwner, getShareGroup, getUpdateShareGroup
Sequenceadd, added, clear, contains, first, isEmpty, isNotEmpty, last, remove, removed
ProjectgetUser, isArchived, valuesFor
UsergetVisibleName, isBanned, hasRole, isInGroup, createNewIssue, watchIssue, unwatchIssue, getTag, getSharedTag, canVoteIssue, voteIssue, canUnvoteIssue, unvoteIssue, notify, sendMail, sendJabber, getIssues
UserGroupgetUsers, notifyAllUsers

To use a method or operation, simply add a dot after any field and write the name of the method or operation. You can continue to add methods and operations to the statement until it generates the desired condition. For example:

when comments.added.isNotEmpty

With code completion, the workflow editor displays a list of possible options that can be used with the preceding element.

  • Methods display the syntax and the object type they are associated with in the schema.
    /help/img/youtrack/7.0/workflowEditorMethods_thumbnail.png
  • Operations are formatted in dark blue text in the editor and display a description of each available operation.
    /help/img/youtrack/7.0/workflowEditorOperations_thumbnail.png

Issues

Changes that are applied to an issue are managed by a series of transactions. A transaction is a collection of current changes that are either saved to the database or discarded as a set. When a user edits an issue, a new transaction is started. The transaction is completed when the user clicks the Submit button. The single transaction includes all of the changes that were made to the issue.

Rules that are not executed according to a schedule are processed at the end of a transaction. Scheduled rules and scheduled blocks in state-machine rules are only processed for issues that are already reported or become reported in the current transaction.

The following methods are available for use with issues. See also Issue Fields.

getId(): string
DescriptionReturns the issue ID.
Example
user.notify("Issue is overdue", "Please, look at the issue: " + issue.getId());
getUrl(): string
DescriptionReturns the issue URL.
Example
user.notify("Issue is overdue", "Please, look at the issue: " + issue.getUrl());
applyCommand(string command, User runAs): void
ParameterscommandThe command that is applied to the issue.
runAsSpecifies the user by which the command is applied. If this parameter is not set, the command is applied on behalf of the current user.
DescriptionApplies a command to an issue.
Example
applyCommand("for me Critical")
createCopy(): Issue
DescriptionClones the current issue.
getEditedComments(): sequence<IssueComment>
DescriptionGets the comments that are edited in the current transaction. Comments that are added and removed are not considered as edited. These values are represented by the issue.comments.added and issue.comments.removed properties.
addComment(string text): IssueComment
ParameterstextThe text to add to the issue as a comment.
DescriptionAdds a comment to the current issue. Sets the issue.comments.changed field to true for the current transaction.
Example
addComment("+1!!!");
clearAttachments(): void
DescriptionRemove all of the attachments from an issue.
hasTag(string name): Boolean
ParametersnameThe name of the tag to check for an the issue.
DescriptionChecks whether the specified tag is attached to an issue.
Example
hasTag("todo");
isStarred(): Boolean
DescriptionChecks whether any user has added the star tag to an issue.
addTag(string name): IssueTag
ParametersnameThe name of the tag to attach to the issue.
DescriptionAdd a tag with the specified name to an issue. YouTrack adds the first matching tag that is visible to the current user. If a match is not found, a new private tag is created for the current user. When you use this method to add the star tag to an issue, the current user is added to the list of watchers.

To add a tag that is not visible to the current user, use the applyCommand method instead. Use "add tag <tagName>" for the command parameter and specify the login for the owner of the tag in the runAs parameter.

Example
addTag("todo");
removeTag(string name): IssueTag
ParametersnameThe name of the tag to remove from the issue.
DescriptionRemove a tag with the specified name from an issue. If the specified tag is not attached to the issue, an exception is thrown.

This method only works when the logged-in user is also the owner of the tag. To remove a tag that is owned by another user, use the applyCommand method instead. Use "remove tag <tagName>" for the command parameter and specify the login for the owner of the tag in the runAs parameter.

Example
removeTag("waiting for reply");
getDuplicateRoot(): Issue
DescriptionReturns the root issue in a tree of duplicates that are linked to the current issue.
Example
when issue.duplicateCluster.changed || issue.duplicates.changed || issue.is duplicated by.changed { info("Processing duplicate-cluster issue " + issue.getId()); var duplicateRoot = issue.getDuplicateRoot(); if (duplicateRoot != null) { issue.duplicates.clear; if (issue != duplicateRoot) { issue.duplicates.add(duplicateRoot); duplicateRoot.duplicates.clear; } } }

Issue Lifecycle

The following methods are related to the lifecycle of an issue. The lifecycle of an issue consists of the following stages:

StageDescription
1. Issue is created in this transactionThe issue is still in draft form and does not have an issue ID. The default custom field values are set in this stage.

Rules are not triggered during this stage.

2. Issue is draftChanges are made after creation but before the issue is reported. This stage includes all edits to the draft issue. Stateless and state-machine rules can be triggered during this stage. Scheduled rules and scheduled blocks in state-machine rules are not processed.
3. Issue becomes reported in this transactionThe issue becomes reported. The issue is submitted and is assigned an ID. All rules including scheduled rules and scheduled blocks in state-machine rules are processed during this stage.
4. Issue is reportedThis stage includes all changes made to an issue after it has been reported. All rules including scheduled rules and scheduled blocks in state-machine rules are processed during this stage.
5. Issue is deleted in this transactionThe issue is deleted and is not available after this transaction is complete.

Rules are not triggered during this stage.

isReported(): Boolean
DescriptionChecks whether an issue is already reported or becomes reported in this transaction (stages 3 and 4). To apply changes to an issue draft (stage 2), use !isReported().
Example
for each dep in depends on { if (dep.isReported()) { assert dep.State.isResolved: l10n ( The issue has unresolved dependencies and thus cannot be set Fixed! ); } }
becomesReported(): Boolean
DescriptionChecks whether an issue becomes reported in this transaction (stage 3).
Example
when Assignee == null && (((Subsystem.changed || project.changed) && isReported()) || becomesReported()) { if (issue.Subsystem != null) { issue.Assignee = issue.Subsystem.owner; } }

The following methods are related to the issue.resolved property. This property is set based on the values that are stored in a custom field with a state data type. Each value that can be stored in this field has a Resolved property. This property determines whether the issue is considered to be resolved when it assigned a value for this field.

The resolved property is associated with the issue, which means that these methods do not contain references to the custom field.

isResolved(): Boolean
DescriptionChecks whether an issue is assigned a state that is considered resolved.
Example
when isResolved() { assert !votes.changed: l10n ( Voting for a resolved issue is not allowed. ); }
becomesResolved(): Boolean
DescriptionChecks whether an issue is assigned a state that is considered resolved in the current transaction.
Example
when issue.isReported() && issue.becomesResolved() && issue.subtask of.isNotEmpty { var parent = issue.subtask of.first; while (parent != null && !parent.isResolved()){ var allSubtasksResolved = true; for each subtask in parent.parent for { if (!subtask.State.isResolved) { allSubtasksResolved = false; break; } } if (allSubtasksResolved) { parent.State = {Done}; message(l10n ( Automatically set{parent.getId()} as Done)); } parent = parent.subtask of.first; } }
becomesUnresolved(): Boolean
DescriptionChecks whether an issue is assigned a state that is considered unresolved in the current transaction.
Example
when issue.becomesUnresolved() && issue.subtask of.isNotEmpty { var parent = issue.subtask of.first; while (parent != null && !(parent.project.isArchived()) && parent.isResolved()) { parent.State = {Open}; if (parent.Type != null) { message(l10n ( Automatically reopen {parent.Type} {parent.getId()} )); } else { message(l10n ( Automatically reopen {parent.getId()} )); } parent = parent.subtask of.first; } }

Notifications

These methods can be used to send notifications to unregistered users with an email address. To send notifications to existing users, use the notify, notifyAllUsers, sendMail, and sendJabber methods.

If overused, sending email messages to unregistered users can slow down the performance of your YouTrack server, which is not designed for use as a bulk email service. You can configure a system property to set a daily email message limit. For more information, see Configuration Parameters.

getNotificationEmail(): string
DescriptionReturns the email address that is used to send notifications for the project. If a From address is not set for the project, the From address for the YouTrack server is returned.
Example
when issue.becomesReported() { if (Last message related emails.isNotEmpty) { for each email in Last message related emails.split(" ", preserveAllTokens) { if (email.isNotBlank && !(email.eq(getNotificationEmail(), ignoreCase))) { if (All related emails.isEmpty) { All related emails = email; } else if (!(All related emails.split(" ", preserveAllTokens).contains(email))) { All related emails = All related emails + " " + email; } } } Last message related emails = null; } }
sendMail(string fromPersonal, string fromEmail, string email, string cc, string subject, string body): void
ParametersfromPersonalThe sender of the email message. If this parameter is not set, the project From address is used. If a From address is not set for the project, the From address for the YouTrack server is used.
fromEmail
emailThe email address of the primary recipient.
ccThe email addresses of additional recipients who receive a copy of the message. Multiple email addresses are delimited with commas. If this parameter is not set, the message is sent to a single recipient.
subjectThe subject line of the email message
bodyThe email message text.
DescriptionSends an email message with the specified parameters.
Example
when comments.added.isNotEmpty { if (Reporter email != null) { sendMail(Reporter email, "[YouTrack, Commented]", "New comment was added: " + comments.added.first.text)); } }
wikify(string text): string
ParameterstextThe string of text to convert to HTML.
DescriptionConverts text with wiki markup to HTML. Use this method to send "pretty" notifications to unregistered users.
Example
when comments.added.isNotEmpty { for each comment in comments.added { sendMail("myuser@example.com", "Issue is commented", wikify(comment.text)); } }

Fields

The following operations are available for all fields.

becomes([field] value): Boolean
ParametersvalueThe value to check for the specified field.
DescriptionChecks whether a specific value is set for a field in the current transaction.
Example
when State == {Verified} && !State.becomes({Verified}) { assert comments.added.isEmpty: l10n ( Commenting for fixed and verified issues is disabled. ); }
canBeReadBy(User user): Boolean
ParametersuserThe user for whom the permission to read the field is checked.
DescriptionChecks whether a specific user has permission to read the field.
canBeUpdatedBy(User user): Boolean
ParametersuserThe user for whom the permission to update the field is checked.
DescriptionChecks whether a specific user has permission to update the field.
Example
when duplicates.added.isNotEmpty && State != {Duplicate} { if (State.canBeUpdatedBy(loggedInUser)) { State = {Duplicate}; } }
changed(): Boolean
DescriptionChecks whether a the value of the field is changed in the current transaction.
Example
for each comment in comments.added { text = text + " " + comment.text; } if (description.changed || becomesReported()) { text = text + " " + description; } if (summary.changed || becomesReported()) { text = text + " " + summary; }
oldValue(): [field type]
DescriptionReturns the previous value of the specified field before an update was applied.
Example
when State == {Verified} && !State.becomes({Verified}) { assert comments.added.isEmpty: l10n ( Commenting for fixed and verified issues is disabled. ); }
required(string message): void
ParametersmessageThe message that is displayed to the user that describes the field requirement.
DescriptionAsserts that a value is set for a field. If a value for the required field is not set, the field is highlighted in the issue and the specified message is displayed.
Example
state Approved { enter { Assignee.required("Please select an assignee"); }

CustomFields

The following method is available for CustomField types. See also CustomField Fields.

getPresentation(): string
DescriptionReturns the presentation of the value for a custom field.
Example
if (!Type.name.eq(Type.getPresentation(), opts)) { message("The " + Type.getPresentation() + " has been changed."); }

ProjectFields

The following methods are available for ProjectField types. See also ProjectField Fields.

getValuePresentation(Issue issue): string
ParametersissueThe issue for which the value presentation is returned.
DescriptionReturns the string presentation of the value that is used for this field in the specified issue.
getBackgroundColor(Issue issue): string
ParametersissueThe issue for which the background color is returned.
DescriptionReturns the background color that is used for this field value in the specified issue. Can return null, "write" or a hex color presentation.
getForegroundColor(Issue issue): string
ParametersissueThe issue for which the foreground color is returned.
DescriptionReturns the foreground color that is used for this field value in the specified issue. Can return null, "write" or a hex color presentation.

IssueTag

The following methods are available for IssueTag types. You can specify a tag with the literal reference {tag: [tagName]}. See also IssueTag Fields.

getShareGroup(): UserGroup
DescriptionReturns the UserGroup for whom the tag is visible. If the tag is visible only to its owner, returns null.
Example
var visible = tag.getShareGroup();
getUpdateShareGroup(): UserGroup
DescriptionReturns the UserGroup by whom the tag is updatable. If the tag is updatable only by its owner, returns null.
Example
var updatable = tag.getUpdateShareGroup();

SavedQuery

The following methods are available for SavedQuery types. You can specify a saved search with the literal reference {savedSearch: [savedSearchName]}. See also IssueTag Fields.

getOwner(): User
DescriptionReturns the User who created the saved search.
Example
var owner = {savedSearch: IDEA Backlog}.getOwner();
getShareGroup(): UserGroup
DescriptionReturns the UserGroup for whom the saved search is visible. If the saved search is visible only to its owner, returns null.
Example
var visible = {savedSearch: IDEA Backlog}.getShareGroup();
getUpdateShareGroup(): UserGroup
DescriptionReturns the UserGroup by whom the saved search is updatable. If the saved search is updatable only by its owner, returns null.
Example
var updatable = {savedSearch: IDEA Backlog}.getUpdateShareGroup();

Sequences

The workflow programming language contains a set of predefined sequences. These sequences include issues, comments, tags, users, issue links, enumerated custom fields, versions, builds, ownedFields, groups, states, static elements for sets of values, and strings. The workflow language does not let you define your own sequence of elements.

When you reference a sequence, you can look up the values that are stored in a specific field for each element. For example, issue.comments returns a sequence of IssueComment elements. You can find the first comment that was added to the issue with the operations added and first. You can then access fields for the first IssueComment, such as text or author. A statement that returns this field would look something like this:

if (comments.added.isNotEmpty) { text = comments.added.first.text;

You can also iterate over the elements in a sequence with a for each statement. For example:

for each version in Fix versions { if (version.releaseDate < now) { project.leader.notify("Overdue version!", "The issue " + getId()+ " has overdue fix version."); } }

The following operations are available for use with all sequence types.

add([sequence type] element): [element type]
ParameterselementThe element to add to the sequence.
DescriptionAdds an element to the specified sequence.
Example
Fix versions.add({Backlog});
added(): sequence<[element type]>
DescriptionReturns a sequence of elements that were added to the sequence during the current transaction.
Example
when State == {Verified} && !State.becomes({Verified}) { assert comments.added.isEmpty: l10n ( Commenting for fixed and verified issues is disabled. ); }
clear(): void
DescriptionRemoves all of the elements in the sequence.
Example
relates to.clear;
contains([sequence type] element): Boolean
ParameterselementThe element to check for in the sequence.
DescriptionChecks whether a sequence contains a specific element.
Example
if (Fix versions.contains({7.0})){ Priority = {Critical}; }
first(): [element type]
DescriptionThe first element of the sequence. If the sequence is empty, a null value is returned.
Example
when comments.added.isNotEmpty { if (All related emails.isNotEmpty){ var myComment = comments.added.first;
isEmpty(): Boolelan
DescriptionTrue if the sequence is empty.
Example
when State == {Duplicate} && duplicates.removed.isNotEmpty { if (duplicates.isEmpty) { State = {Open}; } }
isNotEmpty(): Boolelan
DescriptionTrue if the sequence is not empty.
Example
when parent for.added.isNotEmpty { for each subtask in parent for.added { if (subtask.Assignee == null) { subtask.Assignee = Assignee; } } }
last(): [element type]
DescriptionThe last element of the sequence. If the sequence is empty, a null value is returned.
Example
if (curNumber.is(numeric)) { referringIssue = loggedInUser.getIssues(project, "#" + issueID); if (referringIssue.isNotEmpty && referringIssue.first == referringIssue.last) { refers to.add(referringIssue.first);
remove([sequence type] element): [element type]
ParameterselementThe element to remove from the sequence.
DescriptionRemoves an element from the specified sequence.
Example
Fix versions.remove({Next Release});
removed() sequence<[element type]>
DescriptionReturns a sequence of elements that were removed from the sequence during the current transaction.
Example
var tag = {tag:confirmed}; tags.remove(tag); if (tags.removed.contains(tag)) { message(l10n ( Tag ' {tag.name} ' is removed.));

Projects

The following methods are available for use with projects. See also Project Fields.

getUser(string login): User
ParametersloginThe username of the user.
DescriptionReturns a user by login. If no such user exists, a null value is returned.
Example
if (created < 2012-12-31 && !isResolved()) { tags.add(project.getUser("root").getSharedTag("obsolete?")); }
isArchived(): Boolean
DescriptionChecks the current status of a project.
Example
when Assignee.changed { for each subtask in parent for { if (subtask.project.isArchived()) { continue; } if (subtask.Assignee == Assignee.oldValue) { subtask.Assignee = Assignee; } } }

The following operation is available for use with projects.

valuesFor(CustomField field): sequence<[field type]>
ParametersfieldThe name of the custom field for which values are returned.
DescriptionReturns a read-only sequence of values that are used by the custom field in this project.
Example
when parent for.added.isNotEmpty { for each subtask in parent for.added { if (project != subtask.project && issue.project.valuesFor(Fix versions).first != subtask.project.valuesFor(Fix versions).first) { continue; } if (!subtask.isResolved()) { subtask.Fix versions.clear; for each version in Fix versions { subtask.Fix versions.add(version); } } } }

Users

The following methods are available for use with User objects. See also User Fields.

getVisibleName(): string
DescriptionReturns the full name of the specified user. If the full name is not set, the username is returned.
isBanned(): Boolean
DescriptionChecks whether the user account is banned.
Example
if (Assignee.isBanned()) { Assignee = null; }
hasRole(string role): Boolean
ParametersroleThe name of role you want to check for.
DescriptionChecks whether the user has the specified role in any project.
Example
if (loggedInUser.hasRole("Developer")) { Assignee = loggedInUser; }
isInGroup(): string
DescriptionChecks whether the user is a member of the specified group.
Example
when Assignee.changed && Assignee != null { if (permittedGroup != null && !Assignee.isInGroup(permittedGroup.name)) { message(l10n ( Please take into account that new assignee ' {Assignee.fullName} ' isn't included into the visibility group ' {permittedGroup.name} '!)); } }
createNewIssue(string projectShortName): Issue
ParametersprojectShortNameThe ID of the project in which the issue is created.
DescriptionCreates a new issue in the specified project.
Example
var todoIssue = loggedInUser.createNewIssue(project.shortName); todoIssue.summary = "iPhone :" + issue.summary; todoIssue.tags.add(iOSTag); tags.add(iOSTag);
watchIssue(Issue issue): void
ParametersissueThe issue to which the user is added as a watcher.
DescriptionAdds the current user to the issue as a watcher (add Star tag).
Example
if (loggedInUser.isInGroup("developers") && loggedInUser.hasRole("Developer")) { loggedInUser.watchIssue(issue); } else { loggedInUser.unwatchIssue(issue); }
unwatchIssue(Issue issue): void
ParametersissueThe issue to from which the user is removed as a watcher.
DescriptionRemoves the current user from the list of watchers for the issue (remove Star tag).
Example
if (loggedInUser.isInGroup("developers") && loggedInUser.hasRole("Developer")) { loggedInUser.watchIssue(issue); } else { loggedInUser.unwatchIssue(issue); }
getTag(string tagName, Boolean createIfNotExists): IssueTag
ParameterstagNameThe name of the tag.
createIfNotExistsIf true and the specified tag does not exist or is not visible to the user and the user has permission to create tags, a new tag with the specified name is created.
DescriptionReturns a tag that is visible to the user.
Example
var createIfNotExist = loggedInUser.getSharedTag("iOS") == null; var iOSTag = loggedInUser.getTag("iOS", createIfNotExist);
getSharedTag(string tagName): IssueTag
ParameterstagNameThe name of the tag.
DescriptionReturns a tag with the specified name that is shared with but not owned by the user. If such a tag does not exist, a null value is returned.
Example
var createIfNotExist = loggedInUser.getSharedTag("iOS") == null; var iOSTag = loggedInUser.getTag("iOS", createIfNotExist);
canVoteIssue(Issue issue): Boolean
DescriptionChecks whether the user is able to vote for the specified issue.
Example
var user = project.getUser("user"); if (user.canVoteIssue(issue)) { user.voteIssue(issue); }
voteIssue(Issue issue): void
ParametersissueThe issue to which the vote is added.
DescriptionAdds a vote on behalf of the user to the issue, if allowed.
Example
>var user = project.getUser("user"); if (user.canVoteIssue(issue)) { user.voteIssue(issue); }
canUnvoteIssue(Issue issue): Boolean
DescriptionChecks whether the user is able to remove their vote from the specified issue.
unvoteIssue(Issue issue): void
ParametersissueThe issue from which the vote is removed.
DescriptionRemoves a vote on behalf of the user from the issue, if allowed
notify(string subject, string body, Boolean ignoreNotifyOnOwnChangesSetting)
ParameterssubjectThe subject line of the email notification.
bodyThe message text of the email notification.
ignoreNotifyOnOwnChangesSettingIf false, the message is not sent when changes are performed on behalf of the current user. The corresponding flag is unchecked. Otherwise, the message is sent anyway.
DescriptionSends an email notification to the email address that is set in the user profile.
Example
var projectLeader = project.leader; projectLeader.notify("Attention","Please pay attention to " + getId()); projectLeader.sendJabber("Please look at " + getId());
sendMail(string subject, string body): void
ParameterssubjectThe subject line text of the email notification.
bodyThe message text of the email notification.
DescriptionAn alias for notify(subject, body, true)
Example
sendMail(Reporter email, "[YouTrack, Commented]", "New comment was added: " + comments.added.first.text));
sendJabber(string text): void
ParameterstextThe message text for the Jabber notification.
DescriptionSends a notification message over Jabber. Similar to notify method, the message won't be sent on own changes and corresponding flag unchecked.
Example
project.leader.sendJabber("Please pay attention to " + getId());

The following operation is available for use with User objects.

getIssues(SavedQuery context, string query): sequence<Issue>
ParameterscontextThe name of the saved search to use as the context for the search query. The default context is Everything.
queryThe search query. Can be an empty string.
DescriptionReturns a list of issues based on the specified context and search query.
Example
for each notMyIssue in loggedInUser.getIssues({savedSearch: Reported by me}, "for: -me") { notMyIssue.Assignee = loggedInUser; }
Variations
var issues = project.leader.getIssues(Everything, ""); var issues = project.leader.getIssues({savedSearch: Unassigned in A}, ""); var issues = project.leader.getIssues({savedSearch: Unassigned in A}, "Priority: Critical");

UserGroups

The following methods are available for use with UserGroups. See also UserGroup Fields.

getUsers(): sequence<User>
DescriptionReturns all of the users who are members of the specified group.
Example
var users = Assignees group.getUsers();
notifyAllUsers(string subject, string body): void
ParameterssubjectThe subject line of the email notification.
bodyThe message text of the email notification.
DescriptionSends an email notification to all of the users who are members of the group.
Example
permittedGroup.oldValue.notifyAllUsers("Visibility has been changed", "The visibility group for the issue " + "<a href=\"" + issue.getUrl() + "\">" + issue.getId() + "</a> has been changed to " + permittedGroup.name);
Last modified: 2 February 2017