Published on 5 May 2022 by Andrew Owen (6 minutes)
In this article, I’ll describe a solution to simplify the process of creating release notes in MadCap Flare from a Jira query. Jira is a popular issue tracking platform from Atlassian. But this approach can also be adapted to any other platform that can export issues in XML format and any XML-based doc tool.
We’ll be running a script from the command line to fetch the information we require from Jira, process it, and output a Flare document. To perform the fetch we’ll use a tool called cURL (Client URL). This should already be installed as part of your operating system unless you’re using a version of Windows earlier than Windows 10.
The processing is done using an XSLT (eXtensible Stylesheet Language Transformations) parser. Microsoft provides MSXSL.EXE as part of Microsoft Core XML Services (MSXML) 6.0. However, this only supports XSLT 1.0, so I recommend using Saxon, which has full XSLT 3.0 support.
You’ll probably need to install an XSLT processor. This used to be complicated, but now you can do it with node.js:
npm install -g saxon-js
npm install -g xslt3
You should probably still check with your company’s IT policy before proceeding. You may need to ask your IT department to install the software for you.
Saxon applies the instructions in an XSL file to transform the raw XML fetched by cURL into a Flare document with the required content.
You’ll need to create a Jira API key for the script:
Jira2Flare
and click Create.Note, you should only use this API key within your script. The script should be stored where only you can access it. If you believe your security has been compromised, in Jira navigate to Create and manage API tokens, locate the token and click Revoke to deactivate it.
You’ll also need the Jira query string. Explaining Jira queries is beyond the scope of this article, so I’ll assume you already have a search query that returns the release notes for a specific version of the software:
%
) with a double per cent sign (%%
).fixversion
string with %fixversion%
(with single per cent signs)."
) at the start and end of the string.The Export XML option formats the output as an RSS feed. This determines the structure of the XML file, but you don’t really need to know anything about RSS for the purposes of this article.
In the sample script, I’m assuming you have a custom Jira field with the name Release Notes
. If it’s called something else you can change the script as required. If there is no equivalent field to notify you which tickets should be included in a release note, you should ask your Jira administrator to create one.
Typically, releases in Jira are identified by a fixversion value. We can create a Windows script that takes this value as input and downloads the query results. Paste the following into a text editor and save it as jira2flare.cmd
:
@echo off
echo Please enter a fix version:
set /p fixversion=""
cls
curl -o input.xml -u user@example.com:APIkey "Jira query with the % charcters escaped as %% and the fixversion entered as %fixversion%"
Transform input.xml j2f.xsl > output.html
Replace user@example.com
with your email address, APIkey
with your API key, and replace the Jira query string with the one from your text editor.
The last line of the script performs the transform. We’ll come to that in a moment. Before you do the transform, you should verify that the cURL command is working. If all the parameters are correct, a file called input.xml
is created.
Paste the following into a text editor and save it as j2f.xsl in the same folder where you saved jira2flare.cmd
:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes" />
<xsl:strip-space elements="*" />
<xsl:template match="/">
<html xmlns:MadCap="http://www.madcapsoftware.com/Schemas/MadCap.xsd" MadCap:onlyLocalStylesheets="True">
<head>
<link rel="stylesheet" type="text/css" href="../Resources/Stylesheets/yourstyles.css" />
</head>
<body>
<h1>Release Notes</h1>
<table border="1">
<tr>
<th>Modules</th>
<th>Summary</th>
<th>Ticket</th>
<th>Category</th>
<th>Fix Versions</th>
</tr>
<xsl:for-each select="rss/channel/item/customfields/customfield">
<xsl:if test="customfieldname[text()='Release Notes']">
<tr>
<td>
<xsl:value-of select="../customfield/customfieldname[text()='Modules']/../customfieldvalues/customfieldvalue" />
</td>
<td>
<xsl:value-of select="customfieldvalues/customfieldvalue" disable-output-escaping="yes" />
</td>
<td>
<xsl:value-of select="../../key" />
</td>
<td>
<xsl:value-of select="../customfield/customfieldname[text()='Category']/../customfieldvalues/customfieldvalue" />
</td>
<td>
<xsl:value-of select="../../fixVersion" />
</td>
</tr>
</xsl:if>
</xsl:for-each>
</table>
</body>
</html>
</xsl:template>
</xsl:stylesheet>
The XSL file determines which information from the XML file (the Jira query) is included in the Flare document and how it is formatted. You can change this by editing the XSL file. In this example we want the Modules, Summary, Ticket, Category and Fix Versions.
Here’s a brief summary of what this transform file is instructing the XSLT processor to do:
The values in the XSL tags in the table are instructions to the XSLT processor on how to navigate the source XML file. If you want to learn more about transforming XML using XSLT, w3schools provides an introduction.
Now when you run the jira2flare.cmd
script, in addition to the input.xml
file you should get an output.html
file that you can open directly in Flare.
One important thing to keep in mind is that if you normally edit your release notes in Flare, with this process you should be making your changes in Jira. This has the twofold benefit that reviews can be done in Jira, and your published release notes will match your tickets.
XSL Transformations are a powerful tool for converting XML documents from one form into another. Indeed, we have barely scratched the surface of what’s possible. If you want to take things to the next level, you can talk to your dev ops team about automating the process. But hopefully what you’ve learned here will help speed up your release note workflow.
So, automation. Here’s a sample GitHub action:
name: RSS to Flare
on:
workflow_displatch
jobs:
rss2flare:
runs-on: ubuntu-latest
permissions:
contents: write
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 20
- shell: bash
env:
APIKEY: ${{ secrets.JIRA_API_KEY }}
FIXVERSION: ${{ vars.FIXVERSION }}
run: |
curl -o input.xml -u user.name@example.com:$APIKEY "<jira query including $FIXVERSION>"
- name: install Saxon and transform XML
run: |
npm install -g saxon-js
npm install -g xslt3
xslt3 -s:input.xml -xsl:rss2falre.xsl -o:output.html
- name: check for changes
id: changes
run |
git fetch origin main
echo "result=$(git diff -quiet origin/${{ github.base_ref }} ${{ github.sha }} - ./ || echo 'changes-found')" > $GITHUB_OUTPUT
continue-on-error: true
- name: No changes found
if: steps.changes.outputs.result != 'changes-found'
run: echo "No changes found in the '$({ env.working-directory })' folder in comparison to the 'main' branch. Skipping commit."
- name: Commit files
if: steps.changes.outputs.result == 'changes-found"
run: |
git config --local user.email "github-actions@users.noreply-github.com"
git config --local user.name "github-actions"
git add
git commit -a -m "Commit changes"
- name: Push changes
if: steps.changes.outputs.result == 'changes-found'
run: git push origin main
Image: Original by Danmeil Korpai.