One to many sync with Jira and ADO

I would like to sync some Jira work items and Service Desk requests with Azure DevOps (ADO) using labels.

The label would indicate the ADO project and

The Jira work items would have a label like ADO-- to identify the destiny, preferably with a default
It would also have a dictionary to match codes with real boards

Examples:
For:

Project Dictionary {(DC, Domain Center), (IT, IT TEAM)}

Board Dictionary {(MK3, Marketing 3),(PRJ1,Project 1)}

label: ADO-DC-MK3

Would create a User Story in "Domain Center”\board\”Marketing 3”

label: ADO-IT-PRJ1

Would create a User Story in "IT TEAM”\board\”Project 1”

and by default, if a label only has one “-” it would associate to a project

Label: ADO-PRJ1

Creates a User Story in "Domain Center”\board\”Project 1”

In the ADO side, the User Stories would sync with a different label - “Jira-

Since Jira already uses codes in project, we don’t need a dictionary to translate.

Example
Label: Jira-CYB - Creates a Ticket in CYB Project

Label Jira-ISD - Creates a ticket in the ISD Project.

Hi @Vasco ,

Welcome to the community!

The use case you have described is quite doable via Exalate. So, in order to achieve this, let us consider that the Jira side is already sending out the correct payload. Then you would need the dictionaries and parsing logic in ADO Incoming script to achieve what you want. Although I do not have your exact setup to test, the following code should be quite close to the final product as it would look like on your side:

    def projectDict = [
        "DC": "Domain Center",
        "IT": "IT TEAM"
    ]
    
    // Board dictionary (for Area Path)
    def boardDict = [
        "MK3": "Marketing 3",
        "PRJ1": "Project 1"
    ]

if (firstSync) {
// Find ADO routing label
def adoLabel = replica.labels?.find { it.startsWith(“ADO-”) }

    if (adoLabel) {
        def parts = adoLabel.substring(4).split("-") // Remove "ADO-" prefix
        
        def targetProject = null
        def targetBoard = null
        
        if (parts.size() == 2) {
            // Format: ADO-PROJECT-BOARD
            def projectCode = parts[0]
            def boardCode = parts[1]
            
            targetProject = projectDict[projectCode] ?: projectCode
            targetBoard = boardDict[boardCode] ?: boardCode
            
        } else if (parts.size() == 1) {
            // Format: ADO-BOARD (use default project)
            def boardCode = parts[0]
            
            targetProject = projectDict["DC"] // Default to Domain Center
            targetBoard = boardDict[boardCode] ?: boardCode
        }
        
        // Set the project
        if (targetProject) {
            workItem.projectKey = targetProject
        }
        
        // Set work item type
        workItem.typeName = "User Story"
        
        // Set the Area Path (board)
        if (targetBoard) {
            workItem."Area Path" = "${targetProject}\\${targetBoard}"
        }
        
        // Add Jira reference label
        def jiraProjectKey = replica.key?.split("-")[0]
        if (jiraProjectKey) {
            workItem.labels = ["Jira-${jiraProjectKey}"]
        }
    } else {
        // No ADO label found - handle error or use defaults
        throw new Exception("No ADO routing label found. Please add a label like ADO-DC-MK3 or ADO-PRJ1")
    }
}

// Sync basic fields
workItem.summary = replica.summary
workItem.description = replica.description

Hopefully, this gets you started in the right direction.

Thanks
Majid

Hi Majid;
Thanks for your fast reply.
I did try to apply your code but I got the error:

No signature of method: com.exalate.basic.domain.hubobject.v1.BasicHubLabel.startsWith() is applicable for argument types: (String) values: [ADO-]

I believe that its’ related to the bellow line

def adoLabel = replica.labels?.find { it.startsWith(“ADO-”) }
(I changed the smart quotes to straight quotes)

I didn’t had the opportunity to study this language a bit deeper, but your expertise will be much appreciated.

BR
Vasco

Hi Vasco,

The quotes copied badly - actually, I formatted my code poorly, now that I look at it. But yes, you should replace them with normal quotes and this should compile.

Thanks
Majid