Skip to content

Instantly share code, notes, and snippets.

@ZioHimself
Last active April 23, 2022 01:17
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ZioHimself/ee03afee2d2bdf51507209e880ce9451 to your computer and use it in GitHub Desktop.
Save ZioHimself/ee03afee2d2bdf51507209e880ce9451 to your computer and use it in GitHub Desktop.
Exalate Community 42836640
def boardIds = ["50", "80", "130", "144"] //Boards which sprints will get synced
if(entityType == "sprint" && boardIds.find{it == sprint.originBoardId}){
replica.name = sprint.name
replica.goal = sprint.goal
replica.state = sprint.state
replica.startDate = sprint.startDate
replica.endDate = sprint.endDate
replica.originBoardId = sprint.originBoardId
} else if (entityType == "issue") {
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
replica.customFields."Sprint" = issue.customFields."Sprint"
}
if(entityType == "sprint"){
//Executed when receiving a sprint sync from the remote side
def sprintMap = ["50":"162", "80":"197", "130":"214", "144":"225"] //[remoteBoardId: localBoardId]
sprint.name = replica.name
sprint.goal = replica.goal
sprint.state = replica.state?.toUpperCase()
sprint.startDate = replica.startDate
sprint.endDate = replica.endDate
def localBoardId = sprintMap[replica.originBoardId]
if(localBoardId == null){
throw new com.exalate.api.exception.IssueTrackerException("No board mapping for remote board id "+replica.originBoardId)
}
sprint.originBoardId = localBoardId //Set the board ID where the sprint will be created
} else if(entityType == "issue"){
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
def sprintV = replica.customFields.Sprint.value?.id.collect{ remoteSprintId ->
return nodeHelper.getLocalIssueKeyFromRemoteId(remoteSprintId, "sprint")?.id?.toString()
}.findAll{it != null}
issue.customFields."Sprint".value = sprintV
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment