Create
cancel
Showing results for 
Search instead for 
Did you mean: 
Sign up Log in

It's not the same without you

Join the community to find out what other Atlassian users are discussing, debating and creating.

Atlassian Community Hero Image Collage

JMWE Post Function Creates Issue - but errors on subtask creation

Hello, 

I am using the JIRA Cloud instance.

I have been using JMWE Post Functions to Create a New Issue on another projects board - and have been copying over most of the fields details with no issues (Summary, Description, Attachment, Reporter, etc) and using 'Copy value from current issue'.

Recently, we've started to also want to copy the subtasks and their details from the parent issue on project A --> and attach them the newly created issue on project B.

But i am getting an error message on the subtask creation and cannot seem to figure out how to correct it.

Error Message: 

Field subtasks is not editable on issue

There are no Issue Security levels preventing a subtask from being editable.  I don't know what else to check or where to look. 

Any help or assistance would be greatly appreciated! Until this is figured out, users are having to re-enter subtasks manually which is not an efficient use of their time.

Thank you in advance for any suggestions that may assist me & my organization! 

3 answers

1 accepted

0 votes
Answer accepted

Hi Sandi,

the subtasks field _cannot_ be copied over to the new issue, simply because this is not a standard field. Sub-tasks are actually Jira issues, just like regular issues.

The solution is to use a second Create Issue(s) post-function to copy the sub-tasks to the newly created main issue, using the "multiple issue creation" feature. You can refer to this example which is similar.

Thank you for your reply, so I already have a Create Issue post function setup - you are saying I can use the Multiple Issue Creation option within this post function to create and attach the sub-tasks?

Not exactly. You need to use a second Create Issues post function to create the sub tasks that will belong to the issue created by the first post function. The easiest is to put both post function inside a Sequence so the second post function has access to the key of the issue created by the first post function. 

Like Sandi Slavko likes this

ok, I'll read up on Sequencing. Thank you! This is new to me and trying to piece it all together.  I really do appreciate the feedback!

So I've got sequencing setup, and it is Creating a new Issue on project B.  It is also creating a subtask - so I am 50% of the way there.

The subtask that is being created, is just a duplicate of the parent task -- not a clone of the actual subtasks from project A.

I have followed the setup from this article - what am I missing?

I've done these steps, but keep getting the result noted above:  #3 is where I believe my issue is.

How do I copy/clone the actual Subtask "Summary" & "Description"?

For example, consider a use case where you want to clone an issue and its subtasks to another project, then:

  1. Add the "Sequence of post-functions" post-function to the transition
  2. In the sequence add the "Create issue" post-function.
    1. Select the destination project in "Project"
    2. Select the "Issue type" as "Calculated" and input: {{ issue.fields.issuetype.name }}
    3. Select the "Link to new issue" as "clones"
    4. Configure the fields
    5. Click on Save
  3. Add another "Create issue" post-function to clone the sub-tasks
    1. Select the destination project in "Project"
    2. Select the "Issue type" as "Subtask"
    3. Under the "Parent issue" input the following template:

      1{{ transition.context.newIssueKey }}
    4. Select "Multiple issue creation" option and input the following template:

      1{{ issue | subtasks | length }}
    5. Save the post-function.
  4. Click on "Save"
  5. Publish the workflow.

Hi Sandi,

you're right, the problem is in #3, and more specifically in the iterator. You want the iterator to iterate over the issue's sub-tasks, so it should be:

{{ issue | subtasks("summary,description,priority,issuetype") | dump }}

and you need to select the "Iterator returns JSON" option. That will make the "it"  variable iterator over sub-tasks of the main issue. Note that you can add fields to the subtasks filter if you want to copy additional fields of the sub-tasks to their clones.

Then for the Summary field, you can use:

{{ it.fields.summary }}

Same for the Description field.

And you can even use a "Calculated" issue type:

{{ it.fields.issuetype.id }}
Like Sandi Slavko likes this

First, I would like to THANK YOU for all of your help with this!  I really do appreciate it.

I've edited my configs on this post function as noted above - and it is working, but it is only cloning the 1st subtask of the issue from Project A over to Project B, not the remaining subtasks that are also on the parent issue.

I'm sure it's one small piece that I am missing - but I need any and all subtasks to be cloned over to project B and these vary from 1 subtask to ~5 subtasks.

Any thoughts on this to help me through this final piece?  My configs are below:

Create new issues:

Iterator (returning JSON):

{{issue | subtasks("summary,description,issuetype") | dump}}

Issue type: Sub-task

Parent issue:

{{transition.context.newIssueKey}}

Fields:

Summary: Set to:

{{it.fields.summary}}

Description: Set to:

{{it.fields.description}

Thank you again! 

Actually, it's because of a bug in JMWE. The transition.context.newIssueKey variable gets replaced during the iteration with each sub-task being created, instead of at the end of the post-function. 

This should now be fixed. Can you try again?

Yes!! this is now working as expected!  THANK YOU THANK YOU THANK YOU!

This is going to make things so much easier for my company and it's users.

I really do appreciate you walking me thru this!

Enjoy your day!

How do I clone over custom field values to the newly created subtasks? Thanks to this helpful article, I've been able to accomplish creating a new issue and its respective subtasks along with the fields above. Now, I'm developing and want to incorporate some custom field when cloning.

All help is appreciated.

Like Sandi Slavko likes this

You can just add the custom fields under the "Set fields of new issue" section, just like standard fields.

When I do that, it seems that it's referencing the parent issue rather than the respective subtask that I'm trying to clone. 

For context, I have 2 projects– project A and project B. 

Users interact with project A where they define Parent 1 and its subtasks. I currently have the post function cloning Parent 1 and its subtasks to project B, and it works perfect when it comes to copying over each summary, desc, etc. However, when I try to do what you just mentioned, it return no value, or the value of Parent 2, rather than the respective subtask of Parent 1.

atl 1.png

I guess I misunderstood what you were trying to achieve. You seem to be first cloning an issue, using a first Create Issue(s) post-function, and then cloning its sub-tasks to the issue clone.

In that case, for each field, you need to select the "Set field value to:" option, just like you did for the Product field. You can find out how to insert the value of each field (since it depends on the field type) using the "Issue fields" help tab of the Nunjucks editor.

Conceptually, that cleared up a ton for me. Thank you so much for being quick and helpful! 

I'll follow up if I get stuck again.

New question...does the iterator issue.get("customfield_####") only work if it is a multi-select field?  We tried to use this format with a radio button and a single-select button and I think they return a string instead of an array.  (Basically, we were trying to use this postfunction to create a single task but based on the answer to the radio button.)  Or is there a different format for those kinds of buttons?  thanks.  Sorry to be a pest.

The whole idea of an iterator is to create multiple issues. If you want to create a single issue, no need for the "multiple issue creation" option and its iterator script.

If you want to use the value of a custom field when creating another issue, you can just refer to it directly. What exactly are you trying to do with the value of the single-select field?

So let's say we have a radio button on a transition screen with choices A, B or C.

If button A is selected, create a new issue with the summary, "It's an A issue!"  and with a specific "A" description, plus a bunch of other fields that just copy the parent.

If button B is selected, create a new issue with summary, "It's a B issue!"...etc, etc...

And preferably, if no button is selected, no new issue is created.

We've gotten so used to using this postfunction to create tasks on a transition, we just went straight to it!  But I guess there is a better way.

This can all be done without an iterator.

To avoid creating a new issue when no button is selected, use "conditional execution" with a script like:

!!issue.get("customfield_####")

 For the Summary, you can do either something like:

It's an ${issue.getAsString("customfield_####")} issue!

or use a "Groovy Expression" value like:

switch (issue.getAsString("customfield_####")) {
case "A": return "It's an A issue!";
 case "B": return "It's a B issue!";
case "C": return "It's a C issue!";
}

And for Description, use Set to Groovy Expression with a script like:

switch (issue.getAsString("customfield_####")) {
case "A": return "Description for A";
 case "B": return "Description for B";
case "C": return "Description for C";
}

This looks great.  I'll have to test it tomorrow with the user (she has complicated needs.) But I really appreciate your sage wisdom. 

Can someone tell me HOW to set my "iterator returns JSON" setting?

I'm returning:

["Summary":"BEC MANUAL", "Description":"This is a Bec Manual"]

And in my Summary field, I ask for it.Summary, and in my Description field, I ask for it.Description...and I'm creating an issue with the Summary "it.Summary" and matching description.  /;-]

I figure it's because I haven't set my "iterator returns JSON" setting...but I can't find it?

Thank you!

under the Multiple Issue Creation section - select to 'Create Multiple Issues', this will open up the Iterator and you will see the option just below for "Iterator returns JSON"

 

Multiple issue creation

Create multiple issues

You can create multiple issues at once during the execution of this post-function. For more information, please see the "Expected Value" help section of the editor below.

Iterator:(required)

{{issue | subtasks("summary,description,issuetype") | dump}}

Iterator returns JSON

Use this option to indicate that the Iterator template above returns a JSON array instead of a comma-separated list of strings.

I just don't see anything about JSON (see image below.)  Gosh, I hope this isn't one of those "this is only for Cloud, not for Server" things...I've been trying to get this to work all day long.

image.png

Hi Nancy,

that's because you're on Jira Server or Data Center, not Cloud. JMWE for Jira Server uses Groovy and the iterator can return any collection. 

In your example, you're returning only one "object" (really a Groovy map), so you don't need an iterator at all for that, you can directly set the Summary and Description fields. However, if you want to create multiple issues, with different summaries and descriptions, you need to use an iterator and return an array of objects:

[
 [summary:"issue 1",description:"Desc 1"],
 [summary:"issue 2",description:"Desc 2"]
]

(Sigh. I'm so obviously out of my depth.) 

I'm attempting to read through a multi-select customfield and for each selection, create an issue with a different summary and description (and there will be other fields filled in, but I thought I'd shoot for two to start).  So if a user selects 2 of the values (say, BEC Manual and Export Manual) on customfield (which is a checkbox selection field), this will create an issue for each selection. 

issuevalues=[]
issue.get("customfield_49100").each {
if (it.value=="BEC Manual") {
issuevalues.add('"Summary":"BEC MANUAL", "Description":"This is a Bec Manual"')
}
if (it.value=="Export Manual") {
issuevalues.add('"Summary":"Export MANUAL", "Description":"This is a Export Manual"')
}
}
return issuevalues

And I set the Summary and Description fields to "set value to constant or groovy" expression and it.Summary and it.Description.  

And when I run this, it creates 1 issue with the Summary "it.Summary"   LOL.  

I tested the script and it at least returns "Summary":"BEC MANUAL", "Description":"This is a Bec Manual" (though it should really return "Summary":"BEC MANUAL", "Description":"This is a Bec Manual" "Summary":"Export MANUAL", "Description":"This is a Export Manual" )

Any suggestions?  And is there a freakin' tutorial somewhere?  /;-]

Because both the Summary and the Description can be built from the values selected in the multi-select field, there is a much simpler approach:

- as the iterator, use simply:

issue.get("customfield_49100")

- For the Summary, set it to Constant or Groovy Template  with this value:

${it.value}

- For the Description, set it to Constant or Groovy Template  with this value:

This is a ${it.value}

Why it.value and not simply it? Because each selected value of a multi-select field is represented not by a String but by an Option object that have a value field containing the textual representation of the option.

Okay, I see - interesting! 

But what if I need something other than the actual value?  Like 

issuevalues=[]
issue.get("customfield_49100").each {
if (it.value=="BEC Manual") {
issuevalues.add('"Summary":"Print request", "Description":"Replace this text with information on the print job"')
}
if (it.value=="Export Manual") {
issuevalues.add('"Summary":"Export Rules Chapter", "Description":"Replace this text with information on the new rules."')
}
}
return issuevalues

(I had an over-permissioned user create 42 post functions to create these subtasks one at a time.  I'm trying to consolidate a few.)

Thanks for your awesome advice!

You don't need to do this in the iterator, you can/should do it in the value for the Summary and Description fields. Instead of "Constant or Groovy Template", choose "Groovy expression" and then in the script, you'll be able to map the value to the desired text. The most readable way is:

switch (it.value) {
case "BEC Manual": return "Print request"
case "Export Manual": return "Export Rules Chapter"
}

And do something similar for the Description.

Another oooOOOOoooh!  Can't wait to try this.  I will report back tomorrow.  Thank you!

I got so excited, I logged back in to try.  But just ignore me until you hopefully have time.

Still no joy.  I've attached an image of the post-function summary.  If I test them individually inside the post function they work. (See 2nd image)  But I get this error that says it can't create ... "you must specify a summary"   Thanks for any ideas.  This has been fascinating.

image.pngimage.pngimage.png

It's probably when creating the second issue, for "Export Guide",as it doesn't match any case statement (you wrote "Export Manual")

 

David

OH MY GOSH, I'm an idiot.  

Thank you thank you thank you.  It worked and I can't wait to show everyone tomorrow.

Sweet Johosaphat's underpants!  David, may I bother you one more time?  I spent all day consolidating 42 workflows down to 17 but it isn't going to work because these users put all the values for different issue types into the same custom field.  I'm using the same iterator for each post-function. So what happened above, when I was a proof-reading nincompoop, is happening now.  It gets to the first post function and if it doesn't find the value necessary to create the summary (because that value is in the 2nd or 17th post-function), it errors out.

Is there some way to add to the Summary switch code "and if the value you are looking for isn't here, go to the next post-function?"

Thank you for your patience.

I learned a new expression today :)

I'm not quite sure I understand your problem. Can you elaborate? do you mean that you have 17 different Create Issue(s) post-functions? Or was it workflows? I'm confused.

But I guess the answer to your problem is "conditional execution". You should use conditional execution so that the post-function only runs for the values of that custom field it can handle.

However, why do you need multiple post-functions?

The full story is so long that when I tell it, I can bore for my country.  I've added it below if you really have nothing better to do.  But I don't want to accidentally put you in a coma.

BUT...I think I see what you mean by "conditional execution"...I need to add the condition "run this post function if X or X or X is found in this custom field."  Right?

So is this the right kind of code to add to the condition at the bottom of the postfunction:

issue.get("customfield_53500")?.any{it.value == "SEC Admin Tracker" || it.value == "PG Document" || it.value == "BEC Manual"}    (etc etc)

 

And I have no idea how I would make one post function that creates multiple subtasks with different issue types.

 

IF YOU ARE IN DIRE NEED OF READING MATERIAL...

Here is probably much too much information...

A year or two ago, we were so undermanned that the Atlassian administrator basically gave full developer/admin permissions to a couple of talented users for their project and walked away.  Do you have kids?  You know what happens if you give smart children indelible markers and leave them unsupervised in the living room?  Yep. Complicated, intertwined doodles all over the walls.  We have just recently realized that their project has 51 issue types (Update PG Pages, Update Portfolio Pages, etc.), they've created hundreds of custom fields, and they have workflows with 42 post-functions.  This monster will be impossible to manage if the main architect ever leaves the company.  We should start over, but who has time for that?!

ANYHOO....This "maintenance" workflow...So a user creates a parent ticket with some new information that needs to be added to different documents...maybe it needs to be added to a manual, or portfolio, or guidance document, or all of the above...  On this one parent ticket, they have a checkbox custom field with about 40 values in it.  The user clicks all the different checkboxes that this information must be added to.  And when they transition the ticket to "Editorial Backlog", it goes through 42 post functions, which each have a condition...if the custom field has the value of X, create a subtask with the issue type Y and these fields filled-in.  And many of these post functions are creating the same kind of issue type, just with different fields filled in.  

So with your help, I combined post functions.  For example, I took the 6 post functions that created a "portfolio update" ticket and put them into one post function that used the Switch command to fill in the summary (and other fields) differently depending on the values found in the custom field.  That's the first post function.

The second post function creates subtasks with the issue type "Manual Update" and fills in the summary differently using the Switch command based on the values found in the same custom field blah blah blah...

Except this doesn't currently work because if a value is not found in post function #1, it just errors out.

Whew!

Thank you.

Update:  Nope, even adding a conditional doesn't work, because if I choose two custom field variables that each should create a different issue type, the first one matches the conditional and starts a post function, but it tries to run BOTH values through the switch, doesn't recognize one of the values and crashes.  Sigh.  I should've worked at Starbucks.

If the difference between the different post-functions is the Issue Type of the issues to create, you can use "Calculated:" as the Issue Type and _calculate_ the issue type from the information in the iterator (in your case, from it.value) just like you calculate the Summary or the Description (using a switch statement).

Holy. Cannoli.  I'm off to try this.

So David, is there some way to send you karma, like you can in Slack?  Or brownie points? Or actual brownies?

I like brownies :)

But your satisfaction is enough to make me happy.

David

You know, I just had to stop by and thank you again.  We have a lot of projects that in one way or another need to spin-off tasks or subtasks.  I taught my whole team what you taught me about using calculated and switch and case, etc.  It has made a world of difference to the crazy things we were doing before.  Have a great day!

Wow! Thanks! Happy JMWE makes a difference in your company :)

Suggest an answer

Log in or Sign up to answer
TAGS
Community showcase
Published in Apps & Integrations

🍻🍂Apptoberfest Update: Upcoming Virtual Events 🎉

Hello Community! I hope you've been enjoying the 🍂Apptoberfestivities🍂 (I know I have!) The event is heating up next week with a series of virtual events that we're calling the 🍻🍂Partner App ...

462 views 5 18
Read article

Community Events

Connect with like-minded Atlassian users at free events near you!

Find an event

Connect with like-minded Atlassian users at free events near you!

Unfortunately there are no Community Events near you at the moment.

Host an event

You're one step closer to meeting fellow Atlassian users at your local event. Learn more about Community Events

Events near you