Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

Button handy
blanktrue
color#0052CC
nameSend Feedback
linkhttps://docs.google.com/forms/d/e/1FAIpQLScmToBe3vynAlb5fdKwCGxYqnTbDc66sIBgeecG2BuFDuHc7g/viewform?entry.2002826954=Scripted+Conditions+and+Validators+in+cloud+-+a+new+paradigm+-+804552898
widthauto

When Jira Cloud was launched custom conditions and validators didn’t even exist. This is because they completely break the design of the cloud architecture. Performing an action in the cloud sets off a chain reaction of micro-services and events all at once, like knocking over multiple rows of dominos. Conditions and validators require a pause in those events while they determine if the domino should fall over or if it is allowed to fall over. It really doesn't work like that so instead of being able to use scripted conditions and validators Atlassian release the expressions language which is the only available way to create custom conditions and validators.

Jira expressions is like any problem “solved” by the government or some service provided by the government. Yes, it technically does the job but the experience usually leaves a lot to be desired. While you can use Jira expressions if you really want to, another solution may be to approach the problem from another direction. Instead executing the script that decides if the transition can/should be performed right at that moment in time like conditions and validators do, you could use scripts to pre-calculate the answer. Using listeners you could store the answer to that question in invisible issue fields called issue entity properties. Then, with expressions you could simply check the value of that property thus created a truly scripted solution and minimizing the need to use expressions.

Example

Below is an example of a validator that controls whether or not a user can transition an issue based on the status or resolution of linked issues.

Code Block
// custom script validator
import com.atlassian.jira.component.ComponentAccessor
import com.atlassian.jira.bc.issue.search.SearchService
import com.atlassian.jira.web.bean.PagerFilter
import com.atlassian.jira.jql.parser.JqlQueryParser
import com.opensymphony.workflow.InvalidInputException

def current_user = ComponentAccessor.jiraAuthenticationContext.loggedInUser
def query = /assignee = currentUser() and project = "$issue.projectObject.name" and statusCategory = "In Progress"/ // searching for current user having in-progress issues in current project
def jql = ComponentAccessor.getComponent(JqlQueryParser).parseQuery(query)
def page_filter = new PagerFilter(1) // 1 = search only 1 issue

def in_progress_issues = ComponentAccessor.getComponent(SearchService).search(current_user, jql, page_filter)

if(in_progress_issues){ // exist at least one in-progress issue
    invalidInputException = new InvalidInputException("VALIDATION FAILED MESSAGE YOU WANT")
}else{
    true // true = validation is pass
}

...

Goal: I've got an issue type of "Dev ask" that uses a workflow that is standard for all subtasks. When this groundwork status is updated to "Complete", I want to check that all sibling subtasks are assigned (because this is just part of the responsibilities for the person who completes the groundwork task). If any are Unassigned this transition should fail.

Jira Expressions

Code Block
issue.issueType.name.match('^(Dev Task)$') == null || 
(issue.issueType.name.match('^(Dev Task)$') != null && 
issue.parent.subtasks.filter(subtask => subtask.assignee != null).length == 
issue.parent.subtasks.length)? true : false

Power Scripts alternative solution

The alternative solution is to prepopulate the result of the condition or validator much the same way the Jira Cloud prepopulates JQL functions. A SIL Listener updates hidden field values for the issue (issue entity properties) with the result. Then, in the workflow a condition/validator is added that simply checks the value of that hidden property.

Benefits

  • SIL is easier to write compared to Jira expressions

  • SIL is easier to read compared to Jira expressions

  • SIL is easier to test compare to Jira expressions

SIL Listener or Action script

In this example this script should be placed on the “Complete” transition for the subtask workflow. However, this script can also be used as a listener script that is trigger when the issue is updated.

Code Block
boolean passConditionValue = true;
if(issueType == "Dev Task") {
    for(string s in subtasks(parent)) {
        
        if(s.issueType == "Dev Task && isNull(s.assignee)) {
    return true; } else if (issue.project.key == 'PROJECT' )passConditionValue {= false;
   new Issue('PROJECT-1234').description.plainText.includes(issue.customfield_1235);  } else if (issue.project.key == 'PROJECT2' ) { 
   new Issue('TEST-1235').description.plainText.includes(issue.customfield_1235); 
} else { 
   return false;
}}
    }
}
setIssueEntityPropertyValue(key, "passCondition", passConditionValue);

Jira Expression that uses SIL script value

The benefit of this expressions condition/validator is that is can work any action that uses this method. The expression can be copied from workflow to workflow with only the name of property requiring an update. There is no need to master the difficult expressions syntax.

Code Block
JSON.stringify(issue.properties['

...

passCondition']).includes('

...

true')

We've encountered an issue exporting this macro. Please try exporting this page again later.