Conditions

 

1 - Previous Status Condition

A workflow condition that allows you to disable a particular transition (hiding it from the list of Available Workflow Actions) if the current Issue either:

  • has never been in the specified Status
  • or was not in the specified Status just before it entered the current Status (if "Most recent status only" is checked)

Why on Earth would I need something like this?

 

A typical use for this workflow condition is when you can reach a certain Status from several other Statuses (through the same Transition) and want to be able to return to the originating Status.
Consider the following partial workflow :

JIRA will allow you to create a single Transition from both Open and In Progress statuses to the Waiting for clarification status. But how do you create the transition (Provide info) back to Open and In Progress? And, more importantly, how do you make sure the issue is transitioned back to the originating status?
Here's the trick:

  1. create two Provide info transitions, one from Waiting for clarification to Open, and another from Waiting for clarification to In Progress (just add a space at the end of the name of one of the two transitions so that JIRA doesn't complain about duplicate transition names).
  2. on the first transition, add a Previous Status Condition to make the transition available only if the previous status was Open (don't forget to check the "Most recent status only" checkbox).
  3. on the second transition, add a Previous Status Condition to make the transition available only if the previous status was In Progress (don't forget to check the "Most recent status only" checkbox).

And voilà! Your users will see only one transition from the Waiting for clarification status, and it will transition the ticket back to the originating status.

Note that you could also use an advanced feature of JIRA that allows you to define conditional "<result>" elements in the XML definition of a transition, but you need to edit the workflow XML and this is definitely not for the faint of heart. Below is an example XML snippet extracted from a workflow XML (only the transition XML is shown):

Transition with conditional destination steps
        <action id="801" name="Provide Information" view="fieldscreen">
          <meta name="jira.description">Provide the requested information</meta>
          <meta name="jira.fieldscreen.id">10010</meta>
          <validators>
            <validator name="" type="class">
              <arg name="errorMessage">You must provide your answer in the Comment field.</arg>
              <arg name="class.name">com.innovalog.jmwe.plugins.validators.CommentRequiredValidator</arg>
              <arg name="hidGroupsList"></arg>
            </validator>
          </validators>
          <results>
            <result old-status="Not Done" status="Done" step="1">
              <conditions>
                <condition type="class">
                  <arg name="jira.previousstatus">Open</arg>
                  <arg name="class.name">com.innovalog.jmwe.plugins.conditions.PreviousStatusCondition</arg>
                  <arg name="jira.mostRecentStatusOnly">yes</arg>
                </condition>
              </conditions>
              <post-functions>
                <function type="class">
                  <arg name="class.name">com.googlecode.jsu.workflow.function.CopyValueFromOtherFieldPostFunction</arg>
                  <arg name="destinationField">assignee</arg>
                  <arg name="sourceField">customfield_10090</arg>
                </function>
                <function type="class">
                  <arg name="class.name">com.atlassian.jira.workflow.function.issue.UpdateIssueStatusFunction</arg>
                </function>
                <function type="class">
                  <arg name="class.name">com.atlassian.jira.workflow.function.misc.CreateCommentFunction</arg>
                </function>
                <function type="class">
                  <arg name="class.name">com.atlassian.jira.workflow.function.issue.GenerateChangeHistoryFunction</arg>
                </function>
                <function type="class">
                  <arg name="class.name">com.atlassian.jira.workflow.function.issue.IssueReindexFunction</arg>
                </function>
                <function type="class">
                  <arg name="class.name">com.atlassian.jira.workflow.function.event.FireIssueEventFunction</arg>
                  <arg name="eventTypeId">10008</arg>
                </function>
              </post-functions>
            </result>
            <result old-status="Not Done" status="Done" step="3">
              <conditions>
                <condition type="class">
                  <arg name="jira.previousstatus">In Progress</arg>
                  <arg name="class.name">com.innovalog.jmwe.plugins.conditions.PreviousStatusCondition</arg>
                  <arg name="jira.mostRecentStatusOnly">yes</arg>
                </condition>
              </conditions>
              <post-functions>
                <function type="class">
                  <arg name="class.name">com.googlecode.jsu.workflow.function.CopyValueFromOtherFieldPostFunction</arg>
                  <arg name="destinationField">assignee</arg>
                  <arg name="sourceField">customfield_10090</arg>
                </function>
                <function type="class">
                  <arg name="class.name">com.atlassian.jira.workflow.function.issue.UpdateIssueStatusFunction</arg>
                </function>
                <function type="class">
                  <arg name="class.name">com.atlassian.jira.workflow.function.misc.CreateCommentFunction</arg>
                </function>
                <function type="class">
                  <arg name="class.name">com.atlassian.jira.workflow.function.issue.GenerateChangeHistoryFunction</arg>
                </function>
                <function type="class">
                  <arg name="class.name">com.atlassian.jira.workflow.function.issue.IssueReindexFunction</arg>
                </function>
                <function type="class">
                  <arg name="class.name">com.atlassian.jira.workflow.function.event.FireIssueEventFunction</arg>
                  <arg name="eventTypeId">10008</arg>
                </function>
              </post-functions>
            </result>
            <unconditional-result old-status="Not Done" status="Done" step="7"> <!-- Resolved -->
              <post-functions>
                <function type="class">
                  <arg name="class.name">com.googlecode.jsu.workflow.function.CopyValueFromOtherFieldPostFunction</arg>
                  <arg name="destinationField">assignee</arg>
                  <arg name="sourceField">customfield_10090</arg>
                </function>
                <function type="class">
                  <arg name="class.name">com.atlassian.jira.workflow.function.issue.UpdateIssueStatusFunction</arg>
                </function>
                <function type="class">
                  <arg name="class.name">com.atlassian.jira.workflow.function.misc.CreateCommentFunction</arg>
                </function>
                <function type="class">
                  <arg name="class.name">com.atlassian.jira.workflow.function.issue.GenerateChangeHistoryFunction</arg>
                </function>
                <function type="class">
                  <arg name="class.name">com.atlassian.jira.workflow.function.issue.IssueReindexFunction</arg>
                </function>
                <function type="class">
                  <arg name="class.name">com.atlassian.jira.workflow.function.event.FireIssueEventFunction</arg>
                  <arg name="eventTypeId">10008</arg>
                </function>
              </post-functions>
            </unconditional-result>
          </results>
        </action>

Note that even though you cannot edit conditional results (conditional destination steps) within JIRA, you can still view them in the "Other" tab JIRA adds to the Transition screen:

You can also restore the previous Assignee by saving it in a custom field during the Request clarification transition and then restoring it during the Provide info transition (see the Copy Value From Field To Field workflow post-function). Alternatively, you can use the Assign to last role member function described below to assign the issue to the last user in the Users role.

2- Separation of Duties Condition (new in 1.1)

A workflow condition that enforces separation of duties (for SAS-70                     compliance), i.e. that makes sure the same user cannot trigger two incompatible transitions on the same issue.
For example, you can prevent a user who has triggered the "Resolve Issue" transition on an issue to trigger the "Close" issue.

Specifying the incompatible transition

 

Because JIRA does not keep track of actual transitions (or workflow actions) but only of changes in the Status of an issue, it is impossible to distinguish between two transitions that share the same source and destination Statuses.
Therefore, the Separation of Duties Condition requires that you specify transitions in the form of a destination Status and a source Status (or Any for all transitions leading to the destination Status).

3 - Hide Transition "Condition" (new in 2.2)

The purpose of the Hide Transition workflow condition is to hide a transition from the user, thus preventing the user from triggering it, while making it available to the Transition Parent Issue function or to scripts or remote API calls.