How do I compare against fixVersions field in ScriptRunner

Greetings,

I am trying to create a validator in my JIRA workflow to check against a range of versions in Fix Version field, but can't seem to duplicate what I can execute with JQL.

For example, I can successfully execute fixVersion >= 2.7.0 AND fixVersion <= 2.10.0 in JQL and it will return all tickets that have a Fix Version that is equal to or falls in between those two versions, such as 2.7.1, 2.8.0, 2.9.0, etc.

I try using the same logic in the ScriptRunner validator in my JIRA workflow, but get errors in script:

(issue.fixVersions >= '2.7.0' && issue.fixVersions <= '2.10.0')

I would think if it is possible in JQL, then it is possible in ScriptRunner, and I am probably just missing something simple with my syntax in ScriptRunner.

Any thoughts, ideas, or suggestions would be gratefully appreciated.

Thanks for your support,

Terry

2 answers

I'm guessing JQL is actually comparing those using the project level ordering of the versions; so, for example, if you placed a '3.1.0' in between those in the Version manager for the project, it would show up.

With that thought as my base assumption, for that to work in ScriptRunner, at a minimum you'd probably have to fetch the exact Version object for this project's "2.7.0", and compare against that.  Something like:

VersionManager versionManager = ComponentManager.getInstance().getVersionManager();
Version twoSevenZero = versionManager.getVersion(issue.getProject().getId(),"2.7.0");
Version twoTenZero = versionManager.getVersion(issue.getProject().getId(),"2.10.0");

You'd then have to iterate through the list of versions returned by issue.getFixVersions() and compare each one individually.  Even then, you may have to compare Version.getSequence(), not the direct versions; I'm guessing they don't have a built-in comparitor, as such a thing would only really be feasible for a group of Version objects belonging to the same project.

Hi Terry,

Exactly what @Jeremy Gaudet said, and wrapping it in a validator

import com.atlassian.jira.component.ComponentAccessor
import com.atlassian.jira.issue.Issue
import com.atlassian.jira.project.version.Version
import com.opensymphony.workflow.InvalidInputException

Issue issue = issue
def versionManager = ComponentAccessor.getVersionManager()
def issueVersions = issue.getFixVersions()
def projectId = issue.getProjectId()

Version maxVersion = versionManager.getVersion(projectId, "2.0")
Version minVersion = versionManager.getVersion(projectId, "1.0")

for (version in issueVersions) {
    def comparisonResult = version.sequence &gt;= minVersion.getSequence() &amp;&amp; version.sequence &lt;= maxVersion.getSequence()
// with the first issue's fixVersion that fails the comparison throw exception without waiting to compare the rest
    if (!comparisonResult) {
        invalidInputException = new InvalidInputException("Version " + version.name + " is less than " + minVersion.name + " OR greater than " + maxVersion.name)
    }
}

A note here. If let's say that you create a new version 1.1.1 after the 2.0 then your validator will fail (the same happens with your JQL) because it actually compares the sequences (which depends on which version created earlier)

0 vote

It's true IIRC that in JQL it will use the version sequences, which is counter-intuitive, but I guess will work even when people use things like codenames for versions.

If you want semantic versioning comparison, you can use a utility class which happens to be available in ScriptRunner:

import org.apache.maven.artifact.versioning.DefaultArtifactVersion

    /**
     * Compares two version strings
     *
     * @param v1 a version string
     * @param v2 a version string
     * @return Returns negative if v1 is less than v2, and positive if v1 is greater than v2, else zero
     */
    public static Integer compareVersions (String v1, String v2) {
        new DefaultArtifactVersion(v1).compareTo(new DefaultArtifactVersion(v2))
    }

but you might need to check that the strings can be parsed as versions...

So I am trying to simplify my solution using the Simple Scripted Validator, but it doesn't seem to work due to the way it exits the evaluation if the first clause is met.

For example, I only want to transition the ticket if the Fix Version is NOT set to version A, version B, version C or empty (None)?

I tried using (issue.fixVersions[0].toString() != '2.10.0' && issue.fixVersions[0].toString() != '2.11.0' && issue.fixVersions[0].toString() != 'Future' && issue.fixVersions), but the Simple Scripted Validator doesn't continue to evaluate the second clause if the first is TRUE, so if the Fix Version is set to '2.11.0' it will still transition and not throw the error message since the first clause is met.

I am probably overthinking what should be a simple solution, so any help would be gratefully appreciated.

Thanks for your support,

Terry

that's called short-circuit evaluation. Try something like

! issue.fixVersions*.name.intersect(["2.0.0", "2.1.0", "etc"])

Thanks Jamie!  That looks like it will work for the validator.

I also played around with the Script Condition (Allows the transition if this query matches a JQL query) and was able to get the following to work as well.

fixVersion &gt;= 2.5.3 AND fixVersion &lt;= 2.9.0 OR fixVersion = FB

Thanks again for all of your help!

Just need to figure out which one Product Management wants to use now and go from there.

we have two version names are 1.Future release, 2. Future.
based on one issuetype,on create screen user should not select above both values.

I am trying following line in my workflow validator on create action.
How can restrict user not select above two versions from the version field on create action.

["Future Release","Feature"] in issue.fixVersions*.name

@Jamie Echlin [Adaptavist]I have tried following code on create action, but i am unable to validate.Can you help me to figured it out, 

!('Future Release' in issue.fixVersions*.name || 'Feature' in issue.fixVersions*.name)

Hi Suresh,

If it is for a Simple Scripted Validator then try something like 

! (issue.fixVersions*.name.contains("Version1") || issue.fixVersions*.name.contains("Version2"))

Regards, Thanos 

Thank you Thanos,
we are using custom field ,that loads all the fixversion values.
The customfield(multi select version type) name is: Target Version


do we need to replace with the 'fixVersions' by 'Target Version'?

!(issue.Target Version*.name.contains("Feature") || issue.Target Version*.name.contains("Future Release"))

Suggest an answer

Log in or Sign up to answer
Atlassian Community Anniversary

Happy Anniversary, Atlassian Community!

This community is celebrating its one-year anniversary and Atlassian co-founder Mike Cannon-Brookes has all the feels.

Read more
Community showcase
Bridget Sauer
Published yesterday in Marketplace Apps

Calling all developers––You're invited to Atlas Camp 2018

 Atlas Camp   is our developer event which will take place in Barcelona, Spain  from the 6th -7th of   September . This is a great opportunity to meet other developers and get n...

70 views 0 5
Read article

Atlassian User Groups

Connect with like-minded Atlassian users at free events near you!

Find a group

Connect with like-minded Atlassian users at free events near you!

Find my local user group

Unfortunately there are no AUG chapters near you at the moment.

Start an AUG

You're one step closer to meeting fellow Atlassian users at your local meet up. Learn more about AUGs

Groups near you