YouTrack Cloud 2023.3 Help

Streamline Issue Reporting

You can set up a basic issue reporting process without workflows. It all starts with the configuration of the custom fields in your projects. For most custom fields, you can choose whether the field can or cannot be empty.

If the field is cannot be empty, you must assign a default value in the configuration. This value is automatically assigned to each issue that is reported in the project. Moreover, you cannot clear the value of the field, only replace it with another value.

By defining whether fields can or cannot be empty and setting default values accordingly, you can effectively set the starting point for new issues in your project.

While field configuration options are useful, they have some limitations. There are a number of use cases that are not addressed by empty values and default values:

  • You want to require a value in the Due Date field. Fields that store simple values (like string, integer, float, date, or period) cannot store a default value. In new issues, these fields are always empty.

  • You want reporters to set the value in a specific field without suggesting a default. For example, you want to assign each task to a Subsystem, but there isn’t a logical value that you would suggest as a default.

  • You want to set default values dynamically. For example, you always want the Due Date to be two weeks from today.

  • You want to provide your customers with a template for reporting issues. The template contains predefined values for custom fields and a default description.

  • As an extension of the previous case, you want to provide your customers with a collection of templates for issues in the same project. Each template varies based on the value that is selected for a custom field value (like Type) or can be applied to a draft using menu actions.

Support for these use cases can be implemented with various workflow rules, some of which are already available as default workflows in YouTrack.

Make a Field Mandatory

The first case is about making simple fields mandatory for new issues. This case is addressed by the issue.fields.required(field, message) method. This method checks if the field is empty. If it is, the current changes are rolled back and a message is shown to the reporter. Check out the Require due dates for submitted issues rule from the Due Date workflow:

const entities = require('@jetbrains/youtrack-scripting-api/entities'); const workflow = require('@jetbrains/youtrack-scripting-api/workflow'); exports.rule = entities.Issue.onChange({ title: 'Require due dates for submitted issues', guard: (ctx) => { return ctx.issue.becomesReported; }, action: (ctx) => { ctx.issue.fields.required(ctx.DueDate, workflow.i18n('You must set the Due date!')); }, requirements: { DueDate: { type: entities.Field.dateType, name: "Due Date" } } });

Note the guard in this rule. This guard ensures that the check is only initiated once, after the reporter has filled in the issue content and attempts to create the issue.

If you want to make it so the value for this field cannot be removed for submitted issues, update the guard as follows:

guard: (ctx) => { return ctx.issue.isReported; }

The use case for making reporters set the value in a specific field is solved with the same kind of rule. Simply take a custom field that can be empty and check whether it is empty or not when a new issue is reported. The issue.fields.required(field, message) method works the same for all types of custom fields.

Set Dynamic Defaults

You can use workflows to calculate the default value for a field automatically. For example, the following rule sets the value for the Due date field to a date that is two weeks from the current date:

const entities = require('@jetbrains/youtrack-scripting-api/entities'); const WEEK_IN_MS = 7 * 24 * 60 * 60 * 1000; exports.rule = entities.Issue.onChange({ title: 'Set Due Date on issue submitting', guard: (ctx) => { return ctx.issue.becomesReported && !ctx.issue.fields.DueDate; }, action: (ctx) => { ctx.issue.fields.DueDate = Date.now() + 2 * WEEK_IN_MS; }, requirements: { DueDate: { type: entities.Field.dateType, name: 'Due Date' } } });

Build Issue Templates

Another popular case that is supported by one of the default workflows adds a default description to new issues. Here is how it is implemented in our Default Description workflow:

const entities = require('@jetbrains/youtrack-scripting-api/entities'); const workflow = require('@jetbrains/youtrack-scripting-api/workflow'); exports.rule = entities.Issue.onChange({ title: 'Insert default description template for external users', guard: (ctx) => { const issue = ctx.issue; return !issue.isReported && !issue.becomesReported && !issue.description; }, action: (ctx) => { ctx.issue.description = workflow.i18n('What steps will reproduce the problem?') + "\n1.\n2.\n3.\n\n" + workflow.i18n("What is the expected result?") + "\n\n" + workflow.i18n("What happens instead?") + "\n\n" + workflow.i18n("Please provide any additional information below.") + "\n" + workflow.i18n("Attach a screenshot if possible") + "\n"; }, requirements: {} });

This workflow rule sets the default description for each new issue. This rule is triggered as soon as the reporter edits any value in the new issue, for example, typing a summary or changing the project. Due to technical limitations, this rule can’t be applied at the moment when the New Issue page opens.

You can extend this workflow to let reporters choose between different templates without filling in a lot of data manually. For example, you can use different templates for feature requests and bug reports:

  • For bug reports, you require the steps to reproduce (STR) in the description.

  • For features, you require the suggestion and motivation (what and why). You also want to set the value for the Fix versions field to Backlog.

For this case, the easiest approach consists of two parts:

  • Make the Type field empty by default.

  • Force setting the value for the Type field when the reporter starts to create an issue:

    const entities = require('@jetbrains/youtrack-scripting-api/entities'); exports.rule = entities.Issue.onChange({ title: 'Choose Type when new issue is created', guard: (ctx) => { const issue = ctx.issue; return !issue.isReported && !issue.becomesReported && !issue.fields.Type && !issue.isChanged('project'); }, action: (ctx) => { ctx.issue.fields.required(ctx.Type, 'Please choose issue Type before editing!'); }, requirements: { Type: { type: entities.EnumField.fieldType } } });
  • Add a rule which sets the values based on the selection in the Type field:

    const entities = require('@jetbrains/youtrack-scripting-api/entities'); exports.rule = entities.Issue.onChange({ title: 'Set issue template based on Type', guard: (ctx) => { const issue = ctx.issue; return !issue.isReported && !issue.becomesReported && !issue.description && issue.fields.isChanged(ctx.Type) && !issue.fields.oldValue(ctx.Type); }, action: (ctx) => { const issue = ctx.issue; const typeIs = function (value) { return issue.fields.Type.name === value.name; }; if (typeIs(ctx.Type.Bug)) { issue.description = 'What steps will reproduce the problem?' + '\n1.\n2.\n3.\n\n' + 'What is the expected result?\n\n' + 'What happens instead?\n'; } else if (typeIs(ctx.Type.Feature)) { issue.description = 'What should be implemented?\n\n' + 'Why is this functionality required?\n'; issue.fields.FixVersions.add(ctx.FixVersions.Backlog); } }, requirements: { Type: { type: entities.EnumField.fieldType, Bug: {}, Feature: {} }, FixVersions: { type: entities.ProjectVersion.fieldType, multi: true, name: 'Fix versions', Backlog: {} } } });

Add Templates to the Actions Menu

Another way to support this use case is to provide a list of templates in the form of actions. Action rules are a special type of workflow rule. Each action rule is associated with a command and an item in the list of actions that are shown in the Command Dialog drop-down menu. These rules are triggered when the user executes the command or clicks the corresponding item. For details, see Action Rules.

Here’s a sample action rule for the feature request template:

const entities = require('@jetbrains/youtrack-scripting-api/entities'); exports.rule = entities.Issue.action({ title: 'Feature template', command: 'feature-template', guard: (ctx) => { const issue = ctx.issue; return !issue.isReported && !issue.becomesReported && !issue.description; }, action: (ctx) => { const issue = ctx.issue; issue.description = 'What should be implemented?\n\n' + 'Why is this functionality required?\n'; issue.fields.Type = ctx.Type.Feature; issue.fields.FixVersions.add(ctx.FixVersions.Backlog); }, requirements: { Type: { type: entities.EnumField.fieldType, Feature: {} }, FixVersions: { type: entities.ProjectVersion.fieldType, multi: true, name: 'Fix versions', Backlog: {} } } });

To make reporters select a template, first check if the description is empty. If so, suggest that they choose a template from the menu.

const entities = require('@jetbrains/youtrack-scripting-api/entities'); const workflow = require('@jetbrains/youtrack-scripting-api/workflow'); exports.rule = entities.Issue.onChange({ title: 'Choose a template when new issue is created', guard: (ctx) => { const issue = ctx.issue; return !issue.isReported && !issue.becomesReported && !issue.description; }, action: (ctx) => { workflow.check(false, 'Please, choose one of templates in action menu!'); }, requirements: { Type: { type: entities.EnumField.fieldType } } });

The field-based approach is better for simple cases. When you have complex templates that are defined by a combination of field values, use the action-based approach.

Last modified: 29 February 2024