Forums

Articles
Create
cancel
Showing results for 
Search instead for 
Did you mean: 

Scriptrunnner Clone while replacing text in Description field?

Tim Padgett
Contributor
April 6, 2025

I have this script taken from an example, but I can't find any documentation on any of the classes and can't figure out how to adapt it so that I can clone an issue to a new project without cloning/copying the Description field? 

I see the "FIELD_SELECTED_FIELDS" input, but I can't find any examples of anyone ever using that to specify a select set of fields to clone, or to omit 1 specific field? 

I need to omit the Description because it contains sensitive data, and it is not sufficient to delete the value after the clone because that sensitive data would still be in the issue's history.  If there was some documentation on how to use the "FIELD_ADDITIONAL_SCRIPT" to redact information, then that would be an option, but again, no doco on any of this anywhere beyond a few nearly identical simple examples.

 

        // def projectManager = ComponentAccessor.projectManager
        def issueManager = ComponentAccessor.issueManager
        def projectToCopyTo = projectManager.getProjectByCurrentKey(targetProjectKey)
        def issueToCopy = issueManager.getIssueObject(originalIssue.key)

        // Block creation of intra-project links

        def blockIntraprojectLinks = '{l -> l.sourceObject.projectObject != l.destinationObject.projectObject}'
        if (!issueToCopy) {
            log.warn("Issue ${originalIssue.key} does not exist")
            return
        }

        //Set the creation parameters/inputs (use clone issue but with no link type)
        def inputs = [
            (CloneIssue.FIELD_TARGET_PROJECT)       : projectToCopyTo.key,
            (CloneIssue.FIELD_LINK_TYPE)            : null,
            (ConditionUtils.FIELD_ADDITIONAL_SCRIPT): [
                "checkLink = $blockIntraprojectLinks;",
                ""
            ],
            (CloneIssue.FIELD_SELECTED_FIELDS)      : null, // clone all the fields
            (CloneIssue.SKIP_EPIC_LINKS)            : "true",
        ] as Map<String, Object>

        def executionContext = [issue: issueToCopy] as Map<String, Object>
        def newClonedIssue = ScriptRunnerImpl.scriptRunner.createBean(CloneIssue)

       
// Execute the clone action with the specified inputs
        def updatedExecutionContext = newClonedIssue.execute(inputs, executionContext)

       
//The issue has been successfully cloned
        assert updatedExecutionContext.newIssue
        targetIssue = Issues.getByKey(updatedExecutionContext.newIssue as String)
        log.warn("targetIssue = ${targetIssue}")

 

 

 

 

 

1 answer

0 votes
Trudy Claspill
Community Champion
July 25, 2025

Hello @Tim Padgett 

If you are still looking for help on this...

Can you tell us where you got the example script? It looks similar to a script example I found here that is applicable to Jira Data Center.

I see that the tags on your post indicate you are using Jira Cloud. Is that accurate? Do you need a solution for cloning an issue in Jira Cloud?

If you are indeed looking for a solution for Cloud, take a look at this:

https://www.scriptrunnerhq.com/help/example-scripts/Clone-Issue-And-Link-cloud

 

If you figured out the solution on your own, would you consider sharing it here so the community can learn from your experiences?

Tim Padgett
Contributor
July 29, 2025

I don't remember all of the problems I encountered, but this was the resulting script that I came up with that worked for what I needed.  It should have some examples on how to deal with various data types, and for whatever reason, some fields simply could not be handled as part of the create - they had to be handled in an update.  So the resulting logic uses multiple iterations to get the copy created:





import com.atlassian.jira.component.ComponentAccessor

import com.atlassian.jira.bc.issue.search.SearchService

import com.atlassian.jira.web.bean.PagerFilter

import com.atlassian.jira.jql.parser.JqlQueryParser

import com.atlassian.jira.issue.fields.CustomField

import com.atlassian.jira.issue.customfields.option.Option

import com.atlassian.jira.user.ApplicationUser

import com.atlassian.crowd.embedded.api.Group

import com.atlassian.jira.component.ComponentAccessor

import com.onresolve.scriptrunner.canned.jira.utils.ConditionUtils

import com.onresolve.scriptrunner.canned.jira.workflow.postfunctions.CloneIssue

import com.onresolve.scriptrunner.runner.ScriptRunnerImpl

import com.atlassian.mail.queue.SingleMailQueueItem

import com.atlassian.jira.component.ComponentAccessor

import com.atlassian.jira.mail.Email

import java.util.regex.Pattern

def jobName = 'MYPROJECTCOPY - Copy and Redact MYPROJECT -> MYPROJECTCOPY'





// ///  First, Get all unique MYPROJECT issue keys from existing MYPROJECTCOPY "MYPROJECT Original URL" fields

def mtprojectIssueKeysCsv = ""

/////  AND status not in (Resolved, 'Invalid Issue')

Issues.search("project = 'MYPROJECT' ").each { issue ->

                // log.warn("issue.getCustomFieldValue('MYPROJECT Original URL') = ${issue.getCustomFieldValue("MYPROJECT Original URL")}")

                mtprojectIssueKeysCsv += issue.getCustomFieldValue("MYPROJECT Original URL").split("https://jira.mycompany.com/browse/")[1] + ", "

            }

if (mtprojectIssueKeysCsv.endsWith(", ")) {

    mtprojectIssueKeysCsv = mtprojectIssueKeysCsv.substring(0, mtprojectIssueKeysCsv.lastIndexOf(","))

} else if (mtprojectIssueKeysCsv.endsWith(",")) {

    mtprojectIssueKeysCsv = mtprojectIssueKeysCsv.substring(0, mtprojectIssueKeysCsv.lastIndexOf(","))

}

log.warn("myprojectIssueKeysCsv = '${mtprojectIssueKeysCsv}'")

 

def firstAndLastStacktraceLines = 5

def targetProjectKey = "MYPROJECTCOPY"

// def queryStr = "project = MYPROJECT AND key >= MYPROJECT-209200 and key in (MYPROJECT-209234)"

def queryStr = ''' project = MYPROJECT AND level = "Secure"

                    AND (status not in (Resolved, "Invalid Issue")

                        or updated >= -3d  '''

 

if (mtprojectIssueKeysCsv) {

    queryStr += '''

        or key in (''' + mtprojectIssueKeysCsv + ''')

    '''

}

 

queryStr += '''

    )

    order by key desc

'''





//////   Redaction Function

def redactValues(data) {

    def REDACT_ITEMS = [

        'sensitive'         : 'xxxxxxx',

        'otherstuff'        : 'xxxxxxx'

    ]

   

    if (data instanceof Map) {

        data.each { key, value ->

            data[key] = redactValues(value)

        }

        return data

    } else if (data instanceof List) {

        return data.collect { item -> redactValues(item) }

    } else if (data instanceof String) {

        REDACT_ITEMS.each { redact_item, redact_value ->

            data = data.replaceAll("(?i)" + Pattern.quote(redact_item), redact_value)

        }

        return data

    }

    return data

}

 

//////   Setup Managers and Services

def loggedInUser = ComponentAccessor.jiraAuthenticationContext.loggedInUser

def issueService = ComponentAccessor.issueService

def projectManager = ComponentAccessor.projectManager

def customFieldManager = ComponentAccessor.customFieldManager

 

// Build JQL query for the source issues.

def jqlQueryParser = ComponentAccessor.getComponent(JqlQueryParser)

def sourceJqlQuery = jqlQueryParser.parseQuery(queryStr)

 

// Execute the source query.

def searchService = ComponentAccessor.getComponent(SearchService)

def searchResult = searchService.search(loggedInUser, sourceJqlQuery, PagerFilter.getUnlimitedFilter())

def sourceIssues = searchResult.results

 

log.warn("Found ${sourceIssues.size()} source issues from JQL: ${queryStr}")

 

def successfullyUpdatedTargetIssues = ""

 

sourceIssues.each { originalIssue ->

   

    // try {

 

        // Build the target issue key using the target project key.

        def originalUrl = "https://jira.mycompany.com/browse/" + originalIssue.key

        // log.warn("************ Attempting to sync or create issue =  ${originalIssue.key}")

        // --- Look for an existing target issue using the "MYPROJECT Original URL" custom field ---

        def targetJqlQuery = jqlQueryParser.parseQuery("project = ${targetProjectKey} AND \"MYPROJECT Original URL\" = \"${originalUrl}\"")

        def targetSearchResult = searchService.search(loggedInUser, targetJqlQuery, PagerFilter.getUnlimitedFilter())

        def targetIssue = targetSearchResult?.results?.find()              

 

        if (!targetIssue) {

            // --- Create New Issue in Target project --

            // log.warn("issueInputParameters dump (excluding description and customfield_13311): " + dumpStr)

            log.warn("*** CREATING NEW ISSUE FOR - ${originalUrl}")

   

            def issueTypeName = originalIssue.issueType.name

   

            def customField = customFieldManager.getCustomFieldObjectsByName("Other Custom Date")

            def sdf = new java.text.SimpleDateFormat("d/MMM/yy")

            def otherCustomDateValue = sdf.format(originalIssue.getCustomFieldValue(customField))

 

            customField = customFieldManager.getCustomFieldObjectsByName("Other Custom Text")

            def otherCustomTextValue = redactValues(originalIssue.getCustomFieldValue(customField) as String) ?: ""

            // log.warn ("otherCustomTextValue = ${otherCustomTextValue}")

 

            def customTeamField = customFieldManager.getCustomFieldObjectsByName("Custom Team")

            def customTeamValue = originalIssue.getCustomFieldValue(customTeamField).first()

            // log.warn ("customTeamValue = ${customTeamValue.dump()}")

 

            def customField20Field = customFieldManager.getCustomFieldObjectsByName("Custom Field20")

            def customField20Value = originalIssue.getCustomFieldValue(customField20Field).first() ?: ""

            // log.warn ("customField20Value = ${customField20Value}")





            targetIssue = Issues.create(targetProjectKey, issueTypeName) {

                setSummary(redactValues(originalIssue.getSummary()))

                setDescription(redactValues(originalIssue.getDescription()))

                setPriority(originalIssue.priority)

                // and custom field values

               

                setCustomFieldValue('MYPROJECT Original URL', originalUrl)

               

            }





            // def createResult = issueService.create(loggedInUser, createValidationResult)

            // log.warn("targetIssue = ${targetIssue}")

            if (!targetIssue) {

                log.error("ERROR:    Creation error for source issue ${originalIssue.key}: ${createResult.errorCollection}. All create parameters: " + issueInputParameters.getActionParameters())

            } else {

                log.warn("Successfully created target issue: ${targetIssue.key}.  Now transitioning to status '${originalIssue.getStatus().getName()}'")

                def transitionName = originalIssue.getStatus().getName()

                if(originalIssue.getStatus().getName() == "Invalid Issue"){

                    transitionName = "Invalidate Issue"

                }

                Issues.getByKey(targetIssue.key).transition(transitionName) {

                    // Optionally set additional fields here if needed.

                }

            }

        }

       

        if (targetIssue){

            // log.warn("Updating targetIssue = ${targetIssue.key}")

            // -------------------------

            // Build Issue Input Parameters for Update

            // -------------------------

            def targetProject = projectManager.getProjectByCurrentKey(targetProjectKey)

            def issueInputParameters = issueService.newIssueInputParameters()

            issueInputParameters.setProjectId(targetProject.id as Long)

            issueInputParameters.setIssueTypeId(originalIssue.getIssueTypeId())

            // Process standard fields (summary, description) with redaction.

            issueInputParameters.setSummary(redactValues(originalIssue.getSummary()) as String)

            issueInputParameters.setDescription(redactValues(originalIssue.getDescription()) as String)

            def dueDate = originalIssue.getDueDate()

            if (dueDate) {

                def sdf = new java.text.SimpleDateFormat("d/MMM/yy") // adjust the format as needed

                issueInputParameters.setDueDate(sdf.format(dueDate))

            } else {

                issueInputParameters.setDueDate(null)

            }

            // log.warn("original Due Date '${originalIssue.getDueDate()}', target Due Date '${issueInputParameters.getDueDate()}'")





            // Process custom fields (skip the "GIM Original URL" field for now).

            ///  Skip "Custom Labels", since it always oscillates back and forth if there are 2 or more values

            customFieldManager.getCustomFieldObjects(originalIssue).each { CustomField cf ->

 

                // log.warn("Trying to update customfield = '${cf.getName()}', ${cf.dump()}")

                if (cf.getName() == "MYPROJECT Original URL"

                 || cf.getName() == "Custom Labels"

                   )

                {

                    return

                }

                def value = originalIssue.getCustomFieldValue(cf)

                if (value == null || value == "" || value == " ") {

                    // log.warn("Skipping customfield = '${cf.getName()}', since value = ${value}")

                    return

                }

                try {

                    if (value instanceof String) {

                        def redactedValue = redactValues(value) as String

                        issueInputParameters.addCustomFieldValue(cf.idAsLong, redactedValue)

                    } else if (value instanceof Date) {

                        // log.warn("issueInputParameters - Date = ${value}")

                        // log.warn("Date vs Datetime = ${cf.getCustomFieldType().dump()}")

                        def isDateTime = cf.customFieldType.key == "com.atlassian.jira.plugin.system.customfieldtypes:datetime"

                        def sdf = isDateTime

                            ? new java.text.SimpleDateFormat("d/MMM/yy h:mm a").with { it.setTimeZone(TimeZone.getTimeZone("America/New_York")); it }

                            : new java.text.SimpleDateFormat("d/MMM/yy")

                        issueInputParameters.addCustomFieldValue(cf.idAsLong, sdf.format(value))

                       

                    } else if (value instanceof Option) {

                        issueInputParameters.addCustomFieldValue(cf.idAsLong, value.getOptionId().toString())

                        // log.warn("issueInputParameters - Option.getOptionId() = ${value.getOptionId().toString()}")

                    } else if (value instanceof Collection) {

                        value.each { item ->

                            if (item instanceof Option) {

                                issueInputParameters.addCustomFieldValue(cf.idAsLong, item.getOptionId().toString())

                                // log.warn("issueInputParameters - Collection.Option.getOptionId() = ${item.getOptionId().toString()}")

                            } else if (item instanceof String) {

                                def redactedValue = redactValues(item) as String

                                issueInputParameters.addCustomFieldValue(cf.idAsLong, redactedValue)

                            } else if (item instanceof Group) {

                                def groupName = item.metaClass.respondsTo(item, 'getName') ? item.getName() : item.toString()

                                issueInputParameters.addCustomFieldValue(cf.idAsLong, groupName)

                                // log.warn("issueInputParameters - Collection.Group.getName() = ${groupName}")

                            } else {

                                issueInputParameters.addCustomFieldValue(cf.idAsLong, item.toString())

                            }

                        }

                    } else if (value instanceof Group) {

                        def groupName = value.metaClass.respondsTo(value, 'getName') ? value.getName() : value.toString()

                        issueInputParameters.addCustomFieldValue(cf.idAsLong, groupName)

                        // log.warn("issueInputParameters - Group.getName() = ${groupName}")

                    } else if (value instanceof ApplicationUser) {

                        issueInputParameters.addCustomFieldValue(cf.idAsLong, value.getName())

                        // log.warn("issueInputParameters - ApplicationUser.getName() = ${value.getName()}")

                    } else {

                        issueInputParameters.addCustomFieldValue(cf.idAsLong, value.toString())

                    }

                } catch(Exception e) {

                    log.error("Error processing custom field '${cf.name}' for source issue ${originalIssue.key}: " + e.getMessage())

                }

            }

 

            // --- Update Existing Target Issue ---

            // log.warn("UPDATING  targetIssue = ${(targetIssue)} from originalIssue = ${originalIssue}")

            def changeHolder = new com.atlassian.jira.issue.util.DefaultIssueChangeHolder()

   

            def updateValidationResult = issueService.validateUpdate(loggedInUser, targetIssue.id, issueInputParameters)

            if (!updateValidationResult.valid) {

                log.error("Validation errors for updating target issue ${targetIssue.key}: " + updateValidationResult.errorCollection)

                return // Skip update for this source issue if validation fails.

            }

            def updateResult = issueService.update(loggedInUser, updateValidationResult)

            if (!updateResult.valid) {

                log.error("Update error for target issue ${targetIssue.key}: " + updateResult.errorCollection)

            } else {

                // log.warn("Successfully updated target issue: " + targetIssue.key)

                        // Now the changeHolder should be populated (if the update actually changed values)

                if (changeHolder.getChangeItems()) {

                    successfullyUpdatedTargetIssues += targetIssue.key + ", "

                    changeHolder.getChangeItems().each { changeItem ->

                        log.warn("Updated fields on ${targetIssue.key}:  Field: ${changeItem.getField()} - From: '${changeItem.getFromString()}' to: '${changeItem.getToString()}'")

                    }

                } else {

                    // log.warn("No fields were actually updated on ${targetIssue.key} during this operation.")

                }

               

                if (targetIssue.getStatus().getName() != originalIssue.getStatus().getName()) {

                    log.warn("Transitioning target issue ${targetIssue.key} from status '${targetIssue.getStatus().getName()}' to '${originalIssue.getStatus().getName()}'")

                    def transitionName = originalIssue.getStatus().getName()

                    if(originalIssue.getStatus().getName() == "Invalid Issue"){

                        transitionName = "Invalidate Issue"

                    }

                    Issues.getByKey(targetIssue.key).transition(transitionName) {

                        // Optionally set additional fields here if needed.

                    }

                } else {

                    // log.warn("No transition required for ${targetIssue.key} as the status is already '${targetIssue.getStatus().getName()}'")

                }

            }

           

 

        }

 

        /////////////////////////////////////////

        //////   Special field handling   ///////

        //////   This should already be handled by the update logic above, but some fields just don't get covered in the above.  

        //////    e.g. "Other Custom Date"

        /////////////////////////////////////////

 

        ////   com.adaptavist.hapi.jira.issues.exceptions.IssueUpdateValidationException: The following errors occurred: (reporter=You do not have permission to modify the issue reporter.)

        // Issues.getByKey(targetIssue.key).update {

        //     setReporter(originalIssue.reporter)

        // }





        ////////// Due Date

        def originalDueDate = originalIssue.getDueDate()

        def targetDueDate = targetIssue.getDueDate()

        // log.warn("original 'Due Date' = '${originalDueDate}', target 'Due Date' = '${targetDueDate}'")

        if (originalDueDate != targetDueDate) {

            log.warn("Due Date mismatch for ${targetIssue.key}. Updating due date to ${originalDueDate}")

            def sdf = new java.text.SimpleDateFormat("d/MMM/yy")

            Issues.getByKey(targetIssue.key).update {

                setDueDate(sdf.format(originalDueDate))

            }

        } else {

            // log.warn("Due Date for ${targetIssue.key} matches original.")

        }

 

        ////////// Priority if Needed using HAPI DSL ---

        def originalPriority = originalIssue.getPriority()

        def targetPriority = targetIssue.getPriority()

        if (originalPriority) {

            if (!targetPriority || targetPriority.getName() != originalPriority.getName()) {

                log.warn("Updating ${targetIssue.key} 'Priority':   original = '${originalPriority.getName()}', target = '${targetPriority ? targetPriority.getName() : 'none'}'")

                // log.warn("'Priority' mismatch for ${targetIssue.key}. Updating 'Priority' to ${originalPriority.getName()}")

                Issues.getByKey(targetIssue.key).update {

                    setPriority(originalPriority.getName())

                }

            } else {

                // log.warn("'Priority' for ${targetIssue.key} matches original: ${originalPriority.getName()}")

            }

        } else {

            // log.warn("Source issue ${originalIssue.key} has no 'Priority' set.")

        }





        //////////  Various custom fields that are Strings, skipping "Region"

        def fieldsToSync = ["Custom Priority", "Custom ID"]

        fieldsToSync.each { fieldName ->

            def customField = customFieldManager.getCustomFieldObjectsByName(fieldName)?.find { it.name == fieldName }

 

            if (customField) {

                def originalValue = redactValues(originalIssue.getCustomFieldValue(customField)?.toString())

                def targetValue = targetIssue.getCustomFieldValue(customField)?.toString()

 

                // log.warn("Original '${fieldName}': '${originalValue}', target '${fieldName}': '${targetValue}'")

                if (!(targetValue == null && originalValue == null) &&  (!targetValue || targetValue != originalValue)) {

                    // log.warn("Updating ${targetIssue.key} '${fieldName}':  orginal = '${originalValue}', target ${targetValue} ")

                    log.warn("Updating ${targetIssue.key} '${fieldName}': original = '${originalValue?.take(50)}', target = '${targetValue?.take(50)}'")

 

                    Issues.getByKey(targetIssue.key).update {

                        if (originalValue != null) {

                            setCustomFieldValue(fieldName, originalValue)

                        } else {

                            setCustomFieldValue(fieldName, "")

                        }

                    }

                } else {

                    // log.warn("'${fieldName}' for ${targetIssue.key} already matches source.")

                }

            } else {

                log.error("ERROR:   Custom field '${fieldName}' not found.")

            }

        }





        ////////// --- Handle custom date and datetime fields dynamically ---

        def dateFieldsToSync = ["Custom Due Date", "Custom Due Datetime"]

        dateFieldsToSync.each { fieldName ->

            def customField = customFieldManager.getCustomFieldObjectsByName(fieldName)?.find { it.name == fieldName }

 

            if (customField) {

                def originalDate = originalIssue.getCustomFieldValue(customField) as Date

                def targetDate = targetIssue.getCustomFieldValue(customField) as Date

 

                // Determine if it's a DateTime field

                def isDateTime = customField.customFieldType.key == "com.atlassian.jira.plugin.system.customfieldtypes:datetime"

                def sdf = isDateTime

                    ? new java.text.SimpleDateFormat("d/MMM/yy h:mm a").with { it.setTimeZone(TimeZone.getTimeZone("America/New_York")); it }

                    : new java.text.SimpleDateFormat("d/MMM/yy")

 

                def formattedOriginal = originalDate ? sdf.format(originalDate) : ""

                def formattedTarget = targetDate ? sdf.format(targetDate) : ""

 

                // log.warn("Original '${fieldName}': ${formattedOriginal}, target '${fieldName}': ${formattedTarget}")

 

                if (formattedOriginal != formattedTarget) {

                    log.warn("Updating ${targetIssue.key} '${fieldName}':  orginal = '${formattedOriginal}', target ${formattedTarget} ")

 

                    Issues.getByKey(targetIssue.key).update {

                        if (originalDate) {

                            setCustomFieldValue(fieldName, originalDate)

                        } else {

                            setCustomFieldValue(fieldName, "")

                        }

                    }

                } else {

                    // log.warn("'${fieldName}' for ${targetIssue.key} already matches source.")

                }

            } else {

                log.error("ERROR:   Custom field '${fieldName}' not found.")

            }

        }





        ////////// Labels

        def originalLabels = originalIssue.getLabels() ?: []

        def targetLabels = targetIssue.getLabels() ?: []

        if (originalLabels.sort().join(',') != targetLabels.sort().join(',')) {

            log.warn("Updating ${targetIssue.key} 'Labels': original = '${originalLabels.sort().join(',')}',  target = '${targetLabels.sort().join(',')}'")

       

            if(originalLabels.sort().join(',') == ""){

                // log.warn("Clearing 'Labels'")

                Issues.getByKey(targetIssue.key).update {

                    setLabels {

                        targetLabels.each { label ->

                            remove(label as String)

                        }

                    }

                }

            }

            else{

                // log.warn("Updating 'Labels'")

                Issues.getByKey(targetIssue.key).update {

                    setLabels {

                        originalLabels.each { label ->

                            add(label as String)

                        }

                    }

                }

            }

        } else {

            // log.warn("'Labels' already match for ${targetIssue.key}; no update required.")

        }

 

        //////////   "Custom2 Labels", and "Custom Labels"

        def labelFieldsToSync = ["Custom2 Labels", "Custom Labels"]

        labelFieldsToSync.each { fieldName ->

            def customField = customFieldManager.getCustomFieldObjectsByName(fieldName)?.find { it.name == fieldName }

            if (customField) {

                // log.warn("fieldName: ${fieldName}")

                targetIssue = Issues.getByKey(targetIssue.key)

                originalLabels = originalIssue.getCustomFieldValue(fieldName) as List ?: []

                targetLabels = targetIssue.getCustomFieldValue(fieldName) as List ?: []

                // log.warn("targetLabels: ${targetLabels}")

                def originalLabelsSortedSet = originalLabels.toSet().sort()

                def targetLabelsSortedSet = targetLabels.toSet().sort()

                // log.warn("original = '${originalLabelsSortedSet.join(',')}'")

                // log.warn("target = '${targetLabelsSortedSet.join(',')}'")

 

                if (originalLabelsSortedSet.join(',') != targetLabelsSortedSet.join(',')) {

                    log.warn("Updating ${targetIssue.key} '${fieldName}':  original = '${originalLabelsSortedSet}',  target = '${originalLabelsSortedSet}'")

                    // log.warn("Updating ${targetIssue.key} '${fieldName}':  original = '${originalLabelsSortedSet.join(',')}',  target = '${targetLabelsSortedSet.join(',')}'")

 

                    Issues.getByKey(targetIssue.key).update {

                        if (originalLabelsSortedSet.isEmpty()) {

                            setCustomFieldValue(fieldName, "")

                        } else {

                            setCustomFieldValue(fieldName, *(originalLabelsSortedSet as String[]))

                        }

                    }

                } else {

                    // log.warn("'${fieldName}' already match for ${targetIssue.key}; no update required.")

                }

 

            } else {

                log.error("ERROR:   Could not find custom field '${fieldName}'")

            }

        }

 

        //////// Assignee

        def originalAssignee = originalIssue.getAssignee()

        def targetAssignee = targetIssue?.getAssignee()

        // log.warn("originalAssignee  '${originalAssignee}', targetAssignee = '${targetAssignee}' ")

        def originalAssigneeString = originalAssignee?.toString()

        def targetAssigneeString = targetAssignee?.toString()

        def originalUsername = originalAssigneeString?.indexOf("(") > 0 ? originalAssigneeString.substring(0, originalAssigneeString.indexOf("(")) : originalAssigneeString

        def targetUsername = targetAssigneeString?.indexOf("(") > 0 ? targetAssigneeString.substring(0, targetAssigneeString.indexOf("(")) : targetAssigneeString

 

        if (originalUsername != targetUsername) {

            if (originalUsername && originalUsername != "aappel") {

                Issues.getByKey(targetIssue.key).update {

                    setAssignee(originalUsername)

                }

                log.warn("Updating ${targetIssue.key} 'Assignee' to username: '${originalUsername}'")

            } else {

                Issues.getByKey(targetIssue.key).update {

                    setAssignee("")

                }

                log.warn("Cleared 'Assignee' for ${targetIssue.key} (original had no assignee)")

            }

        } else {

            // log.warn("'Assignee' for ${targetIssue.key} is already the same as the original.")

        }

 

    // //// end of try block    

    // }

    // catch (Exception e) {

    //     log.error("An error occurred while processing issue ${originalIssue.key}: " + e.getMessage())

    //     def stackTraceLines = e.getStackTrace().collect { it.toString() }

    //     def firstTen = stackTraceLines.take(firstAndLastStacktraceLines).join('\n')

 

    //     def lastTen = []

    //     if (stackTraceLines.size() > firstAndLastStacktraceLines) {

    //         lastTen = stackTraceLines.drop(stackTraceLines.size() - firstAndLastStacktraceLines).join('\n')

    //     } else {

    //         lastTen = stackTraceLines.join('\n')

    //     }

    //     log.error("Stack Trace: ${firstTen}\n...\n${lastTen}")

 

    //     // def targetIssueKey = targetIssue?.key ?: "null"

    //     def targetIssue = binding.hasVariable("targetIssue") ? binding.getVariable("targetIssue") : null

    //     def targetIssueKey = (targetIssue != null && targetIssue.key) ? targetIssue.key : "null"

 

       

    //     def email = new Email("tpadgett@axon.com")

    //     def emailSubject = "ERROR in job - ${jobName}"

    //     def emailBody = """

    //         An error occurred in the ScriptRunner job '${jobName}' while syncing issue: ${originalIssue.key} to ${targetIssue?.key ?: 'null'}).

 

    //         Error Message:

    //         ${e.getMessage()}

 

    //         Stack Trace:

    //         ${e.getStackTrace().take(firstAndLastStacktraceLines).join('\n')}

    //         (Full stack trace can be found in the ScriptRunner logs.)

 

    //         Please investigate this issue.

    //         """

    //     email.setSubject(emailSubject)

    //     email.setBody(emailBody)

 

    //     try {

    //         def mailQueue = ComponentAccessor.getMailQueue()

    //         mailQueue.addItem(new SingleMailQueueItem(email))

    //         log.warn("Error notification email sent to ${email.getTo()}") // Use email.getTo() to log recipient

    //     } catch (Exception mailException) {

 

    //         log.error("Error sending notification email: " + mailException.getMessage())

    //         def mailStackTraceLines = mailException.getStackTrace().collect { it.toString() }

    //         def mailFirstTen = mailStackTraceLines.take(firstAndLastStacktraceLines).join('\n')

    //         def mailLastTen = []

    //         if (mailStackTraceLines.size() > firstAndLastStacktraceLines) {

    //             mailLastTen = mailStackTraceLines.drop(mailStackTraceLines.size() - firstAndLastStacktraceLines).join('\n')

    //         } else {

    //             mailLastTen = mailStackTraceLines.join('\n')

    //         }

    //         log.error("Mail Stack Trace: ${mailFirstTen}\n...\n${mailLastTen}")

 

    //     }

    // }   /// end catch block





}

 

if(successfullyUpdatedTargetIssues != ""){

    log.warn("Successfully updated target issues: " + successfullyUpdatedTargetIssues)

}

else{

    log.warn("No updates to ${targetProjectKey}")

}



 

Like Trudy Claspill likes this

Suggest an answer

Log in or Sign up to answer
DEPLOYMENT TYPE
CLOUD
PRODUCT PLAN
STANDARD
TAGS
AUG Leaders

Atlassian Community Events