Developer Portal for YouTrack and Hub Help

Subtasks

This workflow automatically sets the state of a parent task when the state changes in issues that are linked as subtasks.

Name

@jetbrains/youtrack-workflow-subtasks

Auto-attached

yes

Modules

Open parent task when subtask changes to an unresolved state (on-change rule)

Fix parent task when all subtasks are resolved (on-change rule)

Use Case

You want to automatically update the state of a parent task when changes are applied to subtasks.

  • When any subtask is set to an unresolved state, the state of the parent task changes to Open.

  • When all subtasks are set to a resolved state, the state of the parent task changes to Fixed.

Modules

This workflow includes two modules.

Open parent task when subtask changes to an unresolved state

When the state of an issue is set to an unresolved state, this rule checks whether the issue is linked as a subtask of a parent task. If the parent task belongs to an active project and has a resolved state, the state of the parent task is changed to Open.

const entities = require('@jetbrains/youtrack-scripting-api/entities'); const workflow = require('@jetbrains/youtrack-scripting-api/workflow'); exports.rule = entities.Issue.onChange({ title: 'Open parent task when subtask changes to an unresolved state', guard: (ctx) => { return ctx.issue.isReported && ctx.issue.becomesUnresolved; }, action: function (ctx) { const processParent = function (issue) { if (issue.links['subtask of'].isEmpty()) { return; } const parent = issue.links['subtask of'].first(); if (parent && parent.project && !parent.project.isArchived && parent.isReported && parent.isResolved) { const field = parent.project.findFieldByName(ctx.State.name); if (field) { const value = field.findValueByName(ctx.State.Open.name); if (value) { parent.State = value; workflow.message('Automatically reopen {0}', parent.id); return parent; } } } }; let issue = ctx.issue; while (issue) { issue = processParent(issue); } }, requirements: { State: { type: entities.State.fieldType, Open: {} } } });

Fix parent task when all subtasks are resolved

When the state of an issue is set to a resolved state, this rule checks whether the issue is linked as a subtask of a parent task. If the parent task is unresolved, the rule checks the current state for all other issues that are linked to the parent task as subtasks. If all other subtasks are resolved, the state of the parent task is set to Fixed.

The rule then checks the parent task to see if it is linked as a subtask to a parent task and performs the same operation.

const entities = require('@jetbrains/youtrack-scripting-api/entities'); const workflow = require('@jetbrains/youtrack-scripting-api/workflow'); exports.rule = entities.Issue.onChange({ title: 'Fix parent when all subtasks are resolved', guard: (ctx) => { return ctx.issue.isReported && ctx.issue.becomesResolved; }, action: (ctx) => { const processParent = function (issue) { if (issue.links['subtask of'].isEmpty()) { return; } const parent = issue.links['subtask of'].first(); if (parent && parent.project && !parent.project.isArchived && parent.isReported && !parent.isResolved) { const unresolvedSubtask = parent.links['parent for'].find(function (subtask) { return subtask.isReported && !(subtask.fields.State && subtask.fields.State.isResolved); }); if (!unresolvedSubtask) { const field = parent.project.findFieldByName(ctx.State.name); if (field) { const value = field.findValueByName(ctx.State.Fixed.name); if (value) { parent.State = value; if (parent.isVisibleTo(ctx.currentUser)) { workflow.message('Automatically set {0} as Fixed', parent.id); } return parent; } } } } }; let issue = ctx.issue; while (issue) { issue = processParent(issue); } }, requirements: { State: { type: entities.State.fieldType, Fixed: {} } } });
Last modified: 15 March 2024