How to keep parent-child relationship between Azurenode and Jira

Originally asked by Michael Domingues on 13 May 2020 (original question)


How I can get the issue Links on the AzureDevops? I created an Epic, a task and I linked the Task as a Child of the Epic. but, I don’t know how to get that information in the script. I’d like to send that information to a Jira Cloud instance. My objective is transfer that information to Jira Cloud, in order to have the same hierarchy structure. I found documentation to get linkIssues between Jira Server instances (https://docs.idalko.com/exalate/display/ED/How\+to\+synchronize\+issue\+links\+on\+Jira\+Server). but it’s not working to my case. Could you help me with that?

Source: Azure DevOps


Answer by Juan Grases on 14 May 2020

To send that information from azure, you will do:

replica.parentId = issue.parentId

The more complex part happens in the Jira side incoming script. If you want to represent that info on issue links, first you will need to get the local issue linked with the parent work item from azure:

def localParentKey = nodeHelper.getLocalIssueKeyFromRemoteId(replica.parentId)

Then, you will want to create an issue link with it, something like this:

def localParentKey = nodeHelper.getLocalIssueKeyFromRemoteId(replica.parentId)
if(localParentKey){
  httpClient.post("/rest/api/3/issueLink", """{"outwardIssue": "${localParentKey.id}", "inwardIssue": "${issue.id}", "type": {"name": "Relates"}}""")
}

If instead of issue links, you want to use an epic link (assuming the parent issue is an epic in Jira):\

def localParentKey = nodeHelper.getLocalIssueKeyFromRemoteId(replica.parentId)
if(localParentKey){
  issue.customFields."Epic Link".value = localParentKey.urn
}

I haven’t tried this scripts yet, let me know how it goes.


Comments:

Michael Domingues commented on 14 May 2020

Epic link works perfectly.
but the link code not… I’m still trying

Now, on the Jira Cloud side, I’d like to put a Parent issue.
I created a issue of type History and a issue of type Task. I want the Task type to be a child of the issue History.
I tried using

issue.customFields."Parent".value = localParentKey.urn

but, it doesn’t work.

How I could do it?

Juan Grases commented on 14 May 2020

Do you have a custom field named “Parent” if so, which kind of custom field is? When you say the task to be a child of issue history, do you mean that task is a “Sub-task” issue type? In that case you might do:

def localParentKey = nodeHelper.getLocalIssueKeyFromRemoteId(replica.parentId)
if(localParentKey){
  issue.parentId = localParentKey.id
}

This is how you set parent ids to subtasks.

Michael Domingues commented on 14 May 2020

Yes, it’s about “sub-task”.
It’s working now.
Thank you

Harinder Singh commented on 08 September 2020

Hi Support this is what i need but below step is not working can you guys confirm on your side how to make this thing work?

def localParentKey = nodeHelper.getLocalIssueKeyFromRemoteId(replica.parentId)
if(localParentKey){
  httpClient.post("/rest/api/3/issueLink", """{"outwardIssue": "${localParentKey.id}", "inwardIssue": "${issue.id}", "type": {"name": "Relates"}}""")
}
Serhiy Onyshchenko commented on 19 July 2022

Hello, Harinder Singh ,
In case if it’s for Jira Cloud,
might I ask you to convert this script to:

def ISSUE_LINK_TYPE_NAME = "Relates"
def REMOTE_ISSUE_ID = replica. ...  

store(issue)
def localParentKey = nodeHelper.getLocalIssueKeyFromRemoteId(REMOTE_ISSUE_ID)
if(localParentKey){
  def jc = new JiraClient(httpClient)
  def body = groovy.json.JsonOutput.toJson([outwardIssue:localParentKey.id.toString(), inwardIssue:issue.id.toString(), type:[name:ISSUE_LINK_TYPE_NAME]])
  def js = new groovy.json.JsonSlurper()
  jc.http(             "POST",      "/rest/api/3/issueLink",              [:],
             body,      ["Content-Type":["application/json"]]
  ) { response ->  
    if(response.code >= 400) { debug.error("POST /rest/api/3/issueLink failed for body $body: ${response.code} ${response.body}") }         else {           def bodyJson = js.parseText(response.body)           bodyJson         }  }
}

In case if it’s for Jira on-prem, you may do

def ISSUE_LINK_TYPE_NAME = "Relates"
def REMOTE_ISSUE_ID = replica. ... 

def issueLinkManager = com.atlassian.jira.component.ComponentAccessor.getOSGiComponentInstanceOfType(com.atlassian.jira.issue.link.IssueLinkManager.class)
def issueLinkTypeManager = com.atlassian.jira.component.ComponentAccessor.getOSGiComponentInstanceOfType(com.atlassian.jira.issue.link.IssueLinkTypeManager.class)
def nodeService = com.atlassian.jira.component.ComponentAccessor.getOSGiComponentInstanceOfType(com.exalate.api.node.INodeService.class)
def proxyUser = nodeService.proxyUser
def linkTypeId = issueLinkTypeManager.issueLinkTypes.find { it.name == ISSUE_LINK_TYPE_NAME }
Epic.CreateIssue.create(
                    replica,
                    issue,
                    syncRequest,
                    nodeHelper,
                    issueBeforeScript,
                    remoteReplica,
                    traces,
                    blobMetadataList) {
  def localParentKey = nodeHelper.getLocalIssueKeyFromRemoteId(replica.parentId)
  if(localParentKey){
    issueLinkManager.createIssueLink(issue.id as Long, localParentKey.id as Long, linkTypeId, 1, proxyUser)
  }
}

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

Gabriel Rota commented on 16 April 2024

Thank you very much Serhiy Onyshchenkofor the Jira Cloud part.

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