The Exalate team will be on holiday for the coming days - returning Jan 4
Enjoy & stay safe

Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

In Jira Cloud we can create issue links to other issues in Jira and define the relationship between the different issues. This use case will revolve around picking up the issueLinks from Jira Cloud and transferring them over to the Azure DevOps side using a mapping:

In this example we will map two relationships from Jira to relationships in Azure DevOps. The starting point in Jira Cloud would be as follows:


And this would end up in Azure DevOps as the following:


In order to achieve this use case, the only thing that Jira has to do is to send out the issue links, and the parentId (for sub-tasks). This is achieved by using the following lines:


Code Block
languagegroovy
themeEmacs
titleJira Cloud Outgoing
collapsetrue
replica.linkedIssues = issue.issueLinks

replica.parentId       = issue.parentId



On the Azure DevOps side, you will need to add a parent-child relationship corresponding to the task→ sub-task relation in Jira. This is achieved with the following code snippet:

Code Block
languagegroovy
themeEmacs
titleAzure DevOps Incoming
collapsetrue
workItem.parentId = null
if (replica.parentId) {
   def localParent = syncHelper.getLocalIssueKeyFromRemoteId(replica.parentId.toLong())
   if (localParent) 
      workItem.parentId = localParent.id
}


The next part covers the link mapping and link creation on the Azure side. This is achieved by creating a mapping first, and then calling an endpoint to get the relevant links created in Azure DevOps. This can be done using the following snippet:

Code Block
languagegroovy
themeEmacs
titleAzure DevOps Incoming
collapsetrue
def linkTypeMapping = [
    "blocks": "System.LinkTypes.Dependency-Reverse",
    "relates to": "System.LinkTypes.Related"
]
def linkedIssues = replica.linkedIssues
if (linkedIssues) {
    replica.linkedIssues.each{
       def localParent = syncHelper.getLocalIssueKeyFromRemoteId(it.otherIssueId.toLong())
       if (!localParent?.id) { return; }
       localUrl = baseUrl + '/_apis/wit/workItems/' + localParent.id
     def createIterationBody = [
            [
                op: "test",
                path: "/rev",
                value: (int) res.value.size()
            ],
            [
                op:"add",
                path:"/relations/-",
                value: [
                    rel:linkTypeMapping[it.linkName],
                    url:localUrl,
                    attributes: [
                        comment:""
                    ]
                ]
            ]
        ]
        
        
def createIterationBodyStr = groovy.json.JsonOutput.toJson(createIterationBody)
        converter = scala.collection.JavaConverters;
        arrForScala = [new scala.Tuple2("Content-Type","application/json-patch+json")]
        scalaSeq = converter.asScalaIteratorConverter(arrForScala.iterator()).asScala().toSeq();
        createIterationBodyStr = groovy.json.JsonOutput.toJson(createIterationBody)
        def result = await(httpClient.azureClient.ws
            .url(baseUrl+"/${project}/_apis/wit/workitems/${workItem.id}?api-version=6.0")
            .addHttpHeaders(scalaSeq)
            .withAuth(token, token, play.api.libs.ws.WSAuthScheme$BASIC$.MODULE$)
            .withBody(play.api.libs.json.Json.parse(createIterationBodyStr), play.api.libs.ws.JsonBodyWritables$.MODULE$.writeableOf_JsValue)
            .withMethod("PATCH")
            .execute())
   
    }
}


The entire code for the Azure DevOps incoming side is attached here.


A full video demonstration of the issue can be viewed here:

View file
nameJira ADO IssueLinks mapping.mp4
height250