Adding a text string to an Epic Name depending on component's text
Asked by Daniel Schoeneck:

Hello all,

I have set up the following 2 automation rules:

1. If in the field Component/s the component name starts with E add #EMP to the Epic name
2. If in the field Component/s the component name starts with F add #FRA to the Epic name.  

   <br />

This works well as long as there is only ONE component selected in the Epic. But if there are 2 components selected, one starting with "E" and one with "F", only #EMP is added to the iEPic name...but I want #EMP and #FRA to be added to the Epic name.

<br />

![Rule #FRA2.PNG](https://community.atlassian.com/t5/image/serverpage/image-id/275901i955C611179F31316/image-size/large?v=v2&px=999 "Rule #FRA2.PNG")![Rule #EMP2.PNG](https://community.atlassian.com/t5/image/serverpage/image-id/275902i367845ED9312E474/image-size/large?v=v2&px=999 "Rule #EMP2.PNG")![Rule #EMP1.PNG](https://community.atlassian.com/t5/image/serverpage/image-id/275903i001EA49E82DD33EA/image-size/large?v=v2&px=999 "Rule #EMP1.PNG")![Rule #FRA1.PNG](https://community.atlassian.com/t5/image/serverpage/image-id/275904i45249C95C4B19BB6/image-size/large?v=v2&px=999 "Rule #FRA1.PNG")![Problem_only #EMP.PNG](https://community.atlassian.com/t5/image/serverpage/image-id/275907i817370189940D55A/image-size/large?v=v2&px=999 "Problem_only #EMP.PNG")  
Any idea how to solve this?


Answers:
author: Bill Sheboy
body: Hi [@Daniel Schoeneck](/t5/user/viewprofilepage/user-id/2613140) and the community helping on this one!

You do not state the format of your epic name, so let's assume it is something like this:

EPICNAME \[0 to many component indicators, prefixed by " #"\]

Have you considered doing this in one step / edit action (without any conditions), using smart value list filtering? <https://community.atlassian.com/t5/Automation-articles/Filtering-smart-value-lists/ba-p/1827588>

{{issue.epic name.substringBefore(" #")}}{{#issue.components}}{{#if(equals(name.left(1).toUpperCase(),"E"))}} #EMP{{/}}{{/}}

Please repeat the inner section for any component you want to handle

Also, you would need rules to make the update for different triggering events: issue create, components changed, epic name edited by other than rule, etc.

Kind regards,  
Bill

comments: author: Mark Segall
body: Ha - I should've known that Mr Sheboy would come in with a more elegant approach! ?


author: Daniel Schoeneck
body: Thanky you [@Bill Sheboy](/t5/user/viewprofilepage/user-id/1685313)   
Never thought about that...or let's say: I did not know that this is possible I don't even understand how this code works and how to implement into my automation rule ;)  

What would be the advantage of your solution?  

<br />


author: Wouter van den Berg
body: Way cleaner solution definitely. The advantage here is a cleaner solution, less load for automation and no conditions that need matching before execution.

The disadvantage was made clear the moment you replied. This is definitely more advanced. Upon you leaving the system, the one replacing you will probably have some questions how the logic works.

Thanks for sharing this clean solution [@Bill Sheboy](/t5/user/viewprofilepage/user-id/1685313)


author: Bill Sheboy
body: Yes, that is a more complicated approach. And...

In my experience, using automation rules requires learning, experimentation, and documentation. Unfortunately that last one is tricky given current capabilities of rules. A work-around is to document rules outside of the project, such as in Confluence. I also save my rules in a test project, and write an explanation in the details so I can remember what I did last week ;\^) I also add writes to the audit log to explain and assess progress in the rule processing.

Back to Daniel's questions about the suggestion I made...

The first part grabs whatever text in the Epic Name is left of the first Component indicator. This helps when later updates of the Components field need to refresh the name. <https://support.atlassian.com/cloud-automation/docs/jira-smart-values-text-fields/#substringBefore-String-separator->

The next part is using the idea of list iterators, {{#*someList* }}{{*someField* }}{{/}} to allow walking over the Component values. This technique is helpful to format things, list a list of issues for an email, or to build up a JSON expression. <https://support.atlassian.com/cloud-automation/docs/jira-smart-values-lists/#Combined-function-examples>

And inside that iterator, we are using the newer feature of smart value, list filtering. This helps to prune the list only to the values you want. In your case, you wanted to check for specific components' prefix letters.

Finally how to use this: remove all of the condition tests, and a single expression could be used to update the Epic Name field in the Edit Issue action.


author: Daniel Schoeneck
body: [@Bill Sheboy](/t5/user/viewprofilepage/user-id/1685313) Very nice solution, I want to use it (unless I still don't fully understand it, but that is due to my lack of basic programming knowledge).  

I have already created 3 rules that work pretty well using your code:  

* Add Squad #hashtag to Epic Name when Epic is created
* Add Squad #hashtag to Epic Name when Component is added later
* Remove Squad #hashtag from Epic Name when Component is removed

But one problem is left:  

When there is already a component starting with "F" and I add a second component that start with "F", the hashtag #FRA is added once more. I only need the hashtag once in the Epic Name.

How to prevent it is added once more?![Redundant hashtag.PNG](https://community.atlassian.com/t5/image/serverpage/image-id/275988i4B28667CE82FD5EA/image-size/large?v=v2&px=999 "Redundant hashtag.PNG")


author: Bill Sheboy
body: First thing, smart value expressions can be built up from simple pieces. And something what seems like a complicate mess can be explained. That was a disclaimer for what follows...

Your revised goal is to find the ***distinct*** first letters of the component names, and use them to select your tokens/indicators to add to the epic name. Fortunately smart value lists have a function to return just the distinct values: <https://support.atlassian.com/cloud-automation/docs/jira-smart-values-lists/#list.distinct>

The challenge is how to get the distinct values **and** use that in a list filter? Let's look at this step by step:

1. Let's get just the first characters of the component names as a list with {{issue.components.name.left(1).toUpperCase()}}
2. We refine that by adding distinct to the end {{issue.components.name.left(1).toUpperCase().distinct}}
3. And because that is a list, it can still be filtered, like this {{#issue.components.name.left(1).toUpperCase().distinct}}{{#if(equals("E"))}} # EMP{{/}}{{/}}

The tricky part is after we got to step #2, these are now just letters in a list, and no longer have anything to do with components. And so we cannot filter on the "name" attribute any longer.

Fortunately the iterator and conditional filter logic design is smart enough to compare the list element to the "E".

So your revised template would be this...as now this can happen together:

{{issue.epic name.substringBefore(" #")}}{{#issue.components.name.left(1).toUpperCase().distinct}}{{#if(equals("E"))}} #EMP{{/}}{{#if(equals("F"))}} #FRA{{/}}{{/}}


author: Daniel Schoeneck
body: Alright, so I need it actually for 3 different types of components

- Starting with E  
- Starting with F  
- Starting with S  

So I tried this code:  

{{issue.epic name.substringBefore(" #")}} {{#issue.components.name.left(1).toUpperCase().distinct}}  
{{#if(equals("E"))}} #EMP{{/}}  
{{#if(equals("F"))}} #FRA{{/}}  
{{#if(equals("S"))}} #STE{{/}}  
{{/}}  

But now it just removes all the hashtags from the Epic name. What might be wrong?  

<br />

With this code it works nicely (except the problem that a hashtag might be added multiple times):  
{{issue.epic name.substringBefore(" #")}}  
{{#issue.components}}  
{{#if(equals(name.left(1).toUpperCase(),"E"))}} #EMP{{/}} {{#if(equals(name.left(1).toUpperCase(),"F"))}} #FRA{{/}}{{#if(equals(name.left(1).toUpperCase(),"S"))}} #STE{{/}}  
{{/}![Problem.PNG](https://community.atlassian.com/t5/image/serverpage/image-id/276012i6DD84F77DB55C7F4/image-size/large?v=v2&px=999 "Problem.PNG")  


author: Bill Sheboy
body: Fascinating...It is not removing them but they are off the field view on the page! I believe if you click on the field and select all, you will find them off to the right side.

There is something happening due to the use of the stringBefore() function, the iterator, and the extra carriage returns/line feeds you have in the expression. Please try pasting in this exact one and observe what happens:

```
{{issue.epic name.substringBefore(" #").trim}}{{#issue.components.name.left(1).toUpperCase().distinct}}{{#if(equals("E"))}} #EMP{{/}}{{#if(equals("F"))}} #FRA{{/}}{{#if(equals("S"))}} #STE{{/}}{{/}}
```

Please note I added a trim call and removed all extra CR/LF from the expression.


author: Daniel Schoeneck
body: I tried it, but still the same behavior...  
And I also did not find them in the edit mode of the field:  

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


author: Bill Sheboy
body: I tried this with Jira Cloud, so I wonder if there is a difference as you are using Jira Server, correct?

Let's try writing this to the audit log to see if you see the expected values:

```
{{#issue.components.name.left(1).toUpperCase().distinct}}{{.}}{{/}}
```

The result should be the list of just the expected first characters, with comma separators, as a list (not as an array). If it is an array we can try another work-around with join and split.


author: Wouter van den Berg
body: I can see your predicament. When there is a lot of changes you don't want to go back in and change the rules each time. Maybe you could extend the solution provided above with a regular expression. I don't remember if Server supports this but I assume it does. Use the branching logic that [@Mark Segall](/t5/user/viewprofilepage/user-id/4666637) provided but instead of component in you could use:

\^\[eE\] for matching components starting with e or E  
\^\[fF\] for matching components starting with f or F![Screenshot 2023-08-18 at 16.15.12.png](https://community.atlassian.com/t5/image/serverpage/image-id/275927i2A97AC190FF911E1/image-size/large?v=v2&px=999 "Screenshot 2023-08-18 at 16.15.12.png")


author: Wouter van den Berg
body: Hi [@Daniel Schoeneck](/t5/user/viewprofilepage/user-id/2613140)  

UPDATE: Sorry, didn't see you are on server. I'll leave the answer for the people that end up here using Cloud.   

I have tried a different approach. See screenshot:   

![Screenshot 2023-08-18 at 15.24.27.png](https://community.atlassian.com/t5/image/serverpage/image-id/275919iEB6D1B18C66C947E/image-size/large?v=v2&px=999 "Screenshot 2023-08-18 at 15.24.27.png")

Refetch in the first step might not be needed but I always do it anyways. In my case I did the comment action to see if it works but have a go at this.   

Goodluck.


author: Mark Segall
body: Hi [@Daniel Schoeneck](/t5/user/viewprofilepage/user-id/2613140)

From your screenshots, it appears you're using Jira Server automation, correct? If so this will be a little more tricky as you don't get the benefit of advanced branching. However, this could be possible and with a single rule.

Can you confirm whether the Epics will ever have more than 2 components?

comments: author: Wouter van den Berg
body: Ah didn't even notice that. Your approach would be {{issue.components.first.name}} and {{issue.components.last.name}} I presume?


author: Mark Segall
body: I was actually thinking more along the lines of

{{issue.components.name.get(0)}} and {{issue.components.name.get(1)}} but your approach will work too. ?


author: Daniel Schoeneck
body: Hi,   

yes the Epics can have an unlimited number of components


author: Mark Segall
body: Unfortunately, this makes things more complicated because we're constrained on being able to iterate through the components and components do not work with a wildcard search.

Are your components constantly changing? If not, you could go through a one-time pain point of creating two JQL branches:

* BRANCH (JQL)  
  For E\*
  * Key = {{issue.key}} AND Component IN (E1, E2, E3, E4)
* BRANCH (JQL)  
  For F\*  
  * Key = {{issue.key}} AND Component IN (F1, F2, F3, F4)

If the components list changes more frequently, we may be running into limitations of what's possible with Jira Server automation.


author: Daniel Schoeneck
body: Component names might change frequently yes...  
Would it help if we assume that there is a maximum number of components e.g. maximum of 4 components? (in reality 99,9999% of the components will have max. 3 components)


author: Daniel Schoeneck
body: OH, and yes: there will be more Components be added frequently (E5, E6, ... and F5, F6, ...)


author: Daniel Schoeneck
body: May be I need a completely different approach?  

My ultimate goal is to have "hashtags" on the epics in the epic panel in the Scrum backlog (depending on the selected components in the epics), which allows to use the epic panel filter (which only can filter by the epic name...)

![Epic Panel in Backlog.PNG](https://community.atlassian.com/t5/image/serverpage/image-id/275926i56E446913DC5C843/image-size/large?v=v2&px=999 "Epic Panel in Backlog.PNG")


author: Mark Segall
body: I think I found an answer to how to handle this:

* IF CONDITION:
  *

    ```
    {{issue.components.name}}
    Contains Regex
    \bE\w+
    ```

* ELSE CONDITION:
  *

    ```
    {{issue.components.name}}
    Contains Regex
    \bF\w+
    ```

I ran through a few tests in my environment and it seems to be working.


author: Wouter van den Berg
body: Assuming each components starts with a capital. If you want to cover all options you can use:

\^\[eE\] for matching components starting with e or E  
\^\[fF\] for matching components starting with f or F


author: Daniel Schoeneck
body: Thank you, I tried like this:  

But it still only added #FRA to the Epic name although there is an Component starting with E:

![Only FRA.PNG](https://community.atlassian.com/t5/image/serverpage/image-id/275933i4E3454BFBB22B651/image-size/large?v=v2&px=999 "Only FRA.PNG")![Rule.PNG](https://community.atlassian.com/t5/image/serverpage/image-id/275935iB2423B5766ACF4AD/image-size/large?v=v2&px=999 "Rule.PNG")![Error.PNG](https://community.atlassian.com/t5/image/serverpage/image-id/275934i8997043623300AB9/image-size/large?v=v2&px=999 "Error.PNG")


author: Wouter van den Berg
body: You need to Branch. With If/Else automation will stop once it reaches a succes.


author: Mark Segall
body: Good call [@Wouter van den Berg](/t5/user/viewprofilepage/user-id/5197383)


author: Mark Segall
body: I would branch into current issue twice and in between the two branches, do a re-fetch


author: Wouter van den Berg
body: Together we will solve this one [@Mark Segall](/t5/user/viewprofilepage/user-id/4666637) ;)   

[@Daniel Schoeneck](/t5/user/viewprofilepage/user-id/2613140) I saw you are using the Regex Mark has provided. Please make sure you have governance on Component creation. If a user adds a component without capital your rule won't pick this one up as match. The chances users will add a component without capital along the way is very likely if you'd ask me. I have added my solution for this but you are free to use Mark his solution but I still wanted to mention this again.


author: Daniel Schoeneck
body: Guys you are genius!  

Now I have to make sure that the hashtags will be updated when a component is deleted or added later to the epic.   
I will try myself first ;)  

![Solved.PNG](https://community.atlassian.com/t5/image/serverpage/image-id/275940iD46DE2787607C529/image-size/large?v=v2&px=999 "Solved.PNG")![Solution1.PNG](https://community.atlassian.com/t5/image/serverpage/image-id/275942i284537000BEE5550/image-size/large?v=v2&px=999 "Solution1.PNG")