How to stop synchronization for the first value of the field?

Originally asked by Mihai Arama on 15 March 2022 (original question)


Hello,

We have the following use-case:

Jira (cloud) - Service-Now integration.

We have in service now a field called “Assignment level”. It can be 1,2,3 or 4.

When this value changes in service-now, we want to add a comment in Jira with the level and the current assignment group. We achieved this by adding the following code:

    //this next part handles escalation and de-escalation on the service now ticket
    if (replica.assignment_level > (previous?.assignment_level)){
        escalationCommentString = "The Service-Now ticket has been escalated. The new assignment level is: " + replica.assignment_level + " and the assignment group is: " + replica.assignment_group.display_value
        issue.comments = commentHelper.addComment(escalationCommentString, issue.comments)
        issue.setStatus("Backlog")
    }
    
    if (replica.assignment_level < (previous?.assignment_level)){
        deescalationCommentString = "The Service-Now ticket has been de-escalated. The new assignment level is: " + replica.assignment_level + " and the assignment group is: " + replica.assignment_group.display_value
        issue.comments = commentHelper.addComment(deescalationCommentString, issue.comments)
        issue.setStatus("Backlog")
    }

This works fine with one exception. It also adds the comment when the issue is created in service-now, and we have only added this code in the else part of:

if(firstSync){ do stuff, but not add the assignment level anywhere}
else {
	this is where the above code is added
}

So the Jira ticket that gets created also immediately adds a comment with the message: "The Service-Now ticket has been escalated. The new assignment level is: " + replica.assignment_level + " and the assignment group is: " + replica.assignment_group.display_value".

Could we somehow stop this message at creation?

Thank you!

Answer by Mihai Arama on 24 March 2022

We found that it wasn’t a problem of the code, but that in Service now we have a script adding those values a few seconds after the creation.


Answer by Francis Martens (Exalate) on 15 March 2022

Can you provide the full code of your incoming sync - Jira side?


Comments:

Mihai Arama commented on 15 March 2022

Hi,

Sure.

if(firstSync){
   
    issue.projectKey   = "ESNIT" 
    // 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.key + " - " + replica.summary
    issue.description  = nodeHelper.toMarkDownFromHtml(replica.description_html)
    issue.customFields."URL".value = remoteIssueUrl
    
    // Priority sync
    def priorityMapping = [
    // Snow incident priority <-> Jira issue priority
         "1 - Critical": "Blocker",
         "2 - High": "Major",
         "3 - Medium": "Minor",
         "4 - Low": "Trivial"
    ]
    def defaultPriority = "Low"
    def priorityName     = priorityMapping[replica.priority?.name] ?: defaultPriority // set default priority in case the proper urgency could not be found
    issue.priority = nodeHelper.getPriority(priorityName)

    // this part will add the hardcoded "PROD" and "CST" values + the values from 4 service-now fields, if they exist, to the jira labels; 
    // also adding the H Software Product and the HSP Categories values to Components
    def listOfLabels = ['PROD', 'CST']
    def listOfComponents = []
    if (replica.H_software_product) {
        def HSoftwareProductValue = replica.H_software_product.display_value
        def noSpacesHSofwareProductValue = HSoftwareProductValue.replaceAll(" ","_")
        listOfLabels.add(noSpacesHSofwareProductValue)
        listOfComponents.add(HSoftwareProductValue)
    }
    if (replica.H_spc1) {
        def HSoftwareProductCategory1Value = replica.H_spc1.display_value
        def noSpacesHSoftwareProductCategory1Value = HSoftwareProductCategory1Value.replaceAll(" ","_")
        listOfLabels.add(noSpacesHSoftwareProductCategory1Value)
        listOfComponents.add(HSoftwareProductCategory1Value)
    }
    if (replica.H_spc2) {
        def HSoftwareProductCategory2Value = replica.H_spc1.display_value
        def noSpacesHSoftwareProductCategory2Value = HSoftwareProductCategory2Value.replaceAll(" ","_")
        listOfLabels.add(noSpacesHSoftwareProductCategory2Value)
        listOfComponents.add(HSoftwareProductCategory2Value)
    }
    if (replica.H_spc3) {
        def HSoftwareProductCategory3Value = replica.H_spc1.display_value
        def noSpacesHSoftwareProductCategory3Value = HSoftwareProductCategory3Value.replaceAll(" ","_")
        listOfLabels.add(noSpacesHSoftwareProductCategory3Value)
        listOfComponents.add(HSoftwareProductCategory3Value)
    }

    def project = issue.project ?: nodeHelper.getProject(issue.projectKey)
    for (eachComponent in listOfComponents){
        def component = nodeHelper.getComponent(eachComponent, project)
        if(!component) {nodeHelper.createComponent(
            issue,
            eachComponent,
            null,
            null,
            null
            )
            def newComponent = nodeHelper.getComponent(eachComponent, project)
            issue.components += newComponent    
            } else {issue.components += component}
    }
    
    for (eachLabel in listOfLabels){
        issue.labels += nodeHelper.getLabel(eachLabel)
    }

    // this part will create a mapping between the SNOW Country and Jira MO, and add the field value.
    def CountryToMOMapping = [
    // Snow incident country <-> Jira issue MO
        "BR": "Brazil",
        "DE": "Germany"
    ]

    def defaultMO = "Brazil"
    def MOName     = CountryToMOMapping[replica.country.display_value] ?: defaultMO // set default MO in case the proper MO could not be found
    
    issue.customFields."MO".value = MOName     //sets the MO in Jira
    //using the above created MOName, map the MO to a Region, and set it in Jira    
    def MOToRegionMapping = [
        "Brazil": "W2",
        "Germany": "E3"
    ]
    
    def regionName = MOToRegionMapping[MOName]
    issue.customFields."Region".value = regionName

/*   def MOToHubLeaderMapping = [
        "Brazil": "mihai.arama@externals.H.com",
        "Germany": "sascha.g@H.com"
    ]    
    def defaultUser = nodeHelper.getUserByEmail(MOToHubLeaderMapping[MOName]) */
    issue.reporter = nodeHelper.getUserByEmail(replica.opened_by) // ?: defaultUser



    issue.attachments  = attachmentHelper.mergeAttachments(issue, replica)
    issue.customFields."SAP Customer Nr.".value = replica.H_customer.display_value

// if(issue.description[-1] != issue.description) {
//   issue.description  = commentHelper.mergeComments(issue, replica) 
//}
} else {
    
    def statusMapping = ["Closed (resolved)":"Done"]
    def remoteStatusName = replica.state
    if (remoteStatusName == "Closed (resolved)") {
        issue.setStatus(statusMapping[remoteStatusName] ?: remoteStatusName)
    } 
    if (!replica.state.equals(previous?.state)) {
        statusCommentString = "The Service-Now ticket's status is: " + replica.state
        issue.comments = commentHelper.addComment(statusCommentString, issue.comments)
    }

    
    //issue.attachments  = attachmentHelper.mergeAttachments(issue, replica)
    //issue.description  = nodeHelper.toMarkDownFromHtml(replica.description_html)
    //issue.comments     = commentHelper.mergeComments(issue, replica)
    
    

    if (!replica.description_html[0] && !replica.description_html.equals(previous?.description_html)) {
        descriptionCommentString = "The Service-Now ticket's Description was updated to: " + "\n" + nodeHelper.toMarkDownFromHtml(replica.description_html)
        issue.comments = commentHelper.addComment(descriptionCommentString, issue.comments)
    }
    issue.attachments += replica.addedAttachments
    //issue.comments += replica.addedinternalworknotes
    
   if (!replica.internalworknotes.equals(previous?.internalworknotes)) {
        fullInternalWorkNotes = nodeHelper.toMarkDownFromHtml(replica.internalworknotes)
        // each new internal comment in service now starts with a \n\n ...
        def newRowDouble = fullInternalWorkNotes.indexOf("\n\n")
        // if \n\n is found, take left side
        if(newRowDouble != -1) {
            latestInternalNotes = fullInternalWorkNotes.substring(0, newRowDouble);  
            } else { 
            latestInternalNotes = fullInternalWorkNotes
            }
        workNotesCommentString = "New Service-Now Internal Work Notes were added: " + "\n" + latestInternalNotes
        issue.comments = commentHelper.addComment(workNotesCommentString, issue.comments)
    }

    //this next part handles escalation and de-escalation on the service now ticket
    if (replica.assignment_level > (previous?.assignment_level)){
        escalationCommentString = "The Service-Now ticket has been escalated. The new assignment level is: " + replica.assignment_level + " and the assignment group is: " + replica.assignment_group.display_value
        issue.comments = commentHelper.addComment(escalationCommentString, issue.comments)
        issue.setStatus("Backlog")
    }
    
    if (replica.assignment_level < (previous?.assignment_level)){
        deescalationCommentString = "The Service-Now ticket has been de-escalated. The new assignment level is: " + replica.assignment_level + " and the assignment group is: " + replica.assignment_group.display_value
        issue.comments = commentHelper.addComment(deescalationCommentString, issue.comments)
        issue.setStatus("Backlog")
    }

    


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

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

*/

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


Thank you for your quick reply!

Francis Martens (Exalate) commented on 15 March 2022

This code segment looks very impressive.

Can you add a debug.error statement to the right block and see why the ‘addComment’ is being triggered?

Mihai Arama commented on 16 March 2022

Hi Francis,

I’m not sure if I added it correctly.

    if (replica.description_html.equals(previous?.description_html)) {
        descriptionCommentString = "The Service-Now ticket's Description was updated to: " + "\n" + nodeHelper.toMarkDownFromHtml(replica.description_html)
        issue.comments = debug.error(commentHelper.addComment(descriptionCommentString, issue.comments))
    }

I now get this:

No signature of method: com.exalate.hubobject.jira.DebugHelper.error() is applicable for argument types: (ArrayList) values: [[BasicHubComment{@body=`The Service-Now ticket’s Description was updated to: ---BEGIN--- Short description of problem Attach screenshot of any error messages AT Doc Software version Computer information (operating system, connected to internet, re-installation tried) Attach software log files ---END---`, @id=`null`, @remoteId=`null`, @author=`null`, @created=`null`, @updateAuthor=`null`, @updated=`null`, @group=`null`, @role=`null`, @internal= `true`, @executor= `null`}]] Possible solutions: error(java.lang.String), every(), iterator(), grep(), macro(groovy.lang.Closure), print(java.io.PrintWriter)

But I assume that’s not how the debug statement should be used. Any tips there, please?

Thank you!

Francis Martens (Exalate) commented on 16 March 2022

Nope - clearly not
Check details
https://docs.idalko.com/exalate/display/ED/debug.error

Just add it on its own line

Mihai Arama commented on 16 March 2022

Hello,

I tried adding it like this:

    if (replica.description_html.equals(previous?.description_html)) {
        descriptionCommentString = "The Service-Now ticket's Description was updated to: " + "\n" + nodeHelper.toMarkDownFromHtml(replica.description_html)
        issue.comments = commentHelper.addComment(descriptionCommentString, issue.comments)
        debug.error(commentHelper.addComment(descriptionCommentString, issue.comments))
    }

and I get:

No signature of method: com.exalate.hubobject.jira.DebugHelper.error() is applicable for argument types: (ArrayList) values: [[BasicHubComment{@body=`The Service-Now ticket’s Description was updated to: ---BEGIN--- Short description of problem Attach screenshot of any error messages AT Doc Software version Computer information (operating system, connected to internet, re-installation tried) Attach software log files ---END---`, @id=`null`, @remoteId=`null`, @author=`null`, @created=`null`, @updateAuthor=`null`, @updated=`null`, @group=`null`, @role=`null`, @internal= `true`, @executor= `null`}, …]] Possible solutions: error(java.lang.String), every(), iterator(), grep(), macro(groovy.lang.Closure), print(java.io.PrintWriter)

Also, just adding debug.error() does not get me anything.

Also, I do not actually get an error, I just get the value synchronized in a moment when I don’t need it synchronized.

Please let me know if you have any suggestions.

Thank you!

Francis Martens (Exalate) commented on 16 March 2022

a) debug.error expects a string. commentHelper.addComment is returning a comment array so that can not work

With debug.error - you can print out the value of certain variables, like

debug.error(“The value of firstSync is ${firstSync}”)

b) try to understand why that section of the code is being executed by looking at the logic and find out why it is getting there.

Mihai Arama commented on 16 March 2022

Hello,

Thank you for the explanation.

I used two statements:

    if (!replica.description_html.equals(previous?.description_html)) {
        descriptionCommentString = "The Service-Now ticket's Description was updated to: " + "\n" + nodeHelper.toMarkDownFromHtml(replica.description_html)
        issue.comments = commentHelper.addComment(descriptionCommentString, issue.comments)
        //debug.error("The value of the previous description is ${previous?.description_html}")
        //debug.error("The value of the current description is ${replica.description_html}")
    }

This is the output for them:

The value of the previous description is
Details:

Username of affected user(s): ex: ukdemo@hilti.biz
Device Manufacturer and Model: ex: Apple iPhone X
Device Operating System: ex: iOS 11.2.6
Affected tools and their Serial Numbers (if applicable): ex: Hilti DX 5 (64632488) , Hilti SD 6H-A22 (15645625)
Mobile Application version: ex: Hilti Connect v1.2.2
Steps to reproduce: ex: Open the mobile application, attempt to login with username ukdemo@hilti.biz - got error message: System is busy
Date & Time when issue occurred: ex: 26-02-2018 - 13:15 CET
Troubleshooting performed: ex: Attempted login on Android phone - login successful; Attempted login with different username on same phone - login failed
Other details: ex: Other colleagues with different iOS phones can login successfully with this username

The value of the current description is
Details:

Username of affected user(s): ex: ukdemo@hilti.biz
Device Manufacturer and Model: ex: Apple iPhone X
Device Operating System: ex: iOS 11.2.6
Affected tools and their Serial Numbers (if applicable): ex: Hilti DX 5 (64632488) , Hilti SD 6H-A22 (15645625)
Mobile Application version: ex: Hilti Connect v1.2.2
Steps to reproduce: ex: Open the mobile application, attempt to login with username ukdemo@hilti.biz - got error message: System is busy
Date & Time when issue occurred: ex: 26-02-2018 - 13:15 CET
Troubleshooting performed: ex: Attempted login on Android phone - login successful; Attempted login with different username on same phone - login failed
Other details: ex: Other colleagues with different iOS phones can login successfully with this username

I compared the texts and they appear to be the same.

However, in service-now, this is a text field for which I can get the HTML source code, which is:

---BEGIN---
Details:

  1. Username of affected user(s): ex: ukdemo@hilti.biz

  2. Device Manufacturer and Model: ex: Apple iPhone X

  3. Device Operating System: ex: iOS 11.2.6

  4. Affected tools and their Serial Numbers (if applicable): ex: Hilti DX 5 (64632488) , Hilti SD 6H-A22 (15645625)

  5. Mobile Application version: ex: Hilti Connect v1.2.2

  6. Steps to reproduce: ex: Open the mobile application, attempt to login with username [hilti.biz](mailto:ukdemo@<a href=)" rel=“nofollow”>ukdemo@hilti.biz - got error message: System is busy

  7. Date & Time when issue occurred: ex: 26-02-2018 - 13:15 CET

  8. Troubleshooting performed: ex: Attempted login on Android phone - login successful; Attempted login with different username on same phone - login failed

  9. Other details: ex: Other colleagues with different iOS phones can login successfully with this username

---END—

Do you think this could be, somehow, the cause?

Thank you!

This topic was automatically closed 2 days after the last reply. New replies are no longer allowed.