YouTrack Standalone 2020.2 Help

Using the Workflow API

Use the information on this page to learn how to work with specific entities in the workflow API that are not described in other sections of the workflow reference.

Follow these guidelines to access issue properties, values in custom fields, and issue links.

Predefined issue fields like summary, description, and reporter are all properties of the issue entity.

var summary = issue.summary; issue.summary = "Just a bug";

References to values in a custom field vary based on whether the field stores single or multiple values.

  • For fields that store single values, you can reference the value directly:

    var state = issue.fields.State; issue.fields.State = ctx.State.Open; if (issue.fields.State.name === ctx.State.Fixed.name) { // Do stuff }

  • For fields that store multiple values, the values are stored as a set. The operations that are available for sets are described in more detail in the next section.

    var versions = issue.fields["Fix versions"]; versions.forEach(function(v) { subtask.fields["Fix versions"].add(v); });

If you set the alias property for a custom field in the requirements statement, you can use this alias to access values for the field as well. For example, if the alias for the Fix versions field is set to FV:

issue.fields.FV.forEach(function(v) { // Do stuff });

Issue link types are accessed by their inward or outward name. For example, relates to or parent for. Issue links are always treated as a set.

var parent = issue.links["subtask of"].first(); parent.links["parent for"].add(issue);

Note that custom fields and issue link types that contain spaces or other non-alphabetic characters must be set in quotation marks and brackets.

Working with Set Objects

There are several groups of operations you can do with multiple values (returned as Set<value type>):

  • Access them directly (first(), last(), get(index)) or by iterator (entries(), values()).

  • Traverse over all values in Set with forEach(visitor).

  • Look for values with find(predicate) and check if a value is in Set with has(value).

  • Check size with isEmpty(), isNotEmpty() and size property.

  • Modify content with add(element), remove(element) and clear().

  • Get the current changes for a Set object with the added, removed and isChanged properties.

For a detailed description of this object, see Set.

Calling Methods

// Call entity method: var stateCF = issue.project.findFieldByName('State'); // Call static method: var p = entities.Project.findByKey('INT'); // Call issue constructor: var newIssue = new entities.Issue(ctx.currentUser, issue.project, "Subtask");

Finding Specific Entities

There are two ways to find a specific entity, like an issue or a user, and use it in a workflow script:

  1. Add it in the requirements and reference it in the context. Use this approach as often as you can, as it is the most reliable. If the specified entity is not found in your database, the script is not executed.

  2. If the first option is not applicable for whatever reason, use the findBy* and find*By* methods from the workflow API:

Use findBy* methods to find a single occurrence of a specific entity:

var issue = entities.Issue.findById('MP-23'); // an entities.Issue or null var projectByName = entities.Project.findByName('Music Production'); // an entities.Project or null var projectByKey = entities.Project.findByKey('MP'); // an entities.Project or null var user = entities.User.findByLogin('jane.smith'); // an entities.User or null var userGroup = entities.UserGroup.findByName('MP team'); // an entities.UserGroup or null var agiles = entities.Agile.findByName('MP Scrum'); // a Set of entities.Agile var tags = entities.IssueTag.findByName('production'); // a Set od entities.IssueTag var queries = entities.SavedQuery.findByName('MP Backlog'); // a Set of entities.SavedQuery

Use find*By* methods to find child entities:

var sprint = agiles.first().findSprintByName('Sprint 23'); // an entities.Sprint or null var priorityField = projectByKey.findFieldByName('Priority'); // an entities.ProjectCustomField or null var major = field.findValueByName('Major'); // an entities.Field or null var critical = field.findValueByOrdinal(1); // an entities.Field or null var assigneeField = projectByKey.findFieldByName('Assignee'); var jane = assigneeField.findValueByLogin('jane.smith'); // an entities.User or null var groupField = projectByKey.findFieldByName('Requestors'); var newBand = groupField.findValueByName('New Band'); // an entities.UserGroup or null

Finding Multiple Issues

Sometimes you might want to find a set of issues that match certain criteria and process them in the scope of a single rule. For example, you can compile a list of issues and sent it as an email message. In these situations, the search API can help. Here's a simple example:

var entities = require('@jetbrains/youtrack-scripting-api/entities'); var search = require('@jetbrains/youtrack-scripting-api/search'); var workflow = require('@jetbrains/youtrack-scripting-api/workflow'); exports.rule = entities.Issue.onChange({ title: 'Do not allow developers to have more than 1 issue in progress per project', action: function(ctx) { var issue = ctx.issue; if (issue.isReported && (issue.fields.becomes(ctx.State, ctx.State['In Progress']) || issue.fields.isChanged(ctx.Assignee)) && (issue.fields.Assignee || {}).login === ctx.currentUser.login) { // First, we build a search query that checks the project that the issue belongs to and returns all of the issues // that are assigned to current user except for this issue. var query = 'for: me State: {In Progress} issue id: -' + issue.id; var inProgress = search.search(issue.project, query, ctx.currentUser); // If any issues are found, we get the first one and warn the user. if (inProgress.isNotEmpty()) { var otherIssue = inProgress.first(); var message = 'Dear ' + ctx.currentUser.login + ', please close <a href="' + otherIssue.url + '">' + otherIssue.id + '</a> first!'; workflow.check(false, message); } } }, requirements: { State: { type: entities.State.fieldType, 'In Progress': {} }, Assignee: { type: entities.User.fieldType } } });
Last modified: 1 July 2020