Just a heads up: On March 24, 2025, starting at 4:30pm CDT / 19:30 UTC, the site will be undergoing scheduled maintenance for a few hours. During this time, the site might be unavailable for a short while. Thanks for your patience.
×I am creating a post-function that will create a clone and automatically link to the parent on a transition.
Code Below.
This successfully creates the (cloned) issue, however the link is not being created.
import com.atlassian.jira.component.ComponentAccessor
import com.atlassian.jira.ComponentManager
import com.atlassian.jira.issue.MutableIssue
import com.atlassian.jira.project.Project
import com.onresolve.scriptrunner.canned.jira.workflow.postfunctions.CloneIssue
import com.atlassian.jira.issue.comments.CommentManager
import com.atlassian.jira.issue.comments.Comment
import com.atlassian.jira.ComponentManager
import com.atlassian.jira.issue.Issue
import com.atlassian.jira.issue.IssueManager
import com.atlassian.jira.issue.CustomFieldManager
import com.atlassian.jira.issue.fields.CustomField
import com.atlassian.jira.issue.link.IssueLinkTypeManager
import com.atlassian.jira.issue.link.IssueLinkManager
import com.onresolve.scriptrunner.runner.util.UserMessageUtil
import org.apache.log4j.Category
def Category log = Category.getInstance("com.onresolve.jira.groovy")
log.setLevel(org.apache.log4j.Level.DEBUG)
def issueLinkTypeManager = ComponentAccessor.getComponent(IssueLinkTypeManager)
def customFieldManager = ComponentAccessor.getCustomFieldManager()
def issueManager = ComponentAccessor.getIssueManager()
// get the current list of outwards depends on links to get the sequence number
IssueLinkManager issueLinkManager = ComponentAccessor.getIssueLinkManager()
Issue mainIssue = issue
CustomField projectSelected = customFieldManager.getCustomFieldObject("customfield_11918")
String projectSelectedValue = mainIssue.getCustomFieldValue(projectSelected) as String
String actualProjectVal = projectSelectedValue.replaceAll("Project:","")
log.info "Project Selected: "+actualProjectVal
def originalIssueKey = mainIssue
log.info "Original issue Key: " +originalIssueKey
def destinationProjectKey = ComponentAccessor.projectManager.getProjectObjByKey(actualProjectVal.trim())
log.info "Destination Project Key: " + destinationProjectKey
def commentManager = ComponentAccessor.getCommentManager()
cloneIssue(originalIssueKey, destinationProjectKey, log)
issueManager = ComponentAccessor.getOSGiComponentInstanceOfType(IssueManager.class);
void cloneIssue (MutableIssue issue, Project project, Category log ) {
log.info "Project.key = " + project.key
log.info "Issue: " + issue
def params = [
issue : issue,
(CloneIssue.FIELD_TARGET_PROJECT) : project.key,
(CloneIssue.FIELD_SELECTED_FIELDS) : null, //clone all the fields
] as Map<String, Object>
new CloneIssue().doScript(params)
}
def doAfterCreate = {
log = Category.getInstance("com.onresolve.jira.groovy")
log.setLevel(org.apache.log4j.Level.DEBUG)
def issueToLinkTo = issueManager.getIssueByCurrentKey(originalIssueKey.toString().trim())
log.info "Issue to link to: " + issueToLinkTo
def linkTypeName = "Blocks"
def linkType = issueLinkTypeManager.getIssueLinkTypesByName(linkTypeName)
if (!linkType) {
log.warn ("Issue link type with name: ${linkTypeName} does not exist")
}
else {
long sequence = 1
def currentUser = ComponentAccessor.getJiraAuthenticationContext().getUser()
log.info "Created issue: " + issueManager.getIssueObject(issue.id).toString()
issueLinkManager.createIssueLink(issueToLinkTo.id, issue.id, linkType[0].id, sequence, currentUser)
UserMessageUtil.success('Derive Successful.')
}
}
The one different i notice - is Scriptrunner does not declare the doAfterCreate. Howeve I have.
If I remove the declaration, I get an error that it is undeclared.
Please help.
I was able to get around the problem without using the doAfterCreate method.
I basically moved the code section within the doAfterCreate outside and with some tweaks - i was able to get it working as expected.
If anyone can recommend a better approach, please do so.
Code below:
import com.atlassian.jira.component.ComponentAccessor
import com.atlassian.jira.ComponentManager
import com.atlassian.jira.issue.MutableIssue
import com.atlassian.jira.project.Project
import com.onresolve.scriptrunner.canned.jira.workflow.postfunctions.CloneIssue
import com.atlassian.jira.issue.comments.CommentManager
import com.atlassian.jira.issue.comments.Comment
import com.atlassian.jira.ComponentManager
import com.atlassian.jira.issue.Issue
import com.atlassian.jira.issue.IssueManager
import com.atlassian.jira.issue.CustomFieldManager
import com.atlassian.jira.issue.fields.CustomField
import com.atlassian.jira.issue.link.IssueLinkTypeManager
import com.atlassian.jira.issue.link.IssueLinkManager
import com.onresolve.scriptrunner.runner.util.UserMessageUtil
import org.apache.log4j.Category
def Category log = Category.getInstance("com.onresolve.jira.groovy")
log.setLevel(org.apache.log4j.Level.DEBUG)
def issueLinkTypeManager = ComponentAccessor.getComponent(IssueLinkTypeManager)
def customFieldManager = ComponentAccessor.getCustomFieldManager()
def issueManager = ComponentAccessor.getIssueManager()
// get the current list of outwards depends on links to get the sequence number
IssueLinkManager issueLinkManager = ComponentAccessor.getIssueLinkManager()
Issue mainIssue = issue
CustomField projectSelected = customFieldManager.getCustomFieldObject("customfield_11918")
String projectSelectedValue = mainIssue.getCustomFieldValue(projectSelected) as String
String actualProjectVal = projectSelectedValue.replaceAll("Project:","")
log.info "Project Selected: "+actualProjectVal
def originalIssueKey = mainIssue
log.info "Original issue Key: " +originalIssueKey
def destinationProjectKey = ComponentAccessor.projectManager.getProjectObjByKey(actualProjectVal.trim())
log.info "Destination Project Key: " + destinationProjectKey
def commentManager = ComponentAccessor.getCommentManager()
cloneIssue(originalIssueKey, destinationProjectKey, log)
issueManager = ComponentAccessor.getOSGiComponentInstanceOfType(IssueManager.class);
void cloneIssue (MutableIssue issue, Project project, Category log ) {
log.info "Project.key = " + project.key
log.info "Main Issue: " + issue
def originalIssueKey = issue
def params = [
issue : issue,
(CloneIssue.FIELD_TARGET_PROJECT) : project.key,
(CloneIssue.FIELD_SELECTED_FIELDS) : null, //clone all the fields
] as Map<String, Object>
def newIssue = new CloneIssue().doScript(params)
log.info "New Issue: " + newIssue
def newIssueID = newIssue.get('newIssue')
log.info "IssueID: " + newIssueID
def issueManager = ComponentAccessor.getIssueManager()
def issueToLinkMain = issueManager.getIssueByCurrentKey(originalIssueKey.toString().trim())
def newIssuetoLink = issueManager.getIssueByCurrentKey(newIssueID.toString().trim())
log.info "Main Issue to link to: " + issueToLinkMain
log.info "New Issue to link: " + newIssuetoLink
def linkTypeName = "Blocks"
def issueLinkTypeManager = ComponentAccessor.getComponent(IssueLinkTypeManager)
def linkType = issueLinkTypeManager.getIssueLinkTypesByName(linkTypeName)
if (!linkType) {
log.warn ("Issue link type with name: ${linkTypeName} does not exist")
}
else {
long sequence = 1
def currentUser = ComponentAccessor.getJiraAuthenticationContext().getUser()
IssueLinkManager issueLinkManager = ComponentAccessor.getIssueLinkManager()
issueLinkManager.createIssueLink(newIssuetoLink.id, issueToLinkMain.id, linkType[0].id, sequence, currentUser)
UserMessageUtil.success('Derive Successful.')
}
}
Hi Gundlupet,
Is there a reason you can't use the ScriptRunner built-in script to do the cloning and linking?
https://scriptrunner.adaptavist.com/latest/jira/builtin-scripts.html#_clones_an_issue_and_links
Thanks
Johnson
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Hi Johnson,
The built-in functionality only allows to clone and link to the current project.
We are looking for a functionality that will allow users to choose other projects for cloning and linking.
The build-in functionality does not support dynamic project selection. Hence, I am trying to implement my own custom script.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.