Use two smart values to create a single value inside of a loop

Nathan Broom September 15, 2022

Summary

My goal is to convert a dynamic number of epoch values to a different format and use the result in the body of a web request.

It would seem that this is possible at first given that I can do this without issue outside of a loop. But within a loop, I receive this message: "The provided smart value was unable to be resolved to an object."

Any suggestions?

What works outside a loop

Log action:

{{epochDate.toDate("dd/MM/yyyy")
.plusSeconds(ts).convertToTimeZone("America/Chicago")
.format("MMM dd, yyyy hh:mm a z")}}

*line breaks for readability*

Here epochDate is a custom variable that equals 01/01/1970 and ts is a custom variable for testing purposes. The result of this action is Sep 01, 2022 09:28 AM CDT.

Loop that breaks

Log action:

{{#webResponse.body}}
{{epochDate.toDate("dd/MM/yyyy")
.plusSeconds(ts).convertToTimeZone("America/Chicago")
.format("MMM dd, yyyy hh:mm a z")}}
{{/}}

*line breaks for readability*

Here epochDate is the same value as above and ts is the epoch time received from a web request. 

Web request action:

{
"ticket": {
"comment": {
"html_body":
"<table>
<tr>
<th>Time Sent</th>
<th>Status</th>
<th>Subject</th>
<th>Email</th>
<th>Sender</th>
</tr>{{#webResponse.body}}<tr>
<td>{{epochDate.toDate(\"dd/MM/yyyy\").plusSeconds(ts).convertToTimeZone("America/Chicago").format("MMM dd, yyyy hh:mm a z")}}</td>
<td>{{elasticsearch_index}}</td>
<td>{{subject}}</td>
<td>{{email}}</td>
<td>{{sender}}</td>
</tr>
{{/}}

</table>",
"public": false
},
"status": "new"
}
}

*line breaks for readability*

Here epochDate is the same value as above and ts is the epoch time received from a web request. 

All the other smart values that are iterated over are sent correctly, just the time that is causing problems. My guess is that the custom variable epochDate is somehow out of scope within a loop.

What I've tried

  • Casting ts asNumber to ensure it wasn't converted to a string somehow
  • Referencing ts by webResponse.body.ts
  • Adding mustaches around both epochDate and ts with and without enclosing mustaches 
  • Making a list of just converted times but then I have to iterate again

1 answer

1 accepted

0 votes
Answer accepted
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, 2022

Hi @Nathan Broom -- Welcome to the Atlassian Community!

I am assuming you are trying this in an automation for Jira (A4J) rule...and so your scoping observation is correct.

Branches in automation rules which have one-and-only-one value (e.g. Branch on Parent, Branch on Current Issue, etc.) get run in-line, and so any variables in scope at the top-level of the rule are visible because they are the same variable.

However branches which could evaluate to multiple issues (e.g. JQL, child issues, etc.)  are run asynchronously and in parallel.  Per the documentation, there is no guarantee the branch will complete before the next step in the rule...let alone the entire rest of the rule.  And so I hypothesize a created variable referenced from outside the branch likely evaluates to null.

Have you tried to move the variable creation inside of the branch/loop?

Kind regards,
Bill

Nathan Broom September 16, 2022

Hey @Bill Sheboy thank you for the welcome and the suggestion! 

The branch suggestion worked great for using epochDate and the times returned from the webRequest in one smart value. The issue I'm running into now is building all of the iterations into one string that can be used in the body of a webRequest outside the loop so it is just sent once.

This would seem possible at first, given that I can use {{epochDate}} after the branch. But if I try to use {{tableData}} after the branch it appears to be null. Feels like there has to be a method I'm missing. Even if tableData did work after the branch ends, I need to find a different solution. It appears calling .concat(rowData) on the first pass while tableData is empty doesn't work so the first values will be missing.

Appreciate your help!

image.png

Variables

rowData =
<tr>

<td>{{epochDate.toDate("dd/MM/yyyy").plusSeconds(ts).convertToTimeZone("America/Chicago").format("MMM dd, yyyy hh:mm a z")}}</td>
<td>{{elasticsearch_index}}</td>
<td>{{subject}}</td>
<td>{{email}}</td>
<td>{{sender}}</td>
</tr>

tableData = {{tableData.concat(rowData)}}
Nathan Broom September 16, 2022

@Bill Sheboy I'm now realizing I'm probably running into the asynchronous behavior you mentioned. I tried creating a placeholder variable before the loop and concatenating each iteration to that. Then used the variable after the loop but it only ever contained values from the first loop.

Guessing there is no recourse here? Thanks again for the help! 

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, 2022

Yup, that sounds correct.  For use cases like this, I found another approach that can sometimes work:

You appear to be using an advanced branch, based on a web request call's response.  Instead eliminate the branch and use a list iterator on the response and extract all the needed values into a single created variable in one smart value expression.  I recommend writing this in a text/JSON editor first, and then paste it into the rule.

Sometimes this can take a several variables to achieve, building upon each other's results.  For such cases, I add my own delimiter so I can use a split() and then list iterator  or match() function on each variable, as needed, until I get the final expression.

Nathan Broom September 19, 2022

Appreciate your helpfulness. Unfortunately, I don't think it will work for my use case because the only way I could convert the UNIX times was through the branch. 

Thanks!

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 19, 2022

Glad to help, and too bad this would not work.

I was hoping you could use a list iterator to gather up the results, such as...

{{#webResponse.body.fieldFromYourAdvancedBranch}}your logic to create the variable, referencing the smart values like ts and subject{{/}}

Nathan Broom September 19, 2022

Perhaps I'm misunderstanding something. Variables created inside the branch can be accessed later with dot notation?

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 19, 2022

Nope.  I was suggesting to ignore the branch...and whatever smart value you were using to drive your branch to instead use it in the iterator over the web request response.

What was the value in your advanced branch to populate {{response}}

Nathan Broom September 20, 2022

Ah I see. It was {{WebResponse.body}}, but without the branch, I run into the issue of not being able to reference epochTime and ts in the same smart value to convert the UNIX times.

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 20, 2022

Hmmm...Okay, let's try this:

  • trigger: your trigger
  • action: web request
  • condition: check the response status for success, {{webResponse.status}} or {{webResponse.statusCategory}}
  • action: create your epochTime variable as before
  • action: create your ts variable as before
  • action: log this smart value and observe the results
{{#webResponse.body}}<tr>
<td>{{epochDate.toDate("dd/MM/yyyy").plusSeconds(ts).convertToTimeZone("America/Chicago").format("MMM dd, yyyy hh:mm a z")}}</td>
<td>{{elasticsearch_index}}</td>
<td>{{subject}}</td>
<td>{{email}}</td>
<td>{{sender}}</td>
</tr>{{/}}

The references to the created variables should work, and if the other smart values are empty/not found you may need to find the correct place to reference them in the response message.

Nathan Broom September 21, 2022

It still does not like epochDate being inside the loop. ts is part of the response so it should not need to be created btw. This was the result:

Value to log:
{{epochDate}}
{{#webResponse.body}}<tr>
<td>{{epochDate.toDate("dd/MM/yyyy").plusSeconds(ts).convertToTimeZone("America/Chicago").format("MMM dd, yyyy hh:mm a z")}}</td>
<td>{{elasticsearch_index}}</td>
<td>{{subject}}</td>
<td>{{email}}</td>
<td>{{sender}}</td>
</tr>{{/}}

Result:
01/01/1970
<tr>
<td></td> //Empty value where the date should be
<td>bounced-2022-09-17</td>
<td>Subject Example</td>
<td>example@email.com</td>
<td>sender@email.com</td>
</tr><tr>
<td></td> //Empty value where the date should be
<td>bounced-2022-09-15</td>
<td>Subject Example</td>
<td>example@email.com</td>
<td>sender@email.com</td>
</tr><tr>
</tr>

Thanks again for responding. Is there anyway to call to date on a string? So instead of using a smart value, I could do something like {{(01/01/1970).toDate("dd/MM/yyyy").plusSeconds(ts)}} I tried this and a few other variations with no luck.

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 21, 2022

Thanks for that info...this confirms a created variable cannot be used inside of an iterator.

One work-around is use the variable later using replaceAll(), like below.  Please simplify if you wish to use fewer variables  :^)

  • create epochDate
  • create ts
  • create your table date as a variable
    • name: varTableDate
    • smart value:
{{epochDate.toDate("dd/MM/yyyy").plusSeconds(ts).convertToTimeZone("America/Chicago").format("MMM dd, yyyy hh:mm a z")}}
  • create your table as a variable, substituting in a PLACEHOLDER literal text value
    • name: varTable
    • smart value:
{{#webResponse.body}}<tr>
<td>PLACEHOLDER</td>
<td>{{elasticsearch_index}}</td>
<td>{{subject}}</td>
<td>{{email}}</td>
<td>{{sender}}</td>
</tr>{{/}}
  • now replace the placeholder with the correct value: {{varTable.replaceAll("PLACEHOLDER",varTableDate)}}

 

Sorry for all the back-and-forth on this, as I should have remembered that variables do not work in all smart value expressions/functions.

Nathan Broom September 22, 2022

No worries at all. I've learned a lot from your replies. 

It probably got muddied in the back and forth, but ts is a value in the webResponse that is different for each json object in the WebResponse.body. So I'm not sure how to escape needing to use epochDate inside 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.
September 22, 2022

Hmm...The only other thing I can think of is to start with ts, and add the literal value for the epoch Date in seconds, and try to convert to a datetime type from there.  I'm unclear how to do that within the iterator.

Nathan Broom September 27, 2022

Man, I really thought this was going to work. There might something here. Going to play with it more once time allows. 

 

{{#webResponse.body}}
{{now.withDayOfYear(1)
.withYear(1970)
.withHour(0)
.withMinute(0)
.withSecond(0)
.withMillis(0)
.plusSeconds(ts)}},
{{/}}
Like Bill Sheboy likes this

Suggest an answer

Log in or Sign up to answer
DEPLOYMENT TYPE
CLOUD
PRODUCT PLAN
PREMIUM
TAGS
AUG Leaders

Atlassian Community Events