Exalate uses synchronization rules to handle outgoing and incoming messages. We call them Sync Rules. You can find Sync Rules as a separate tab when you select the connection to edit.
How to create a Sync Rule?
Sync rules are groovy based scripts that can be used to implement filtering, mapping, and transformation. These are essential operations in any synchronization.
Groovy is a dynamic language for the Java platform. Check out the following links to get more details about Groovy and how to develop in this language:
Sync rules types
There are 2 different types in the Sync Rules. Each with its own purpose.
For more details check the synchronization process explanation.
Outgoing sync
Defines what information is sent to the destination side.
Exalate runs the outgoing sync processor when you start the synchronization or update the local issue which is under sync.
You can assign issue fields to a replica on the outgoing sync. Check issue fields available for synchronization.
variable | explanation | |
---|---|---|
Input | issue | local issue data you need to synchronize. |
Output | replica | copy of the issue data which will be sent to the destination instance. |
Simple examples of the Outgoing sync rules
replica.summary = issue.summary // send summary replica.description = issue.description // send description replica.comments = issue.comments // send comments replica.attachments = issue.attachments // send attachments
Condition example in the Outgoing Sync rules
Don't send anything when priority is trivial
// If the issue priority is "Trivial" don't send any data. In other cases send the summary, description, comments and attachments if (issue.priority.name == "Trivial") { return } replica.summary = issue.summary replica.description = issue.description replica.comments = issue.comments replica.attachments = issue.attachments
Incoming sync
When you receive data from the other side you need to apply this data on your instance. You can define how to handle the received information on your instance with the help of the incoming sync rules.
Exalate runs the incoming sync every time there's new data received from the remote side.
When you receive the synchronization data from the remote side for the first time, Exalate creates the issue locally in your instance.
Starting from this moment the issue is considered under synchronization(under sync). From that moment every issue update will trigger the update of the synced issue on the other side.
variable | explanation | |
---|---|---|
Input | replica | information received from the source instance. |
previous | previous information received from the source instance. | |
Output | issue | issue object which will be used to create/update the local issue. |
When you leave the incoming sync empty, then nothing is synchronized. Check the Unidirectional synchronization for more details.
Simple Incoming sync example
if(firstSync){ // If it's the first sync for an issue and local copy of the issue does not exist yet // Set project key from source issue, if not found set a default issue.projectKey = nodeHelper.getProject(replica.project?.key)?.key ?: "TEST" // Set type name from source issue, if not found set a default issue.typeName = nodeHelper.getIssueType(replica.type?.name, issue.projectKey)?.name ?: "Task" } issue.summary = replica.summary issue.description = replica.description issue.comments = commentHelper.mergeComments(issue, replica) issue.attachments = attachmentHelper.mergeAttachments(issue, replica)
Incoming requests are distinguished based on the information stored in a replica.
So if you want to have different sync rules for the first synchronization and then others for synced issue updates you should use conditional statements.
if (firstSync) { return // don't create any issues, only sync changes to the issue which are already under sync } issue.summary = replica.summary issue.description = replica.description issue.labels = replica.labels issue.comments = commentHelper.mergeComments(issue, replica) issue.comments = attachmentHelper.mergeAttachments(issue, replica)
More advanced configuration
You can set your own values for the local issue based on the received data from the other side.
For example, if the synced issue status changes to Done on the remote side → set the local issue status to Resolved.
To configure advanced conditions for your synchronization use script helper methods.
Check the example below.
// Create a request in the support project "SD", but if it's a critical issue in the customer's WEB project, assign it to Kevin Spacey issue.project = nodeHelper.getProject("SD") if (replica.priority.name = "Critical" && replica.project.key = "WEB") { issue.assignee = nodeHelper.getUser("kspacey") // assign to Kevin issue.priority = nodeHelper.getPriority("Blocker") } else { issue.priority = nodeHelper.getPriority("Major") } issue.summary = replica.summary issue.projectKey = "SD" issue.typeName = "Request"
Default configuration
By default, Exalate configures some basic scripts in the Sync Rules for your convenience.
Below is the default configuration of the Outgoing and Incoming sync.
It helps to synchronize basic issue data: summary, description, comments, resolution, status, attachments and project.
Default Outgoing sync
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
Default Incoming sync
if(firstSync){ // If it's the first sync for an issue (local issue does not exist yet) // Set project key from source issue, if not found set a default issue.projectKey = nodeHelper.getProject(replica.project?.key)?.key ?: "TEST" // Set type name from source issue, if not found set a default issue.typeName = nodeHelper.getIssueType(replica.type?.name, issue.projectKey)?.name ?: "Task" } issue.summary = replica.summary issue.description = replica.description issue.comments = commentHelper.mergeComments(issue, replica) issue.attachments = attachmentHelper.mergeAttachments(issue, replica)