Introduction
Sometimes one wishes an issue to pass through a set of transitions, but the order in which they are run does not matter. For example, if an issue must be approved by 3 different managers, the order usually doesn't matter.
JIRA uses the OSWorkflow library to manage transitions. OSWorkflow is technically capable of handling our situation, through its mechanism of splits and joins. Although JIRA's workflow editor is not capable of adding splits and joins (see JRA-4147), they can be added by hand to the workflow definition, in XML form, and this modified workflow loaded back into JIRA.
This page describes how to implement a simple split where 3 managers are required to approve an issue before it can be worked on:
/--> Manager1 Approves -\
/ \
(Create) -+---> Manager2 Approves ------> Open --> In Progress -> ...
\ /
\--> Manager3 Approves /

Try this at your own risk. JIRA does not 'know' about OSWorkflow splits and joins, and use of them will break parts of JIRA. Specifically:
Overall, you should only attempt to do this if you are happy to fix broken issues in the database if it all goes wrong. The relevant relations are described in the database schema documentation. If you are not willing to take this risk, please vote and watch JRA-4147, which will be updated with official progress towards meeting this need. |
Create an interim template workflow
First, create a workflow that is as close as possible to what we want. You probably already have a workflow, and want to add an approval step at some point. For this example, we take the default JIRA workflow.
Add new statuses
We wish 3 managers to approve our issue. We need a "Pending Approval" state for issues being approved. Create two other temporary statuses too:

Create new workflow
Copy the workflow you wish to add approvals to. Call it "Interim Approval Workflow" or somesuch, since we will not actually be using it in this form.

Now edit the interim workflow. Add new approval steps, each linked to one of the new statuses. Also add a transition to each to the step you wish the approval to end with. In our case, we want approved issues to be Open.
You probably want each approval step to be restricted to a certain group, so add a Condition to each step to meet your requirements.
The end result of all this editing will look like this:

Edit the workflow XML.
Return to the page listing the workflows, and click 'XML' to get a copy of the interim workflow's XML. Save this to disk.
We now need to edit the workflow XML by hand, to:
- Modify the transition that creates the issue, to split the issue into our 3 new steps.
- Modify our 3 steps so that their "ManagerX Approves" transition invoke a join (undoing the split).
- Modify our 3 steps to refer to the same status ("Pending Approval")
Adding a split
Open up the workflow XML in a text editor. At the end, before the closing </workflow> add the split definition:
<splits> <split id="1"> <unconditional-result old-status="Finished" step="7" status="Underway"/> <unconditional-result old-status="Finished" step="8" status="Underway"/> <unconditional-result old-status="Finished" step="9" status="Underway"/> </split> </splits>
Here we've defined a 'split' that results in 3 steps.
Now modify the transition where we want to invoke the split. In our case, we want to split immediately the issue is created, so we go to the 'initial' action, and change:
<initial-actions> <action id="1" name="Create Issue"> .... <unconditional-result old-status="Finished" status="Open" step="1">
to:
<initial-actions> <action id="1" name="Create Issue"> .... <unconditional-result old-status="Finished" split="1">
ie. instead of resulting in step 1 ("Open") we result in split 1.
The step IDs in the join definition (7, 8, 9) should refer to the 3 steps we created:
...
<step id="7" name="Pending Manager1 Approval">
...
<step id="8" name="Pending Manager2 Approval">
...
<step id="9" name="Pending Manager3 Approval">
The join is evaluated whenever an approval step is evaluated.
Adding a join
Similarly, add the join definition at the end of the file, before the </workflow>:
<joins> <join id="1"> <conditions type="AND"> <condition type="beanshell"> <arg name="script"> "Finished".equals(jn.getStep(7).getStatus()) && "Finished".equals(jn.getStep(8).getStatus()) && "Finished".equals(jn.getStep(9).getStatus()) </arg> </condition> </conditions> <unconditional-result old-status="Finished" status="Approved" step="1"/> </join> </joins>
Again, make sure that the steps referenced (7, 8, 9) refer to the right steps.
We want this join to be invoked whenever a "ManagerX Approves" transition is run. So go to each approval step and modify the transition's unconditional result, eg. from:
<step id="7" name="Pending Manager1 Approval"> <meta name="jira.status.id">10000</meta> <actions> <action id="711" name="Manager1 Approves"> <meta name="jira.description"/> <results> <unconditional-result old-status="Not Done" status="Done" step="1"> .....
to:
<step id="7" name="Pending Manager1 Approval"> <meta name="jira.status.id">10000</meta> <actions> <action id="711" name="Manager1 Approves"> <meta name="jira.description"/> <results> <unconditional-result old-status="Finished" join="1"> .....
Note: we changed old-status to Finished, deleted the status attribute and replaced step="1" with join="1".
Do the same for Pending Manager2 Approval and Pending Manager3 Approval.
Make approval steps refer to same status.
We want all three approval steps (edited above) to refer to the Pending Approval state. Change:
<step id="8" name="Pending Manager2 Approval"> <meta name="jira.status.id">10001</meta>
to:
<step id="8" name="Pending Manager2 Approval"> <meta name="jira.status.id">10000</meta>
and:
<step id="8" name="Pending Manager3 Approval"> <meta name="jira.status.id">10002</meta>
to:
<step id="8" name="Pending Manager3 Approval"> <meta name="jira.status.id">10000</meta>
Import the edited XML
Now import the XML from the JIRA workflow editor. When importing, we've called it "Approval Workflow":

Clicking on it, it should look like this:

Apply new workflow
Now create a workflow scheme:

and associate it with a project.
Now try creating an issue. Immediately after creation, you should see 3 transitions available (depending on the conditions you placed on the steps):

Clicking on any 'Approve' transition will 'remove' it:


and after the last approval, the issue progresses to the 'Open' state:


Comments (4)
Nov 28, 2007
Laurent BEDE says:
Hi, how do I prevent a manager from approving more than once ? thx, LaurentHi,
how do I prevent a manager from approving more than once ?
thx,
Laurent
Feb 04, 2008
Yancy Way says:
This would be done in the groups that have permissions for each of these worflow...This would be done in the groups that have permissions for each of these worflows. As long as you don't have someone in more than one of the approval groups, the manager should only be able to approve one time.
That said, I've already had to clean up a few issues in the DB after a few months of usage, so the warnings are apt!
Mar 04, 2008
Dean Vermeire says:
How do I prevent someone from going in and editing the other fields after the is...How do I prevent someone from going in and editing the other fields after the issue has been approved?
Aug 26
instrumentality says:
Can a workflow be selected through a combination of two or more field values? F...Can a workflow be selected through a combination of two or more field values? For instance, I would like to use this for change management. Suppose my "project" is a particular application--let's call it Easyapp. Also suppose I wanted to have a different workflow for standard changes (e.g. two people approve before the change goes to "Open" state) as opposed to emergency changes (e.g. one person approves before the change goes to "Resolved" state). Based on the fact that "Issue Type" is the only other field that pops up on the "Create New Issue" screen, I imagine I would need to set up new issue types "Change - Standard" and "Change - Emergency." How can I set this up such that the *workflow* is different for a standard Easyapp change vs. an emergency Easyapp change, and how do I set it such that the workflow structure is the same for changes to another app but different individuals/groups fill the approver slots?