Just a heads up: On March 24, 2025, starting at 4:30pm CDT / 21: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.
Online forums and learning are now in one easy-to-use experience.
By continuing, you accept the updated Community Terms of Use and acknowledge the Privacy Policy. Your public name, photo, and achievements may be publicly visible and available in search engines.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.