Forums

Articles
Create
cancel
Showing results for 
Search instead for 
Did you mean: 

Create subtasks from multi select custom field values

Peter June 1, 2020

I want a groovy script that will create a subtask or a series of subtasks if a multi select custom field has any values selected. So the subtask would use the multi select custom field values as summaries for the subtasks that would be created. I will set up the script to trigger if there is any change to the custom field, so it will need to check if there are any subtasks created using the custom field value as the summary also. Can anyone help on this?

2 answers

0 votes
Peter June 3, 2020

 

 

0 votes
Nic Brough -Adaptavist-
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
June 1, 2020

I keep meaning to get this added to https://library.adaptavist.com and never quite find time.

Please note,

  • I'm not a proper coder, it probably could be more elegant
  • It was written for Jira 7.6-ish
  • I've not tested it properly on newer versions
  • My multi-select field is called "Animals"
  • It's minimal, creating issues with the absolute minumum - summary and the structrual stuff
  • If you use "issue.getSubTasks()", you should get a list of existing subtasks so you can try to parse them for existing ones.  I've done something like that too, but it was messier and was predicated on having specific fields, so not much use to you probably

But it should get you most of the way there:

 


import com.atlassian.jira.issue.Issue
import com.atlassian.jira.issue.MutableIssue
import com.atlassian.jira.user.ApplicationUser
import com.atlassian.jira.security.JiraAuthenticationContext
import com.atlassian.jira.component.ComponentAccessor
 
// Never create a sub-task of a sub-task, it breaks, spectacularly
if ( issue.getIssueType().isSubTask() ) return 0
 
def customFieldManager = ComponentAccessor.getCustomFieldManager()
def optionsManager = ComponentAccessor.getOptionsManager()
def issueFactory = ComponentAccessor.getIssueFactory()
def subTaskManager = ComponentAccessor.getSubTaskManager()
def constantManager = ComponentAccessor.getConstantsManager()
def issueManager = ComponentAccessor.getIssueManager()
def currentUser = ComponentAccessor.getJiraAuthenticationContext().getLoggedInUser()
 
def subTaskTypeId = constantManager.getAllIssueTypeObjects().find{ it.getName() == "Sub-task type Name" }.id
List<String> summariesList = []
 
def buildFromField = customFieldManager.getCustomFieldObjects(issue)find {it.name == "Animals"}
def optionsFieldConfig = buildFromField.getRelevantConfig(issue)
def optionsFound = optionsManager.getOptions (optionsFieldConfig)
 
optionsFound.each { optionName ->
    summariesList.add( optionName.getValue() + ": " + issue.getSummary())
}
 
summariesList?.each { subTaskSummary ->
    MutableIssue newSubTask = issueFactory.getIssue()
 
    newSubTask.setSummary(subTaskSummary)
    newSubTask.setParentObject(issue)
    newSubTask.setProjectObject(issue.getProjectObject())
    newSubTask.setIssueTypeId(subTaskTypeId)
 
    Map<String,Object> newIssueParams = ["issue" : newSubTask] as Map<String,Object>
    issueManager.createIssueObject(currentUser, newIssueParams)
    subTaskManager.createSubTaskIssueLink(issue, newSubTask, currentUser)
}


Peter June 2, 2020

Thanks Nic, I very much appreciate the help! I'll let you know how i get on as I test this out.

DQ DevOps June 2, 2020

So ive made a couple of changes to the script but I'm getting the following error on my listener (issue updated event - I've added values to the field carrier represented by the customfieldID value)

Time (on server): Tue Jun 02 2020 11:06:18 GMT+0100 (British Summer Time)

The following log information was produced by this execution. Use statements like:log.info("...") to record logging information.

2020-06-02 10:06:18,135 ERROR [runner.AbstractScriptListener]: *************************************************************************************
2020-06-02 10:06:18,149 ERROR [runner.AbstractScriptListener]: Script function failed on event: com.atlassian.jira.event.issue.IssueEvent, file: null
java.lang.NullPointerException: Cannot get property 'id' on null object
 at Script25.run(Script25.groovy:18)

 

import com.atlassian.jira.issue.Issue
import com.atlassian.jira.issue.MutableIssue
import com.atlassian.jira.user.ApplicationUser
import com.atlassian.jira.security.JiraAuthenticationContext
import com.atlassian.jira.component.ComponentAccessor

// Never create a sub-task of a sub-task, it breaks, spectacularly
if ( issue.getIssueType().isSubTask() ) return 0

def customFieldManager = ComponentAccessor.getCustomFieldManager()
def optionsManager = ComponentAccessor.getOptionsManager()
def issueFactory = ComponentAccessor.getIssueFactory()
def subTaskManager = ComponentAccessor.getSubTaskManager()
def constantManager = ComponentAccessor.getConstantsManager()
def issueManager = ComponentAccessor.getIssueManager()
def currentUser = ComponentAccessor.getJiraAuthenticationContext().getLoggedInUser()

def subTaskTypeId = constantManager.getAllIssueTypeObjects().find{ it.getName() == "Subtask" }.id
List<String> summariesList = []

def buildFromField = customFieldManager.getCustomFieldObjects(issue)find {it.name == "customFieldId=12300"}
def optionsFieldConfig = buildFromField.getRelevantConfig(issue)
def optionsFound = optionsManager.getOptions (optionsFieldConfig)

optionsFound.each { optionName ->
summariesList.add( optionName.getValue() + ": " + issue.getSummary())
}

summariesList?.each { subTaskSummary ->
MutableIssue newSubTask = issueFactory.getIssue()

newSubTask.setSummary(subTaskSummary)
newSubTask.setParentObject(issue)
newSubTask.setProjectObject(issue.getProjectObject())
newSubTask.setIssueTypeId(subTaskTypeId)

Map<String,Object> newIssueParams = ["issue" : newSubTask] as Map<String,Object>
issueManager.createIssueObject(currentUser, newIssueParams)
subTaskManager.createSubTaskIssueLink(issue, newSubTask, currentUser)

DQ DevOps June 2, 2020

I've just made a change to remove the speech marks from the customfieldID and its giving me the following error

Screenshot 2020-06-02 at 11.11.41.png

Nic Brough -Adaptavist-
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
June 2, 2020

I'd say it's not finding an issue type named "Subtask"

DQ DevOps June 2, 2020

Ahh good point the subtask issue type is actually Sub-Task; Now changed and run a test, now getting this error:

 

Time (on server): Tue Jun 02 2020 11:26:14 GMT+0100 (British Summer Time)

The following log information was produced by this execution. Use statements like:log.info("...") to record logging information.

2020-06-02 10:26:14,351 ERROR [runner.AbstractScriptListener]: *************************************************************************************
2020-06-02 10:26:14,351 ERROR [runner.AbstractScriptListener]: Script function failed on event: com.atlassian.jira.event.issue.IssueEvent, file: null
java.lang.NullPointerException: Cannot invoke method getRelevantConfig() on null object
 at Script36.run(Script36.groovy:22)
DQ DevOps June 2, 2020

Screenshot 2020-06-02 at 11.28.18.png

Nic Brough -Adaptavist-
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
June 2, 2020

Ok, that's a bullet point I missed off!

My script was written as a post-function - it runs when an issue goes through a  transition.  In post-functions, you automatically have the variable "issue" holding the current issue that the post-function is running against.

I suspect you are running this in a console.  If that is the case, then you'll need an extra line, above line 8, to get an issue to act upon.  

Something like

def issue = issueManager.getIssueByKey("ABC-123") 

DQ DevOps June 2, 2020

Ahh, i was actually running this as a listener, so that when a ticket is updated or created it runs and creates subtasks based on that custom field. Should i have that custom field value in speech marks btw do you think?

Nic Brough -Adaptavist-
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
June 2, 2020

Oh, a listener!  In that case, try

def issue = event.issue

Peter June 3, 2020

So on reflection i think im actually going to leave this as a post function script in a workflow transition. I've got the script working, but its got a bit of a bug, its creating subtasks from values in the custom field but its creating a subtask from every value in the custom field whether the value is selected or not. I need to update the script to only create a custom field if the value is selected. Any ideas how i can isolate just the selected values?

Yashwanth Jakkula
I'm New Here
I'm New Here
Those new to the Atlassian Community have posted less than three times. Give them a warm welcome!
February 1, 2023

Hi,

 

I have tried below script in workflow post function. got an error.

2023-02-01 17:29:33,520 ERROR [workflow.AbstractScriptWorkflowFunction]: Workflow script has failed on issue workflowMode=live&workflowName=Software+Simplified+Workflow+for+Project+CDB&descriptorTab=postfunctions&workflowTransition=11&highlight=1 java.lang.NullPointerException: Cannot invoke method getRelevantConfig() on null object at Script21.run(Script21.groovy:22)

 

 

import com.atlassian.jira.issue.Issue
import com.atlassian.jira.issue.MutableIssue
import com.atlassian.jira.user.ApplicationUser
import com.atlassian.jira.security.JiraAuthenticationContext
import com.atlassian.jira.component.ComponentAccessor

// Never create a sub-task of a sub-task, it breaks, spectacularly
if ( issue.getIssueType().isSubTask() ) return 0

def customFieldManager = ComponentAccessor.getCustomFieldManager()
def optionsManager = ComponentAccessor.getOptionsManager()
def issueFactory = ComponentAccessor.getIssueFactory()
def subTaskManager = ComponentAccessor.getSubTaskManager()
def constantManager = ComponentAccessor.getConstantsManager()
def issueManager = ComponentAccessor.getIssueManager()
def currentUser = ComponentAccessor.getJiraAuthenticationContext().getLoggedInUser()

def subTaskTypeId = constantManager.getAllIssueTypeObjects().find{ it.getName() == "Sub-task" }.id
List<String> summariesList = []

def buildFromField = customFieldManager.getCustomFieldObjects(issue)find {it.name == "customFieldId=17075"}
def optionsFieldConfig = buildFromField.getRelevantConfig(issue)
def optionsFound = optionsManager.getOptions (optionsFieldConfig)

optionsFound.each { optionName ->
summariesList.add( optionName.getValue())
}

summariesList?.each { subTaskSummary ->
MutableIssue newSubTask = issueFactory.getIssue()

newSubTask.setSummary(subTaskSummary)
newSubTask.setParentObject(issue)
newSubTask.setProjectObject(issue.getProjectObject())
newSubTask.setIssueTypeId(subTaskTypeId)

Map<String,Object> newIssueParams = ["issue" : newSubTask] as Map<String,Object>
issueManager.createIssueObject(currentUser, newIssueParams)
subTaskManager.createSubTaskIssueLink(issue, newSubTask, currentUser)
}

Suggest an answer

Log in or Sign up to answer