Error syncing internal comments JSM Cloud

Originally asked by Hannes Bünger on 03 March 2023 (original question)


Hi or as we used to say in nothern Germany Moin,

I´m currently having trouble syncing issues between two Jira Service Management Cloud Instances.

The affected issues contain internal comments.

The error I get in Exalate is: Internal comments cannot be processed. The reason is: Request Type custom field is required, but not set…

The config on the side where the error appears contains the following script parts.

Outgoing

//replica.comments = issue.comments

replica.comments = issue.comments.findAll{!it.internal}

Incoming

issue.comments = commentHelper.mergeComments(issue, replica)

On the other instance it looks like this:

Outgoing

replica.comments = issue.comments

Incoming

issue.comments = commentHelper.mergeComments(issue, replica)

Intention:

I want internal comments only to be synced incoming on my instance but not outgoing.

Any help would be greatly appreciated.

Best regards,

Hannes


Answer by Serhiy Onyshchenko on 06 March 2023

Moin, Hannes Bünger
Thanks for raising this on community :smile:

I’d suggest to change the if(firstSync) block of the incoming sync of JSM side to not only set the issueType and project, but also set the Request Type (which should be matching the issue type):

if(firstSync) {
  //...    issue.typeName = ...
    issue."Request Type" = "Get IT Help" // where Get IT Help should be replaced with the proper request type for the given issue type
}

This change to the script should help with all the newly synced issues.

For all the existing ones, I’m afraid the only way forward is to set the request type manually.

Let me know , how it goes,
Regards, Serhiy.


Comments:

Hannes Bünger commented on 06 March 2023

Hi Serhiy Onyshchenko,

I edited the sync script to include issue.``"Request Type" but it only gave me unexpected errors while syncing.

Prior to this i saw that my collegue used issue.customFields.“Request Type”. Unfortunately this doesn´t sync the request type.

Any idea?

Best regards,
Hannes

Serhiy Onyshchenko commented on 06 March 2023

Hello, Hannes Bünger , Might I ask you to share the incoming sync script here?
That way It’s going to be clearer, what we’re looking into here.

Hannes Bünger commented on 06 March 2023

Sure, here you go:

if(firstSync){
issue.projectKey = “FKOLA”
// Set type name from source issue, if not found set a default
issue.typeName = nodeHelper.getIssueType(replica.type?.name, issue.projectKey)?.name ?: “Submit a request or incident”

}
issue.summary = replica.summary
issue.description = replica.description ?: “No description provided”
issue.comments = commentHelper.mergeComments(issue, replica)
issue.attachments = attachmentHelper.mergeAttachments(issue, replica)
issue.labels = replica.labels
issue.issueLinks = replica.issueLinks
//issue.approvers = replica.approvers

/*
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(“default@idalko.com”)
issue.reporter = nodeHelper.getUserByEmail(replica.reporter?.email) ?: defaultUser
issue.assignee = nodeHelper.getUserByEmail(replica.assignee?.email) ?: defaultUser
*/

issue.reporter = nodeHelper.getUserByEmail(replica.reporter?.email)

/*
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
def statusMapping = [“Open”:“New”, “To Do”:“Backlog”]
def remoteStatusName = replica.status.name
issue.setStatus(statusMapping[remoteStatusName] ?: remoteStatusName)
*/

def remoteStatusName = replica.status.name
issue.setStatus(remoteStatusName)

/*
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
*/

issue.customFields.“IssueTypeSync”.value = replica.customFields.“IssueTypeSync”.value
issue.customFields.“XXX_ReporterSync”.value = replica.reporter?.email
issue.customFields.“Request Type”.value = replica.customFields.“Request Type”?.value

/*
Component Syncronization
*/
issue.components = replica.components.collect {
component ->
nodeHelper.createComponent(
issue,
component.name,
component.description,
component.leadKey,
component.assigneeType?.name()
)
}

//debug.error()

Serhiy Onyshchenko commented on 08 March 2023

Alright, here’s my suggestion applied

if(firstSync){
   issue.projectKey   = "FKOLA" 
   // Set type name from source issue, if not found set a default
   issue.typeName     = "Submit a request or incident"
   def issueTypeToRequestType = [
        "Submit a request or incident" : "Get IT Help",
   ]
   issue."Request Type" = issueTypeToRequestType[issue.typeName] ?: "Get IT Help"
}
issue.summary        = replica.summary
issue.description    = replica.description ?: "No description provided"
issue.comments       = commentHelper.mergeComments(issue, replica)
issue.attachments    = attachmentHelper.mergeAttachments(issue, replica)
issue.labels         = replica.labels
issue.issueLinks     = replica.issueLinks
//issue.approvers    = replica.approvers


issue.reporter = nodeHelper.getUserByEmail(replica.reporter?.email)



def remoteStatusName = replica.status.name
issue.setStatus(remoteStatusName)



issue.customFields."IssueTypeSync".value = replica.customFields."IssueTypeSync".value
issue.customFields."XXX_ReporterSync".value = replica.reporter?.email
issue.customFields."Request Type".value =  replica.customFields."Request Type"?.value


/*
Component Syncronization
*/
issue.components = replica.components.collect { 
    component ->
    nodeHelper.createComponent(
        issue, 
        component.name, 
        component.description, 
        component.leadKey, 
        component.assigneeType?.name()
    )
}

//debug.error()

In this case I’m setting the request type “Get IT Help” if the issue type is “Submit a request or incident”. Please, replace with an appropriate Request type for this issue type.

Could I also ask to share the error that happens with such rules?
Regards, Serhiy.

Answer by Normann P. Nielsen on 03 March 2023

How about:

replica.comments = commentHelper.filterLocal(issue.comments)

We use this always on outgoing, so only public comments are synced.


Comments:

Serhiy Onyshchenko commented on 06 March 2023

That’s a nice work-around, Normann P. Nielsen !

Hannes Bünger commented on 06 March 2023

Hi Normann,

I´ll give that a try.

Thank you!