Any help with this would be greatly appreciated.
I have two youtrack projects 'Support' and 'Bug DB'. In the support project I have a workflow rule that a specific state transition to a state 'Awaiting Fix' automatically generates an issue in the 'Bug DB' project and links back to the original issue with an 'affects helpdesk log' link type.
In the 'Bug DB' project I want to add a rule to automatically update the state of the issue in the 'Support' project to 'Action Required' when a specific state transition occurs.
I can manage the state transition parts but I have two outstanding problems in my code for the 'Bug DB' project:
Currently I have a function that (I hope) just checks that a link exists - ideally this should check that the link specifically points to an issue in the 'Support' project.
const issue_0 = ctx.issue;
...
function hasLinkedSupportIssue() {
//I think this is equivalent to a C# .Any()
return issue_0.links.added
}
To apply the new state I am iterating the linked issues (because I don't know how to get a specific one)
issue_0.links['affects helpdesk log'].added.forEach(updateState)
and I then have a function that will do the actual update
const updateState = function(supportIssue) {
//Check here that this is a 'Support' issue
//because my guard is not sufficient
if(supportIssue.project.key === 'Support') {
//not sure I can do assignment like this
supportIssue.state = ctx.SupportState.ActionRequired;
}
}
....
requirements: {
BugState: {
name: "State",
type: entities.State.fieldType,
InProgress: {name: "In Progress"},
Closed: {name: "Closed"}
},
SupportState: {
name: "State",
type: entities.State.fieldType,
AwaitingFix: {name: "Awaiting Fix"},
ActionRequired: {name: "Action Required"}
}
For anyone trying to do this, this was the eventual solution I came up with:
var entities = require('@jetbrains/youtrack-scripting-api/entities');
var workflow = require('@jetbrains/youtrack-scripting-api/workflow');
exports.rule = entities.Issue.onChange({
title: 'Support_bug_resolved',
guard: (ctx) => {
const logger = new Logger(ctx.traceEnabled);
const thisIssue = ctx.issue;
function checkFieldState() {
//check that state is changing from closed to resolved
return thisIssue.fields.isChanged(ctx.BugState) && thisIssue.fields.was(ctx.BugState, ctx.BugState.Resolved) && thisIssue.fields.becomes(ctx.BugState, ctx.BugState.Closed);
}
function hasLinkedSupportIssue() {
//Check we have a linked issue from the support project
return thisIssue.links["helpdesk log affected by"] != 0;
}
function checkFieldFn() {
var check = checkFieldState();
var hasLink = hasLinkedSupportIssue();
return check && hasLink;
};
try {
return checkFieldFn();
} catch (err) {
logger.error(err.message);
}
},
action: function(ctx) {
const logger = new Logger(ctx.traceEnabled);
const thisIssue = ctx.issue;
//Get the first linked support issue - we assume there is always only one
const supportIssue = thisIssue.links['helpdesk log affected by'].first();
try {
//If the current state of the linked issue is 'Awaitingfix', make it 'ActionRequired'
if(supportIssue.State.name == "AwaitingFix") {
supportIssue.State = ctx.SupportState.ActionRequired;
}
} catch(err) {
logger.error(err.message);
}
},
requirements: {
BugState: {
name: "State",
type: entities.State.fieldType,
Resolved: {name: "Resolved"},
Closed: {name: "Closed"}
},
SupportState: {
name: "State",
type: entities.State.fieldType,
AwaitingFix: {name: "AwaitingFix"},
ActionRequired: {name: "ActionRequired"}
}
}
});
function Logger(useDebug = true) {
return {
log: (...args) => useDebug && console.log(...args),
warn: (...args) => useDebug && console.warn(...args),
error: (...args) => useDebug && console.error(...args)
}
}