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:
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:
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.