JSU Script runner create and link issue

Martin Ondracek January 27, 2020

Hi,

I'm trying to create an Epic and then some issues linked to that Epic. This will be triggered everytime new fixVersion is created.

My script bellow works almost fine. Last thing I need is to somehow create link between Epic and those normal issues. Epic link would be the best.

Is there some way how to achieve this and have link between those newly created issues?

 

import com.atlassian.jira.component.ComponentAccessor
import com.atlassian.crowd.embedded.api.User
import com.atlassian.jira.issue.IssueFactory
import com.atlassian.jira.project.ProjectManager
import com.atlassian.jira.project.Project
import com.atlassian.jira.user.util.UserUtil
import com.atlassian.jira.issue.customfields.CustomFieldType
import com.atlassian.jira.issue.customfields.*
import com.atlassian.jira.issue.CustomFieldManager
import com.atlassian.jira.issue.IssueManager
import com.atlassian.jira.issue.index.IndexException
import com.atlassian.jira.bc.issue.search.SearchService
import com.atlassian.jira.issue.MutableIssue
import com.atlassian.jira.issue.Issue;
import com.atlassian.jira.web.bean.PagerFilter
import com.atlassian.jira.issue.util.DefaultIssueChangeHolder
import com.atlassian.jira.issue.ModifiedValue
import com.atlassian.fugue.Option
import org.apache.log4j.Category
import com.atlassian.jira.issue.issuetype.IssueType
import com.atlassian.jira.issue.link.IssueLinkType
import com.atlassian.jira.issue.link.IssueLinkTypeManager
import com.atlassian.jira.issue.Issue
import com.atlassian.plugin.PluginAccessor
import com.atlassian.jira.issue.util.IssueChangeHolder
import com.opensymphony.workflow.WorkflowContext
import com.atlassian.jira.workflow.WorkflowTransitionUtil;
import com.atlassian.jira.workflow.WorkflowTransitionUtilImpl;
import com.atlassian.jira.util.JiraUtils;
import com.atlassian.jira.event.issue.IssueEvent;
import com.atlassian.jira.issue.comments.CommentManager
import com.atlassian.jira.user.ApplicationUser
import com.atlassian.jira.issue.link.IssueLink;
import com.atlassian.jira.issue.priority.Priority;
import java.util.ArrayList;
import com.atlassian.jira.project.version.Version
import com.atlassian.jira.event.type.EventDispatchOption
import com.atlassian.jira.project.version.VersionManager
import com.atlassian.jira.bc.project.component.ProjectComponentManager;

def issueMgr = ComponentAccessor.getIssueManager()
def issueFactory = ComponentAccessor.getIssueFactory()
def projectMgr = ComponentAccessor.getProjectManager()
CustomFieldManager customFieldManager = ComponentAccessor.getCustomFieldManager()
def userManager = ComponentAccessor.getUserManager()
//We will execute actions using a jira user with permissions
def linkMgr = ComponentAccessor.getIssueLinkManager()
def currentUserObj = userManager.getUserByName("user")




def epicSummariesList = ["Security patching " +event.version.name]
epicSummariesList.each {
def projectName = "ENOP"
def newissue = issueFactory.getIssue();
newissue.setSummary(it)
newissue.setProjectObject (projectMgr.getProjectByCurrentKey(projectName))
newissue.setIssueTypeId("6")
def project = projectMgr.getProjectByCurrentKey(projectName)

newissue.setAssigneeId(ComponentAccessor.getJiraAuthenticationContext().getLoggedInUser().getKey())
newissue.setReporterId(ComponentAccessor.getJiraAuthenticationContext().getLoggedInUser().getKey())
def versionManager = ComponentAccessor.getVersionManager()
def projectManager = ComponentAccessor.getProjectManager()
def versions = versionManager.getVersions(project)
//Get collection of all fixVersions
def newversions = versions.collect()
//Select latest fixVersion from collection
def versionToUse = newversions.last();
newissue.setFixVersions([versionToUse])
newissue.setPriorityId("10000");
newissue.setDescription("OSPatching for this quarter")
Project project2 = newissue.getProjectObject()
ProjectComponentManager projectComponentManager = ComponentAccessor.getProjectComponentManager();
def component = ComponentAccessor.getProjectComponentManager().findByComponentName(project2.getId(),"Security")
newissue.setComponent([component])
//Create new issue with fields above
def newissue2 = issueMgr.createIssueObject(currentUserObj, newissue)
}



def taskSummariesList = ["OS Patching",
"Kernel patching",
"Update packages"]
//On new version created we want a new ticket in PROJECT with all related tasks linked to the ticket
taskSummariesList.each
{
def projectName = "ENOP"
def newissue = issueFactory.getIssue();
newissue.setSummary(it)
newissue.setProjectObject (projectMgr.getProjectByCurrentKey(projectName))
newissue.setIssueTypeId("3")
def project = projectMgr.getProjectByCurrentKey(projectName)
newissue.setAssigneeId(ComponentAccessor.getJiraAuthenticationContext().getLoggedInUser().getKey())
newissue.setReporterId(ComponentAccessor.getJiraAuthenticationContext().getLoggedInUser().getKey())
def versionManager = ComponentAccessor.getVersionManager()
def projectManager = ComponentAccessor.getProjectManager()
def versions = versionManager.getVersions(project)
//Get collection of all fixVersions
def newversions = versions.collect()
//Select latest fixVersion from collection
def versionToUse = newversions.last();
newissue.setFixVersions([versionToUse])
newissue.setPriorityId("10000");
newissue.setDescription("OS Patching for this quarter")
Project project2 = newissue.getProjectObject()
ProjectComponentManager projectComponentManager = ComponentAccessor.getProjectComponentManager();
def component = ComponentAccessor.getProjectComponentManager().findByComponentName(project2.getId(),"Security")
newissue.setComponent([component])
newissue = issueMgr.createIssueObject(currentUserObj, newissue)
}

 

1 answer

1 accepted

0 votes
Answer accepted
Peter-Dave Sheehan
Community Leader
Community Leader
Community Leaders are connectors, ambassadors, and mentors. On the online community, they serve as thought leaders, product experts, and moderators.
January 27, 2020

Hi

I haven't scoured through your entire script, but setting a link between the epic and the issue should be as simple as setting the value of the "Epic Link" field for the issue to the epic issue object

Here is a short snippet that works for me in the console:

import com.atlassian.jira.event.type.EventDispatchOption
import com.atlassian.jira.component.ComponentAccessor

def currentUser = ComponentAccessor.jiraAuthenticationContext.loggedInUser
def epic = ComponentAccessor.issueManager.getIssueObject('JSP-4481')
def issue = ComponentAccessor.issueManager.getIssueObject('JSP-1922')

def cf = ComponentAccessor.customFieldManager.getCustomFieldObjectByName('Epic Link')
issue.setCustomFieldValue(cf, epic)
ComponentAccessor.issueManager.updateIssue(currentUser, issue, EventDispatchOption.DO_NOT_DISPATCH, false)
Martin Ondracek January 27, 2020

Thank you, this is definitely useful piece for making this work.

There's some cavity though. In your snippet you have defined exact issue key, but in my case issue key of Epic will be different every time + I'm creating that Epic also via this script and I'm still not sure how can I parse this info from newly created issue.

Peter-Dave Sheehan
Community Leader
Community Leader
Community Leaders are connectors, ambassadors, and mentors. On the online community, they serve as thought leaders, product experts, and moderators.
January 27, 2020

Not really, your script is creating an issue object already.

All I did was to acquire an existing epic issue object.

Let me simplify and fix your script, maybe this will help.

import com.atlassian.jira.component.ComponentAccessor
import com.atlassian.jira.issue.IssueManager
import com.atlassian.jira.issue.MutableIssue
import com.atlassian.jira.issue.Issue
import com.atlassian.jira.issue.index.IssueIndexingService
import com.atlassian.jira.util.ImportUtils

def summaries = [
[
epicSummary:"Security patching $event.version.name",
issueSummaries:['OS Patching','Kernel patching','Update packages']
],
//here you can add other epics you might want to create wit their corresponding issues
]
//main loop through all the epics to create
summaries.each{ summaryMap->
//create the epic issue
Issue epicIssue = createIssue('ENOP',summaryMap.epicSummary.toString(),'OSPatching for this quarter','6', 'Security' )
//now loop through all the issueSummaries for the issues to create in the epic
summaryMap.issueSummaries.each{issueSummary->
createIssue('ENOP',issueSummary.toString(),'OS Patching for this quarter', '3', 'Security', epicIssue)
}
}

Issue createIssue(String projectName, String summary,String description,String issueTypeId,String componentName,Issue epicIssue =null){
def versionManager = ComponentAccessor.versionManager
def projectManager = ComponentAccessor.projectManager
def projectMgr = ComponentAccessor.projectManager
def issueMgr = ComponentAccessor.issueManager
def issueFactory = ComponentAccessor.issueFactory
def projectComponentManager = ComponentAccessor.projectComponentManager
def currentUserObj = ComponentAccessor.jiraAuthenticationContext.loggedInUser
def issueIndexingService = ComponentAccessor.getComponent(IssueIndexingService.class)

MutableIssue newIssue = issueFactory.getIssue()
def project = projectMgr.getProjectByCurrentKey(projectName)
newIssue.setSummary(summary)
newIssue.setProjectObject (project)
newIssue.setIssueTypeId(issueTypeId)
newIssue.setAssignee(currentUserObj)
newIssue.setReporter(currentUserObj)

def versions = versionManager.getVersions(project)
//Get collection of all fixVersions
def newversions = versions.collect()
//Select latest fixVersion from collection
def versionToUse = newversions.last();
newIssue.setFixVersions([versionToUse])
newIssue.setPriorityId("10000");

def component = projectComponentManager.findByComponentName(project.id,componentName)
newIssue.setComponent([component])

if(epicIssue){
def cfm = ComponentAccessor.customFieldManager
def epicLinkCf = cfm.getCustomFieldObjectsByName('Epic Link').first()
newIssue.setCustomFieldValue(epicLinkCf, epicIssue)
}
//Create and store the new issue with fields above
def issue = issueMgr.createIssueObject(currentUserObj, newIssue)

//index the issue
boolean wasIndexing = ImportUtils.isIndexIssues()
ImportUtils.setIndexIssues(true)
issueIndexingService.reIndex(issue)
ImportUtils.setIndexIssues(wasIndexing)

//return the created issue object
return issue
}

You will see that I combined and moved all code to create the epic and stories into a function. And groups your epic summary and issue summary into a single "summaries" object.

I removed all the superfluous imports and simplified many of manager definitions.

And finally, I added a few lines to make sure your newly created issues are all indexed and searchable.

Martin Ondracek January 29, 2020

Thank you for your work Peter, you are my savior, kudos to you :)

Can I ask you for last touch as I don't have much experience and really struggle with this? How can I add Scrum team field and Epic Name fields? I've tried few changes but haven't been successful.

Peter-Dave Sheehan
Community Leader
Community Leader
Community Leaders are connectors, ambassadors, and mentors. On the online community, they serve as thought leaders, product experts, and moderators.
January 29, 2020

Here is how to can add the Epic Name and Scrum team fields to your epic

import com.atlassian.jira.component.ComponentAccessor
import com.atlassian.jira.issue.IssueManager
import com.atlassian.jira.issue.MutableIssue
import com.atlassian.jira.issue.Issue
import com.atlassian.jira.issue.index.IssueIndexingService
import com.atlassian.jira.util.ImportUtils

def summaries = [
[
epicSummary:"Security patching $event.version.name",
issueSummaries:['OS Patching','Kernel patching','Update packages']
],
//here you can add other epics you might want to create wit their corresponding issues
]
//main loop through all the epics to create
summaries.each{ summaryMap->
//create the epic issue
Issue epicIssue = createIssue('ENOP',summaryMap.epicSummary.toString(),'OSPatching for this quarter','6', 'Security' )
//now loop through all the issueSummaries for the issues to create in the epic
summaryMap.issueSummaries.each{issueSummary->
createIssue('ENOP',issueSummary.toString(),'OS Patching for this quarter', '3', 'Security', epicIssue)
}
}

Issue createIssue(String projectName, String summary,String description,String issueTypeId,String componentName,Issue epicIssue =null, String epicName = "", String scrumtTeamName = ""){
def versionManager = ComponentAccessor.versionManager
def projectManager = ComponentAccessor.projectManager
def projectMgr = ComponentAccessor.projectManager
def issueMgr = ComponentAccessor.issueManager
def issueFactory = ComponentAccessor.issueFactory
def projectComponentManager = ComponentAccessor.projectComponentManager
def currentUserObj = ComponentAccessor.jiraAuthenticationContext.loggedInUser
def issueIndexingService = ComponentAccessor.getComponent(IssueIndexingService.class)

MutableIssue newIssue = issueFactory.getIssue()
def project = projectMgr.getProjectByCurrentKey(projectName)
newIssue.setSummary(summary)
newIssue.setProjectObject (project)
newIssue.setIssueTypeId(issueTypeId)
newIssue.setAssignee(currentUserObj)
newIssue.setReporter(currentUserObj)

def versions = versionManager.getVersions(project)
//Get collection of all fixVersions
def newversions = versions.collect()
//Select latest fixVersion from collection
def versionToUse = newversions.last();
newIssue.setFixVersions([versionToUse])
newIssue.setPriorityId("10000");

def component = projectComponentManager.findByComponentName(project.id,componentName)
newIssue.setComponent([component])
if(epicIssue){
//define the custom fields to populate
def cfm = ComponentAccessor.customFieldManager
def epicLinkCf = cfm.getCustomFieldObjectsByName('Epic Link').first()
def epicNameCf = cfm.getCustomFieldObjectsByName('Epic Name').first()
def scrumTeamCf = cfm.getCustomFieldObjectsByName('Scrum team').first()

//set values on those custom fields
newIssue.setCustomFieldValue(epicLinkCf, epicIssue)
newIssue.setCustomFieldValue(epicNameCf, epicName)
newIssue.setCustomFieldValue(scrumTeamCf, scrumTeamName)
}

//Create and store the new issue with fields above
def issue = issueMgr.createIssueObject(currentUserObj, newIssue)

//index the issue
boolean wasIndexing = ImportUtils.isIndexIssues()
ImportUtils.setIndexIssues(true)
issueIndexingService.reIndex(issue)
ImportUtils.setIndexIssues(wasIndexing)

//return the created issue object
return issue


If the scrum team is a single select, then you would need to adjust that a bit to get te optionId for a given scrum team name

def config =scrumTeamCf.getRelevantConfig(newIssue)
def scrumTeamOption = ComponentAccessor.optionsManager.getOptions(config).find{it..value == scrumTeamName}
newIssue.setCustomFieldValue(scrumTeamCf, scrumTeamOption )

 

Martin Ondracek February 3, 2020

Once more thank you for your advice, I've managed to get it working now.

Suggest an answer

Log in or Sign up to answer
TAGS
AUG Leaders

Atlassian Community Events