# Sync Jira Sub-tasks to Azure DevOps as Parent–Child Work Items

**URL:** <https://community.exalate.com/t/sync-jira-sub-tasks-to-azure-devops-as-parent-child-work-items/8339>\
**Category:** Script Library\
**Tags:** jira-cloud, azure-devops, sub-task\
**Created:** [August 28, 2026, 10:12pm UTC](https://community.exalate.com/t/sync-jira-sub-tasks-to-azure-devops-as-parent-child-work-items/8339 "2026-08-28T22:12:51Z")\
**Posts on this page:** 1\
**Page:** 1

<div class="post-metadata">

**Author:** ![Javier](https://dub1.discourse-cdn.com/flex018/user_avatar/community.exalate.com/javier/32/338_2.png) [@Javier](https://community.exalate.com/u/Javier)\
**Post date:** [August 28, 2026, 10:12pm UTC](https://community.exalate.com/t/sync-jira-sub-tasks-to-azure-devops-as-parent-child-work-items/8339/1 "2026-08-28T22:12:51Z")

</div>

This script allows you to preserve the Jira parent/sub-task hierarchy when synchronizing issues from Jira to Azure DevOps.

For example:

```auto
Jira Azure DevOps

PROJ-100 Task → User Story 123
   └─ PROJ-101 → └─ Task 124
      Sub-task Child

```

The Jira sub-task’s parent is sent through the replica, and Exalate resolves the corresponding synchronized Azure DevOps work item before assigning it as the parent.

* * *

## Script Overview

On the Jira side, we include the issue’s `parentId` in the replica:

```auto
replica.parentId = issue.parentId

```

On the Azure DevOps side, we use:

```auto
syncHelper.getLocalIssueKeyFromRemoteId()

```

to find the Azure DevOps work item that corresponds to the Jira parent.

* * *

## Final Solution

## Jira Outgoing Sync

Add the following to the Jira outgoing sync:

```auto
replica.parentId = issue.parentId

```

For regular Jira issues without a parent, `parentId` will simply be empty.

## Azure DevOps Incoming Sync

On the Azure DevOps side, resolve the Jira parent to its corresponding local work item:

```auto
//
if (replica.parentId) {

    def localParent = syncHelper.getLocalIssueKeyFromRemoteId(
      replica.parentId.toLong()
    )

    if (localParent) {
        workItem.parentId = localParent.id
    }
}

```

A complete example could look like:

```auto
if (firstSync) {

    def typeMap = [
        "Task" : "User Story",
        "Sub-task": "Task"
    ]

    workItem.typeName =
        nodeHelper.getIssueType(typeMap[replica.type?.name])?.name ?: "Task"

    workItem.summary = replica.summary
}

workItem.description = replica.description

// Jira Parent -> Azure DevOps Parent
if (replica.parentId) {

    def localParent = syncHelper.getLocalIssueKeyFromRemoteId(
        replica.parentId.toLong()
    )

    if (localParent) {
        workItem.parentId = localParent.id
    }
}

```

* * *

## Notes

- The Jira parent issue should already be synchronized with Azure DevOps before the sub-task is synchronized.

* * *

## Version

5.37.0
