Jira Automation: how to read the previous state of an issue?
Asked by Christian Schneider:

Dear community,

I would like to now the *previous state* of an issue within a Jira Automation.

I can get the change history of an issue via web request:

![1.png](https://community.atlassian.com/t5/image/serverpage/image-id/330415iDB5EFD31A63F0AEA/image-size/large?v=v2&px=999 "1.png")

I then read the response into a variable by **{{webhookResponse.body.changelog.histories.items}}**.

There are all the changes, which have been done to an issue.

**Question** : how do I parse it down to the *previous state* of the issue?

I tried to follow this approach by [@Erin Quick-Laughlin](/t5/user/viewprofilepage/user-id/4299733), but I am very much struggling with the {{smart values}}.

<https://community.atlassian.com/t5/Automation-questions/Re-Re-How-to-parse-through-an-json-array-where-field-na/qaq-p/2297738/comment-id/6353#M6353>

I have tried this, but get an empty audit log back:

```
{{#webhookResponse.body.changelog.histories.items}} {{#if(equals(field, "status"))}} {{fromString}} {{/}} {{/}}
```

Any help is very much appreciated.

Chris


Answers:
author: Bill Sheboy
body: Hi [@Christian Schneider](/t5/user/viewprofilepage/user-id/4404092)

Short answer: in my opinion, there is no simple / elegant way to do this using the REST API functions in a rule, and saving the prior status in a custom field may be easier to implement and maintain.

More information...

The changelog for an issue could be quite long, and so you may not find your status field in the first 100 records returned. And so paging to repeatedly call the REST API may be required, increasing the rule complexity...and reducing the chances of success.

Let's assume the rule trigger is *issue transitioned*, and so we can experiment and increase the chances of finding at least one match to the status field in the histories.

Next, rules have problems processing lists-within-lists inside of iterators. In this case, the histories are a list and so are histories.items. Inside the iterator, the fields will not resolve correctly when conditional filtering is used: they collapse to *null*. Noting the earlier post you linked-to for your question, that is why I suggested using inline-iteration and the match() function.

Thus one possible workaround for this is to flatten the structure into a known, delimited format; split to a list; and then use match...returning only the first record. That will be the one with the prior status id information in the "from" attribute.

Kind regards,  
Bill

comments: author: Bill Sheboy
body: Here is a follow-up example with that workaround...assuming the answer is in the current response for the Send Web Request action.

* create variable:
  * name: varHistory
  * smart value:

```
{{#webhookResponse.body.changelog.histories}}field:{{items.field}}@@@{{items.from}}~~{{/}}
```

That would produce a delimited, text string like this:

```
field:status@@@3~~field:Fix Version@@@null~~field:status@@@10003~~and so on...
```

* to parse out the status histories' "from" value with the status id, use this expression:

```
{{varHistory.split("~~").match("field:status@@@(.*)")}}
```

* and you want the most recent one, which should be the first in the list:

```
{{varHistory.split("~~").match("field:status@@@(.*)").first}}
```


author: Christian Schneider
body: Dear [@Bill Sheboy](/t5/user/viewprofilepage/user-id/1685313)

Thank you very much for your input. Up until now, I did not unterstand the **.split** , **.match** and **.first**, but I am a big fan of regex. :-)

I very much value your inputs about the changelog. As it seems, the webresponse is ordered in a descending way -\> newest entries come first. The webresponse from my current test ticket has 4000+ lines and I can still find all state-changes. I am confident, that the newest one should be available anyway, but I will try to implement a default behaviour, if no previous state could be found. (Trigger for my automation will be "comment created".)

My integration provider suggested a solution using **.substringBetween** to parse the webrequest response.

All your inputs got me going and I tried many different things.

#### Regex to get the state-change history entries {#toc-hId-346737714}

To get a list of all state changes from the history, I found this:

```
{{response.match("((?=\{field=status)\{field=status, fieldtype=jira, fieldId=status, from=\d*, fromString=(([\w\s]*)|(\w)*), to=\d*, toString=(([\w\s]*)|(\w)*)\})")}}
```

This will result in something like this:
> {field=status, fieldtype=jira, fieldId=status, from=3, fromString=In Progress, to=10006, toString=Warten auf Kunden}, {field=status, fieldtype=jira, fieldId=status, from=10006, fromString=Warten auf Kunden, to=3, toString=In Progress}, {field=status, fieldtype=jira, fieldId=status, from=10005, fromString=Pendent, to=10006, toString=Warten auf Kunden}, {field=status, fieldtype=jira, fieldId=status, from=10016, fromString=Selected for Development, to=10005, toString=Pendent}, {field=status, fieldtype=jira, fieldId=status, from=10004, fromString=in Vorbereitung, to=10016, toString=Selected for Development}, {field=status, fieldtype=jira, fieldId=status, from=10003, fromString=Backlog, to=10004, toString=in Vorbereitung}, {field=status, fieldtype=jira, fieldId=status, from=10016, fromString=Selected for Development, to=10003, toString=Backlog}, {field=status, fieldtype=jira, fieldId=status, from=10003, fromString=Backlog, to=10016, toString=Selected for Development}

by adding the **.first**, I can reduce it to the newest entry.

![2.png](https://community.atlassian.com/t5/image/serverpage/image-id/331058iBE00F7B8D0922A4C/image-size/large?v=v2&px=999 "2.png")

Then, I would have to use **.split** and **.match** to read the "from=" or "fromString".

Downsides are...

* ... the big, long regex. It is designed for your state-names. (-\> one word or several words with spaces) and
* ... I have to use several steps with .match and .split to get the final result.

#### Regex to get the newest from stateId {#toc-hId--1460716749}

I then modified my approach a little bit.

This line directly provides the list of all from-status from all state-changes. (newest first)

```
{{response.match("((?<=\{field=status, fieldtype=jira, fieldId=status, from=)\d*)")}}
```

Again, by adding the **.first**, I get the ID I need directly into a variable.

```
{{response.match("((?<=\{field=status, fieldtype=jira, fieldId=status, from=)\d*)").first}}
```

![1.png](https://community.atlassian.com/t5/image/serverpage/image-id/331057i98BE86C8AD2D9873/image-size/large?v=v2&px=999 "1.png")

The duration of the processing time is approx. 3-4 seconds.

Looking forward to your feedback on this solution.

Chris

EDIT: the original web response is a JSON. It would be so much easier, if the {{webhookResponse.body}} would be a JSON-object as well. Is there a way to read the response as JSON?


author: Bill Sheboy
body: Thanks for your extra analysis, Christian!

Answering your last question, first...no, there is no way to read *all possible* responses as JSON. I recall there is an open suggestion to add a text function for rules to correctly interpret as JSON, allowing dereferencing by attributes at all levels / structures.

Next regarding use of more advanced, complicated regular expressions...the [documentation states this](https://support.atlassian.com/cloud-automation/docs/jira-smart-values-text-fields/#match--), with emphasis added by me:
> The underlying implementation **is based on** Java's Pattern class and uses Matcher.find() to find matches.

I have not found stated what is / is not supported in regular expressions for rules. Several community posts indicate expressions that work with other regular expression parsing tools do not work the same in automation rules. This can be caused by the parsing order, particularly when escaping characters is used. (One workaround for that is to store the expression in a created variable first, and then use it in the match() function.)

I recommend using the simplest regular expression that can possibly work, testing, and incrementally adding to handle edge cases. And if you have something that works, save that expression / rule, before modifying to enhance it.

Regarding the performance, I suspect at least 1 second of that time is for the Send Web Request call. And I have observed both complicated regular expressions and large text strings adding to rule run time. I cannot tell from your question if you are using Jira Cloud, Server, or Data Center. If Cloud, I have seen rule performance be inconsistent, even for trivially simple rules.

Perhaps try removing rule steps to isolate where the time is going, and then trying to improve those.


author: Arkadiusz Inglot
body: Hi,

I see two another solutions which may be helpful:

A) Create hidden custom fields and put there your status names: <https://confluence.atlassian.com/jirakb/how-to-transition-to-the-previous-status-of-an-issue-using-automation-rules-in-jira-1236599919.html>

B) Depending on complexity of your workflow you can rename all transitions to make the name uniques between statuses. You can create a combined Lookup Table inside automation rule with propper mappings as you will have transition names that defines "from" and "to" statuses.

This is more complex solution and it will not work if you want tyo globalise that rule across projects/workflows.

comments: author: Christian Schneider
body: Thank you for your response. I have seen that approach as well, but I don't want to create another set of customfields, if I can get this done *on the fly*.

My automation should trigger, if a customer comments on an issue and then, the automation should transition the issue back to its previous state. As I have different workflows with different transitions in our Service Desk, I would like to solve this elegantly. :-)


Tags: history

json

rest-api

smart-value

webhook