Jira Groovy Script Runner - Clone an issue and link - set the reporter of the new issue

Greg Hoggarth March 19, 2014

I'd like to set the reporter value of the new issue that is created to either:

a) the value of a custom field from the original issue (a username custom field called Developer)

b) the username of the person executing the transition that had the clone post-function

Here's what I've tried so far, which doesn't work:

issue.reporter = originalIssue.getCustomFieldValue(componentManager.getCustomFieldManager().getCustomFieldObjectByName("Developer"))

5 answers

0 votes
Greg Hoggarth April 7, 2014

Here's the groovy script that is being run:

package com.onresolve.jira.groovy.canned.workflow.postfunctions

import com.atlassian.jira.ComponentManager
import com.atlassian.jira.config.ConstantsManager
import com.atlassian.jira.issue.Issue
import com.atlassian.jira.issue.MutableIssue
import com.atlassian.jira.issue.link.IssueLinkManager
import com.atlassian.jira.issue.link.IssueLinkType
import com.atlassian.jira.issue.link.IssueLinkTypeManager
import com.atlassian.jira.util.ErrorCollection
import com.atlassian.jira.util.SimpleErrorCollection
import com.onresolve.jira.groovy.canned.CannedScript
import com.onresolve.jira.groovy.canned.utils.CannedScriptUtils
import com.onresolve.jira.groovy.canned.utils.ConditionUtils
import com.onresolve.jira.groovy.canned.utils.WorkflowUtils

class CloneIssue extends CopyIssueWithAttachments implements CannedScript{

    String getName() {
        return "Clones an issue and links."
    }

    public String getHelpUrl() {
        "https://jamieechlin.atlassian.net/wiki/display/GRV/Built-In+Scripts#Built-InScripts-Clonesanissueandlinks"
    }

    String getDescription() {
        return """Clones this issue to another issue, optioninally in another project, and optionally a different issue type.
        """
    }

    List getCategories() {
        ["Function", "Listener"]
    }

    List getParameters(Map params) {
        [
            ConditionUtils.getConditionParameter(),
            [
                Name:FIELD_TARGET_PROJECT,
                Label:"Target Project",
                Type: "list",
                Description:"Target project. Leave blank for the same project as the source issue.",
                Values: CannedScriptUtils.getProjectOptions(true),
            ],
            [
                Name:FIELD_TARGET_ISSUE_TYPE,
                Label:"Target Issue Type",
                Type: "list",
                Description:"""Target issue type. Leave blank for the same issue type as the source issue.
                    <br>NOTE: This issue type must be valid for the target project""",
                Values: CannedScriptUtils.getAllIssueTypes(true),
            ],
            ConditionUtils.getOverridesParam(),
            [
                Name:FIELD_LINK_TYPE,
                Label:'Issue Link Type / Direction',
                Type: "list",
                Description:"What link type to use to create a link to the cloned record.",
                Values: CannedScriptUtils.getAllLinkTypesWithInwards(true)
            ],
        ]
    }

    public ErrorCollection doValidate(Map params, boolean forPreview) {
        SimpleErrorCollection errorCollection = new SimpleErrorCollection()
        if (!params[FIELD_LINK_TYPE]) {
            errorCollection.addError(FIELD_LINK_TYPE, "You must provide a link type.")
        }
        // todo: validation for issue type if set
        return errorCollection
    }

    Map doScript(Map<String,Object> params) {
        MutableIssue issue = params['issue'] as MutableIssue

        Boolean doIt = ConditionUtils.processCondition(params[ConditionUtils.FIELD_CONDITION] as String, issue, false, params)
        if (! doIt) {
            return [:]
        }

        params = super.doScript (params)

        Issue newIssue = params[NEW_ISSUE] as Issue

        // handling also reverse links (inwards) with keeping compatibility (no text appended to id)
        String linkTypeId
        String linkDirection
        if (params[FIELD_LINK_TYPE]) {
            (linkTypeId, linkDirection) = params[FIELD_LINK_TYPE].split(/ /) as List
        }

        // get the current list of outwards depends on links to get the sequence number
        IssueLinkManager linkMgr = ComponentManager.getInstance().getIssueLinkManager()

        if (linkTypeId && linkMgr.isLinkingEnabled()) {
            IssueLinkTypeManager issueLinkTypeManager = (IssueLinkTypeManager) ComponentManager.getComponentInstanceOfType(IssueLinkTypeManager.class)

            IssueLinkType linkType = issueLinkTypeManager.getIssueLinkType(linkTypeId as Long)

            if (linkType) {
                Boolean reversed = linkDirection == CannedScriptUtils.INWARD_FIELD_NAME
                linkMgr.createIssueLink (reversed ? newIssue.id : issue.id, reversed ? issue.id : newIssue.id, linkType.id, 0, WorkflowUtils.getUser(params))
            }
            else {
                log.warn ("No link type $linkTypeId found")
            }
        }

        params
    }


    String getDescription(Map params, boolean forPreview) {
        ConstantsManager constantsManager = ComponentManager.getInstance().getConstantsManager()

        StringBuffer sb = new StringBuffer()
        sb << getName() + "<br>Issue will be cloned to project <b>" + (params[FIELD_TARGET_PROJECT] ?: "same as parent") + "</b>"
        sb << "<br>With issue type: <b>" + (params[FIELD_TARGET_ISSUE_TYPE] ? constantsManager.getIssueTypeObject(params[FIELD_TARGET_ISSUE_TYPE] as String)?.name : "same as parent") + "</b>"
        sb.toString()
    }

    public Boolean isFinalParamsPage(Map params) {
        true
    }
}

So I think the issues I'm dealing with are "issue" as the parent, and "newIssue" as the cloned copy. However the pre-canned example scripts are outdated and don't even work, obviously things have changed in Jira since the examples were written. This of course makes it harder to work out what the correct syntax needs to be.

The "additional issue actions" I believe get bundled up into the "params" variable, which I presume is what is being exected at line 110 in the above script.

0 votes
Radek Kantor
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.
April 6, 2014

Check API,

1. You have "issue" so if parent exists it is no problem lookup it. Otherwise if original issue is some another issue, you must probably use proper manager to access it. Dont known you business logic of original issue, if there is some relation with "issue" defined by link, or original issue is hardcoded by ID, etc.

issue.getParentObject()

https://docs.atlassian.com/jira/6.2.1/com/atlassian/jira/issue/Issue.html

2. You use another way, script syntax to set field values. I usually write scripts more like java code. If I look on IssueInputParameters there is method to set reporter.

issueInputParameters.setReporterId(String reporterId)

https://docs.atlassian.com/jira/6.2.1/com/atlassian/jira/issue/IssueInputParameters.html

0 votes
Radek Kantor
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.
April 3, 2014

Hi,

how you read original issue? Use getCustomFieldObject method for cases when more fields has same name and set value to MutableIssue.

Try this:

ComponentManager cm = ComponentManager.getInstance();
CustomFieldManager cfm = cm.getCustomFieldManager();
JiraAuthenticationContext authenticationContext = cm.getJiraAuthenticationContext();

MutableIssue currentIssue = (MutableIssue) issue;

// Value from CustomField
String myFieldName = "customfield_10615";
CustomField myCF = cfm.getCustomFieldObject(myFieldName);
currentIssue.setReporter(originalIssue.getCustomFieldValue(myCF));

// Value from logged in user
currentIssue.setReporter(authenticationContext.getLoggedInUser());

Greg Hoggarth April 6, 2014

That didn't work at all.

My "originalIssue" didn't actually come from anywhere, which is a large part of the problem. Jira script runner has example scripts you can start with. If I click the "set custom field" example it fills out the additional script with this:

def cf = customFieldManager.getCustomFieldObjects(issue).find {it.name == 'My Custom Field'}
issueInputParameters.addCustomFieldValue(cf.id, 'cf value')

So I don't think all that componentmanager etc stuff is required since it isn't present in the example script.

Basically I have two things to solve:

1. How do I 'get' the original / parent issue.
2. How do I set the value of the reporter field on the newly cloned issue. The example has a way to add a custom field value, or set a summary, but there's no example for how to set the reporter.

0 votes
Greg Hoggarth April 3, 2014

Any help on this one?

Suggest an answer

Log in or Sign up to answer