Create Sub-task

Originally asked by Patrick Mennecke on 08 March 2021 (original question)


How can I create sub-tasks if the tasks come from ServiceNow but the patent ticket already exists in JIRA?

The tasks must be assigned correctly


Answer by Francis Martens (Exalate) on 10 March 2021

Hi Patrick Mennecke

You can create a subtask just by setting the right issue type and parentid

if (firstSync) {
   issue.typeName = "Sub-task"
   issue.parentId = <correct parent id>
}

Of course you need to find out what the right parent id is. Assume that you want to set the parent to the twin of a ServiceNow customercase ‘CR1234567’

You can use for this the getLocalIssueFromRemoteUrn

if (firstSync) {
   ...
   def targetParent = nodeHelper.getLocalIssueFromRemoteUrn("CR1234567")
   if (!targetParent) {
      // make sure that the parent is found, else bail out
      throw new Exception("Parent not found")
   }
   issue.parentId = targetParent.id
}

Of course that is not very dynamic.
So if you manage to have the parent in the replica, you can use that to find the twin parent

if (firstSync) {
   def targetParentURN = replica.customKeys.parentURN
   if (! targetParentURN) {
      // make sure that the parent is found, else bail out
      throw new Exception("No parent URN provided ...")
   }
   def targetParent = nodeHelper.getLocalIssueFromRemoteUrn(targetParentURN)
   if (! targetParent) {
      // make sure that the parent is found, else bail out
      throw new Exception("Parent not found")
   }
   issue.parentId = targetParent.id
}

Comments:

Karen Jennings commented on 25 April 2022

Francis Martens (Exalate)

How do you get the replica.customKeys.parentURN from ServiceNow? What does the ServiceNow outgoing script look like?

We are trying to sync Change Tasks from ServiceNow to Jira.

I can send the parent sys_id (parent Change of the Change Task) using the getReference node helper. I got that by hard coding the Change number in the script:

replica.parent = nodeHelper.getReference("change_request", "number" , "CHG0053092")?.sys_id

However when I try to map it to

replica.customKeys.parentURN = nodeHelper.getReference("change_request", "number" , "CHG0053092")?.sys_id

I get a null value.

What am I missing?

Answer by Karen Jennings on 16 May 2022

Update: I am able to get the Change Task (subtask) created in Jira by hard coding the parent issue ID in the ServiceNow outgoing script:

replica.parentID = "12345"

and using this in the Jira incoming script:

issue.parentId = replica.parentID

The issue now is how do we dynamically get the Jira parent ID from the parent Change in ServiceNow.

That information resides in a custom field called u_external_correlation_id on the parent Change in ServiceNow.

In trying to get that information, I have been looking at the ServiceNow API and updating the outgoing script to do an API call. However, I am now getting a Bad Gateway message when accessing Exalate, which I am sure is related to the outgoing script. Will submit a support ticket to get that cleared.

Please note there are separate connections created for Change and Change Task. I have also tried combining them into one connection but I have yet to get that to work to create Changes from Jira to ServiceNow.


Answer by Karen Jennings on 03 May 2022

Our ServiceNow outgoing script that gives us the parent Change is this:

if(entity.tableName == “change_task”) {
replica.key = entity.key
replica.summary = entity.short_description
replica.description = entity.description
replica.attachments = entity.attachments
replica.comments = entity.comments
replica.state = entity.state
replica.assignment_group = entity.assignment_group
replica.close_notes = entity.close_notes
replica.u_start_date = entity.start_date
replica.u_end_date = entity.end_date
replica.u_prod = entity.u_prod
// replica.parentid = parent.u_external_correlation_id
// replica.parentid = parent.entity.u_external_correlation_id
// replica.parent = nodeHelper.getReference(“change_request”, “number” , “CHG0053092”)?.sys_id
//replica.customKeys.parentURN = nodeHelper.getReference(“change_request”, “number” , “CHG0053092”)?.sys_id
// replica.customKeys.parentURN = entity.change_request
// replica.customKeys.parentURN= entity.customKeys.change_request?.value
//replica.parentId = change_request.u_external_correlation_id
//replica.parentId = nodeHelper.getTableByName(“change_request”, “u_external_correlation_id”)
replica.parentID = entity.change_request?.display_value
//replica.customKeys.parentURN = change_task.parent

As you can see, we tried several methods and the only one that gives us a value is replica.parentID = entity.change_request?.display_value

If I change replica.parentID to replica.customKeys.parentURN I get null.


Answer by Karen Jennings on 26 April 2022

I was able to get the ServiceNow parent issue key (number) to send over to Jira but getting the local issue now is where I get stuck.

if (firstSync) {
def targetParentURN = replica.parentID

[debug.info](http://debug.info)("targetParentURN is ${targetParentURN}") --I get the ServiceNow parent Change Number--
if (! targetParentURN) {
// make sure that the parent is found, else bail out
throw new Exception("No parent URN provided ...")
}
def targetParent = nodeHelper.getLocalIssueFromRemoteUrn(targetParentURN)
[debug.info](http://debug.info)("targetParent is ${targetParent}") I get [targetParent is null]--
if (! targetParent) {
// make sure that the parent is found, else bail out
throw new Exception("Parent not found")
}
issue.parentId = [targetParent.id](http://targetParent.id)
}

Looking at this documentation tells me the nodeHelper is correct.

https://docs.idalko.com/exalate/display/ED/getLocalIssueFromRemoteUrn

Why is targetParent null?

This is Jira Cloud


Comments:

Daniel Carvajal commented on 03 May 2022

Hi Karen Jennings

Can you share your SNOW outgoing script?

Cheers,

Daniel

Karen Jennings commented on 03 May 2022

Our ServiceNow outgoing script that gives us the parent Change is this:

if(entity.tableName == “change_task”) {
replica.key = entity.key
replica.summary = entity.short_description
replica.description = entity.description
replica.attachments = entity.attachments
replica.comments = entity.comments
replica.state = entity.state
replica.assignment_group = entity.assignment_group
replica.close_notes = entity.close_notes
replica.u_start_date = entity.start_date
replica.u_end_date = entity.end_date
replica.u_prod = entity.u_prod
// replica.parentid = parent.u_external_correlation_id
// replica.parentid = parent.entity.u_external_correlation_id
// replica.parent = nodeHelper.getReference(“change_request”, “number” , “CHG0053092”)?.sys_id
//replica.customKeys.parentURN = nodeHelper.getReference(“change_request”, “number” , “CHG0053092”)?.sys_id
// replica.customKeys.parentURN = entity.change_request
// replica.customKeys.parentURN= entity.customKeys.change_request?.value
//replica.parentId = change_request.u_external_correlation_id
//replica.parentId = nodeHelper.getTableByName(“change_request”, “u_external_correlation_id”)
replica.parentID = entity.change_request?.display_value
//replica.customKeys.parentURN = change_task.parent

As you can see, we tried several methods and the only one that gives us a value is replica.parentID = entity.change_request?.display_value

If I change replica.parentIDto replica.customKeys.parentURN I get null.

Karen Jennings commented on 03 May 2022

I also added this to the top of the ServiceNow outgoing script, the capture the parent change info:

def optionList = httpClient.get("/api/now/table/change_task?sysparm_display_value=all&sysparm_exclude_reference_link=true&sysparm_fields=change_request%2Ccorrelation_id&sysparm_limit=1")

Daniel Carvajal commented on 08 June 2022

We tested the following code snippet to work to sync from SNOW to Jira cloud and maintain the Change request/change task <> Parent/child relation

SNOW outgoing:

if(entity.tableName == "change_request") {
    replica.key            = entity.key
    replica.summary        = entity.short_description
    replica.description    = entity.description
    replica.attachments    = entity.attachments
    replica.comments       = entity.comments
    replica.state          = entity.state
    replica.assignment_group    = entity.assignment_group
    replica.close_notes        = entity.close_notes
    replica.u_start_date    = entity.start_date
    replica.u_end_date    = entity.end_date
    replica.u_prod      = entity.u_prod    
    replica.tableName = entity.tableName    
}
if(entity.tableName == "change_task") {
    replica.key            = entity.key
    replica.summary        = entity.short_description
    replica.description    = entity.description
    replica.attachments    = entity.attachments
    replica.comments       = entity.comments
    replica.state          = entity.state
    replica.assignment_group    = entity.assignment_group
    replica.close_notes        = entity.close_notes
    replica.u_start_date    = entity.start_date
    replica.u_end_date    = entity.end_date
    replica.u_prod      = entity.u_prod
   replica.parentID = entity.change_request?.display_value
   def var = entity.change_request?.display_value?.toString()
   replica.tableName = entity.tableName
   if(!syncRequest){
   def request = httpClient.get("/api/now/table/change_request?sysparm_query=number%3D$var&sysparm_limit=1")   
   
replica.changeRequest = request.result.find().sys_id
   }
} 

Jcloud Incoming(change the project key accordingly):

if(firstSync){
    if(replica.tableName == 'change_task'){
        if(replica.changeRequest == null){
            //possibly insert error
    return
        } else {
            issue.projectKey   = "KAN" 
            issue.typeName     = "Sub-task"
            issue.parentId     = syncHelper.getLocalIssueKeyFromRemoteId(replica.changeRequest, "changeRequest")?.idStr
        }
    } else {
        issue.projectKey   = "KAN" 
        issue.typeName     = nodeHelper.getIssueType(replica.type?.name, issue.projectKey)?.name ?: "Task"
    }