Subtasks should inherit field values from the parent task on create

Hello.

I am trying to configure JIRA so that subtasks inherit field values from their parent, when they are created. The workflow postfunction offered by ScriptRunner does not work when creating the issue, as the link between parent and child is not yet created.

I installed the "Copy to Subtask" plugin but it doesn't work. No fields are inherited from the parent issue.

I am using JIRA 6.4.3 and ScriptRunner 3.0.14.

I would be interested in implementing some sort of listener for this, but I haven't had much luck with them. Does anybody know if there is a problem with creating inline Groovy classes? I've run mutiple examples from the documentation but none work.

 

Thank you,

Cristina

 

 

4 answers

1 accepted

Hey,

So the solution was ridiculously simple. Because i usually view my workflows in text mode, i hadn't noticed the "Create" transition before the first status. I added a "Copy values" postfunction on that transition and it all works like a charm.

Thanks for the answers, I'm sure they'll be useful to me in other ways.

Hi Cristina, 

When i'm in Transition: Create Issue > Post Functions > Add post function is see a list of available functions but no 'Copy values' function. Did you do anything to make this function available? 

but this will only work for sub tasks,,,not for linked issues to a parent task ?

 

Hi Cristina, 

I have followed your suggestions - and it is working well for all fields except for Labels - where I get and error (please see below)

Is it working for you for lables as well ?

Thanks!

Naama

2017-06-16 13:45:34,766 http-bio-8443-exec-24025 ERROR naama 825x6280973x1 2ig2dz 10.1.5.250,10.1.8.105 /secure/QuickCreateIssue.jspa [c.a.j.bc.issue.DefaultIssueService] Error creating issue:
com.atlassian.jira.exception.CreateException: Unable to copy value from field 'Labels' to 'Labels'.
at com.atlassian.jira.issue.managers.DefaultIssueManager.createIssue(DefaultIssueManager.java:588)
at com.atlassian.jira.issue.managers.DefaultIssueManager.createIssue(DefaultIssueManager.java:494)
at com.atlassian.jira.bc.issue.DefaultIssueService.create(DefaultIssueService.java:230)
at com.atlassian.jira.bc.issue.DefaultIssueService.create(DefaultIssueService.java:199)
at sun.reflect.GeneratedMethodAccessor2676.invoke(Unknown Source)

I wrote this postfunction to copy values from a parent task to a subtask:

import com.atlassian.jira.component.ComponentAccessor
import com.atlassian.jira.event.type.EventDispatchOption
import com.atlassian.jira.issue.CustomFieldManager
import com.atlassian.jira.issue.Issue
import com.atlassian.jira.issue.IssueManager
import com.atlassian.jira.issue.MutableIssue
import com.atlassian.jira.issue.UpdateIssueRequest
import com.atlassian.jira.issue.fields.CustomField
import com.atlassian.jira.user.ApplicationUser

IssueManager issueManager = ComponentAccessor.getIssueManager();
Issue parentIssue = issueManager.getIssueObject(issue.getParentId());

ComponentAccessor.getCommentManager().create(issue, ComponentAccessor.getJiraAuthenticationContext().getUser(), "test", false);

issue.subTaskObjects.any

CstFldCoper cstFldCoper = new CstFldCoper();

cstFldCoper.copyCustomFieldFromParentToSubTask(parentIssue, issue, 10008L);  //Ответственный
cstFldCoper.copyCustomFieldFromParentToSubTask(parentIssue, issue, 10005L); //РФГ
cstFldCoper.copyCustomFieldFromParentToSubTask(parentIssue, issue, 10716L); //координатор разработчиков

public class CstFldCoper{
    private CustomField cstFld;
    private CustomFieldManager cstFldMng = ComponentAccessor.getCustomFieldManager();
    UpdateIssueRequest updIssReq;
    ApplicationUser curUser = ComponentAccessor.getJiraAuthenticationContext().getUser();
    IssueManager issueManager1 = ComponentAccessor.getIssueManager();

    public CstFldCoper(){
        //Задаём параметры для обновления запроса
        UpdateIssueRequest.UpdateIssueRequestBuilder issueRequestBuilder = new UpdateIssueRequest.UpdateIssueRequestBuilder();
        issueRequestBuilder.eventDispatchOption(EventDispatchOption.ISSUE_UPDATED);
        issueRequestBuilder.sendMail(false);
        updIssReq = new UpdateIssueRequest(issueRequestBuilder);
    }

    public void copyCustomFieldFromParentToSubTask(Issue _parent, MutableIssue _subTask, long _cstFldId){
        cstFld = cstFldMng.getCustomFieldObject(_cstFldId);
        _subTask.setCustomFieldValue(cstFld, _parent.getCustomFieldValue(cstFld));
        issueManager1.updateIssue(curUser, _subTask, updIssReq);
    }
}

I've done this using a listener, a sample is included below.  It's not an inline script, I had to put the file in /home/jira/jira_data/com/myorg/listeners.  I've sanitized it somewhat (removed workflow and organization names), but it should do the trick.  It syncs two fields, "Fix Version/s" and a custom field called "Verified Version/s".  It's based on this example:

http://stackoverflow.com/questions/18428756/update-jira-subtask-fix-version-when-parent-issue-fix-version-updated

But is updated to account for being out of date, plus it handles the empty list case.  It's designed to listen for all projects and events, and use the name of the workflow to determine if the sync should take place, that way nobody can forget to include it in the listener when new projects are created.  Finally, it does the sync for edge cases like adding a sub-task to an existing parent.

Hmm, actually, this is more than what you asked for in that it will keep them in sync after creation.  Oh well, hopefully it helps.

package com.myorg.listeners;
import org.apache.log4j.Category;
import com.atlassian.jira.ComponentManager;
import com.atlassian.jira.event.issue.AbstractIssueEventListener;
import com.atlassian.jira.event.issue.IssueEvent;
import com.atlassian.jira.issue.Issue;
import com.atlassian.jira.project.version.Version;
import com.atlassian.jira.config.SubTaskManager;
import com.atlassian.jira.issue.IssueManager;
import com.atlassian.jira.issue.CustomFieldManager;
import com.atlassian.jira.issue.fields.CustomField;
import com.atlassian.jira.event.type.EventDispatchOption;
import com.atlassian.jira.workflow.WorkflowManager;
import com.atlassian.jira.workflow.JiraWorkflow;
import java.util.ArrayList;
import java.util.Collection;
class SyncParentFixVerifiedVersionsToSubTask extends AbstractIssueEventListener 
{
    Category log = Category.getInstance(SyncParentFixVerifiedVersionsToSubTask.class);
    SubTaskManager subTaskManager = ComponentManager.getInstance().getSubTaskManager();
    WorkflowManager workflowManager = ComponentManager.getInstance().getWorkflowManager();
    IssueManager issueManager = ComponentManager.getInstance().getIssueManager();
    CustomFieldManager customFieldManager = ComponentManager.getInstance().getCustomFieldManager();
    Boolean changed = false;
    Long workflowId;
    @Override
    void workflowEvent(IssueEvent event) {
        try {
            if (subTaskManager.isSubTasksEnabled()) {
                Issue eventIssue = event.getIssue();
                JiraWorkflow workflow = workflowManager.getWorkflow(eventIssue);
                if (workflow.getName() == "Put Workflow Name Here") {
                    CustomField vvcf = customFieldManager.getCustomFieldObjectByName("Verified Version/s");
                    if ( !eventIssue.getIssueTypeObject().isSubTask() ) {
                        // Change is on a potential parent, sync to sub-tasks if there are any
                        Collection<Issue> subTasks = eventIssue.getSubTaskObjects();
                        List changeItems = event.getChangeLog().getRelated("ChildChangeItem");
                        // Sync FixVersion/s
                        if( changeItems.any {it.get('field')=='Fix Version'} ) {
                            changed = true;
                            // Collection<Version> fixVersions = new ArrayList<Version>();
                            // fixVersions = eventIssue.getFixVersions();
                            Collection<Version> fixVersions = eventIssue.getFixVersions();
                            if (!subTasks.isEmpty()) {
                                subTasks.each {
                                    it.setFixVersions(fixVersions);
                                }                     
                            }
                        }
                        // Sync Verified Version/s
                        if( changeItems.any {it.get('field')=='Verified Version/s'} ) {
                            changed = true;
                            Collection<Version> verifiedVersions = new ArrayList<Version>();
                            verifiedVersions = eventIssue.getCustomFieldValue(vvcf);
                            if (!subTasks.isEmpty()) {
                                subTasks.each {
                                    it.setCustomFieldValue(vvcf,verifiedVersions);
                                }
                            }
                        }
                        if (changed) {
                            subTasks.each {
                                issueManager.updateIssue(event.getUser(), it, EventDispatchOption.ISSUE_UPDATED, false);
                            }
                        }
                    } else {
                        // Change is on a sub-task, sync from the parent if they are out of sync
                        Issue parentIssue = eventIssue.getParentObject();
                        // Sync "Fix Version/s"
                        Collection<Version> parentFixVersions = parentIssue.getFixVersions();
                        if (parentFixVersions == null) parentFixVersions = new ArrayList<Version>();
                        Collection<Version> fixVersions = eventIssue.getFixVersions();
                        if (fixVersions == null) fixVersions = new ArrayList<Version>();
                        if(!(parentFixVersions.containsAll(fixVersions) && fixVersions.containsAll(parentFixVersions))) {
                            eventIssue.setFixVersions(parentFixVersions);
                            changed = true;
                        }
                        // Sync "Verified Version/s"
                        Collection<Version> parentVerifiedVersions = parentIssue.getCustomFieldValue(vvcf);
                        if (parentVerifiedVersions == null) parentVerifiedVersions = new ArrayList<Version>();
                        Collection<Version> verifiedVersions = eventIssue.getCustomFieldValue(vvcf);
                        if (verifiedVersions == null) verifiedVersions = new ArrayList<Version>();
                        if(!(parentVerifiedVersions.containsAll(verifiedVersions) && verifiedVersions.containsAll(parentVerifiedVersions))) {
                            eventIssue.setCustomFieldValue(vvcf,parentVerifiedVersions);
                            changed = true;
                        }
                        if (changed) {
                            issueManager.updateIssue(event.getUser(), eventIssue, EventDispatchOption.ISSUE_UPDATED, false);
                        }
                    }
                }
            }
        }
        catch (ex) {
            log.debug "Event: ${event.getEventTypeId()} fired for ${event.issue} and caught by SyncParentFixVerifiedVersionsToSubTask"
            log.debug (ex.getMessage())
        }
    }
}
0 votes

There's now a very easy to configure way to copy field values from parents to sub-tasks (and vice versa) using Automation for JIRA!

You can easily modify related issues (such as parents, stories, sub-tasks, epics, linked issues and even JQL) using our related issues action and condition:

(this example transitions sub-tasks, but you could just as easily change this to edit field values on the sub-tasks etc)

For more details see https://blog.codebarrel.io/synchronize-parent-and-sub-task-issues-with-automation-for-jira-bdcca6c9d453

Hi 

Can you tell me how to copy fields from a parent to a sub task?

At the moment, I cant seem to get anything from the parent issue to the sub-task usign automation. In the additional fields box I have:

 

{
"fields": {
"First Name": "{{issue.parent.fields.First Name}}",
"Last Name": "{{issue.parent.fields.Last Name}}"
}
}

 

However it is not working. If I just add text instead of {{issue.parent.fields.First Name}}. The text appears. 

Hi Luke,

What you posted should work, but it depends a bit on your rule config.  Can you post a screenshot of your entire rule configuration at https://codebarrel.io/support please?

Cheers,
  Andreas

Suggest an answer

Log in or Join to answer
Community showcase
Sarah Schuster
Posted Jan 29, 2018 in Jira

What are common themes you've seen across successful & failed Jira Software implementations?

Hey everyone! My name is Sarah Schuster, and I'm a Customer Success Manager in Atlassian specializing in Jira Software Cloud. Over the next few weeks I will be posting discussion topics (8 total) to ...

2,826 views 12 18
Join discussion

Atlassian User Groups

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

Find a group

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

Find my local user group

Unfortunately there are no AUG chapters near you at the moment.

Start an AUG

You're one step closer to meeting fellow Atlassian users at your local meet up. Learn more about AUGs

Groups near you
Atlassian Team Tour

Join us on the Team Tour

We're bringing product updates and pro tips on teamwork to ten cities around the world.

Save your spot