State-machine Rules
A state-machine rule regulates the transitions from one value to another for a custom field. YouTrack provides templates for two types of state-machine rules.
A basic state-machine rule that regulates the transitions from one value to another for a custom field. To learn more about this type of state-machine, see Basic State-machines.
A state-machine rule that imposes separate sets of state transitions based on the current value in a specified field. To learn how to script this type of state-machine, see State-machine Rules State-machines per Issue Type.
Both of these state-machine types are built using a similar collection of parameters.
You can apply a state-machine rule to any custom field. However, the most common use case for a state-machine rule is to regulate transitions between values for the State field or another custom field that stores a state
type.
When a state-machine rule is applied to a project, the options that are shown in the drop-down list for the field are restricted to the transitions that are defined in the state-machine rule for the current state. Custom fields that are regulated by a state-machine rule are marked with a Workflow-driven field icon. The action that is defined for each value in the state-machine rule is displayed in the drop-down list. The actual values are shown to the right. The following image illustrates how the list of allowed transitions for the State field changes based on the current value.
Basic State-machines
A basic state-machine regulates the transitions from one value to another for a custom field for all issues in any project that uses the workflow. For each transition, you can add one or more actions. Additional properties for each transition determine how these actions are applied.
Transitions that use
onEnter
andonExit
properties perform an action when the value for the field is set. These actions are executed by the user who changes the value of the field.Transitions that use the
after
property perform an action after the specified time frame. These actions are executed by the workflow user account.
This example that follows shows a simplified state-machine rule. This rule defines the transitions that are allowed for the State field.
The following transitions are defined in this rule:
From the initial Open state, the value can change to In Progress. An additional transition with the name
reminder
includes anafter
property that reminds the project owner if an issue remains in the Open state for more than two days.When the issue transitions from Open to In Progress, the
onEnter
property for theIn progress
state automatically assigns the issue to the user who changes the value of the State field.From In progress, the value can change to Fixed or Open. When an issue transitions from In Progress back to Open an automation for this transition asks the user to unassign the issue, otherwise the transition is blocked.
The final state is Fixed. There are no additional transitions that are defined for this value. Once this value is set, it cannot be changed.
The following diagram shows an abstract representation of this rule.
The workflow rule that supports this state-machine is written as follows:
The components that define this state-machine rule are as follows:
The
require
statements reference theentities
module and theworkflow
module in the workflow API.The
exports.TWO_DAYS
property sets a local variable that is used to send the reminder for issues that have the Open status. This variable is assigned a value that equals 2 days in milliseconds.The
exports.rule
property uses theIssue.stateMachine
method to export the script that follows the declaration as a state-machine rule.The body of the rule itself contains definitions for the following properties:
Property
Description
title
An optional human-readable title.
fieldName
The name of the custom field that is managed by the state-machine.
states
The list of field values and definitions for the transitions between them. Values that contain spaces and special characters are set in single quotes.
requirements
The list of entities that are required for the rule to execute without errors. This property ensures that rules can be attached to projects safely.
In this example, we only require that there is an Assignee field that stores a
user
type in the projects to which the rule is attached. If this field is absent, an error is shown in the Workflows list. The rule cannot be enabled until the required field is attached.For a state-machine rule, you do not need to add the field that is managed by the state-machine to the requirements. This field and its values are derived from the
states
property.Each of the values that are defined in the
states
property contain definitions for the following additional properties:Property
Description
initial
A Boolean property that determines which of the values in the list is set when an issue is created. Exactly one value must set this property to
true
. For other values that are not set as the initial value, this property is optional and can be omitted.onEnter
An optional function declaration that is called when the corresponding value is assigned to an issue. These functions behave similar to actions in other types of rules.
onExit
An optional function declaration that is called when the field value is changed from the current value to another value. These functions behave similar to actions in other types of rules.
transitions
The list of possible target values that can be set for each value in the list.
In this example, we only require that there is an Assignee field that stores a
user
type in the projects to which the rule is attached. If this field is absent, an error is shown in the Workflows list. The rule cannot be enabled until the required field is attached.For a state-machine rule, you do not need to list the values that are used by fields that are managed by the state-machine in the requirements. This field and its values are derived from the
states
property.Each of the values that are defined in the
transitions
property contain aname
property. The name is used to set this value in a command and is also shown in the list of values for a custom field. Each transition name contains definitions for the following additional properties:Property
Description
targetState
The actual name of the value that is set when the command specified in the
name
property is applied.after
An optional property that sets an interval for performing an action. The action itself is specified in the
action
property.action
An optional property for any transition that behaves similar to actions in other types of rules..
guard
An optional condition that determines when the transition is allowed. If the guard condition is not met, the value for the custom field cannot change to the value that is defined for this transition.
In this example, for an issue to transition from In progress back to an Open state, the issue must be unassigned. The guard contains a function that uses the
message
method from theworkflow
module to provide feedback to the user who attempts to reopen an issue without unassigning it first.
State-machines per Issue Type
A state-machine per issue type adds an additional dimension to a basic state-machine. Instead of regulating a single set of transitions for values in a custom field, the rule provides separate state-machines for each of the possible values in a separate field.
Just like you can apply a state-machine rule to any custom field, not just the default State field, you can make type-specific transitions depend upon the value in any enumerated field, not just the default Type field. The most common use case is to regulate transitions between values for the State field based on the current value for the issue Type.
A state-machine per issue type is written similarly to a basic state-machine, with the following changes:
The
fieldName
property is replaced with an alias,stateFieldName
in the template for a new state-machine rule. The value for this property determines which field is managed by the state-machine rule.A separate property for the
typeFieldName
lets you specify the field that dictates which state-machine applies to the state field. The presence of this property is the main difference between a basic state-machine (which doesn't use it) and a state-machine per issue type.The
states
property is replaced with an alias,defaultMachine
. This property describes the default set of transitions for values in the managed field. This state-machine applies to issues that are not assigned a value for which an alternative state-machine has been defined.The
alternativeMachines
property stores a collection of state-machine transitions for designated values in the custom field that is set for thetypeFieldName
property.
When you specify a value for the typeFieldName
, configure the defaultMachine
, and define at least one state-machine for a value in the alternativeMachines
section of the rule, you end up with a state-machine per issue type. The field that you specify for the typeFieldName
property functions as a switch between the default state-machine and the collection of alternative state-machines.
The following example shows how to build a state-machine per issue type. Each of the tabs below describes the state-machine that corresponds to one of the possible values for the Type field.
First, we take the logic that is applied in the basic state-machine rule above and apply it as a default to any type of issue in a project. As a result, the values for the State field in issues that are assigned the Task type are regulated according to the model shown above. This state-machine also applies to issues that are assigned any type that isn't assigned an alternative state-machine.
Next, we'll add an alternative state-machine just for issues that are assigned the Bug type.
For this issue type, we make it possible to assign the value Can't Reproduce to the State field.
We'll make it a little more flexible than the default state-machine, allowing a transition from Fixed back to Open. This means that we can reopen issues when a regression occurs instead of having to report the same problem more than once.
We'll also make it possible to transition from Can't Reproduce back to Open.
We add some automation to specific states and transitions.
When an issue moves from Open to In Progress, the issue is assigned to the user who changes the issue state. This is the same definition for the
onEnter
property that is used for theIn progress
state in the basic state-machine.For the transition from In Progress to Can't Reproduce we add an
action
. This displays an alert that asks the user to describe what steps they took to try to reproduce the bug.From Fixed the issue can only transition back to the Open state. As a result, we can add an automation for the
onExit
property to the definition for theFixed
field. This automation sends a notification to the assignee to inform them that the issue was reopened.
We'll add one more alternative state-machine and apply this to issues that are assigned the Feature type.
For these types of issues, we add the possibility to move an issue directly from an Open state to Rejected. If anybody suggests a feature that the team decides doesn't fit with their vision of the product, they can throw it out.
Just to be open to the possibility for a change in direction, we'll allow issues to transition from Rejected back to Open.
All of the other transitions are similar to the state-machine for bugs.
To keep it simple, we haven't added any automations to this state-machine. That doesn't mean that there aren't any opportunities to automate or enhance the process for this issue type. Possible enhancements include:
Using an
after
event to the set of transitions for the Open state to tag issues that remain in this state for over six months. You can then review all of the tagged issues in your next backlog grooming session.Adding an
onEnter
event to the In Progress state, prompting the user to assign the feature to a specific milestone or pipeline in the roadmap.Adding an
action
event to the transition from Rejected to Open, prompting the user to justify why they would reopen the feature request for future consideration.
We can take the sample code for the basic state-machine rule and quickly convert it into a state-machine per issue type with just a few changes.
While it's not required, we have replaced the name of the
fieldName
property with its alias,stateFieldName
. As with the sample for the basic state-machine, we're managing transitions between values for a field calledState
. We don't change the value for this property.We've added the property
typeFieldName
and specified'Type'
as its value. This means that the Type field can now be used as a switch to determine whether to apply the default state-machine or an alternative state-machine that is assigned to one of the possible values for this field.We've applied another change just for cosmetic purposes, replacing the name of the
states
property with its alias,defaultMachine
. We don't change the value for this property. Instead, we reuse the basic state-machine rule, which will apply to any issue that isn't assigned one of the types that are defined in thealternativeMachines
section of the rule.We've added a new section for
alternativeMachines
. Here, we specify state-machines for issues that are assigned the values Bug and Feature in the Type custom field.
Here's the modified state-machine rule:
The components that define this state-machine rule are as follows:
The
require
statements reference theentities
andworkflow
modules in the workflow API.The
exports.TWO_DAYS
property sets a local variable that is used to send the reminder for issues that have the Open status. This variable is assigned a value that equals 2 days in milliseconds.The
exports.ONE_WEEK_IN_MS
property sets a local variable that is used to send the reminder for bugs that have been In Progress for more than one week. This variable is assigned a value that equals one week in milliseconds.The
exports.rule
property uses theIssue.stateMachine
method to export the script that follows the declaration as a state-machine rule.The body of the rule itself contains definitions for the following properties:
Property
Description
title
An optional human-readable title.
stateFieldName
The name of the custom field that is managed by the state-machine.
typeFieldName
The name of the custom field that regulates which state-machine is applied to the managed field.
defaultMachine
The list of field values and definitions for the transitions between them for the default state-machine. The default state-machine applies to any issue that isn't assigned one of the types that are defined in the
alternativeMachines
section of the rule.Values that contain spaces and special characters are set in single quotes.
alternativeMachines
Stores a collection of state-machine transitions for designated values in the custom field that is set for the
typeFieldName
property.requirements
The list of entities that are required for the rule to execute without errors. This property ensures that rules can be attached to projects safely.
In this example, we only require that there is an Assignee field that stores a
user
type in the projects to which the rule is attached. If this field is absent, an error is shown in the Workflows list. The rule cannot be enabled until the required field is attached.For state-machines by issue type, you don't need to add any of the fields that are managed by the state-machine to the requirements. This field and its values are derived from the
defaultMachine
property and the collection of fields that are defined for each value in thealternativeMachines
section of the rule. The field that is set for thetypeFieldName
property is also implicitly added to the requirements for the workflow rule.Each of the values that are defined in the
defaultMachine
property and each of the fields that are defined for each value in thealternativeMachines
section of the rule contain definitions for the following additional properties:Property
Description
initial
A Boolean property that determines which of the values in the list is set when an issue is created. Exactly one value must set this property to
true
. For other values that are not set as the initial value, this property is optional and can be omitted.onEnter
An optional function declaration that is called when the corresponding value is assigned to an issue. These functions behave similar to actions in other types of rules.
onExit
An optional function declaration that is called when the field value is changed from the current value to another value. These functions behave similar to actions in other types of rules.
transitions
The list of possible target values that can be set for each value in the list.
In this example, we only require that there is an Assignee field that stores a
user
type in the projects to which the rule is attached. If this field is absent, an error is shown in the Workflows list. The rule cannot be enabled until the required field is attached.For a state-machine rule, you do not need to list the values that are used by fields that are managed by the state-machine in the requirements. This field and its values are derived from the
states
property.Each of the values that are defined in the
transitions
property contain aname
property. The name is used to set this value in a command and is also shown in the list of values for a custom field. Each transition name contains definitions for the following additional properties:Property
Description
targetState
The actual name of the value that is set when the command specified in the
name
property is applied.after
An optional property that sets an interval for performing an action. The action itself is specified in the
action
property.action
An optional property for any transition that behaves similar to actions in other types of rules..
guard
An optional condition that determines when the transition is allowed. If the guard condition is not met, the value for the custom field cannot change to the value that is defined for this transition.
In this example, for an issue to transition from In progress back to an Open state, the issue must be unassigned. The guard contains a function that uses the
message
method from theworkflow
module to provide feedback to the user who attempts to reopen an issue without unassigning it first.The
alternativeMachines
property stores a set of values from the field that is referenced in thetypeFieldName
property. Each of the values that are assigned dedicated state-machines are simply referenced by name.