Azure DevOps pipeline → update a rich-text table in multiple existing Jira issues using Exalate

Hi,

I’m looking for some advice on whether Exalate can support an Azure DevOps → Jira integration that is slightly different from the usual one-to-one work item synchronization.

What we’re trying to achieve

We have an Android build pipeline running in Azure DevOps.

When the pipeline creates a new APK, we want to update a custom Build information field (customfield_1234) in all Jira issues related to that build.

The purpose is simple: testers looking at a Jira ticket should be able to see the latest Android build containing that change and download it.

Azure DevOps is the source of the update, and this is one-way only: Azure DevOps → Jira.

Information produced by the pipeline

For each build, the pipeline already determines:

  • The affected Jira issue keys, for example JIR-123, JIR-124, JIR-125
  • Build name, for example 1.2.0-5678
  • A link to the APK in Azure Artifacts
  • Environment, for example Development, Integration, or Production

The pipeline already contains the logic for identifying which Jira issues are associated with the build.

Updating the Jira field

Each affected Jira issue has a rich-text custom field called Build information (customfield_1234).

For the purposes of this question, assume that this field contains a single table such as:

Environment Build
Development 1.2.0-5677
Integration 1.2.0-5676
Production 1.2.0-5677

If a new build is generated for Integration, for example:

  • Build: 1.2.0-5678
  • Environment: Integration
  • APK: https://…

we want to update only the Integration row in each affected Jira issue.

The build name in the second column should also be a hyperlink to the APK.

If the Integration row doesn’t already exist, it should be added. If the field/table doesn’t exist yet, it should be created.

The current implementation already does this successfully by reading customfield_1234 through Jira’s REST API, manipulating its Atlassian Document Format JSON, and writing the updated value back.

The complication: we don’t use Azure DevOps work items

Our development teams use Jira for work tracking, not Azure DevOps Boards.

Therefore, there isn’t an Azure DevOps work item corresponding to each Jira issue.

The event we effectively want to process is a pipeline/build run, and one build can apply to multiple existing Jira issues.

For example:

Azure pipeline

  |

  | Build 1.2.0-5678

  | Environment: Integration

  |

  +--> JIR-123

  +--> JIR-124

  +--> JIR-125

Possible Exalate approach

One option we’ve considered is having the pipeline create an Azure DevOps work item representing the build event, with information along these lines:

{

“ticketIds”: [

"JIR-123",

"JIR-124",

"JIR-125"

],

“buildName”: “1.2.0-5678”,

“buildLink”: “https://…”,

“environment”: “Integration”

}

Exalate would then somehow need to use that information to update the existing Jira issues listed in ticketIds.

Once processed, the Azure DevOps work item could simply be marked as completed.

We’re not committed to this design. It’s just one possible way we thought of providing the pipeline-generated information to Exalate.

Questions

What we’d like to understand is:

  1. Can Exalate use one Azure DevOps work item/event to update multiple existing Jira issues?
  2. Can the list of target Jira issues be determined dynamically from Jira issue keys supplied in an Azure DevOps field, rather than having a predefined one-to-one Exalate relationship?
  3. On the Jira side, can an Exalate script read the existing value of a rich-text custom field, modify it (by updating the row or creating a new one) of an Atlassian Document Format table, and save the updated field?
  4. If this architecture doesn’t fit the way Exalate is intended to work, is there a better Exalate-supported pattern for passing pipeline-generated information to multiple existing Jira issues when there are no corresponding Azure DevOps work items?

Our main requirement is essentially:

Pipeline produces build → pipeline identifies Jira issues → latest build for an environment is added/updated in the Build information table of each Jira issue.

We currently achieve this by calling Jira’s REST API directly from the pipeline, but we’re investigating Exalate so that we don’t have to manage Jira API credentials within our Azure DevOps pipeline. That aligns with our internal preference for centrally managed integrations rather than independently created API credentials.

Any advice on whether this is possible with Exalate, and what the recommended architecture would be, would be greatly appreciated.

Thanks!

Great questions! Here’s a breakdown of what’s possible with Exalate for your scenario, based on current documentation and best practices:

  1. Can Exalate use one Azure DevOps work item/event to update multiple existing Jira issues?

    Exalate is primarily designed for synchronizing items between platforms on a one-to-one basis (e.g., one Azure DevOps work item to one Jira issue). However, with Script Mode, you can implement custom logic in the sync scripts. While Exalate doesn’t natively support updating multiple Jira issues from a single Azure DevOps work item in a single transaction, you can use scripting to trigger updates on multiple issues by leveraging Jira’s REST API from within the sync script. This approach requires careful handling and is considered an advanced customization.

    Learn more about Script Mode and custom sync logic.

  2. Can the list of target Jira issues be determined dynamically from Jira issue keys supplied in an Azure DevOps field, rather than having a predefined one-to-one Exalate relationship?

    Yes, in Script Mode, you can parse a custom field (e.g., a JSON array of Jira issue keys) from the Azure DevOps work item and use that information to identify which Jira issues to update. You’d need to write a sync script that reads this field and then, using Jira’s REST API, updates each referenced issue. This is not out-of-the-box functionality but is achievable with custom scripting.

    See how to use custom fields and scripting in Exalate.

  3. On the Jira side, can an Exalate script read the existing value of a rich-text custom field, modify it (by updating the row or creating a new one) of an Atlassian Document Format table, and save the updated field?

    Exalate scripts can access and update custom fields, including rich-text fields. However, manipulating Atlassian Document Format (ADF) JSON within a sync script is complex and requires you to handle the JSON structure directly. You can read the current value, parse the ADF JSON, modify the table as needed, and write it back. This is feasible but requires advanced scripting and a good understanding of ADF.

    More on updating custom fields with Exalate.

  4. Is there a better Exalate-supported pattern for passing pipeline-generated information to multiple existing Jira issues when there are no corresponding Azure DevOps work items?

    Exalate is optimized for item-to-item synchronization. Your proposed approach—creating a “build event” work item in Azure DevOps and using it as the trigger for updates—is a reasonable workaround. Alternatively, you could consider using Exalate’s Bulk Connect to establish relationships, but this is typically for initial setup rather than ongoing dynamic updates.

    If your main goal is to avoid managing Jira API credentials in the pipeline, Exalate can centralize integration logic and credentials. However, the multi-issue update pattern will require custom scripting and possibly calling Jira’s REST API from within the sync script.

Summary:

  • Exalate can support your scenario with advanced scripting in Script Mode, but it’s not a native, out-of-the-box feature.
  • You’ll need to write custom sync scripts that parse your Azure DevOps work item, extract the list of Jira issues, and update each one’s custom field—potentially by invoking Jira’s REST API from within the script.
  • Manipulating ADF for rich-text fields is possible but requires careful handling.

For more details and script examples, check out the Script Mode documentation and custom field handling.

If you need help with specific script examples or want to discuss the architecture further, let me know!