access a created variable's value (from a list), using it in a function...within an iterator

Bill Sheboy
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
January 26, 2022

Hello community!

The problem I am trying to solve is to store a list of values in a created variable, and then access one of the values with a function inside of an iterator.  Has anyone done this?

For example:

  • Created variable named varList contains a list, such as dates: 2021-12-24, 2021-12-31, 2022-01-15
  • Iterator attempts to split and then use the values from the list.  To only list the values, use {{.}}
{{#varList.split(",")}}{{.}}{{/}}
  • But to use the list value in a function, the {{.}} cannot be used:
{{#varList.split(",")}}{#if(issue.created.diff(.).days.gte(0))}}+1{{/}}{{/}}
  • I wonder if there is another smart value which represents {{.}} that can be used
{{#varList.split(",")}}{#if(issue.created.diff(WHAT_TO_PUT_HERE).days.gte(0))}}+1{{/}}{{/}}
  • Other things I tried which did not help:
    • Nest the list split() to use the same list inside the iterator, accessed by get(index).  This evaluates to null, leading to the conclusion: a list cannot be accessed inside its own iterator, or that index loses meaning as a function parameter.
    • Copy the created variable list to another variable, and then try the nested list technique with one list insider of another's iterator.  This evaluates to null.
    • Format the list in the created variable as JSON, use the encode function, and then attempt to access the list by attribute name.  This evaluates to null.

The thing I cannot figure out is how to access the list iterator value.  I wonder:

  1. Is there an internal smart value name for {{.}} that can be referenced; or
  2. Can a created variable be structured as an object with attribute names (like "value"), and then split for later reference/use; or
  3. This not possible.

The only work-around I have found is to store the values in an entity property instead of the created variable.

Thanks for your ideas!

4 answers

0 votes
Odimar Tomazeli September 15, 2023

I have a similar but different issue. I'm new to Jira Automation and trying to figure it out any help will be appreciated

Ok So the issue lies on Organizations Locked field in Jira Service Management I need to bring this information to a project in Jira Software so I created a custom field called Organization(s) and Assigned to both projects my Idea was every time the Organizations field changes i update the Organization(s) field then when I create the issue in Jira Software I only have to copy the value as if i try to copy directly from Organizations field it doesn't work.
My problem is that I'm not able to convert Organizations field type Organization into Organization(s) field type labels.

Any idea how I can achieve this?

I have tried to create a variable {{Orgs}} and assign the below expression
{{Issue.Organizations.name.flatten()}}

then restore it to the Organization(s) field using
 {{Orgs.split(",")}}

Bill Sheboy
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
September 16, 2023

Hi @Odimar Tomazeli 

I recommend creating a new question for this one, and perhaps linking back to this one.  Otherwise only the people following this older thread will see it, limiting the amount of community suggestions offered.

When you post your question, please include images of your complete rule, showing details of the actions, and of the audit log details showing the rule execution.  Those will provide context for the community to offer more targeted ideas.  Thanks!

Kind regards,
Bill

0 votes
Slava Gefen
Contributor
April 16, 2023

Hi All!

It seems after a while I was able to solve this issue. Bellow is the example of my Automation rule. This Automation is getting a list from 1,2,3, ... string variable.

1. Set a manual trigger
2. Then create a variable
Capture1.JPG

3. Then add value to the log
Capture2.JPG

4. Then make additional Log
Capture3.JPG
5. Then create Advanced branching
Capture4.JPG
6. And finally log action again
Capture5.JPG
As a result, you'll get this:
Capture6.JPG

 

Even More you can continue with the new available smart-value called lookup table

1. At first this
Capture7.JPG
2. Then Log action
Capture8.JPG
3. And finally access your table
Capture9.JPG

As a result, you'll get this:
Capture10.JPG

Hope it helps!
With kind regards
Slava

Bill Sheboy
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
April 16, 2023

Hi @Slava Gefen 

Thanks for your suggestions.

As I noted to you in my other post for the open backlog/suggestion item on created variables...that does not help in this scenario as the advanced branches are executed asynchronously and non-deterministically.  The scoping issues would prevent usage of the accumulator result.

And...I can confirm that although the new lookup tables help with some things, they also cannot by iterated over as an alternative.

My understanding from Atlassian people is that eventually created variables will be typed/objects; when (if?) that happens split lists can be referenced by other than {{.}} to enable more complex use cases.

Kind regards,
Bill

Like Darryl Lee likes this
Slava Gefen
Contributor
April 16, 2023

.that does not help in this scenario as the advanced branches are executed asynchronously and non-deterministically

@Bill Sheboy could you please describe the exact scenario you want to achieve?

Bill Sheboy
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
April 16, 2023

The scenario, as posted more than a year ago, is in the original question.  It is a pattern to use iterator data within functions when the iterator has no structure.  There are other work-arounds for this (e.g., repeated if/else with created variables).

Slava Gefen
Contributor
April 20, 2023

Hey @Bill Sheboy thanks for the answer!

The scenario,as posted more than a year ago

Could you please give a simple example what data do you have and what do you want to get after?

Sorry, I can't get it from the description.

For example:
I have list of Dates then I need to get date greater than ... Something like this.

0 votes
David Pezet
Contributor
February 1, 2023

@Bill Sheboy Any chance you figured out a solution since when this was posted?

Bill Sheboy
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
February 1, 2023

Hi @David Pezet 

No, I did not.  Created variables are still just text, with no structure.  The closest I have gotten to this was to use a homemade, delimited variable and then a match() function later to process it.

Here is an example of that technique to find the latest sprint an issue was in: https://community.atlassian.com/t5/Jira-Software-questions/Re-How-to-create-an-automation-to-set-the-issue-s-last-s/qaq-p/2253719/comment-id/245069#M245069

Kind regards,
Bill

David Pezet
Contributor
February 1, 2023

@Bill Sheboy Thanks for the quick reply. I've been able to flip my thinking to get away from having to reference the current element, and now run into another problem (sorry to derail the thread here). I think I run into the same problem with the string matching solution too. The issue I'm running into is that it doesn't seem I can access a variable inside the list functions (since I'm trying to iterate through two lists).

For example, I have an array of ids [1,2,3.4] stored in a variable (testArray) and an array of objects ("options") [{"id":1,"value":"text1"}, ...] returned by a web request.

If I use,

{{#webResponse.body.data.options}}
{{#if(equals(id,3))}}
{{value}}
{{/}}
{{/}}

this returns the string for the corresponding value.

My hope was to do something like,

{{#webResponse.body.data.options}}
{{#if(testArray.split(",").contains(id))}}
{{value}}
{{/}}
{{/}}

But it seems that other variables are not able to be referenced inside of the list since,

{{testArray}} 

will log the variable just fine outside the list, but

{{#webResponse.body.data.options}}
{{testArray}}
{{/}}

logs nothing ({{value}} works).

Any suggestions are greatly appreciated.

Bill Sheboy
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
February 1, 2023

Some things to note...

  • Create variables (and even some issue fields) appear not to work in all possible functions. 
  • And...smart value, list filtering has the same challenge, as you can read in the comments to this article: https://community.atlassian.com/t5/Automation-articles/Filtering-smart-value-lists/ba-p/1827588
  • And...smart value list iterators cannot both walk the list and reference the entire list at once.  (e.g. walk the fixVersions and reference the maximum date in the iterator)
  • My hypothesis is some of those smart values passed to a functions are not evaluated and resolve to null, and then the iterator either collapses to null or returns all list items.

This symptom is the idea behind the work-around I noted: if you can create a regular expression to use in a match() then that eliminates the need to use the iterator for filtering.

For your scenario you could build the regular expression by expanding your array of id values into something like 1|2|3|4 within the expression, and use that with match as:

{{webresponse.body.data.options.match(varForYourRegularExpression)}}

Then add appropriate list and text functions to the end to process your results.

Like Trang Ngoc Nguyen likes this
David Pezet
Contributor
February 6, 2023

@Bill Sheboy I can't thank you enough. With the help of your info/links and a some more wrangling I was able to get a working solution. I think the biggest key bit of info was leveraging match, and that variables seem to turn everything into a string. So where referencing webhookData may keep things as object arrays, once you store it in a variable, you may have to then manipulate it again to get it back in to a form you can work with.  

In case this helps anyone else who ends up here, these were my challenges and the solutions I was able to get to work. (There very well could be better solutions, these just got me to a point where I could move on, and at least monitor for edge condition errors).

To summarize, we have an Incoming Webhook that sends info we want to store in Jira. Part of that incoming info only sends IDs, which need to be reconciled for humans. So we also have a Web Request that gets an object array of possible IDs and their Values from that external API. Since it returns the complete list of options, we only want the applicable values. Thanks to Bill's suggestion to use match(), the following is what worked for me.

1. Web Request to external API to get the complete list of possible IDs and their values.

2. Create Variable for the regular expression to match the IDs that were in the Incoming Webhook data.

((?<=label=)((?!label=).)+(?=[,][ ]id=({{#webhookData.someArrayID.split(",")}}{{.}}{{^last}}|{{/}}{{/}})}))

3. Store the results in Jira field (in this case a checkbox field).

{
"fields": {
"customfield_12345": [{{webResponse.body.data.options.asJsonStringArray.match(rx).asJsonObject("value")}}]
}
}

Another part of our challenge was that we also needed to pass some of this information to another automation. Since I couldn't find a way to simply pass the original webhookData to the next automation, I had to recreate the necessary data as Custom Data in the web request (e.g., { {"newObjectName" : "{{webhookData.something}}" } } ). So while working with the original external API data on the first incoming webhook I was able to use 

{{webResponse.body.data.options.asJsonStringArray.match(rx).asJsonObject("value")}}

(rx being the regular expression variable), I would need to pass it to the next automation already formatted for the storing in the Jira issue as 

{{webResponse.body.data.options.asJsonStringArray.match(rx).asJsonObject("value").jsonEncode}}

so it could then be put back into an array when setting the Jira value 

"customfield_12345": [{{webhookData.newObjectName}}]

--There is probably a solution for passing just that match results (not formatted asJsonObject), but I experienced issues between needing to pass jsonEncode 'd  and dealing with string vs arrays on the other side, I decided to skip figuring this out.

Another thing to watch out for was making sure to group (extra wrapping parentheses) the regular expressions results so they came through correctly. Also, instead of custom formatting the string to be evaluated by the regex, I decided to use a regex that worked with the json formatted string using lookaheads/behinds. This is what ended up working for me and the match would output an array of any of the matches.

((?<=value=)((?!value=).)+(?=[,][ ]id=({{#webhookData.someArrayID.split(",")}}{{.}}{{^last}}|{{/}}{{/}})})) 

Hope this helps. Feedback welcome. I look forward to a future where created variables can be used inside lists  and current list values could be referenced as something like {{this}} instead of {{.}} for simpler a solutions...

0 votes
Darryl Lee
Community Leader
Community Leader
Community Leaders are connectors, ambassadors, and mentors. On the online community, they serve as thought leaders, product experts, and moderators.
January 26, 2022

This is not an actual answer, but commiseration. I went down a rabbit-hole trying to find an answer to Perla's additional request to iterate with a counter value. 

I tried to represent {{counterValues}} in all kinds of list formats, but got nowhere fast.

I think I even tried splitting "1,2,3,4" into its own variable, hoping it would "magically" convert to a list, but Automation did not like that.

Now that I've come back to the question, I see your very clever usage of the index value. That is incredibly SLICK, as I could not for the life of me figure out how to get array values into such a loop.

We really could use the ability to properly define arrays and then some functions for them. When you see something like .split you just naturally think there should be a way to go the other direction.

Slava Gefen
Contributor
April 16, 2023

Hey @Darryl Lee 

I think I even tried splitting "1,2,3,4" into its own variable, hoping it would "magically" convert to a list, but Automation did not like that.

I was able to split 1,2,3 string variable into a map. Please look at am answer above.

With kind regards
Slava

Suggest an answer

Log in or Sign up to answer
TAGS
AUG Leaders

Atlassian Community Events