Introducing Jira Expressions

I am happy to announce that Jira has just gotten a new powerful feature, which you can start using right now!

Jira expressions is a way to evaluate custom code in the context of Jira entities. It’s a domain-specific language designed with Jira in mind. All Jira expressions are evaluated on the Jira Cloud side. There are currently two ways to use Jira expressions:

The REST endpoint can be used to test the expressions that you plan to use elsewhere, or to load data in a new flexible way. For example, if you wanted to build an efficient and lightweight visualization of issue comments, you could fetch a minimal required set of data (id, author and the content excerpt) with the following expression:

issue.comments.map(c => [c.id, c.author.key, c.body.plainText.slice(0, 200) + '...'])

The web condition gives you almost infinite control over the visibility of your web elements. For example, you could use the following expression to show your panel only if the current user commented on the current issue:

issue.comments.filter(c => c.author.accountId = user.accountId).length > 0

These are just two simple examples. I’m sure you can come up with something even more useful.

Looking forward to hearing your feedback and seeing all the amazing things you will be able to build with this!

28 Likes

Fantastic!

And, it is really great that you have added this. But, for real power, please consider enabling us to do something like this (syntax may be broken, but I am sure you will get the gist):

project.issues.filter( i => i.sprint = “SomeSprint”).reduce((total, current) => total + current.storyPoints, 0)

AFAICT, the above operation is a surprising number of round trips to do currently…

Kind Regards

Mads

Hi, @mabd,

Thanks for your feedback! You are definitely not the first one to request aggregation operations on sets of issues, so stay tuned :slight_smile:

However, I’d like to clarify one thing to better understand the problem we are trying to solve here. You said that currently that would require a lot of round trips. But, wouldn’t it be enough to do a JQL search project = KEY AND sprint = “SomeSprint”, get the issues and then do the aggregation manually on the results? It seem that currently just one HTTP call and some simple processing on the client side would be enough to do what you showed.

Sure, doing that in one expression and just getting the number back in the response would save some bandwidth, but in JQL searches you can limit the set of returned fields, so savings wouldn’t even be that dramatic.

Glad to hear about the aggregation operations on sets of issues. Sound really great.

And, you are right about it not taking that many operations - I got my uses cases mixed up: I actually needed to summarize user points on several sprints. (And, I am aware about the fields variable on /search, etc).

I am a bit short on time, right now, but how about this (syntax probably broken)

bucket={};project.issues.forEach( i => bucket[i.sprint].append(i));bucket.forEachKey( k = > bucket[k].reduce((total, current) => total + current.storyPoints, 0)

Nah. That will probably be too much trouble. Sorry, could not resist :smiley:

1 Like

And thanks a lot for your quick answer!

Thanks for the clarification, @mabd. Reducing to a map is just a matter of having operations on Maps that can create a new map from the current one with a new entry – this is something that could be totally possible in the future.

I’m thinking of something like this:

project.issues.reduce((bucket, i) => 
           bucket.with([i.sprint], bucket(i.sprint) + i.storyPoints, {})

Note that currently this is still just one REST API call to the JQL search endpoint with some simple post-processing afterwards, is it not?

Sounds swell!

I was thinking about how to solve the things I needed do using the expression call only.

Reading my own comments, I can understand why that was not clear to you. I was probably in too much haste! :-).

And, you are right, it is no big deal using the existing rest api, but for reasons I am not going to bother you with, it is sometimes a lot easier in our end to code a single call that presents the info we need, rather than having to postprocess. (And, it is also easier to move between languages / platforms).

Anyway: Will make sure to follow this part of the api.

Thanks!

1 Like

I really like this feature and think it’s awesome!

However, I was testing it today and somehow figured out that it’s not possible to only provide a project in the context data (i.e. leaving out an issue key). Is this intentional?
For example, if I use the following JSON as the HTTP body to evaluate an expression using the REST API, I receive an internal server error response:

{ “expression”: “project.key == ‘TEST’”, “context”: { “project”: { “key”: “TEST” } } }

This seems to be a quite simple expression to me and I’m wondering why it’s not working. Please correct me if I misunderstood something here…

1 Like

Whoa! This is definitely not intentional. It should be totally possible to provide just a project. Thanks for reporting this, @shesse! I will fix it as soon as possible.

Edit: fixed.

2 Likes

Hi,
Do you have any plan supporting for Jira Server about Jira expression?

Hi, @abe.kenichi,

This feature is available exclusively on Jira Cloud.

Indeed, it doesn’t make much sense on Jira Server.

The problem Jira expressions are trying to solve is that certain classes of extension points require fast and reliable computations (e.g. workflow or web conditions). With Jira expressions, such extension points can now be offered to third-party apps.

But that problem doesn’t exist on Jira Server, since you can already enhance Jira Server in whatever way you need with P2 plugins running on the same JVM.

Best regards
Krzysztof

1 Like

Hi @kkercz how would I go about counting the number of linked issues (of type “is blocked by”) that are not resolved. I have tried using issue.linkedIssues(“is blocked by”) but that doesn’t seem to work.

Thanks
Paul

Edit: Changed to ask the right person (sorry abe)

1 Like

Hi @kkercz ,

I thought that’s right.

But if it were available on Jira Server too, we could use the almost same implementation in add-ons for Jira Server and Cloud.

Thanks
Kenichi

Hi, @paul,

Unfortunately, getting linked issues is currently not available, but it is on our roadmap. I’ll keep you posted.

By the way, all available issue fields are listed in the documentation, in the Context variables section: https://developer.atlassian.com/cloud/jira/platform/rest/#api-api-2-expression-eval-post

Best regards
Krzysztof

Hi @kkercz, thanks for that. I’d seen the documentation page but couldn’t find anything on linked issues.

I have a customer wanting a feature based on knowing the number of resolved linked issues, do you have any idea when this will be available, or do I just need to keep checking the documentation.

Thanks
Paul

I don’t have any dates yet, @paul. I’ll let you know if this becomes available. Alternatively, you can also create an issue in the ACJIRA project on ecosystem.atlassian.net and keep track of it.

1 Like

Hi @kkercz, thanks for this powerful feature!

When using expressions as web conditions is it possible (or planned) to use other entity properties for evaluating conditions similar to entity_property_contains_context ?

For example, in expressions docs there is this example:

['Bug', 'Task'].includes(issue.issueType.name)

but the list to search within is static. And with entity_property_contains_context I can create something like this:

{
  "condition": "entity_property_contains_context",
  "params": {
    "entity": "addon",
    "propertyKey": "issueTypes",
    "contextParameter": "issue.issueType.name"
  }
}

to make the issueTypes list dynamic. Can I use something like this in expressions too?

addon.issueTypes.includes(issue.issueType.name)

Kind regards,
Kirill

Hi, @k.menshov,

It is already possible to use entity properties in Jira expressions. See the Entity properties section in the documentation for more details.

Unfortunately, add-on properties are currently not available, but it is high on our roadmap. After we add it, the expression equivalent to your example will be :

addon.properties.issueTypes.includes(issue.issueType.name)

Meanwhile, perhaps you could store your configuration per project, in project properties?

project.properties.issueTypes.includes(issue.issueType.name)

The above is supported right now.

Best regards,
Krzysztof

1 Like

Thanks a lot, Krzysztof! I don’t think I will be able to use projects unfortunately (there’s too many of them, and I would have to create the same list for all of them), but it’s great to know that the addon entity is coming. Really looking forward to it, thanks again!

1 Like

Hi, @k.menshov,

App properties are now available in Jira expressions. You can access them through the app context variable, which is available:

So you can for example store an object containing a list of issue type names in a property named “your.app.key.property”:

{
   "issueTypeNames": ["Bug", "Task"]
}

And then write a condition that checks if the current issue type has a name included on the list:

app.properties['your.app.key.property'].issueTypeNames.includes(issue.issueType.name)

By the way, it’s probably better to refer to issue types by IDs, since names are configurable and can be changed at any time by Jira administrators. You can do issue.issueType.id to get the ID of an issue type.

Best regards,
Krzysztof

1 Like