Validators check that any input available to the transition (such as user-supplied input) is valid before the transition is performed. If a transition's validator 'fails', the transition's post functions will not be executed and the issue will not progress to the destination step of the transition.
You can use JJupin and SIL to define a large set of validators beside the default validators offered by Jira, by just adding a (k) SIL Validator to a transition and publishing the workflow, as described here.
Below are just a few common examples:
Required plugins
Comment required
A validator that forces users to enter a comment during a transition, otherwise displaying a customized error message:
string errorMsg = "You must enter a comment!"; if(!hasInput("comment")) { return false, "comment", errorMsg; }
Field has single value
A SIL validator for checking if a multi-valued field does not contain more than one value during a transition:
string errorMsg = "You must choose a single fix version!"; if(size(fixVersions) > 1) { return false, "fixVersions", errorMsg; }
Parent status
A SIL validator which ensures that the current issue's parent issue is in one of the specified Statuses:
string[] statuses = {"Opened", "Reopened"}; string errorMsg = "Parent issue should have status Opened or Reopened!"; if(!isNull(parent) && !elementExists(statuses, parent.status)) { return false, errorMsg; }
Validation on linked issues
Blocking Start Progress transition whenever current issue has a link of type Blocks with an issue in a status different from Resolved and Closed:
string errorMsg = "Progress can't start because there is at least one blocking issue."; string[] statuses = {"Resolved", "Closed"}; string[] blockingIssues = linkedIssues(key, "Blocks"); for(string issue in blockingIssues) { if(!elementExists(statuses, %issue%.status)) { return false, errorMsg; } }
Forbidding issue links of types Blocks and Cloners with issues of type Bug:
string errorMsg = "Issue links of types 'Blocks' and 'Cloners' with 'Bugs' are forbidden."; string[] links = {"Blocks", "Cloners"}; for(string link in links) { string[] linkedIssues = linkedIssues(key, link); for(string issue in linkedIssues) { if(%issue%.issueType == "Bug") { return false, errorMsg; } } }
Validation on non-linked issue
Preventing a transition from being executed if the rest of issues in the project aren't closed:
string errorMsg = "There are still unclosed issues in the current project."; string[] issues = selectIssues("project = " + project + " AND status != Closed AND key != " + key); if(size(issues) > 0) { return false, errorMsg; }
Compare two parsed texts
A SIL validator which checks if description contains summary:
string errorMsg = "Description must contain summary"; if(!contains(description, summary)) { return false, "description", errorMsg; }
Users in a field are/aren't in a project role
A SIL validator which checks if users selected in a multi user picker custom field are in a given project role:
string PROJECT_ROLE = "Developers"; for(string user in customfield_10500) { if(!isUserInRole(user, project, PROJECT_ROLE)) { string errorMsg = "User " + user + " is not in project role " + PROJECT_ROLE; return false, "customfield_10500", errorMsg; } }
A custom field is/isn't initialized
A SIL validator which checks if a custom field is initialized during transaction:
string errorMsg = "Field was not initialized!"; if(!hasInput("customfield_10500")) { return false, "customfield_10500", errorMsg; }
Check user property
A SIL validator which checks if a user property has a certain value:
string COUNTRY = "Romania"; string errorMsg = "Assignee country must be " + COUNTRY; if(getUserProperty(assignee, "country") != COUNTRY) { return false, "assignee", errorMsg; }