Exalate Assignee Getting Removed

Experiencing an issue where the assignee field is wiped out when the ticket is opened in the exalated board. See detailed steps below:

  1. ticket created in the client-side Jira board (for simplicity sake, “A”)

  2. the ticket exalates over to our Jira board (for simplicity sake, “A1”)

  3. client assigns an assignee and we see it on the client-side Jira board (“A”)

  4. we open the ticket on our Jira board (“A1”)

  5. on the client-side Jira board (“A”), the assignee is then removed

A few things to note:

  • we don’t have the assignees on “A” in “A1” - their users are strictly in “A”

  • touching the ticket on “A1” triggers exalate to re-push to “A” with no assignee even though we haven’t made any changes to the ticket, just simply opening it

Any help would be appreciated!

Hi and welcome to the Exalate Community!

Thanks for sharing your question or insight, we appreciate your contribution.

A member of the Exalate team or community will review this post and respond as soon as possible.

In the meantime, feel free to explore related topics or join other conversations. We’re glad to have you here!

Hi @Kristie ,

Thank you for being a part of Exalate Community.

Could you please share your Outgoing/Incoming Sync rule from both the sides?

In case you’re not already using this approach, so you may want to try it out within Incoming Sync script on the ‘A’ side.

In this Article, scroll down to ‘issue assignee → Jira Cloud to Jira Cloud case’:

And there are further two methods for syncing the ‘Assignee’ field.

issue.assignee = nodeHelper.getUser(replica.assignee.key) 
// or
issue.assignee = nodeHelper.getUserByEmail(replica.assignee.email)

Kind regards,

Ashar

Hi Ashar,

Here is the outgoing sync rule:

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.priority       = issue.priority
replica.attachments    = issue.attachments
//replica.attachments = issue.attachments.findAll { attachment -> attachment.filename.endsWith(".png") }
replica.project        = issue.project
replica.due = issue.due
replica.issueLinks = issue.issueLinks
if (issue.issueType.name != "Epic") {
    replica.parentId = issue.parentId
}

// Ensure that the Epic is synced first, such that stories sent later can be associated to the right epic


// Mapped Status. local:remote
def statusMap = [
  "In Review": "In Progress",
  "Ready for DEV Deploy": "In Progress",
  "Ready for Test (Internal)": "In Progress",
]

switch (issue.status.name) {
  case statusMap.keySet():
    replica.status = statusMap[issue.status.name]
    break
  default:
    replica.status = issue.status
    break
}

//New Conditional Comment (Accomodate different conditions for different projects) 
    replica.comments = issue.comments.findAll { comment -> 
        (comment.author.displayName == "Denise Soto") || 
        (comment.author.displayName == "Kristie Fung")|| 
        (comment.author.displayName == "Pi") ||
        (comment.author.displayName == "Doug Burton") ||
        (comment.author.displayName == "Hannah Barnhardt") 
    }.collect { comment ->
        def matcher = comment.body =~ /\[~accountid:([\w:-]+)\]/
        def newCommentBody = comment.body
        matcher.each {
            target = nodeHelper.getUser(it[1])?.displayName
            newCommentBody = newCommentBody.replace(it[0], target)
        }
        comment.body = newCommentBody
        comment
    }

Epic.send()

// Exalate API Reference Documentation: https://docs.exalate.com/docs/exalate-api-reference-documentation

and here is the incoming sync rule:

// Define labelNames early so it's available everywhere
def labelNames = replica.labels*.label
def hasInternalLabel = labelNames.contains("NBCU_INTERNAL")

if (firstSync) {
    issue.projectKey  = "NBCU"
    issue.typeName    = nodeHelper.getIssueType(replica.type?.name, issue.projectKey)?.name ?: "Task"
    issue.customFields."Client".value = "NBCU" 
    issue.labels += nodeHelper.getLabel("EXALATE")

    if (!hasInternalLabel) {
        issue.watchers += nodeHelper.getUserByEmail("Kristie@tmtinsights.com")
        issue.watchers += nodeHelper.getUserByEmail("Pi.Waller@tmtinsights.com")
    }

    def defaultAssignee = nodeHelper.getUserByEmail("doug.burton@tmtinsights.com")
    def foundAssignee = null

    if (replica.assignee?.email) {
    foundAssignee = nodeHelper.getUserByEmail(replica.assignee.email)
}


    if (replica.type?.name == "Bug") {
        issue.assignee = defaultAssignee
        issue.watchers += nodeHelper.getUserByEmail("denise.soto@tmtinsights.com")
        log.info("Issue type is 'Bug' — assigning to Doug Burton.")
    } else if (foundAssignee) {
        issue.assignee = foundAssignee
        log.info("Assigning to found user '${foundAssignee?.displayName}'.")
    } else {
        issue.assignee = null
        log.info("No local match for assignee — leaving unassigned.")
    }
}

issue.summary      = replica.summary
issue.description  = replica.description
issue.comments     = commentHelper.mergeComments(issue, replica)
issue.attachments  = attachmentHelper.mergeAttachments(issue, replica)
issue.labels       = replica.labels 
issue.due          = replica.due
issue.customFields."Components (Project Specific)".value = replica.customFields."Components (Project Specific)"?.value ?: []


def defaultPriority = nodeHelper.getPriority("Medium")
issue.priority = nodeHelper.getPriority(replica.priority?.name) ?: defaultPriority

issue.customFields."Remote issue URL".value = remoteIssueUrl 
issue.customFields."Remote Key".value = replica.key

def statusMap = [
    "Open"               : "Open",
    "Backlog"            : "Backlog",
    "Reopened"           : "Reopened",
    "Ready for Prod Deploy" : "Ready for PROD Deploy",
    "Done"               : "Done",
    "Won't Do"           : "Done",
    "Closed"             : "Done"
]

def remoteStatusName = replica.status?.name

if (remoteStatusName) {
    if (hasInternalLabel) {
        log.info("NBCU_INTERNAL label found — applying remote status as-is: ${remoteStatusName}")
        issue.setStatus(remoteStatusName)
    } else if (statusMap.containsKey(remoteStatusName)) {
        issue.setStatus(statusMap[remoteStatusName])
    } else {
        log.info("Status '${remoteStatusName}' not in allowed list and NBCU_INTERNAL not present — skipping status update.")
    }
}

if (issue.typeName != "Epic") {
    issue.parentId = replica.parentId
    Epic.receive()
}

can you help clarify if there is somewhere in the incoming and outgoing sync rule where the incoming sync rule should still be applied or not?

Thanks,

Kristie

Hi @Kristie ,

Thank you for sharing.

I have reviewed the sync rules, and I will also need to check the Outgoing Sync rule from the A side, as well as the Incoming Sync rule from the A1 side.

Additionally, please provide the local replica and remote replica from the A1 side so we can verify the payload and confirm when a null value is being sent for the Assignee field from A1 to A.

  1. Go to side A1
  2. Navigate to Entity Sync Status tab
  3. Search for the Jira Work Item (with a problem)
  4. There you will find ‘local replica’ and ‘remote replica’ options
  5. At the extreme top corner, you’ll find the ‘Copy’ button

Kind regards,

Ashar

Hi @Kristie ,

Just checking in on my previous request for the data — do you happen to have that available so we can move forward?

Kind regards,
Ashar

Hi @Kristie ,

I just wanted to follow up once more regarding my earlier request for the data. If you’re able to share it, we can proceed accordingly. If not, no worries—please let me know either way so I can plan the next steps.

Thank you,
Ashar

Hi Ashar,

Apologies for not responding sooner - I’ve been on business travel and it’s been very hectic.

We have resolved the issue for now. I will return to the forum with any additional issues that I will need assistance with.

Thanks!

Kristie

Hi @Kristie ,

Thanks for getting back to me, Kristie, and I’m glad to hear the issue has been resolved!

If you don’t mind sharing, could you let us know what solution worked for you? It could be really helpful for others in the community who might run into a similar situation.

Kind regards,
Ashar