Scripts in Visual Mode

    Script rules can be used in Visual Mode when the standard mapping rules are not sufficient to cover the use case.
    Creating a script rule is straightforward.

    • Edit your visual connection
    • Select the rules
    • Select the 'Add script'

    How does it work?

    The scripts are groovy-based, meaning that all groovy structures can be used to define the behavior of the mapping. For instance, if a mapping is needed between the assignees of one side with the instance name 'left' and another side with the instance name 'right', the following code snippet implements the mapping:

    // define the mapping
    def leftToRightAssignee = [
        // left Assignee ---> right Assignee
        "" : "",
        "" : "",
    // look up the corresponding email, default to
    def targetUserEmail = leftToRightAssignee[left.issue.assignee?.email] ?: ""
    // assign to right issue
    right.issue.assignee = nodeHelper.getUserByEmail(targetUserEmail)



    your_instance_shortname.issue.labels = remote_instance_shortname.issue.labels


    your_instance_shortname.issue.components = remote_instance_shortname.issue.components.collect { component ->
    def remoteComponentLeadEmail = component.lead?.email
    def localComponentLeadName = nodeHelper.getUserByEmail(remoteComponentLeadEmail)
        component.description, // can also be null
        localComponentLeadName?.key, // can also be null
        component.assigneeType?.name() // can also be null


    Set the local resolution same as on the remote side, if there's no such resolution on your side don't set anything

    if(nodeHelper.getResolution(remote_instance_shortname.issue.resolution?.name)) {
         your_instance_shortname.issue.resolution = remote_instance_shortname.issue.resolution   


    // assign fix versions from JIRA A to JIRA B
    your_instance_shortname.issue.fixVersions = remote_instance_shortname.
      // ensure that all the fixVersions are available on B
      .collect { v -> nodeHelper.createVersion(issue,, v.description) }
    // assign affected versions from JIRA A to JIRA B
    your_instance_shortname.issue.affectedVersions = remote_instance_shortname
      .collect { v -> nodeHelper.createVersion(issue,, v.description) }

    User fields


    your_instance_shortname.issue.assignee = nodeHelper.getUser(remote_instance_shortname.issue.assignee?.key)


    your_instance_shortname.issue.reporter = nodeHelper.getUser(remote_instance_shortname.issue.reporter?.key)

    Custom fields

    Text/String custom fields

    Sync value from "remote side select list custom field" to the local "select list custom field"

    your_instance_shortname.issue.customFields."text custom field".value = remote_instance_shortname.issue.customFields."remote side text custom field".value

    Set a fixed value in the local custom field 

    Single select list/radio button

    Sync value from "remote side select list custom field" to the local "select list custom field"

    your_instance_shortname.issue.customFields."select list custom field".value = remote_instance_shortname.issue.customFields."remote side select list custom field".value

    Set a fixed value in the local custom fields "My select list"

    your_instance_shortname.issue.customFields."My Select list".value = "Red"

    Multi-select list/Checkbox

    // sync value from "remote multi-select list custom field" to the local "select list multiple choice"
    your_instance_shortname.issue.customFields."select list multiple choice".value = remote_instance_shortname.issue.customFields."remote multi-select list custom field".value?.value
    // Add "Red" as a value in the custom fields "My multi-select list"
    your_instance_shortname.issue.customFields."My multi-select list".value += nodeHelper.getOption("Red")

    Multi-cascade custom fields

    Sync only existing option values 

    def sourceRegion = remote_instance_shortname.issue.customFields."Source Region/Country"?.value?.parent?.value
    def sourceCountry = remote_instance_shortname.issue.customFields."Source Region/Country"?.value?.child?.value
    def region = nodeHelper.getOption(
      "Destination Region/Country",
    def country = region.childOptions.find{it.value == sourceCountry}
    if ( region != null && (sourceCountry == null || country != null)) {
      your_instance_shortname.issue.customFields."Destination Region/Country"?.value = nodeHelper.getCascadingSelect(
    } else if (sourceRegion == null) {
      your_instance_shortname.issue.customFields."Destination Region/Country"?.value = null

    Date/DateTime custom fields

    // if you have a custom field called "My Date" (of type Date Picker or Date Time Picker)
    // on your Side and you'd like to populate it from
    // "Their Date" of remote Side (of type Date Picker or Date Time Picker)
    your_instance_shortname.issue.customFields."My Date".value = remote_instance_shortname.issue.customFields."Their Date".value
    // or if you'd like to assign a fixed moment in time:
    your_instance_shortname.issue.customFields."My Date".value = new java.text.SimpleDateFormat("yyyy-MM-dd HH:mm:ss z")
        .parse("2019-10-24 13:30:59 EET")

    URL custom fields

    // sync value from "remote side url custom field" to the local "url custom field"
    your_instance_shortname.issue.customFields."url custom field".value = remote_instance_shortname.issue.customFields."remote side url custom field".value
    // Set a fixed value "" in the custom field with name  "My url custom field"
    your_instance_shortname.issue.customFields."My url custom field".value = ""

    Label custom fields

    // sync value from "remote side labels" to the local "My labels"
    your_instance_shortname.issue.customFields."My labels".value = remote_instance_shortname.issue.customFields."remote side labels".value
    // add "attention" to the custom field "My labels"
    your_instance_shortname.issue.customFields."My labels".value += nodeHelper.getLabel("attention")

    User picker custom fields

    // sync value from "remote side user picker custom field" to the local "user picker custom field"
    your_instance_shortname.issue.customFields."user picker custom field".value = nodeHelper.getUser(remote_instance_shortname.issue.customFields."remote side user picker custom field".value)
    // Set a fixed value "557358:bda57a72g56a9-4219-9c29-7d666481388f" (id for a user in your system) in the custom field with name  "My user picker"
    your_instance_shortname.issue.customFields."My user picker".value = "557358:bda57a72g56a9-4219-9c29-7d666481388f"

    Number custom fields

    your_instance_shortname.issue.customFields."numeric custom field".value = remote_instance_shortname.issue.customFields."remote side numeric custom field".value

    Advanced Scripts

    Set a custom field with the issue key of the remote twin in the Visual mode

    How to set a custom field like 'Remote Key' with the key of the twin issue.  This example shows how to implement it on a Jira Cloud to Jira Cloud, but the approach can also be used on other permutations.

    Assume you have set up a connection using the visual configuration mode between 'local' and 'remote'.

    You have the requirement that a text field 'Remote Key' on the local issue must contain the issue key of the remote twin.


    What needs to happen is that

    • once the remote issue is created, a message is sent back from the remote to the local, containing the issue key of the remote.
    • this incoming message on the local can then be used to populate the local custom field.

    Triggering a message back can be done using the syncBackAfterProcessing function.


    Add the following script rule to the connection.

    • Line 1 - limit the sync back to the first sync transaction.
      Warning:  This must be done, otherwise it creates a loop that sends messages back and forth continuously.
    • Line 2 - trigger the sync back transaction using the syncHelper.syncBackAfterProcessing.
    • Line 5 - assign the value of the remote key to the local customfield 'Remote Key'.