Subtasks should inherit field values from the parent task on create

Cristina_Abunei
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.
February 3, 2016

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

6 votes
Answer accepted
Cristina_Abunei
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.
February 3, 2016

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.

L. Drewes February 17, 2016

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? 

Like Jana Schumann likes this
Corinna March 16, 2016

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

 

Naama Lev
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 15, 2017

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)

1 vote
Jeremy Gaudet
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.
February 3, 2016

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
andreas
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.
November 21, 2016

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

Luke Pilkington September 15, 2017

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. 

andreas
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.
September 15, 2017

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

0 votes
Vasiliy Zverev
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.
February 3, 2016

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);
    }
}

Suggest an answer

Log in or Sign up to answer