Community 42836640

002_Destination_Jira_onprem_incoming.groovy
if(firstSync){
    //project mapping
    def projectMapping = [
        "IZO":"AEM",
        "IZOINT":"ACS"
        ] 

    /*
    Issue Type Mapping
    */
    
    //map issue types between source and destination instances.
    def issueTypeMapping = [
    // "remote issue type" : "local issue type"
            "Research": "Task",
            "Requirements": "Task",
            "Documentation": "Task",
            "Designs": "Task",
            "Wireframes": "Task",
            "Bug": "Bug",
            "Development": "Task",
            "Feature Request": "Improvement",
            "Story": "Story",
            "Task": "Task",
            "Subtask": "Sub-task",
            "Sub-task": "Sub-task",
            "Subtask Design": "Sub-task",
            "Epic" : "Epic"
    ]
 
    issue.typeName = issueTypeMapping[replica.type?.name] ?: "Task"

    // Set type name from source issue, if not found set a default
    // issue.typeName     = nodeHelper.getIssueType(replica.typeName)?.name ?: "Task"
    // ["REMOTE PROJECT KEY": "LOCAL PROJECT KEY"]
    issue.projectKey = projectMapping[replica.project.key]
    //debug.error("remote project key = ${replica.project.key}, mspped to ${projectMapping[replica.project.key]}")
    if (replica.parentId) { 
        def localParent = nodeHelper.getLocalIssueFromRemoteId(replica.parentId.toLong())
        if(localParent){
            issue.parentId = localParent.id
        } else {
            throw new com.exalate.api.exception.IssueTrackerException("Subtask cannot be created: parent issue with remote id " + replica.parentId + " was not found. Please make sure the parent issue is synchronized before resolving this error" )
        }
    }    
    //debug.error("issue.parentid = ${issue.parentId} issue.typename = ${issue.typeName} remote project key = ${replica.project.key}, mspped to ${projectMapping[replica.project.key]}")
}

issue.summary      = replica.summary
issue.description  = replica.description
issue.labels       = replica.labels
//issue.comments     = commentHelper.mergeComments(issue, replica)
issue.attachments  = attachmentHelper.mergeAttachments(issue, replica)

/*
User Synchronization (Assignee/Reporter)

Set a Reporter/Assignee from the source side, if the user can't be found set a default user
You can use this approach for custom fields of type User
*/
def defaultUser = nodeHelper.getUserByEmail("akruck@maark.com")
issue.reporter = nodeHelper.getUserByEmail(replica.reporter?.email) ?: defaultUser
issue.assignee = nodeHelper.getUserByEmail(replica.assignee?.email) ?: defaultUser

 
/*
Comment Synchronization

Sync comments with the original author if the user exists in the local instance
Remove original Comments sync line if you are using this approach
*/
issue.comments = commentHelper.mergeComments(issue, replica)

{ it.executor = nodeHelper.getUserByEmail(it.author?.email) }
 
/*
Status Synchronization

Sync status according to the mapping [remote issue status: local issue status]
If statuses are the same on both sides don't include them in the mapping
*/

/*
Status Mapping
*/

def statusMappingAEM = [
    "Open" : "Backlog",
    "Created" : "Backlog",
    "Blocked" : "Blocked",
    "In Progress" : "In Progress",
    "In Code Review" : "In Progress",
    "Ready to Deploy" : "In Progress",
    "On Dev" : "In Progress",
    "Selected for Release" : "Ready for Staging",
    "Ready for Deploy" : "Ready for Staging",
    "Staging Review" : "UAT",
    "Done" : "Production Check",
    "DONE" : "Production Check",
    "Code Review" : "In Progress",
    "Stage Review" : "UAT",
    "Client Review" : "UAT",
    "Under Review" : "UAT",
    "Internal Review" : "In Progress",
    "Requirements Check" : "In Progress",
    "Reopened" : "In Progress"
    ]

def statusMappingACS = [
    "Open" : "Backlog",
    "Reopened" : "Backlog",
    "Blocked" : "Blocked",
    "In Progress" : "In Progress",
    "Code Review" : "In Progress",
    "Ready For Deploy" : "In Progress",
    "Ready for Deploy" : "In Progress",
    "Internal Review" : "In Progress",
    "Under Review" : "UAT",
    "Done" : "Production Check",
    "DONE" : "Production Check"
    ]

def statusMapping = issue.projectKey == "AEM" ? statusMappingAEM : statusMappingACS

def targetStatus = statusMapping[replica.status?.name]

if (!targetStatus) {
    debug.error("The remote status '${replica.status?.name}' is not found in the status mapping ")
    
} 


issue.setStatus(targetStatus)


/* OLD STATUS MAPPING CODE
def statusMapping = [
        "Open" : "Backlog",
         "Blocked" : "Blocked",
         "In Progress" : "In Progress",
         "In Code Review" : "In Progress",
         "Ready to Deploy" : "In Progress",
         "On Dev" : "In Progress",
         "Selected for Release" : "Ready for Staging",
         "Ready for Deploy" : "Ready for Staging",
         "Staging Review" : "UAT",
         "Done" : "Closed",
         "DONE" : "Closed",
         "Code Review" : "In Progress",
         "Stage Review" : "UAT",
         "Client Review" : "UAT",
         "Under Review" : "UAT",
         "Internal Review" : "In Progress",
        "Requirements Check" : "In Progress"
    ]
def remoteStatusName = replica.status.name
issue.setStatus(statusMapping[remoteStatusName] ?: remoteStatusName)
*/

/*
Priority Mapping


def priorityMapping = [
        // remote side priority <-> local side priority            
        "Highest": "Highest",
        "High": "High",
        "Low": "Low",
        "Lowest": "Lowest",
    ]
def priorityName = priorityMapping[replica.priority?.name] ?: "Low" 
// set default priority in case the proper urgency could not be found
issue.priority = nodeHelper.getPriority(priorityName)
*/
 

 
// this will overwrite the current time tracking information
  
issue.timeSpent   = replica.timeSpent
issue.originalEstimate   = replica.originalEstimate
issue.remainingEstimate  = replica.remainingEstimate
 
 
//any issue that is synced via Exalate will get an "exalate" label for easy identification
if (replica.issueType.name != "fakeissuetype") {
   issue.labels += nodeHelper.getLabel("exalate")
}

/*
VERSION SYNC
*/

// for the create processor, be sure that the project is set to the issue variable before running the following code
//issue.projectKey = "AEM" //Included only on create processor
issue.fixVersions = replica.fixVersions.collect {
    v -> nodeHelper.createVersion(issue, v.name, v.description)
}
 
// assign fix versions from JIRA A to JIRA B
issue.fixVersions = replica
  .fixVersions
  // ensure that all the fixVersions are available on B
  .collect 

{ v -> nodeHelper.createVersion(issue, v.name, v.description) }
// assign affected versions from JIRA A to JIRA B
issue.affectedVersions = replica
  .affectedVersions
  .collect { v -> nodeHelper.createVersion(issue, v.name, v.description) }


/* VERSION SYNC update - Exalate support September 2, 2021
issue.projectKey = "AEM"

if(replica.fixVersions)

{ issue.fixVersions = replica
.fixVersions
.collect { v -> nodeHelper.getVersion(v.name, project) }
    .findAll{it !=null}

} else {issue.fixVersions = replica     
.fixVersions
.collect { v -> nodeHelper.createVersion(issue, v.name, v.description) }

}

issue.affectedVersions = replica
    .affectedVersions
    .collect { v -> nodeHelper.getVersion(v.name, project) }
    .findAll

{it !=null}
*/

  
//Epic sync works using an external scrip on Jira On-prem, may require update if fails 
try {
Epic.receive()
}
catch(e){
    com.atlassian.jira.component.ComponentAccessor
        .getOSGiComponentInstanceOfType(com.exalate.api.error.IErrorService.class)
        .addError(syncRequest, e, com.exalate.api.domain.ErrorEntityType.ISSUE, null, false)
throw e        
}


/*
Custom Fields

This line will sync Text, Option(s), Number, Date, Organization, and Labels CFs
For other types of CF check documentation
issue.customFields."CF Name".value = replica.customFields."CF Name".value
*/

//debug.error("Rankvalue is ${replica.customKeys."RankValue"?.asString()}")

// Copy the customKeys field 'RankValue' to the text field 'Remote Master Rank'
issue.customFields."Remote Master Rank".value = replica.customKeys."RankValue"
issue.customFields."Remote Issue Key".value = replica.key

001_Source_Jira_cloud_outgoing.groovy
replica.key = issue.key
replica.type = issue.type 
replica.assignee = issue.assignee 
replica.reporter = issue.reporter
replica.summary = issue.summary
replica.description = issue.description
replica.labels = issue.labels
replica.comments = issue.comments
replica.resolution = issue.resolution
replica.status = issue.status
replica.parentId = issue.parentId
replica.priority = issue.priority
replica.attachments = issue.attachments
replica.project = issue.project
//Comment these lines out if you are interested in sending the full list of versions and components of the source project.
//replica.project.versions = []
replica.project.components = []
/*
Custom Fields
replica.customFields."CF Name" = issue.customFields."CF Name"
*/
//send the fix versions set on a synced issue
replica.fixVersions = issue.fixVersions
replica.affectedVersions = issue.affectedVersions
Epic.send()

/*
** Copy the ranking value from the issue to a custom key
** Rank is the standard ranking custom field.
*/
 
replica.customKeys."RankValue" = issue.customFields."Rank"?.value?.value
002_Destination_Jira_onprem_incoming.groovy
if(firstSync){
    //project mapping
    def projectMapping = [
        "IZO":"AEM",
        "IZOINT":"ACS"
        ] 

    /*
    Issue Type Mapping
    */
    
    //map issue types between source and destination instances.
    def issueTypeMapping = [
    // "remote issue type" : "local issue type"
            "Research": "Task",
            "Requirements": "Task",
            "Documentation": "Task",
            "Designs": "Task",
            "Wireframes": "Task",
            "Bug": "Bug",
            "Development": "Task",
            "Feature Request": "Improvement",
            "Story": "Story",
            "Task": "Task",
            "Subtask": "Sub-task",
            "Sub-task": "Sub-task",
            "Subtask Design": "Sub-task",
            "Epic" : "Epic"
    ]
 
    issue.typeName = issueTypeMapping[replica.type?.name] ?: "Task"

    // Set type name from source issue, if not found set a default
    // issue.typeName     = nodeHelper.getIssueType(replica.typeName)?.name ?: "Task"
    // ["REMOTE PROJECT KEY": "LOCAL PROJECT KEY"]
    issue.projectKey = projectMapping[replica.project.key]
    //debug.error("remote project key = ${replica.project.key}, mspped to ${projectMapping[replica.project.key]}")
    if (replica.parentId) { 
        def localParent = nodeHelper.getLocalIssueFromRemoteId(replica.parentId.toLong())
        if(localParent){
            issue.parentId = localParent.id
        } else {
            throw new com.exalate.api.exception.IssueTrackerException("Subtask cannot be created: parent issue with remote id " + replica.parentId + " was not found. Please make sure the parent issue is synchronized before resolving this error" )
        }
    }    
    //debug.error("issue.parentid = ${issue.parentId} issue.typename = ${issue.typeName} remote project key = ${replica.project.key}, mspped to ${projectMapping[replica.project.key]}")
}

issue.summary      = replica.summary
issue.description  = replica.description
issue.labels       = replica.labels
//issue.comments     = commentHelper.mergeComments(issue, replica)
issue.attachments  = attachmentHelper.mergeAttachments(issue, replica)

/*
User Synchronization (Assignee/Reporter)

Set a Reporter/Assignee from the source side, if the user can't be found set a default user
You can use this approach for custom fields of type User
*/
def defaultUser = nodeHelper.getUserByEmail("akruck@maark.com")
issue.reporter = nodeHelper.getUserByEmail(replica.reporter?.email) ?: defaultUser
issue.assignee = nodeHelper.getUserByEmail(replica.assignee?.email) ?: defaultUser

 
/*
Comment Synchronization

Sync comments with the original author if the user exists in the local instance
Remove original Comments sync line if you are using this approach
*/
issue.comments = commentHelper.mergeComments(issue, replica)

{ it.executor = nodeHelper.getUserByEmail(it.author?.email) }
 
/*
Status Synchronization

Sync status according to the mapping [remote issue status: local issue status]
If statuses are the same on both sides don't include them in the mapping
*/

/*
Status Mapping
*/

def statusMappingAEM = [
    "Open" : "Backlog",
    "Created" : "Backlog",
    "Blocked" : "Blocked",
    "In Progress" : "In Progress",
    "In Code Review" : "In Progress",
    "Ready to Deploy" : "In Progress",
    "On Dev" : "In Progress",
    "Selected for Release" : "Ready for Staging",
    "Ready for Deploy" : "Ready for Staging",
    "Staging Review" : "UAT",
    "Done" : "Production Check",
    "DONE" : "Production Check",
    "Code Review" : "In Progress",
    "Stage Review" : "UAT",
    "Client Review" : "UAT",
    "Under Review" : "UAT",
    "Internal Review" : "In Progress",
    "Requirements Check" : "In Progress",
    "Reopened" : "In Progress"
    ]

def statusMappingACS = [
    "Open" : "Backlog",
    "Reopened" : "Backlog",
    "Blocked" : "Blocked",
    "In Progress" : "In Progress",
    "Code Review" : "In Progress",
    "Ready For Deploy" : "In Progress",
    "Ready for Deploy" : "In Progress",
    "Internal Review" : "In Progress",
    "Under Review" : "UAT",
    "Done" : "Production Check",
    "DONE" : "Production Check"
    ]

def statusMapping = issue.projectKey == "AEM" ? statusMappingAEM : statusMappingACS

def targetStatus = statusMapping[replica.status?.name]

if (!targetStatus) {
    debug.error("The remote status '${replica.status?.name}' is not found in the status mapping ")
    
} 


issue.setStatus(targetStatus)


/* OLD STATUS MAPPING CODE
def statusMapping = [
        "Open" : "Backlog",
         "Blocked" : "Blocked",
         "In Progress" : "In Progress",
         "In Code Review" : "In Progress",
         "Ready to Deploy" : "In Progress",
         "On Dev" : "In Progress",
         "Selected for Release" : "Ready for Staging",
         "Ready for Deploy" : "Ready for Staging",
         "Staging Review" : "UAT",
         "Done" : "Closed",
         "DONE" : "Closed",
         "Code Review" : "In Progress",
         "Stage Review" : "UAT",
         "Client Review" : "UAT",
         "Under Review" : "UAT",
         "Internal Review" : "In Progress",
        "Requirements Check" : "In Progress"
    ]
def remoteStatusName = replica.status.name
issue.setStatus(statusMapping[remoteStatusName] ?: remoteStatusName)
*/

/*
Priority Mapping


def priorityMapping = [
        // remote side priority <-> local side priority            
        "Highest": "Highest",
        "High": "High",
        "Low": "Low",
        "Lowest": "Lowest",
    ]
def priorityName = priorityMapping[replica.priority?.name] ?: "Low" 
// set default priority in case the proper urgency could not be found
issue.priority = nodeHelper.getPriority(priorityName)
*/
 

 
// this will overwrite the current time tracking information
  
issue.timeSpent   = replica.timeSpent
issue.originalEstimate   = replica.originalEstimate
issue.remainingEstimate  = replica.remainingEstimate
 
 
//any issue that is synced via Exalate will get an "exalate" label for easy identification
if (replica.issueType.name != "fakeissuetype") {
   issue.labels += nodeHelper.getLabel("exalate")
}

/*
VERSION SYNC
*/

// for the create processor, be sure that the project is set to the issue variable before running the following code
//issue.projectKey = "AEM" //Included only on create processor
issue.fixVersions = replica.fixVersions.collect {
    v -> nodeHelper.createVersion(issue, v.name, v.description)
}
 
// assign fix versions from JIRA A to JIRA B
issue.fixVersions = replica
  .fixVersions
  // ensure that all the fixVersions are available on B
  .collect 

{ v -> nodeHelper.createVersion(issue, v.name, v.description) }
// assign affected versions from JIRA A to JIRA B
issue.affectedVersions = replica
  .affectedVersions
  .collect { v -> nodeHelper.createVersion(issue, v.name, v.description) }


/* VERSION SYNC update - Exalate support September 2, 2021
issue.projectKey = "AEM"

if(replica.fixVersions)

{ issue.fixVersions = replica
.fixVersions
.collect { v -> nodeHelper.getVersion(v.name, project) }
    .findAll{it !=null}

} else {issue.fixVersions = replica     
.fixVersions
.collect { v -> nodeHelper.createVersion(issue, v.name, v.description) }

}

issue.affectedVersions = replica
    .affectedVersions
    .collect { v -> nodeHelper.getVersion(v.name, project) }
    .findAll

{it !=null}
*/

  
//Epic sync works using an external scrip on Jira On-prem, may require update if fails 
try {
Epic.receive()
}
catch(e){
    com.atlassian.jira.component.ComponentAccessor
        .getOSGiComponentInstanceOfType(com.exalate.api.error.IErrorService.class)
        .addError(syncRequest, e, com.exalate.api.domain.ErrorEntityType.ISSUE, null, false)
throw e        
}


/*
Custom Fields

This line will sync Text, Option(s), Number, Date, Organization, and Labels CFs
For other types of CF check documentation
issue.customFields."CF Name".value = replica.customFields."CF Name".value
*/

//debug.error("Rankvalue is ${replica.customKeys."RankValue"?.asString()}")

// Copy the customKeys field 'RankValue' to the text field 'Remote Master Rank'
issue.customFields."Remote Master Rank".value = replica.customKeys."RankValue"
issue.customFields."Remote Issue Key".value = replica.key

001_Source_Jira_cloud_outgoing.groovy
replica.key = issue.key
replica.type = issue.type 
replica.assignee = issue.assignee 
replica.reporter = issue.reporter
replica.summary = issue.summary
replica.description = issue.description
replica.labels = issue.labels
replica.comments = issue.comments
replica.resolution = issue.resolution
replica.status = issue.status
replica.parentId = issue.parentId
replica.priority = issue.priority
replica.attachments = issue.attachments
replica.project = issue.project
//Comment these lines out if you are interested in sending the full list of versions and components of the source project.
//replica.project.versions = []
replica.project.components = []
/*
Custom Fields
replica.customFields."CF Name" = issue.customFields."CF Name"
*/
//send the fix versions set on a synced issue
replica.fixVersions = issue.fixVersions
replica.affectedVersions = issue.affectedVersions
Epic.send()

/*
** Copy the ranking value from the issue to a custom key
** Rank is the standard ranking custom field.
*/
 
replica.customKeys."RankValue" = issue.customFields."Rank"?.value?.value
002_Destination_Jira_onprem_incoming.groovy
if(firstSync){
    //project mapping
    def projectMapping = [
        "IZO":"AEM",
        "IZOINT":"ACS"
        ] 

    /*
    Issue Type Mapping
    */
    
    //map issue types between source and destination instances.
    def issueTypeMapping = [
    // "remote issue type" : "local issue type"
            "Research": "Task",
            "Requirements": "Task",
            "Documentation": "Task",
            "Designs": "Task",
            "Wireframes": "Task",
            "Bug": "Bug",
            "Development": "Task",
            "Feature Request": "Improvement",
            "Story": "Story",
            "Task": "Task",
            "Subtask": "Sub-task",
            "Sub-task": "Sub-task",
            "Subtask Design": "Sub-task",
            "Epic" : "Epic"
    ]
 
    issue.typeName = issueTypeMapping[replica.type?.name] ?: "Task"

    // Set type name from source issue, if not found set a default
    // issue.typeName     = nodeHelper.getIssueType(replica.typeName)?.name ?: "Task"
    // ["REMOTE PROJECT KEY": "LOCAL PROJECT KEY"]
    issue.projectKey = projectMapping[replica.project.key]
    //debug.error("remote project key = ${replica.project.key}, mspped to ${projectMapping[replica.project.key]}")
    if (replica.parentId) { 
        def localParent = nodeHelper.getLocalIssueFromRemoteId(replica.parentId.toLong())
        if(localParent){
            issue.parentId = localParent.id
        } else {
            throw new com.exalate.api.exception.IssueTrackerException("Subtask cannot be created: parent issue with remote id " + replica.parentId + " was not found. Please make sure the parent issue is synchronized before resolving this error" )
        }
    }    
    //debug.error("issue.parentid = ${issue.parentId} issue.typename = ${issue.typeName} remote project key = ${replica.project.key}, mspped to ${projectMapping[replica.project.key]}")
}

issue.summary      = replica.summary
issue.description  = replica.description
issue.labels       = replica.labels
//issue.comments     = commentHelper.mergeComments(issue, replica)
issue.attachments  = attachmentHelper.mergeAttachments(issue, replica)

/*
User Synchronization (Assignee/Reporter)

Set a Reporter/Assignee from the source side, if the user can't be found set a default user
You can use this approach for custom fields of type User
*/
def defaultUser = nodeHelper.getUserByEmail("akruck@maark.com")
issue.reporter = nodeHelper.getUserByEmail(replica.reporter?.email) ?: defaultUser
issue.assignee = nodeHelper.getUserByEmail(replica.assignee?.email) ?: defaultUser

 
/*
Comment Synchronization

Sync comments with the original author if the user exists in the local instance
Remove original Comments sync line if you are using this approach
*/
issue.comments = commentHelper.mergeComments(issue, replica)

{ it.executor = nodeHelper.getUserByEmail(it.author?.email) }
 
/*
Status Synchronization

Sync status according to the mapping [remote issue status: local issue status]
If statuses are the same on both sides don't include them in the mapping
*/

/*
Status Mapping
*/

def statusMappingAEM = [
    "Open" : "Backlog",
    "Created" : "Backlog",
    "Blocked" : "Blocked",
    "In Progress" : "In Progress",
    "In Code Review" : "In Progress",
    "Ready to Deploy" : "In Progress",
    "On Dev" : "In Progress",
    "Selected for Release" : "Ready for Staging",
    "Ready for Deploy" : "Ready for Staging",
    "Staging Review" : "UAT",
    "Done" : "Production Check",
    "DONE" : "Production Check",
    "Code Review" : "In Progress",
    "Stage Review" : "UAT",
    "Client Review" : "UAT",
    "Under Review" : "UAT",
    "Internal Review" : "In Progress",
    "Requirements Check" : "In Progress",
    "Reopened" : "In Progress"
    ]

def statusMappingACS = [
    "Open" : "Backlog",
    "Reopened" : "Backlog",
    "Blocked" : "Blocked",
    "In Progress" : "In Progress",
    "Code Review" : "In Progress",
    "Ready For Deploy" : "In Progress",
    "Ready for Deploy" : "In Progress",
    "Internal Review" : "In Progress",
    "Under Review" : "UAT",
    "Done" : "Production Check",
    "DONE" : "Production Check"
    ]

def statusMapping = issue.projectKey == "AEM" ? statusMappingAEM : statusMappingACS

def targetStatus = statusMapping[replica.status?.name]

if (!targetStatus) {
    debug.error("The remote status '${replica.status?.name}' is not found in the status mapping ")
    
} 


issue.setStatus(targetStatus)


/* OLD STATUS MAPPING CODE
def statusMapping = [
        "Open" : "Backlog",
         "Blocked" : "Blocked",
         "In Progress" : "In Progress",
         "In Code Review" : "In Progress",
         "Ready to Deploy" : "In Progress",
         "On Dev" : "In Progress",
         "Selected for Release" : "Ready for Staging",
         "Ready for Deploy" : "Ready for Staging",
         "Staging Review" : "UAT",
         "Done" : "Closed",
         "DONE" : "Closed",
         "Code Review" : "In Progress",
         "Stage Review" : "UAT",
         "Client Review" : "UAT",
         "Under Review" : "UAT",
         "Internal Review" : "In Progress",
        "Requirements Check" : "In Progress"
    ]
def remoteStatusName = replica.status.name
issue.setStatus(statusMapping[remoteStatusName] ?: remoteStatusName)
*/

/*
Priority Mapping


def priorityMapping = [
        // remote side priority <-> local side priority            
        "Highest": "Highest",
        "High": "High",
        "Low": "Low",
        "Lowest": "Lowest",
    ]
def priorityName = priorityMapping[replica.priority?.name] ?: "Low" 
// set default priority in case the proper urgency could not be found
issue.priority = nodeHelper.getPriority(priorityName)
*/
 

 
// this will overwrite the current time tracking information
  
issue.timeSpent   = replica.timeSpent
issue.originalEstimate   = replica.originalEstimate
issue.remainingEstimate  = replica.remainingEstimate
 
 
//any issue that is synced via Exalate will get an "exalate" label for easy identification
if (replica.issueType.name != "fakeissuetype") {
   issue.labels += nodeHelper.getLabel("exalate")
}

/*
VERSION SYNC
*/

// for the create processor, be sure that the project is set to the issue variable before running the following code
//issue.projectKey = "AEM" //Included only on create processor
issue.fixVersions = replica.fixVersions.collect {
    v -> nodeHelper.createVersion(issue, v.name, v.description)
}
 
// assign fix versions from JIRA A to JIRA B
issue.fixVersions = replica
  .fixVersions
  // ensure that all the fixVersions are available on B
  .collect 

{ v -> nodeHelper.createVersion(issue, v.name, v.description) }
// assign affected versions from JIRA A to JIRA B
issue.affectedVersions = replica
  .affectedVersions
  .collect { v -> nodeHelper.createVersion(issue, v.name, v.description) }


/* VERSION SYNC update - Exalate support September 2, 2021
issue.projectKey = "AEM"

if(replica.fixVersions)

{ issue.fixVersions = replica
.fixVersions
.collect { v -> nodeHelper.getVersion(v.name, project) }
    .findAll{it !=null}

} else {issue.fixVersions = replica     
.fixVersions
.collect { v -> nodeHelper.createVersion(issue, v.name, v.description) }

}

issue.affectedVersions = replica
    .affectedVersions
    .collect { v -> nodeHelper.getVersion(v.name, project) }
    .findAll

{it !=null}
*/

  
//Epic sync works using an external scrip on Jira On-prem, may require update if fails 
try {
Epic.receive()
}
catch(e){
    com.atlassian.jira.component.ComponentAccessor
        .getOSGiComponentInstanceOfType(com.exalate.api.error.IErrorService.class)
        .addError(syncRequest, e, com.exalate.api.domain.ErrorEntityType.ISSUE, null, false)
throw e        
}


/*
Custom Fields

This line will sync Text, Option(s), Number, Date, Organization, and Labels CFs
For other types of CF check documentation
issue.customFields."CF Name".value = replica.customFields."CF Name".value
*/

//debug.error("Rankvalue is ${replica.customKeys."RankValue"?.asString()}")

// Copy the customKeys field 'RankValue' to the text field 'Remote Master Rank'
issue.customFields."Remote Master Rank".value = replica.customKeys."RankValue"
issue.customFields."Remote Issue Key".value = replica.key

001_Source_Jira_cloud_outgoing.groovy
replica.key = issue.key
replica.type = issue.type 
replica.assignee = issue.assignee 
replica.reporter = issue.reporter
replica.summary = issue.summary
replica.description = issue.description
replica.labels = issue.labels
replica.comments = issue.comments
replica.resolution = issue.resolution
replica.status = issue.status
replica.parentId = issue.parentId
replica.priority = issue.priority
replica.attachments = issue.attachments
replica.project = issue.project
//Comment these lines out if you are interested in sending the full list of versions and components of the source project.
//replica.project.versions = []
replica.project.components = []
/*
Custom Fields
replica.customFields."CF Name" = issue.customFields."CF Name"
*/
//send the fix versions set on a synced issue
replica.fixVersions = issue.fixVersions
replica.affectedVersions = issue.affectedVersions
Epic.send()

/*
** Copy the ranking value from the issue to a custom key
** Rank is the standard ranking custom field.
*/
 
replica.customKeys."RankValue" = issue.customFields."Rank"?.value?.value