const { issues, search } = require('@forge/jira');
const jql = `status = Completed AND updated <= '-7d' AND 'Work Type' = Incident`;
const searchResult = await search.findJiraIssues(jql);
for (const issue of searchResult.issues) {
const issueKey = issue.key;
console.log(`Processing issue: ${issueKey}`);
const availableTransitions = await issues.getTransitions({ issueKey });
const closeTransition = availableTransitions.transitions.find(t => t.to.name.toLowerCase() === 'closed');
if (closeTransition) {
await issues.transition({
issueKey: issueKey,
transition: { id: closeTransition.id }
});
console.log(`Successfully transitioned ${issueKey} to Closed.`);
} else {
console.error(`Could not find a transition to 'Closed' for issue ${issueKey}.`);
}
}
const { fields } = require('@forge/jira');
// IMPORTANT: Replace these placeholder IDs with your actual custom field IDs.
const SUBCATEGORY_FIELD_ID = 'customfield_10100';
const ASSIGNMENT_GROUP_FIELD_ID = 'customfield_10101';
const issueKey = context.issue.key;
const subcategoryField = await fields.get({ issueKey, fieldId: SUBCATEGORY_FIELD_ID });
const subcategory = subcategoryField?.value;
if (!subcategory) {
console.log(`No Subcategory set for ${issueKey}. Exiting.`);
return;
}
const routingMap = {
'Re-Image Laptop': 'Computer/Accessories',
'Password Reset': 'Computer/Accessories',
'PC': 'Computer/Accessories',
'Access': 'Application Services',
'Software Installation': 'Application Services',
'Workday Issues/Request': 'HR - Workday',
'System Integration': 'ERP Solutions',
'Subscriptions': 'Mobile / Cell Phones'
};
const assignmentGroup = routingMap[subcategory];
if (assignmentGroup) {
console.log(`Setting Assignment Group to '${assignmentGroup}' for ${issueKey}.`);
await fields.set({
issueKey,
fieldId: ASSIGNMENT_GROUP_FIELD_ID,
value: { value: assignmentGroup } // Assumes a single-select list field type
});
}
// This script runs as a transition validator and must return a boolean value.
// 'true' allows the transition, 'false' blocks it.
const commentsAdded = context.issue.comments.added;
if (commentsAdded && commentsAdded.length > 0) {
// A comment was added during the transition, so allow it.
return true;
} else {
// No comment was added, so block the transition.
return false;
}
const { search, issues } = require('@forge/jira');
const jql = `status = Pending AND updated <= '-3d' AND 'Work Type' = Incident`;
const searchResult = await search.findJiraIssues(jql);
for (const issue of searchResult.issues) {
const issueKey = issue.key;
const assignee = issue.fields.assignee;
if (assignee && assignee.accountId) {
const mention = `[~accountid:${assignee.accountId}]`;
const commentBody = `${mention}, this incident has been in 'Pending' status for over 3 days. Please provide an update or progress the issue.`;
console.log(`Adding escalation comment to ${issueKey}`);
await issues.addComment({
issueKey,
body: commentBody
});
} else {
console.log(`Issue ${issueKey} is unassigned, skipping comment.`);
}
}
const { issues } = require('@forge/jira');
const issueKey = context.issue.key;
const changelog = context.changelog;
const assigneeChange = changelog.items.find(item => item.fieldId === 'assignee');
// Check if assignee was changed from unassigned to assigned
if (assigneeChange && !assigneeChange.from && assigneeChange.to) {
console.log(`Issue ${issueKey} was assigned. Checking if it should be transitioned.`);
const availableTransitions = await issues.getTransitions({ issueKey });
const wipTransition = availableTransitions.transitions.find(t => t.to.name.toLowerCase() === 'work in progress');
if (wipTransition) {
console.log(`Transitioning ${issueKey} to 'Work in Progress'.`);
await issues.transition({
issueKey: issueKey,
transition: { id: wipTransition.id }
});
} else {
console.error(`Could not find a transition to 'Work in Progress' for issue ${issueKey}.`);
}
}
// This script runs as a transition validator and must return a boolean value.
// 'true' allows the transition, 'false' blocks it.
// IMPORTANT: Replace this placeholder ID with your actual 'Close Code' custom field ID.
const CLOSE_CODE_FIELD_ID = 'customfield_10102';
// Get the value of the field from the transition screen
const closeCodeField = context.fields[CLOSE_CODE_FIELD_ID];
if (closeCodeField && closeCodeField.value) {
// The field has a value, so allow the transition.
return true;
} else {
// The field is empty, so block the transition.
return false;
}