Create
cancel
Showing results for 
Search instead for 
Did you mean: 
Sign up Log in

Concatenated Components in automation rule

Martin Karlsson
Contributor
January 22, 2025 edited

 

What I want

When a Component is removed from a Story / Bug I want to

  1. transition any linked Issues (of a certain link type) that also have the removed Component.
  2. remove the Component(s) in question from any open Sub-tasks that also have it.

 

My rule

Main branch

Trigger: Value deleted for the Component field

If: JQL: issuetype in (bug, story)

If: Sub-task is present

Then: A variable, "deletedComponents", is created for the deleted Component(s), with smart value:

{{#changelog.component}}{{fromString}}{{/}} 

main_branch.png

First branch

For: Linked Issues of correct link type

If: JQL: component = {{deletedComponents}}

Then: transition Issue

first_branch.png

Second branch

For: Sub-tasks

If: JQL: status != done

Then: Edit Issue, advanced editing:

{ 
  "update":{
    "components": [{
      "remove": {"name": "{{deletedComponents}}"}
    }]
  }
}

second_branch.png

 

The problem

The setup works as expected if I remove a single Component from the Bug or Story, the problems start when I remove more than one Component:

  1. the first branch fails on the JQL condition: no Issues match the condition. But there are linked Issues with the removed Components.
  2. the second branch fails on the editing action: "[issuekey] (Could not find valid 'id' or 'name' in component object. (components))"".

So I printed {{deletedComponents}} and it turns out all removed Components are put together in a single string, e g comp1comp2comp3, which I guess explains why it works with a single Component but not more than that. comp1, comp2 and comp3 are existing Components and thus recognized but no component called comp1comp2comp3 exists.

Being new to Jira automation, smart values etc my guess is that it's got something to do with the smart value for the variable:

{{#changelog.component}}{{fromString}}{{/}}. 

but I'm not sure how to fix it. Found other questions discussing a split function but I'm not a developer so I couldn't get that working.

(I have another rule which creates linked Issues based on Components added to Bugs / Stories, and adds them to the Sub-tasks, in which I use

{{#changelog.component}}{{toString}} 

to get at the added Component(s) and that handles multiple Components just fine.)

Audit log

audit_log.png

 

2 answers

1 accepted

1 vote
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.
January 22, 2025

Hi @Martin Karlsson 

Yes, and...to the other suggestions:

Your created variable for deletedComponents has no delimiters.  To use it as Dick suggests, please change the Create Variable action's value to this:

{{#changelog.component}}"{{fromString}}"{{^last}},{{/}}{{/}}

That will use list iteration to surround each value with quotation marks and join the values with a comma delimiter, allowing them to work in the JQL:

 

 Later in the dynamic JSON, I would parse that to remove each value individually:

{
"update": {
"components": [
{{#deletedComponents.split(",")}}
{ "remove": { "name": {{.}} } } {{^last}}, {{/}}
{{/}}
]
}
}

Please note that because the quotation marks were already surrounding the values, they are not added to the JSON expression. 

 

Kind regards,
Bill

Martin Karlsson
Contributor
January 23, 2025

Alright, that solved it! Thanks!

I'd like to understand the details of what's going on with the changes you did, do you mind if we step-by-step it?

 

{{#changelog.component}}"{{fromString}}"{{^last}},{{/}}{{/}}

{{#changelog.component}}
Here we iterate through the changelog for the Component field.

"{{fromString}}"
fromString looks at the old / removed value(s) (as opposed to toString). the quotation marks means that quotation marks are added around each value.

{{^last}}
what's going on here?

{{/}}{{/}}
two close? is the second one for {{^last}}?

 

 {
"update": {
"components": [
{{#deletedComponents.split(",")}}
{ "remove": { "name": {{.}} } } {{^last}}, {{/}}
{{/}}
]
}
}

{{#deletedComponents.split(",")}}
we iterate through the value(s) saved in the deletedComponents variable and .split(",") splits the values and inserts a comma between them.


{ "remove": { "name": {{.}} } } {{^last}}, {{/}
here I really only understand the remove part. why do we have to insert "name"? and I guess the "." refers to the Component values but how? and the {{^last}} part again?

Like • Bill Sheboy likes this
Dick
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 23, 2025

{{^last}}
what's going on here?

 

^ = Skip (the last), meaning for all other instances in the list, append the comma, except for the last instance..

 

{{/}}{{/}}
two close? is the second one for {{^last}}?

Yes. Both the {{#   }}  and {{^    }} need closure.

 

{{#deletedComponents.split(",")}}
we iterate through the value(s) saved in the deletedComponents variable and .split(",") splits the values and inserts a comma between them. As the last entry is not followed by a comma, that is skipped. 

 

Not quite: here the individual values are constructed from the comma-separated list using a split on it, using the comma as the delimiter (which means it is not a part of the list of strings this expression produces)

 

{ "remove": { "name": {{.}} } } {{^last}}, {{/}
here I really only understand the remove part. why do we have to insert "name"? and I guess the "." refers to the Component values but how? and the {{^last}} part again?

Here the individual split-off strings are inserted using the {{.}}  (also new to me, thanks @Bill Sheboy , I'll be bookmarking this one). into the remove JSON (also given in my answer). 

 

 

Like • Bill Sheboy likes this
Dick
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 23, 2025

I'm curious @Bill Sheboy , could the whole comma-delimited concatenation for storage and subsequent splitting-the-components to remove them consecutively be replaced by the .asJsonArray function? 

Kind regards,

Dick

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 23, 2025

Thanks for filling in the details I left off, @Dick Teamwork makes the community work!

And, I have not tried with Atlassian's interpretation of JSON for automation ;^)  if sending that type of update as an array will work with either the "add" or "remove" actions.  I have always assumed it would not work (same as I do for rule's use of regex), and so sent each update action separately.  I only use those built-in automation JSON functions (e.g., asJsonArray) when the specific value for a field has a certain structure, needs quotation marks, etc.

 

Hi, @Martin Karlsson -- Sorry I did not explain that expression earlier.  Please also note the link I provided to the combined examples for list iteration.  That is the only place in the documentation where it shows the syntaxes for things like:

  • {{.}}
  • {{^last}} ... {{/}}
  • {{index}}
  • and so on...
Like • Dick likes this
Martin Karlsson
Contributor
January 23, 2025

@Dick  @Bill Sheboy  Thank you both for taking the time to explain this to me. Very informative and helpful, I appreciate it a lot. 

Br

Martin K

Like • 2 people like this
0 votes
Dick
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 22, 2025 edited

Hi @Martin Karlsson 

ad 1:  your condition if issue matches JQL should be component in ( {{deletedComponent}} )

The way it is now, you query for exactly one component. This fails when there are multiple.

ad 2: your JSON should be like (no quotes around the smart value and your variable does not end with s)

 

{
"update": {
"components": [{
"remove": {"name": {{deletedComponent.asJsonString}}}
}]
}
}

If you anticipate multiple components to change, you would need the .asJsonArray as extension.

Kind regards,

Dick

Martin Karlsson
Contributor
January 23, 2025

Right, missed the JQL problem.

Thanks!

Like • Dick likes this

Suggest an answer

Log in or Sign up to answer
DEPLOYMENT TYPE
CLOUD
PRODUCT PLAN
STANDARD
TAGS
atlassian, team '25, conference, certifications, bootcamps, training experience, anaheim ca,

Want to make the most of Team ‘25?

Spend the day sharpening your skills in Atlassian Cloud Organization Admin or Jira Administration, then take the exam onsite. Already ready? Take one - or more - of 12 different certification exams while you’re in Anaheim at Team' 25.

Learn more
AUG Leaders

Upcoming Jira Events