A user asked a question about something that I think would be very useful to us, and I was after some ideas about how we might do it (or if it's possible).
We track some standard tasks in JIRA, and these tasks often have a set of standard steps to follow. For example, a standard upgrade might be something like "1. Copy to off-line instance" "2. Install new components" "3. Carry out Test A" "4. Carry out Test B" "5. Switch upgraded instance to live"
Is there a good way to create some sort of template for these issues, so that users could create an issue of type "Upgrade" and it would create a master issue, and then automatically create sub-tasks for each step in the standard task?
In the initial case, there wouldn't need to be much information in the sub-tasks apart from an issue name, which could be standard for each step. We would need the same standard tasks ("Upgrade" and so on) across a number of projects.
A small amount of development work is probably an option if anybody can give a good starting point.
Thanks,
Richard
Community moderators have prevented the ability to post new answers.
I set up something similar on Jira instance. When an issue of type User Story is created a Jython script is run that auto-creates a set of subtasks: 4 development tasks, 1 QA task, 1 documentation task and 1 infrastructure task.
To implement, install the Script Runner plugin. Update the below script for your needs and put it in $JIRA_HOME/jss/jython/workflow. In the workflow for your master issue, create a post-function for the initial transition ("Create") that calls the script. Presto! When a new issue is created a set of subtasks will also be created.
### # createSubtasks.jy
# Get the initial (parent) issue key (passed in)
# Get some of the parent's values (assignee, components, labels)
# Create new sub-tasks:
# 4 x Dev Task (issuetype.ID = 14)
# 1 x QA Task (issuetype.ID = 17)
# 1 x Documentation Task (issuetype.ID = 15)
# 1 x Infrastructure Task (issuetype.ID = 16)
#
# Issue is inherited.
# Sub-tasks inherit components from the parent issue
### from com.atlassian.jira.util import ImportUtils from com.atlassian.jira import ManagerFactory from com.atlassian.jira import ComponentManager from com.atlassian.jira.util import EasyList import java.util.ArrayList as ArrayList issueManager = ComponentManager.getInstance().getIssueManager() issueFactory = ComponentManager.getInstance().getIssueFactory() authenticationContext = ComponentManager.getInstance().getJiraAuthenticationContext() subTaskManager = ComponentManager.getInstance().getSubTaskManager(); def addSubTask(issueTypeId, subTaskName): log.debug("Adding subTask: " + subTaskName) issueObject = issueFactory.getIssue() issueObject.setProject(issue.getProject()) issueObject.setIssueTypeId(str(issueTypeId)) issueObject.setParentId(issue.getId()) issueObject.setSummary(subTaskName) issueObject.setAssignee(issue.getAssignee()) issueObject.setDescription(subTaskName) issueObject.setReporter(issue.getReporter()) subTask = issueManager.createIssue(authenticationContext.getUser(), issueObject) # issue.getGenericValue() gets a dump of the entire issue object log.debug("issue.getGenericValue(): " + str(issue.getGenericValue())) subTaskManager.createSubTaskIssueLink(issue.getGenericValue(), subTask, authenticationContext.getUser()) # Once all the subtasks have been created # Update search indexes ImportUtils.setIndexIssues(True); ComponentManager.getInstance().getIndexManager().reIndex(subTask) ImportUtils.setIndexIssues(False)
# Note: Jira v4.2.2 version requires an excplit flush.
# ManagerFactoryWARN.getCacheManager().flush(ManagerFactory.getCacheManager().ISSUE_CACHE, subTask);
# Add the subtasks to the User Story log.debug("Calling function addSubTask Adding Dev Task: Design Review") addSubTask(14,'Design Review') log.debug("Calling function addSubTask Adding Dev Task: Code Review") addSubTask(14,'Code Review') log.debug("Calling function addSubTask Adding Dev Task: Test Case Review") addSubTask(14,'Test Case Review') log.debug("Calling function addSubTask Adding Dev Task: Development Documentation Review") addSubTask(14,'Development Documentation Review') log.debug("Calling function addSubTask Adding QA Task: QA Documentation Review") addSubTask(17,'QA Documentation Review') log.debug("Calling function addSubTask Adding Documentation Task: Write Documentation") addSubTask(15,'Write Documentation') log.debug("Calling function addSubTask Adding Infrastructure Task: Infrastructure Task Placeholder") addSubTask(16,'Infrastructure Task Placeholder')
Excellent, thanks. That looks like the sort of thing I was hoping to do.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
If you install the plugin mentioned you can make use of the create subtask built-in script, so could be done without coding. However you get more control if you write a script as Byron has done, plus it's more fun.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Hi Byron,
Thank you for posting the answer for this question which I was really looking for past two-three months. I am new to Jython and Jira administration tasks and currently I am working with workflow configuring in order to auto create some sub tasks under each user story when creating each user story. Your solution is the most convenient one for that. I have installed script runner and create on transition plugins. I have used the jython post function in the transiton and used your code there. But it raises an error as follows,
Error creating issue: root cause: Traceback (most recent call last): File "<string>", line 42, in <module> File "<string>", line 27, in addSubTask at com.atlassian.jira.workflow.OSWorkflowManager.createIssue(OSWorkflowManager.java:779) at com.atlassian.jira.issue.managers.DefaultIssueManager.createIssue(DefaultIssueManager.java:402) at com.atlassian.jira.issue.managers.DefaultIssueManager.createIssue(DefaultIssueManager.java:389) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source) at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) at java.lang.reflect.Method.invoke(Unknown Source) java.lang.NullPointerException: java.lang.NullPointerException
Above error is raised when using Jira v4.4.
Please help me.
Thanks in advance.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Hi Byron,
This is conected with my previous post.
And following error is raised when using Jira5.2.1,
Error creating issue: root cause: Traceback (most recent call last): File "<string>", line 42, in <module> File "<string>", line 27, in addSubTask at com.atlassian.jira.issue.managers.DefaultIssueManager.createIssue(DefaultIssueManager.java:451) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) at java.lang.reflect.Method.invoke(Method.java:597) com.atlassian.jira.exception.CreateException: com.atlassian.jira.exception.CreateException: com.atlassian.jira.workflow.WorkflowException
Thank you.
/Sujith
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
This is the error in Jira5.2.1,
Error creating issue: root cause: Traceback (most recent call last): File "<string>", line 42, in <module> File "<string>", line 27, in addSubTask at com.atlassian.jira.issue.managers.DefaultIssueManager.createIssue(DefaultIssueManager.java:451) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) at java.lang.reflect.Method.invoke(Method.java:597) com.atlassian.jira.exception.CreateException: com.atlassian.jira.exception.CreateException: com.atlassian.jira.workflow.WorkflowException
I am new to Jython and script runner can you help me out this.
Thanks in advance.
/Sujith
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Hi Byron,
Thank you for posting the answer for this very special case which I was searching for since two-three months ago. I am currently using Jira 4.4 and I have installed Script Runner and Create on Transition plugins. And I want to add a post function for creating pre-defined sub tasks when creating a user story. Your code is perfectly matched for that. I have applied your code as a jython post function. But when creating the user story it raises an exception as follows (This is the same got by "mfrieser" at the end of this page)
Error creating issue: root cause: Traceback (most recent call last): File "<string>", line 42, in <module> File "<string>", line 27, in addSubTask at com.atlassian.jira.workflow.OSWorkflowManager.createIssue(OSWorkflowManager.java:779) at com.atlassian.jira.issue.managers.DefaultIssueManager.createIssue(DefaultIssueManager.java:402) at com.atlassian.jira.issue.managers.DefaultIssueManager.createIssue(DefaultIssueManager.java:389) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source) at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) at java.lang.reflect.Method.invoke(Unknown Source) java.lang.NullPointerException: java.lang.NullPointerException
Could you please tell me what is the reason for this and any help is highly appreciated.
I have tried with Jira5.2.1(Latest version) and the same error is arised. I will insert that error in the following post......
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
One more thing: make sure that the createSubtasks post-function is the last one, after the creation of the parent issue. I just spent a frustrating afternoon trying to figure that one out, mocked by the knowledge that I was having trouble implementing a script I wrote myself.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Here is a check for the subtask existance:
if (optionsset.get(i).getValue() =~ /Equipment Purchase/ && !(issue.getSubTaskObjects()*.summary =~ /Please Perform Equipment Purchase/)) {
and a check to see if this is a subtask: if (issue.getIssueTypeObject().isSubTask()) {
log.error ("This issue is already a sub-task...") return } else { log.error("Adding subTask: " + subTaskName) }
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Here is a groovy script that I converted from the one above that conditionally creates a subtask based on a custom multi checkbox.
**** You should verify that the subtask does not already exist before you create a new one or that this is alaready a subtask!
import com.atlassian.jira.util.ImportUtils import com.atlassian.jira.issue.fields.config.FieldConfig; import com.atlassian.jira.issue.AttachmentManager; import com.atlassian.jira.issue.attachment.Attachment; import com.atlassian.jira.ComponentManager; import com.atlassian.jira.issue.CustomFieldManager; import com.atlassian.jira.issue.comments.CommentManager; import com.opensymphony.workflow.WorkflowContext; import com.atlassian.jira.issue.fields.CustomField; import com.atlassian.jira.issue.IssueManager; import com.atlassian.jira.issue.Issue; import com.atlassian.jira.issue.util.DefaultIssueChangeHolder; import com.atlassian.jira.issue.ModifiedValue; import org.apache.log4j.Category; import com.atlassian.jira.issue.customfields.manager.OptionsManager import java.util.ArrayList as ArrayList Issue issue = issue CustomFieldManager cfm = ComponentManager.getInstance().getCustomFieldManager(); issueManager = ComponentManager.getInstance().getIssueManager() issueFactory = ComponentManager.getInstance().getIssueFactory() authenticationContext = ComponentManager.getInstance().getJiraAuthenticationContext() subTaskManager = ComponentManager.getInstance().getSubTaskManager() OptionsManager optionsManager = ComponentManager.getComponentInstanceOfType(OptionsManager.class) def addSubTask(issueTypeId, subTaskName) { log.error("Adding subTask: " + subTaskName) def issueObject = issueFactory.getIssue() issueObject.setProject(issue.getProject()) issueObject.setIssueTypeId(issueTypeId) issueObject.setParentId(issue.getId()) issueObject.setSummary(subTaskName) issueObject.setAssignee(issue.getAssignee()) issueObject.setDescription(subTaskName) issueObject.setReporter(issue.getReporter()) subTask = issueManager.createIssue(authenticationContext.getUser(), issueObject) log.error("issue.getGenericValue(): " + issue.getGenericValue()) subTaskManager.createSubTaskIssueLink(issue.getGenericValue(), subTask, authenticationContext.getUser()) // Once all the subtasks have been created // Update search indexes ImportUtils.setIndexIssues(true); ComponentManager.getInstance().getIndexManager().reIndex(subTask) ImportUtils.setIndexIssues(false) } CustomField customfield = cfm.getCustomFieldObject("customfield_10210") FieldConfig fieldConfig = customfield.getRelevantConfig(issue) def options = optionsManager.getOptions(fieldConfig) //------------------------------------ // THESE ARE THE OPTIONS THAT ARE SET //------------------------------------ Object optionsset = customfield.getValue(issue); for(i=0; i < optionsset.size(); i += 1) { if(optionsset.get(i).getValue() =~ /Equipment Purchase/) { log.error(" FOUND Equipment Purchase: " + optionsset.get(i).getValue()) //addSubTask("47","This is a subtask summary") } else { log.error("NO MATCH getoptionid: " + optionsset.get(i).getOptionId() + " getoption value " + optionsset.get(i).getValue()) } }
//------------------------------------ // THESE ARE A LIST OF ALL OPTIONS //------------------------------------ //for(i=0; i < options.size(); i += 1) { // log.error("customfield: " + customfield + " getoptionid: " + options.get(i).getOptionId() + " getoption value " + options.get(i).getValue()) //}
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
I have used the same exact script that you mentioned and changed 'customfield_10210','
~
/Equipment
Purchase/' and '
log.error(
" FOUND Equipment Purchase:' to match our customization.
I am seeing the following error whenever there is a transition:
/secure/WorkflowUIDispatcher.jspa [onresolve.jira.groovy.GroovyFunctionPlugin] Error executing post-function
javax.script.ScriptException: javax.script.ScriptException: groovy.lang.MissingMethodException: No signature of method: com.atlassian.jira.issue.customfields.option.LazyLoadedOption.size() is applicable for argument types: () values: []
Possible solutions: is(java.lang.Object), store(), find(), find(groovy.lang.Closure), use([Ljava.lang.Object;), with(groovy.lang.Closure)
COuld you please help me in figuring out what the problem is?
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
The idea behind the script is that the user can choose which sub-tasks to create based on a checkbox selection, make sure you create a multi-checkbox with the names of the subtasks you want the script to create. The names in the checkbox should be of sub-tasks you already defined.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Hi Richard
Instead of cloning You can always use Issue Templates plugin to create new issue (with almost any field / customfield and subtasks and its values) based on templates.
https://marketplace.atlassian.com/plugins/com.intenso.jira.issue-templates
Cheers, Kris
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
I'm also interested in a way of allowing users to automatically create subtasks, but only if the user manually triggers it.
In my case, I don't want the subtasks automatically created when the issue is created. Instead, I want the user to drive the creation only if he wants the subtasks. So, for instance, if the parent issue had a new button that the user could press to trigger the auto-creation of the subtasks, that would be ideal.
Since I want this to be user driven, I don't want to trigger the auto-create function off a transition.
Any clues on how to allow this via user driven interface?
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.
Use can use Clone Plus Plugin for JIRA to clone an issue and subtasks from a template project. JIRA Command Line Interface can be used if you want to automate this creation. An alternative is create or clone the primary issue and only create all the subtasks on a transition using Create On Transition for JIRA
Update: How to create projects or sets of issues based on a template
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
The script provided by Byron works fine. The only isse I have is that Greenhopper (I am creating the subtasks for a story via a transition to from "open" to "open" status) does not recognize the create sub tasks. I have to perform a full re-index to see the created tasks.
Does Greenhopper needs a special "indexing" call?
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Hello!
I have a problem executing the script above.
I am running JIRA 5.1.3 and installed the latest groovy plugin the newest JIRA version.
When the post function is executed, i get an error:
This code casues the problem:
subTask = issueManager.createIssue(authenticationContext.getUser(), issueObject)
Here the full exception message ... it would be great if you can help me out with this
javax.script.ScriptException: com.atlassian.jira.exception.CreateException:
com.atlassian.jira.exception.CreateException: com.atlassian.jira.workflow.WorkflowException
in <script> at line number 42 at org.python.jsr223.PyScriptEngine.scriptException(PyScriptEngine.java:191) at org.python.jsr223.PyScriptEngine.eval(PyScriptEngine.java:42) ..................... ..................... Caused by: Traceback (most recent call last): File "<script>", line 42, in <module> File "<script>", line 27, in addSubTask at com.atlassian.jira.issue.managers.DefaultIssueManager.createIssue(DefaultIssueManager.java:452) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source) at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) at java.lang.reflect.Method.invoke(Unknown Source) com.atlassian.jira.exception.CreateException: com.atlassian.jira.exception.CreateException: com.atlassian.jira.workflow.WorkflowException at org.python.core.PyException.fillInStackTrace(PyException.java:70) at java.lang.Throwable.<init>(Throwable.java:181) at java.lang.Exception.<init>(Unknown Source) at java.lang.RuntimeException.<init>(Unknown Source) at org.python.core.PyException.<init>(PyException.java:46) at org.python.core.PyException.<init>(PyException.java:43) at org.python.core.Py.JavaError(Py.java:481) at org.python.core.Py.JavaError(Py.java:474) at org.python.core.PyReflectedFunction.__call__(PyReflectedFunction.java:188) at org.python.core.PyReflectedFunction.__call__(PyReflectedFunction.java:204) at org.python.core.PyObject.__call__(PyObject.java:422) at org.python.core.PyObject.__call__(PyObject.java:426) at org.python.core.PyMethod.__call__(PyMethod.java:139) at org.python.pycode._pyx26.addSubTask$1(<script>:38) at org.python.pycode._pyx26.call_function(<script>) at org.python.core.PyTableCode.call(PyTableCode.java:165) at org.python.core.PyBaseCode.call(PyBaseCode.java:149) at org.python.core.PyFunction.__call__(PyFunction.java:327) at org.python.pycode._pyx26.f$0(<script>:42) at org.python.pycode._pyx26.call_function(<script>) at org.python.core.PyTableCode.call(PyTableCode.java:165) at org.python.core.PyCode.call(PyCode.java:18) at org.python.core.Py.runCode(Py.java:1261) at org.python.core.__builtin__.eval(__builtin__.java:484) at org.python.core.__builtin__.eval(__builtin__.java:488) at org.python.util.PythonInterpreter.eval(PythonInterpreter.java:198) at org.python.jsr223.PyScriptEngine.eval(PyScriptEngine.java:40) ... 174 more Caused by: com.atlassian.jira.exception.CreateException: com.atlassian.jira.workflow.WorkflowException at com.atlassian.jira.issue.managers.DefaultIssueManager.createIssue(DefaultIssueManager.java:452) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source) at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) at java.lang.reflect.Method.invoke(Unknown Source) at org.python.core.PyReflectedFunction.__call__(PyReflectedFunction.java:186) ... 192 more Caused by: com.atlassian.jira.workflow.WorkflowException at com.atlassian.jira.workflow.OSWorkflowManager.createIssue(OSWorkflowManager.java:827) at com.atlassian.jira.issue.managers.DefaultIssueManager.createIssue(DefaultIssueManager.java:441) ... 197 more Caused by: java.lang.NullPointerException at com.atlassian.jira.workflow.OSWorkflowManager.createIssue(OSWorkflowManager.java:764) ... 198 more
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Hi mfrieser,
I also having the same exception with that code. Code section just above
subTask = issueManager.createIssue(authenticationContext.getUser(), issueObject)
is working perfectly. I think there is a problem with issueObject. Did you find any solution. If so and if you don't mind please share it.
Thanks in advance.
/Sujith
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
I'm confused by the error you posted above. You mentioned you are trying to run in a groovy environment, but the stacktrace looks like python. Perhaps your script has a jy entension?
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Hi Richard,
I am not aware of any existing plugin that does a similar job. But if you invest some time into Jelly you can create a Script that does such jobs (creating and linking issues after another issue with certain specifica was created). Maybe you can use a hidden Custom Field (not visible on any screen) to track the flag if these tasks were created already.
Regards,
Niels
Examples of Atlassian: http://confluence.atlassian.com/display/JIRA/Jelly+Escalation
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.
But it can't be triggered so that it runs each time an issue is created? OK, thanks.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
The Jelly scripts seem to run either once (by hand) or periodically. Is it possible to have one "watching" for new issues? Or would you need to create the main issue and then wait until the next scheduled run of the script before seeing the subtasks appear? (Or run the script yourself by hand after creating the main issue?)
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
If you run the Script with the Jelly Service, it is just the service (executed periodically). But it was also possible to write a plugin that executes Jelly scripts after Events. Unfortunately something like this does not exist yet. I could have used it for myself some weeks ago :-)
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
You can run the script manually after creating the main issue or let it run periodically (e.g. every 5 mins) and check for new issues with a special filter. Imagine the following procedure:
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Community moderators have prevented the ability to post new answers.
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.