Groovy
Post-function: Clear issue links and leave a comment in the affected issues
import com.atlassian.jira.component.ComponentAccessor
import com.atlassian.jira.event.type.EventDispatchOption
import com.atlassian.jira.issue.link.IssueLinkTypeManager
def issueManager = ComponentAccessor.getIssueManager()
def issueLinkManager = ComponentAccessor.getIssueLinkManager()
def customFieldManager = ComponentAccessor.getCustomFieldManager()
def commentManager = ComponentAccessor.getCommentManager()
def adminUser = ComponentAccessor.getUserManager().getUserByName("jira-automat") //to be replaced with actual admin user by providing user name
def issueLinkIdToBeChanged = 10500 as long //"split to" link, supposed to be changed to default Epic Link or SAJ link ("Child Epics", "Parent Epic") depending on issue types
def defaultEpicLinkTypeId = 10001 as long; //default Epic Link id; to be replaced with actual Id
def sajEpicToEpicLinkTypeId = 12345 as long; //custom link created with SAJ ("Child Epics", "Parent Epic"); to be replaced with actual Id
def availableIssueLinkTypes = ComponentAccessor.getComponent(IssueLinkTypeManager).issueLinkTypes
def sajEpicToEpicLinkType = availableIssueLinkTypes.findByName("Epic-to-Epic") //custom link created with SAJ ("Child Epics", "Parent Epic"); to be replaced with actual link type name
def epicFieldName = "Epic Link" //if German language in use: "Epic-Verknüpfung"
/* ---------- Get and check all outward links of current issue ---------- */
def outwardLinks = issueLinkManager.getOutwardLinks(issue.id) //current issue --- outward Link > destination issue
for (link in outwardLinks) {
def destinationIssue = issueManager.getIssueObject(link.destinationId)
if (link.issueLinkType.getId() == defaultEpicLinkTypeId) { //if an OUTWARD Epic Link exists... (current issue --- outward Epic Link > destination issue)
/* ---------- Change or remove invalid Epic Links and leave comment ---------- */
if (destinationIssue.getIssueType().name == "Epic") {
if (issue.getIssueType().name == "Epic") {
//IF: Epic --- outward Epic Link > Epic
issueLinkManager.changeIssueLinkType(link, sajEpicToEpicLinkType, adminUser)
//THEN: Epic --- "Child Epics" link > Epic
commentManager.create(issue, adminUser, "(!) {color:#505F79}Invalid outward default Epic Link to Epic " + destinationIssue.getKey() + " replaced with \"" + sajEpicToEpicLinkType.getName() + "\" link.{color}", false)
commentManager.create(destinationIssue, adminUser, "(!) {color:#505F79}Invalid inward default Epic Link from Epic " + issue.getKey() + " replaced with \"" + sajEpicToEpicLinkType.getName() + "\" link.{color}", false)
} else {
//IF: current issue (any type) --- outward Epic Link > Epic
issueLinkManager.removeIssueLink(link, adminUser)
//THEN: remove link
commentManager.create(issue, adminUser, "(!) {color:#505F79}Invalid outward default Epic Link to Epic " + destinationIssue.getKey() + " removed.{color}", false)
commentManager.create(destinationIssue, adminUser, "(!) {color:#505F79}Invalid inward default Epic Link from " + issue.getIssueType().name + " " + issue.getKey() + " removed.{color}", false)
}
}
} else if (link.issueLinkType.getId() == sajEpicToEpicLinkTypeId) { //if a "Child Epics" link exists... (current issue --- "Child Epics" link > destination issue)
/* ---------- Remove incorrect SAJ links ("Child Epics", "Parent Epic") and leave comment ---------- */
if (issue.getIssueType().name == "Milestone" || issue.getIssueType().name == "Task" || issue.getIssueType().name == "Story") {
//IF: Milestone/Task/Story --- "Child Epics" link > destination issue (any type)
issueLinkManager.removeIssueLink(link, adminUser)
//THEN: remove link
commentManager.create(issue, adminUser, "(!) {color:#505F79}Incorrect \"Child Epics\" link to " + destinationIssue.getIssueType().name + " " + destinationIssue.getKey() + " removed.{color}", false)
commentManager.create(destinationIssue, adminUser, "(!) {color:#505F79}Incorrect \"Parent Epic\" link to " + issue.getIssueType().name + " " + issue.getKey() + " removed.{color}", false)
}
} else if (link.issueLinkType.getId() == issueLinkIdToBeChanged) { //if a "split to" link exists... (current issue --- "split to" link > destination issue)
/* ---------- Change "split to" link to default Epic Link or SAJ link ("Child Epics", "Parent Epic") depending on issue types ---------- */
if (issue.getIssueType().name == "Epic") {
if (destinationIssue.getIssueType().name == "Epic" || destinationIssue.getIssueType().name == "Milestone") {
//IF: Epic --- "split to" link > Epic/Milestone
issueLinkManager.changeIssueLinkType(link, sajEpicToEpicLinkType, adminUser)
//THEN: Epic --- "Child Epics" link > Epic/Milestone
commentManager.create(issue, adminUser, "(!) {color:#505F79}Link \"split to\" to " + destinationIssue.getIssueType().name + " " + destinationIssue.getKey() + " replaced with \"" + sajEpicToEpicLinkType.getName() + "\" link.{color}", false)
commentManager.create(destinationIssue, adminUser, "(!) {color:#505F79}Link \"split to\" to Epic " + issue.getKey() + " replaced with \"" + sajEpicToEpicLinkType.getName() + "\" link.{color}", false)
} else if (destinationIssue.getIssueType().name == "Task" || destinationIssue.getIssueType().name == "Story") {
//IF: Epic --- "split to" link > Task/Story
issueLinkManager.removeIssueLink(link, adminUser)
def epicLinkCustomField = customFieldManager.getCustomFieldObjects(destinationIssue).findByName(epicFieldName)
destinationIssue.setCustomFieldValue(epicLinkCustomField, issue)
//THEN: Epic --- outward Epic Link > Task/Story
commentManager.create(issue, adminUser, "(!) {color:#505F79}Link \"split to\" to " + destinationIssue.getIssueType().name + " " + destinationIssue.getKey() + " replaced with outward default Epic Link.{color}", false)
commentManager.create(destinationIssue, adminUser, "(!) {color:#505F79}Link \"split to\" to Epic " + issue.getKey() + " replaced with inward default Epic Link.{color}", false)
}
} else if (issue.getIssueType().name == "Milestone") {
if (destinationIssue.getIssueType().name == "Epic") {
//IF: Milestone --- "split to" link > Epic
issueLinkManager.removeIssueLink(link, adminUser)
issueLinkManager.createIssueLink(destinationIssue.id, issue.id, sajEpicToEpicLinkTypeId, 1L, adminUser)
//THEN: Milestone --- "Parent Epic" link > Epic / Milestone < "Child Epics" link --- Epic
commentManager.create(issue, adminUser, "(!) {color:#505F79}Link \"split to\" to Epic " + destinationIssue.getKey() + " replaced with \"" + sajEpicToEpicLinkType.getName() + "\" link.{color}", false)
commentManager.create(destinationIssue, adminUser, "(!) {color:#505F79}Link \"split to\" to Milestone " + issue.getKey() + " replaced with \"" + sajEpicToEpicLinkType.getName() + "\" link.{color}", false)
}
} else if (issue.getIssueType().name == "Task" || issue.getIssueType().name == "Story") {
if (destinationIssue.getIssueType().name == "Epic") {
//IF: Task/Story --- "split to" link > Epic
issueLinkManager.removeIssueLink(link, adminUser)
def epicLinkCustomField = customFieldManager.getCustomFieldObjects(issue).findByName(epicFieldName)
issue.setCustomFieldValue(epicLinkCustomField, destinationIssue)
//THEN: Task/Story < inward Epic Link --- Epic
commentManager.create(issue, adminUser, "(!) {color:#505F79}Link \"split to\" to Epic " + destinationIssue.getKey() + " replaced with inward default Epic Link.{color}", false)
commentManager.create(destinationIssue, adminUser, "(!) {color:#505F79}Link \"split to\" to " + issue.getIssueType().name + " " + issue.getKey() + " replaced with outward default Epic Link.{color}", false)
}
}
}
issueManager.updateIssue(adminUser, destinationIssue, EventDispatchOption.ISSUE_UPDATED, false)
}
/* ---------- Get and check all inward links of current issue ---------- */
def inwardLinks = issueLinkManager.getInwardLinks(issue.id) //current issue <--- inward Link --- source issue
for (link in inwardLinks) {
def sourceIssue = issueManager.getIssueObject(link.sourceId)
if (link.issueLinkType.getId() == defaultEpicLinkTypeId) { //if an INWARD Epic Link exists... (current issue < inward Epic Link --- source issue)
/* ---------- Change or remove invalid Epic Links and leave comment ---------- */
if (issue.getIssueType().name == "Epic") {
if (sourceIssue.getIssueType().name == "Epic") {
//IF: Epic < inward Epic Link --- Epic
issueLinkManager.changeIssueLinkType(link, sajEpicToEpicLinkType, adminUser)
//THEN: Epic --- "Parent Epic" link > Epic / Epic < "Child Epics" link --- Epic
commentManager.create(issue, adminUser, "(!) {color:#505F79}Invalid inward default Epic Link from Epic " + sourceIssue.getKey() + " replaced with \"" + sajEpicToEpicLinkType.getName() + "\" link.{color}", false)
commentManager.create(sourceIssue, adminUser, "(!) {color:#505F79}Invalid outward default Epic Link to Epic " + issue.getKey() + " replaced with \"" + sajEpicToEpicLinkType.getName() + "\" link.{color}", false)
} else {
//IF: Epic < inward Epic Link --- Task/Story
issueLinkManager.removeIssueLink(link, adminUser)
//THEN: remove link
commentManager.create(issue, adminUser, "(!) {color:#505F79}Invalid inward default Epic Link from " + sourceIssue.getIssueType().name + " " + sourceIssue.getKey() + " removed.{color}", false)
commentManager.create(sourceIssue, adminUser, "(!) {color:#505F79}Invalid outward default Epic Link to Epic " + issue.getKey() + " removed.{color}", false)
}
}
} else if (link.issueLinkType.getId() == sajEpicToEpicLinkTypeId) { //if a "Parent Epic" link exists... (current issue < "Child Epics" Link --- source issue (inward) / current issue --- "Parent Epic" Link > source issue (outward))
/* ---------- Remove incorrect SAJ links ("Child Epics", "Parent Epic") and leave comment ---------- */
if ((issue.getIssueType().name == "Milestone" && sourceIssue.getIssueType().name != "Epic") || issue.getIssueType().name == "Task" || issue.getIssueType().name == "Story") {
//IF: Milestone < "Child Epics" Link --- source issue (any type except Epic); OR: Task/Story < "Child Epics" Link --- source issue (any type)
issueLinkManager.removeIssueLink(link, adminUser)
//THEN: remove link
commentManager.create(issue, adminUser, "(!) {color:#505F79}Incorrect \"Parent Epic\" link to " + sourceIssue.getIssueType().name + " " + sourceIssue.getKey() + " removed.{color}", false)
commentManager.create(sourceIssue, adminUser, "(!) {color:#505F79}Incorrect \"Child Epics\" link to " + issue.getIssueType().name + " " + issue.getKey() + " removed.{color}", false)
}
} else if (link.issueLinkType.getId() == issueLinkIdToBeChanged) { //if a "split to" link exists... (current issue < "split to" link --- source issue)
/* ---------- Change "split to" link to default Epic Link or SAJ link ("Child Epics", "Parent Epic") depending on issue types ---------- */
if (sourceIssue.getIssueType().name == "Epic") {
if (issue.getIssueType().name == "Epic" || issue.getIssueType().name == "Milestone") {
//IF: Epic/Milestone < "split to" link --- Epic
issueLinkManager.changeIssueLinkType(link, sajEpicToEpicLinkType, adminUser)
//THEN: Epic/Milestone --- "Parent Epic" link > Epic / Epic/Milestone < "Child Epics" Link --- Epic
commentManager.create(issue, adminUser, "(!) {color:#505F79}Link \"split to\" to Epic " + sourceIssue.getKey() + " replaced with \"" + sajEpicToEpicLinkType.getName() + "\" link.{color}", false)
commentManager.create(sourceIssue, adminUser, "(!) {color:#505F79}Link \"split to\" to " + issue.getIssueType().name + " " + issue.getKey() + " replaced with \"" + sajEpicToEpicLinkType.getName() + "\" link.{color}", false)
} else if (issue.getIssueType().name == "Task" || issue.getIssueType().name == "Story") {
//IF: Task/Story < "split to" link --- Epic
issueLinkManager.removeIssueLink(link, adminUser)
def epicLinkCustomField = customFieldManager.getCustomFieldObjects(issue).findByName(epicFieldName)
issue.setCustomFieldValue(epicLinkCustomField, sourceIssue)
//THEN: Task/Story < inward Epic Link --- Epic
commentManager.create(issue, adminUser, "(!) {color:#505F79}Link \"split to\" to Epic " + sourceIssue.getKey() + " replaced with inward default Epic Link.{color}", false)
commentManager.create(sourceIssue, adminUser, "(!) {color:#505F79}Link \"split to\" to " + issue.getIssueType().name + " " + issue.getKey() + " replaced with outward default Epic Link.{color}", false)
}
} else if (sourceIssue.getIssueType().name == "Milestone") {
if (issue.getIssueType().name == "Epic") {
//IF: Epic < "split to" link --- Milestone
issueLinkManager.removeIssueLink(link, adminUser)
issueLinkManager.createIssueLink(issue.id, sourceIssue.id, sajEpicToEpicLinkTypeId, 1L, adminUser)
//THEN: Epic --- "Child Epics" link > Milestone / Epic < "Parent Epic" link --- Milestone
commentManager.create(issue, adminUser, "(!) {color:#505F79}Link \"split to\" to Milestone " + sourceIssue.getKey() + " replaced with \"" + sajEpicToEpicLinkType.getName() + "\" link.{color}", false)
commentManager.create(sourceIssue, adminUser, "(!) {color:#505F79}Link \"split to\" to Epic " + issue.getKey() + " replaced with \"" + sajEpicToEpicLinkType.getName() + "\" link.{color}", false)
}
} else if (sourceIssue.getIssueType().name == "Task" || sourceIssue.getIssueType().name == "Story") {
if (issue.getIssueType().name == "Epic") {
//IF: Epic < "split to" link --- Task/Story
issueLinkManager.removeIssueLink(link, adminUser)
def epicLinkCustomField = customFieldManager.getCustomFieldObjects(sourceIssue).findByName(epicFieldName)
sourceIssue.setCustomFieldValue(epicLinkCustomField, issue)
//THEN: Epic --- outward Epic Link > Task/Story
commentManager.create(issue, adminUser, "(!) {color:#505F79}Link \"split to\" to " + sourceIssue.getIssueType().name + " " + sourceIssue.getKey() + " replaced with outward default Epic Link.{color}", false)
commentManager.create(sourceIssue, adminUser, "(!) {color:#505F79}Link \"split to\" to Epic " + issue.getKey() + " replaced with inward default Epic Link.{color}", false)
}
}
}
issueManager.updateIssue(adminUser, sourceIssue, EventDispatchOption.ISSUE_UPDATED, false)
}
issueManager.updateIssue(adminUser, issue, EventDispatchOption.ISSUE_UPDATED, false)
PLEASE NOTE
Script is restricted to the issue types Epic, Milestone, Task and Story. |
© 2023, STAGIL