Automate Jira releases from Azure DevOps pipelines and save 1 hour per day

Published on February 07, 2021

My team uses Jira as a project management tool and we use the “Releases” feature to audit our releases and to update our customers.

Atlassian provides a UI to create releases on Jira but we wanted to automate these types of things as much as possible to maintain our level of continuous delivery.

If you use Node.js and Azure devops you can use Semantic Release to create the release in Jira. I had some trouble figuring out the Jira key format and wanted to share that bit with you. Otherwise the plugin does all the work!

We save an estimated 1 hour per day depending on how many releases we create in a day. Usually 4-5 releases.

By automating a process like this you know it will always be accurate (and not forgotten about)!

Setup Semantic Release

So you need to have Semantic release working. I’ve described how to setup semantic release for your NodeJs project in this article. See the “Bumping versions based on commit message” section.

It’s helpful to have semantic versioning also. This creates release notes that are generally readable and consistent.

Add the jira releases package

Once you have semantic release configured and running you can add the plugin package to allow us to integrate with Jira.

yarn add -D semantic-release-jira-releases

Configure the plugin

Now we need to add to the semantic release configuration for the jira releases plugin to describe our project

 "release": {
        "plugins": [

                    "projectId": "PROJ",
                    "releaseNameTemplate": "v${version}",
                    "jiraHost": "",
                    "ticketPrefixes": [
                    "releaseDescriptionTemplate": "<%= notes %> ",
                    "released": false

The critical properties here are the project id, the jira host and the ticket prefix. The other settings are optional and suit my needs but yours might be different. You can see a description of the settings on the github page.

Releases description is a bit messy because we use Markdown text but Jira Releases doesn’t support markdown. Even if the format is difficult to read, it does at least provide the list of items in the release which can be edited later.

Setting “released” to false means we can push the button on Jira later when our PM has reviewed the work and wants to kick off automation that sends an email to our customers.

Create a jira api key

You need to create an api key on Jira. The api keys come from your account page. At the moment this is Atlassian might change the specific page in the future but it should always be on your id.atlassian account page.

Create a key on there and copy it to a notepad or similar.

It’s important to note that the key we need to supply for the jira releases plugin uses a base64 encoded version of the jira api key.

You must base64 encode the string of your username and the api key separated with a ”:“. It probably looks like this.

Encode this from a file using cat myfile.txt | openssl base64 | tr -d '\n' | pbcopy.

I used nodejs to encode my key. So that’s an option for you also.

To base64 encode on NodeJS use this

const base64String = Buffer.from(


You can test your key by using curl

curl -v -H "Authorization: Basic BASE64_ENCODED_KEY"

This should not return a 401

Inject JIRA_AUTH pipeline variable

Ok so this will depend on how you set up your CI pipeline but it will be somewhere in the “Library” on Azure Devops. I called mine JiraAuthToken.

Now add this library variable as an env var to an Azure Devops script where you call semantic release.

- script: |
    npx semantic-release
  displayName: 'Perform semantic release'
    GH_TOKEN: $(GithubToken)
    JIRA_AUTH: $(JiraAuthToken)


That’s it! you should be able to run the pipeline and it will ping Jira to create a release.

The plugin will scan any commit messages on the branch that semantic release is running on. It will detect Jira ticket numbers and set the release version on the tickets in Jira. Then it will create a new release and will add all those tickets to the release.

Thanks so much to the plugin author! It saves my team roughly 1 hour a day updating releases in Jira.

Hit me up on Twitter if you have any questions!

Darragh ORiordan

Hi! I'm Darragh ORiordan.

I live and work in Sydney, Australia building and supporting happy teams that create high quality software for the web.

I also make tools for busy developers! Do you have a new M1 Mac to setup? Have you ever spent a week getting your dev environment just right?

My Universal DevShell tooling will save you 30+ hours of configuring your Windows or Mac dev environment with all the best, modern shell and dev tools.

Get DevShell here: ✨

Read more articles like this one...

List of article summaries


Extract user profile attributes from an Azure ADB2C tenant using the Microsoft Graph API

I had to retrieve a list of users from an Azure Active Directory B2C instance today. I thought I could just go through the Azure UI but that’s limited to short pages of data and limited attributes.

There is a CSV export provided on the UI but you won’t get the required identity objects in the csv output if you need a user’s signin email address.

I had to use the Microsoft Graph Api to get what I needed. This is a bit hacky but it does the trick!


Force restart your Azure App service site and host

Sometimes your Azure App service host will need to be restarted. You can do this but it’s hidden away in the Azure resource manager site. Here’s how to find it!


Scheduling a feature toggle using no-code with Azure Logic Apps

I use launch darkly to toggle features on an app. There is one third-party dependency that has regular scheduled maintenance and I need to toggle the feature on and off on schedule.

Launch Darkly has built in scheduling to handle this scenario but you have to be on the enterprise plan to use it. The enterprise plan is too expensive to upgrade to for scheduling alone so I needed to find a different way to automate this.


Avoid rebuild of React App in every CI stage

If you have a react app you can use env vars like REACT_APP_MY_ENV_VAR in your application and React will automatically pull them in to your app when you build the production application.

This is very useful but if you have variables that change for each environment and your application build takes a long time, you might want to avoid building unnecessarily in CI. For example you might have a QA environment and a Staging environment that have different configuration.

We type-check our code on each build and that was taking 5 minutes+ to build each environment so we had to make it faster. We changed our app from using REACT_APP env vars to using a configuration file that we could quickly write to using CI.

Our CI system is Azure DevOops so the CI scripts here are specifically for Azure DevOps but they apply to most CI systems with small changes.

The real work happens in a Node.js script that would work anywhere.