Skip to main content

How to Sync Comment Threads and User Mentions in Comments between Jira and Salesforce

  

A Jira Salesforce integration use case can be an interesting one, an amalgamation of business and technical teams. 

 

In this article, we’ll discuss an advanced comment use case that allows syncing threads of comments and user mentions between these 2 platforms so that they speak the same language. 

 

The Use Case

The use case is implemented between a Jira Cloud and a Salesforce instance. 

 

The following are the key requirements: 

  • An issue (or a ticket) created in Jira is synced over to the Salesforce instance as a Case. It might as well be any other Salesforce object. 
  • Basic fields like summary, description, and comments are synced between Jira Cloud and Salesforce.
  • Threaded replies to comments (chatter feed capability) from Salesforce are synced to Jira. Comments from Jira are reflected in Salesforce. 
  • User mentions in Jira tags the correct corresponding user in Salesforce (if the user exists on both systems). 
  • Comment formatting is maintained. 

The Challenges

  • There is a transformation challenge between the 2 instances. Since Salesforce uses HTML internally to represent comments and Jira uses Wiki Markup, there are inherent differences in formatting between these 2 platforms. These must be addressed correctly. 
  • There is a fully supported “chatter feed” functionality in Salesforce that allows threaded replies to comments. Jira does not have similar functionality. The challenge then is to reflect these replies back in Jira. 

 

The Solution: Exalate

Exalate is a one-way or two-way synchronization solution that supports multiple platforms like Jira, Salesforce, Azure DevOps, GitHub, Zendesk, etc. 

 

Its intuitive Groovy-based scripting engine allows you to implement advanced use cases. The Sync rules can be modified to set up deeper integrations. In addition to this, you can use Triggers and set up advanced automatic synchronization too.

 

Note: The Exalate Academy is a great way to learn more about Exalate. Give it a try! 

 

How to Implement Advanced Comment Sync Using Exalate

Prerequisites

  • You need to install Exalate on both Jira Cloud and Salesforce instances. 
  • You should create in Script Mode a connection between the platforms. 

 Note: You can learn more about setting up a connection between Jira and Salesforce through the Getting Started guide or read this complete Jira Salesforce Integration guide.

 

The Implementation Using Exalate

Once the Connection has been created, you need to configure the Sync Rules. 

 

These rules are Groovy-based scripts that control what information to send and receive between the 2 platforms.

 How to Sync Comment Threads and User Mentions in Comments between Jira and Salesforce A Jira Salesforce integration use case can be an interesting one, an amalgamation of business and technical teams.

The scripts you see are generated by default when the Connection has been created. So common fields like summary, description, comments, etc are already there and can be synchronized out-of-the-box.

Now, we need to edit them to accommodate our sync requirements. 

 

Jira: 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.collect {

comment ->

def matcher = comment.body =~ /\[~accountid:([\w:-]+)\]/

def newCommentBody = comment.body

matcher.each {

target = nodeHelper.getUser(it[1])?.email

newCommentBody = newCommentBody.replace(it[0],target)

}

comment.body = newCommentBody

comment

}

replica.resolution = issue.resolution

replica.status = issue.status

replica.parentId = issue.parentId

replica.priority = issue.priority

replica.attachments = issue.attachments

replica.project = issue.project

//Comment these lines out if you are interested in sending the full list of //versions and components of the source project.

replica.project.versions = []

replica.project.components = []

The Outcoming Sync script looks like this.

image3.png

Salesforce: Outgoing Sync

if(entity.entityType == "Case") {

replica.key = entity.Id

replica.summary = entity.Subject

replica.description = entity.Description

replica.attachments = entity.attachments

replica.Status = entity.Status

replica.comments = entity.comments.inject([]) { result, comment ->

def res = httpClient.get("/services/data/v54.0/query/?q=SELECT+Name+from+User+where+id=%27${comment.author.key}%27")

comment.body = nodeHelper.stripHtml(res.records.Name[0] + " commented: " + comment.body)

result += comment

def feedResponse = httpClient.getResponse("/services/data/v54.0/chatter/feed-elements/${comment.idStr}")

def js = new groovy.json.JsonSlurper()

def feedJson = groovy.json.JsonOutput.toJson(feedResponse.body)

feedResponse.body.capabilities.comments.page.items.collect {

res = httpClient.get("/services/data/v54.0/query/?q=SELECT+Name+from+User+where+id=%27${it.user.id}%27")

def c = new com.exalate.basic.domain.hubobject.v1.BasicHubComment()

c.body = res.records.Name[0] + " commented: " + it.body.text

c.id = it.id

result += c

}

result

}

}

The Outgoing Sync script looks like this.

 

image1.png

Salesforce: Incoming Sync

if(firstSync){

entity.entityType = "Case"

}

if(entity.entityType == "Case"){

entity.Subject = replica.summary

entity.Description = replica.description

entity.Origin = "Web"

entity.Status = "New"

entity.attachments = attachmentHelper.mergeAttachments(entity, replica)

def commentMap = [

"mathieu.lepoutre@idalko.com" : "0058d000004df3DAAQ",

"syed.majid.hassan@idalko.com" : "0057Q000006fOOOQA2"

]

def flag = 0

replica.addedComments.collect {

comment ->

def matcher = comment.body =~ /([a-zA-Z0-9._-]+@[a-zA-Z0-9._-]+\.[a-zA-Z0-9_-]+)/

def newCommentBody = comment.body

matcher.each {

newCommentBody = newCommentBody.replace(it[0],"")

def res = httpClient.post("/services/data/v54.0/chatter/feed-elements", \

"{\"body\":{\"messageSegments\":[{\"type\":\"Text\", \"text\":\"${newCommentBody} \" },{\"type\":\"Mention\", \"id\":\"${commentMap[it[0]]}\"}]},\"feedElementType\":\"FeedItem\",\"subjectId\":\"${entity.Id}\"}")

flag = 1

}

}

if (flag == 0)

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

}

The Incoming Sync script looks like this. 

 image2.png

Jira: Incoming Sync

There is no need to modify this since the default behavior is sufficient for our use case. 

 Output

 

So when you insert a threaded comment in Salesforce.

image4.png

All of them get reflected in Jira.

image5.pngAlso, user mentions in Jira will tag the corresponding user in Salesforce, if he/ she exists. 

 

So mention a user in Jira.

image8.pngAnd see the corresponding user being tagged in Salesforce.

image6.png 

Conclusion

In this article we just saw an example of an advanced comment sync between Jira and Salesforce. A lot of other advanced sync requirements can also be implemented using Exalate because of its support for Groovy-based scripts. 

 

Book a demo with Exalate to learn more about how it can be customized for your specific scenario. 

0/9000