Jira Cloud issue edited trigger, how to reliably determine what was edited.

  • 27 January 2023
  • 1 reply
  • 143 views

Userlevel 1

This conversation is more of a “Howto” than a question. I haven’t found much in the Zapier community on how to filter based off of what was edited on an issue, so I thought it would be helpful to others. The below information has been tested on Jira Software Cloud, so I’m not sure how correct it is for Jira Server.

 

Introduction

Currently with Zapier’s platform, they only have three different triggers, An issue being created, an issue being created with JQL, and an issue being edited. With the “issue edited” trigger, there is no way to determine what was edited, and all that is returned is the full breadth of the ticket as if it was returned in JSON format from an API.

This makes the “issue edited” trigger almost useless without filters considering I don’t know of anybody that would want a zap to trigger every time some small change occurs on an issue. However, there is some stuff that we can do with this.

 

Workflow

The best way I have found to reliably get what was edited on a zap, is to:

  1. Use the “Issue Edited” zap trigger.
  2. Immediately after, filter for the state of the issue AFTER the edit you want to listen for. In my case I wanted to trigger when one issue was linked to another. So I filtered for: if the issue has a inward/outward linked issue, and what Project that issue was in. This will filter out the large majority of the triggers so that you aren’t using tasks. (Only downside to this really is when you are looking at your history, you get an obscene amount of triggers where it says “0 tasks used” and it makes it very hard to search through)
  3. Get changelog information from the JIRA API and filter based off of time when the issue was created.

 

The Jira API

Yes, Jira has an API that is extremely intuitive. Due to this, we can still determine what was most recently edited. If you didn’t notice in the initial trigger data there is a field called “expand” that lets you know what more information you can get from using the api.

URL:

Your URL will most likely be the URL of the issue, so in the initial trigger data, you can use “self” to get the issue link, and then you can add whatever you want to the end of it. In our case we can use the webhooks task to send a GET request and in the parameters we can put expand = changelog (this effectively edits the URL to add “?expand=changelog” at the end of the URL. You can learn more about expansions in the API here. The reason why we use the expansion and not the “/changelog” endpoint is because the “/changelog” endpoint is paginated, whereas the expansion returns all of the results.

Headers:

For the headers, all you really need is “Accept: application/json”

Authentication:

Thankfully, Jira allows the use of basic authentication with a Personal Access Token, so in the authentication step you can put <username>|<personal access token> and that will authenticate to the server even if your organization uses 2-factor authentication.

 

Response:

The response you get from sending an api request is a list of changes that look like this (There’s a little bit more data at the beginning that I’m not adding outside of the change list):

{
"id": "0000000",
"author": {
"self": "https://api.atlassian.com/ex/jira/<tenant_id>/rest/api/3/user?accountId=<user_account_id>",
"accountId": "<user_account_id>",
"emailAddress": "<user.name@domain.com>",
"avatarUrls": {
...
},
"displayName": "<User's Name>",
"active": true,
"timeZone": "<Time zone of user account>",
"accountType": "atlassian",
},
"created": "<time the edit was created (IMPORTANT!)>",
"items": [
{
"field": "<field_name>",
"fieldType": "<field_type>",
"from": "<value, if no value then null>",
"fromString": "<value description, if no value then null>",
"to": "<value it was changed to>",
"toString": "<value description>",
}
]
}

 

How I used this

Using the webhook task wasn’t good enough for me because I needed to be able to filter through a lot of changes to be able to determine what was the last link that occurred (hopefully the one that triggered this zap! So due to that, I used the python code step in Zapier to be able to do what I needed. Thankfully Zapier allows you to import requests, datetime, and more, and so you should be able to do what you need to.

 

Here’s what my code looks like to get what I need:

import requests
from requests.auth import HTTPBasicAuth
import json


# Add the appropriate information to variables and send the request. Note: input_data["self"] is the "self" field in the initial trigger data.
url = f'{input_data["self"]}?expand=changelog'
headers = {'Content-Type': 'application/json'}
auth = HTTPBasicAuth("my.email@domain.com", "mypersonalaccesstoken")
response = json.loads(requests.get(url, headers=headers, auth=auth).text)


# Get the last 10 entries of the changelog
changelog = response['changelog']['histories'][-10:]


# Copy the dictionary object so that we can loop through it, but make changes to changelog
temp_object = changelog.copy()


# Filter out every single changelog item where the field, and the value do not match what we want from the list.
for change in temp_object:
if "Link" not in change['items'][0]['field'] or not change['items'][0]['to'] or "<Project Key>" not in change['items'][0]['to']:
changelog.remove(change)


# Return the time of the latest change that fits our criteria.
return {"linked_time": changelog[-1]['created']}

Making sure that the last change returned was recent:

From here, we can use date.manipulation under the Format task to get the difference between now, and the returned time, to make sure that the latest change we filtered for was actually recent. To use the current time, we can type in a custom value of {{zap_meta_utc_iso}} inside the Format task which will give us the current time when running the zap. You can read more about getting the current time here.

 

That should be it! After that you can pretty much guarantee that what is being picked up from the trigger is the appropriate change.

NOTE: the reason why I am getting the last 10 entries in the changelog is because we can’t exactly determine if the user has made multiple changes within the time that it took to run the zap, but its also a good bet that they didn’t make 10+ changes within the time that the zap was triggered.


This post has been closed for comments. Please create a new post if you need help or have a question about this topic.

1 reply

Userlevel 1

NOTE:

I was just checking this and realized that with the JIRA API, the ?expand=changelog puts all of the changes at the most recent first, whereas the /changelog endpoint puts the oldest change first. This is important as I had to change my python code to get the first 10 entries, and then return the very first in the list.