Customizing the TRAC ticket workflow
I did a quick investigation into TRAC configuration yesterday, and discovered how to customize the ticket workflow to better fit our process.
Out of the box, the normal workflow for tickets is pretty simple: a ticket start out as "new" - it is then assigned for someone to work on, eventually accepted as done, and then finally closed. There are couple of ways to deviate from this process, such as when the work gets rejected and needs more work, or when the ticket needs to be reassigned for somebody else to work on for some reason, but that's generally how it goes.
Our process on larger projects is quite a bit more detailed than that - in fact, most places I've worked, the process is usually a bit more granular than that. Our process is something along the lines of this:
1. A new tickets is created
2. The ticket is assigned for someone to work on.
3. A solution in implemented
4. The solution is deployed to a test (aka "staging") site, for review
5. The work is reviewed and accepted
Again, there are a couple of ways to deviate from that workflow, includes the ones mentioned before, and also in some cases closing a ticket (for example because it's invalid) or reopening a ticket that had already previously been closed.
The Wrong Approach
Some people resort to simply adding a new property to tickets, which is very easy to do - here's a snippet from a custom option added to the "trac.ini" file:
[ticket-custom] progress = select progress.label = Progress progress.options = new|assigned|implemented|reviewing|accepted|rejected|closed progress.value = new
This adds a new drop-down to tickets, labeled "Progress", with the choices you can see defined by the "progress.options" setting above. You will need to make some adjustments to the reports, because custom values don't show up by default, but that's doable.
Why is this wrong?
Ponder for a moment why we had words like "new" and "assigned" in our Progress field - words which also appear in the ticket status.
The problem is that Progress is basically synonymous with Status, and what we end up with is basically two different Status settings. This causes a number of problems, including the fact that our new Progress field doesn't actually mean anything in TRAC as such - it's just a label. And for another, the fact that you can create conflicting Status and Progress combinations - for example, your ticket could be "accepted" and "rejected", at the same time!
So without a fair amount of discipline, and agreement and understanding of how to manage these values "correctly" amongst the team-members, this is not really going to work well.
The Right Approach
Fortunately, when you look into it, and experiment with it for a bit, you will discover that the ticket workflow in TRAC is in fact incredibly flexible!
It's a bit hard to understand and configure than a simple custom field, but so much more valuable, as you can fully customize this to fit your team's workflow.
Here is the workflow-configuration I came up with, implementing the workflow I described in the beginning of this article:
[ticket-workflow] leave = * -> * leave.name = No status change - leave leave.operations = leave_status leave.default = 0 assign = new -> assigned assign.permissions = TICKET_MODIFY assign.operations = set_owner assign.name = Assign assign.default = -1 implement = assigned,rejected -> implemented implement.permissions = TICKET_MODIFY implement.name = Implemented implement.default = -2 deploy = assigned,implemented,rejected -> reviewing deploy.permissions = TICKET_MODIFY deploy.name = Deployed for review deploy.default = -3 accept = reviewing -> closed accept.permissions = TICKET_MODIFY accept.operations = set_resolution accept.set_resolution = fixed accept.name = Accept accept.default = -4 reject = reviewing -> rejected reject.permissions = TICKET_MODIFY reject.name = Rejected (needs more work) reject.default = -5 close = new,assigned,implemented,reviewing,rejected -> closed close.permissions = TICKET_MODIFY close.operations = set_resolution close.name = Close close.default = -6 reassign = assigned,implemented,reviewing,rejected -> assigned reassign.permissions = TICKET_MODIFY reassign.operations = set_owner reassign.name = Re-assign reassign.default = -7 reopen = closed -> assigned reopen.permissions = TICKET_CREATE reopen.operations = set_owner reopen.name = Re-open and Assign reopen.default = -8
Each section of this configuration defines a single possible action in the workflow - the activities you can perform: assign, implement, deploy, accept or reject, close, and reassign or reopen when needed.
The first setting for each defined action (with the "
->" symbol in it) defines allowed status(es) and the new status after performing that action - for example, the "deploy" action is defined as "assigned,implemented,rejected -> reviewing", meaning you can change the ticket-status to "reviewing" only when the status is "assigned", "implemented" or "rejected". Note that the statuses themselves are not formally defined in the configuration file - the possible statuses are implicitly defined by configuring actions.
The "permissions" setting is optional, and defines what level of permission is required to perform the action. For the most part, the right to modify a ticket (TICKET_MODIFY) is enough - but in our case, we think that reopening a ticket should only be allowed if you're allowed to create new tickets (TICKET_CREATE).
The "operations" setting defines one or more operations you want TRAC to do when this action is performed. This affects the user-interface - for example, the "set_resolution" operation (which we used for the "close" action above) displays with a drop-down to select the resolution. Note that the "set_resolution" operation has an optional "set_resolution" setting, which allows you to specify one or more resolution-types allowed for this action - for example, the "accept" action we defined, only allows one resolution: "fixed".
The are two more simple, but very important (and underused) settings for actions. The "name" setting defines how the action is displayed - for example, "Re-open and Assign" is more descriptive than simply "reopen" - use this setting to clarify the meaning of the action and how or when to use it. And finally, the perhaps somewhat misleadingly named "default" setting, which actually defines the priority (sort order) of available actions in the user-interface. This is important, because it enables you to communicate which action is most likely next, by displaying it first. Oddly, the options are sorted backwards by this value, which is why I used a negative number in our configuration.
TRAC is a very powerful tool that comes with a lot of humble (sometimes underwhelming) configuration out of the box - but when you look under the surface, it really is an incredibly powerful tool with lots of optional features and an incredible degree of flexibility, allowing you to adapt it to pretty much any work-environment.
I hope you enjoyed this little tutorial and a glimpse of our process.