Jira expressions - unique custom field in project

pawhan November 2, 2020

I am considering migration to cloud from server and looking if all custom scripts can be migrated.

We have one proj that has 5000 isses with custom fields named SerialNumber. We have one script that ensures unique value of SerialNumber field within project. It is added as validator in multiple places.

From what I undestand in cloud we have to work wth Jira Expressions. Can this validation be implemented using expressions?

Thanks!

6 answers

1 vote
pawhan November 2, 2020

Thanks for reply, we use simple groovy script to execute jql and process results from that later:

import com.atlassian.jira.component.ComponentAccessor
import com.atlassian.jira.bc.issue.search.SearchService
import com.atlassian.jira.jql.parser.JqlQueryParser
import com.atlassian.jira.web.bean.PagerFilter
import com.opensymphony.workflow.InvalidInputException


def issueManager = ComponentAccessor.getIssueManager()
def jqlQueryParser = ComponentAccessor.getComponent(JqlQueryParser)
def searchService = ComponentAccessor.getComponent(SearchService.class)
def customFiledManager = ComponentAccessor.getCustomFieldManager();
def user = ComponentAccessor.getJiraAuthenticationContext().getUser()


//extract proj type and SN value
def serialNumberObject = customFiledManager.getCustomFieldObjectByName('Serial Number')
def projKey = issue.getProjectObject().getKey()
def serialNumber = issue.getCustomFieldValue(serialNumberObject)

//build and execute querry
def queryString = 'project = ' + projKey + ' AND "Serial Number" ~ "\\"' + serialNumber + '\\""'
def query = jqlQueryParser.parseQuery(queryString)
def results = searchService.search(user, query, PagerFilter.getUnlimitedFilter())

// list issues with entered SerialNumber
def msg = ''
results.getResults().each {result ->
def resIssue = issueManager.getIssueObject(result.id)
msg += resIssue.key + ' '
}

// throw exception if sn exists
if(results.getTotal() != 0)
{
throw new InvalidInputException (serialNumberObject.getId(),"SN must be unique, entered arleady used in ${msg}")
}

 

Workarounds like email notifications can be done but this leads to dysfunctional project in our scenario. Worst case I could roll back change in post function?

I read that from validator project context variable is exposed. Can't we simply say something like project.issues.. ?

I must say that I am really confised how jira expressions are suposed to work. Do you have more detailed documentation with examples other than this one:

https://developer.atlassian.com/cloud/jira/platform/jira-expressions/#loading-data

Thanks!

David Fischer
Community Leader
Community Leader
Community Leaders are connectors, ambassadors, and mentors. On the online community, they serve as thought leaders, product experts, and moderators.
November 2, 2020

I believe that's the most extensive documentation there is (and it's the official documentation from Atlassian). JMWE includes online help for Jira expressions, but it's basically the same content.

What you'd want is this: https://ecosystem.atlassian.net/browse/ACJIRA-1789. But Atlassian has indicated they won't implement it.

Like John Funk likes this
1 vote
David Fischer
Community Leader
Community Leader
Community Leaders are connectors, ambassadors, and mentors. On the online community, they serve as thought leaders, product experts, and moderators.
November 2, 2020

Unfortunately, the Jira expressions language cannot run JQL searches, which I bet is what you're currently doing on Server.

The only workaround I can think of is to use a post-function to check the unicity of the serial number and send an email (or add a comment) if the serial number is not unique.

0 votes
Bill Bill June 19, 2021

I worked out a way to do this.  It's not the prettiest but it will get the job done.

You need a new custom field, called "Validation Errors".  You will also need a new Workflow state.  Let's say that previously you had a workflow that looked like:

Working ------(Finish)-------> Done

where Working and Done are states and Finish is a transition.

Your new workflow should look like this:

Working ------(Test)------->Candidate------(Finish)-------> Done

Add additional Transitions from Candidate back to Working.  I call mine "Fix".

You should make your Candidate field read-only to anyone except scriptrunner by setting the State Property "jira.permission.edit.group" to "atlassian-addons-admin" (instead of just setting jira.issue.editable to false, which blocks scriptrunner).  You do this so that your test process is always correct, that you can't get to Done by simply deleting your working error and continuing workflow.

In your Finish transition, set a Condition such that your "Validation Errors" is empty, like

issue.customfield_10169 == null || issue.customfield_10169.length == 0

Now all that's left is for you to create a post-function that will populate your Validation Errors field with any validation issues that used to be your uniqueness Condition, back in Jira Server world.

Here's my such script, I have nothing proprietary here.  This will ensure that each subtask (segment template) will have a unique name within the context of the parent issue.  You could easily adapt this to be unique within some other dataset.

def errors = ""
def parent = issue.fields.parent.key
def siblings = "parent = ${parent} and key != ${issue.key}"
siblings = get("/rest/api/3/search?jql=" + java.net.URLEncoder.encode(siblings, "UTF-8")).asObject(Object).body.issues
for (def s : siblings) {
if (s.fields.summary == issue.fields.summary) {
errors += "Summary \"${issue.fields.summary}\" is replicated by sibling segment template ${s.key}. Change one or the other of them before continuing.\n"
}
}

def fields = get("/rest/api/3/field").asObject(Object).body
def outputField = fields.find {it.name == "Validation Errors"}
logger.info "outputField ${outputField} into which shall be put \"${errors}\""
if (errors.length() > 0) {
put("/rest/api/3/issue/${issue.id}")
.header('Content-Type', 'application/json')
.body ( [ fields: [ (outputField.id):
[
type: "doc",
version: 1,
content: [
[
type: "paragraph",
content: [
[
type: "text",
text: errors
]
]
]
]
] ] ] )
.asObject(Object)
} else {
// for this to work, set Candidate property jira.permission.edit.group to atlassian-addons-admin
put("/rest/api/3/issue/${issue.id}")
.header('Content-Type', 'application/json')
.body ( [ fields: [ (outputField.id):
[
type: "doc",
version: 1,
content: [ ]
]
] ] )
.asObject(Object)
}

This way you can finally express a complex condition that includes a JQL expression, albeit indirectly, in one of these stupid, awful, virtually powerless Jira Expressions.

This was a hell of a lot of work to finagle a (hacky) solution.  I hope it helps somebody else!

0 votes
pawhan November 3, 2020

Thanks for reply. Last question I hope, can this be achieved in post function with scriptrunner or other tool, espacially:

-run jql using rest api and process results

-delete issue

-sent custom email to person that created deleted issue

 

Thanks!

David Fischer
Community Leader
Community Leader
Community Leaders are connectors, ambassadors, and mentors. On the online community, they serve as thought leaders, product experts, and moderators.
November 3, 2020

I can't speak for ScriptRunner, but this can certainly be achieved using JMWE for Jira Cloud. You can add a "Sequence of post-functions" post-function, and in that sequence add (in that order):

- an Email Issue(s) post-function

- a Delete Issue(s) post-function

And then add conditional execution on the Sequence to run the sequence only if the JQL search (run with the jqlSearch filter) returns an issue.

0 votes
pawhan November 2, 2020

Thanks for reply, i see that validators are very limited now.

What are the alternitives to enforce tkat kind of requirements? I am used to situation where on jira server scriptrunner allows me to do almost anything,

David Fischer
Community Leader
Community Leader
Community Leaders are connectors, ambassadors, and mentors. On the online community, they serve as thought leaders, product experts, and moderators.
November 3, 2020

My only recommendation would be... patience. We are hoping that Atlassian will eventually open up Conditions and Validators beyond Jira expressions, once Forge becomes mainstream. But that will likely take another couple of years. 

Like pawhan likes this
0 votes
John Funk
Community Leader
Community Leader
Community Leaders are connectors, ambassadors, and mentors. On the online community, they serve as thought leaders, product experts, and moderators.
November 2, 2020

Hi Pawhan - Welcome to the Atlassian Community!

You should also be able to use Jira Miscellaneous Workflow Extensions (JMWE) add-on to create a custom validator. 

@David Fischer 

Bill Bill June 12, 2021

Please do explain.  I've been fighting the same battle as Pawhan and I can't find a way with this highly crippled "validator" tool.

Like John Funk likes this

Suggest an answer

Log in or Sign up to answer