Author Archive

Customizing the TRAC ticket workflow

Tuesday, March 26th, 2013

At GORGES (among other tools) we use TRAC to manage bugs and feature requests (aka “tickets”) and tracking those against various version control systems.

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.

Conclusion

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.

Rasmus Schultz has worked for web development companies, advertising agencies and a music software company during his extensive development career. His main strengths are software development and database design. Rasmus has more than a decade of experience with many development platforms, languages and standards.

<b> and <i> are still good

Wednesday, June 27th, 2012

I just had a small “a-hah”.

The <b> and <i> tags have been generally dismissed, in favor of <strong> and <em> which have semantic meaning.

But as they pointed out in the twitter bootstrap documentation, <b> and <i> are still valid!

Most people seem to think they were deprecated because they have no semantic meaning – that was certainly my impression.

But they were not deprecated – in fact they were kept around for the very same reason – because they have no semantic meaning.

In other words, if you need to highlight words of phrases without conveying additional importance, you should be using <b>, while <i> can be used for example to stress technical terms or voice, again, without communicating anything semantic, just for visual distinction.

This may seem like a tiny, irrelevant thing, but I find these details can be helpful when thinking about HTML as a “rich text” medium.

Rasmus Schultz has worked for web development companies, advertising agencies and a music software company during his extensive development career. His main strengths are software development and database design. Rasmus has more than a decade of experience with many development platforms, languages and standards.

Client-side Data Binding

Monday, February 6th, 2012

Anybody give much thought to client-side data-binding these days?

OrientDB is nearing version 1.0, and it has a native HTTP/JSON interface – it supports classes, inheritance and all kinds of relationships, all the things we try to simulate with object-relational mappers when building a domain-model, which makes me wonder… why use an ORM at all?

If you’re going to do all your data-binding on the client-side, and if a graph database can natively represent your domain-model without a line of code, why struggle to achieve the same thing with server-side code and object-relational mapping?

You’d only need controllers/actions for actual business-operations. You could probably implement a thin “proxy” for operations like updates and deletes, access control and user identity, etc… You would never need to render a template, generate tables or forms or parse a form-post or implement tedious CRUD operations on the server-side.

It all sounds dreamy, and I can see this working out great for applications.

But what about SEO? The internet lives and breathes HTML. So it seems it’s not an approach that will work for public-facing pages.

Any thoughts? :-)

Rasmus Schultz has worked for web development companies, advertising agencies and a music software company during his extensive development career. His main strengths are software development and database design. Rasmus has more than a decade of experience with many development platforms, languages and standards.

jQuery replacement for window.console

Friday, December 9th, 2011

Can you honestly say you have never left a console.log() statement in production code?

There are legitimate reasons to leave them in test/staging code, if you’re still working out some details.

So I wrote this little library as a replacement.

It doesn’t blow up when the console is not available, adds chainable log() and warn() methods to jQuery selectors, and improves a bit on the display in FF and IE9.

Tested and working nicely in FF, IE9 and Chrome.

I realize this isn’t a groundbreaking idea – but I looked at a couple of existing libraries that do something similar, and nothing really seemed to work well in IE.

Also, this kind of thing should be small – this script compresses to less than 0.5 KB.

Rasmus Schultz has worked for web development companies, advertising agencies and a music software company during his extensive development career. His main strengths are software development and database design. Rasmus has more than a decade of experience with many development platforms, languages and standards.

jQuery DOM shortcuts

Monday, June 13th, 2011

Working daily with jQuery, at GORGES I frequently need to construct little document snippets and forms on the fly. Today I came up with a quick little meta-programming “hack” that makes this very easy and fast.

Most people simply do something along the lines of this:

$('body').append('<h1>Hello, World</h1>');

jQuery injects the HTML string into the DOM, and all is well.

But sometimes you need to inject more structured content, or even entire forms – what I typically do is something along the lines of this:

jQuery('body').append(
  $('<div/>').append(
    $('<div/>').text('Hi there'),
    $('<p/>').text('How do you do?')
  )
);

With all the parentheses, angle brackets and repetitive calls to append(), this doesn’t exactly look nice.

Recognizing the repetitive construction of elements, followed by calls to append, what if we had a set of tiny functions that would do both in one simple operation? I decided to give it a shot, and here’s what it looks like:

jQuery('body').append(
  $div(
    $h2('Do you love it?'),
    $form(
      $div('Sign here:', $text()),
      $div($label($checkbox('yes'), 'I love it!')),
      $ul(
        $li($radio('1'), 'Option One'),
        $li($radio('2'), 'Option Two'),
        $li($radio('3'), 'Option Three')
      ),
      $submit('I submit!')
    )
  )
);

The functions prefixed with the $-sign create the elements, and pass down any arguments to the append() method.

The input element methods, such as $radio and $submit are a bit different – they create input elements, set the type-attribute, and if you pass them an argument, they apply that as the value-attribute on the element. (input elements can’t have child-elements, so this doesn’t get in the way of anything.)

You can see a working example and source code here.

Because JavaScript is a highly dynamic language, I didn’t need to write each of these $-functions by hand – with just 13 lines of JavaScript, applying a simple meta-programming technique, all of the functions are automatically generated.

Finally, it’s worth noting that something like $('<div/>') actually results in a string of HTML being parsed and then inserted into the browser. My handy little DOM-helpers avoid the parser – they access the DOM and create HTML elements directly, which means they execute around 10 times faster compared to the first example.

Update

One of my GORGES colleagues pointed out the fact that I had no convenient way to apply attributes to the created elements – if you don’t like the repetitive calls to attr(), try this updated version, which provides a simplified way to apply attributes quickly. This takes a bit more code, but I suspect he’s now porting this to CoffeeScript

Rasmus Schultz has worked for web development companies, advertising agencies and a music software company during his extensive development career. His main strengths are software development and database design. Rasmus has more than a decade of experience with many development platforms, languages and standards.

Transition operating systems

Monday, May 16th, 2011

Modern mobile operating systems are all the hype, and we’re feeling it here at GORGES – clients are becoming increasingly aware of the importance of mobile technology.

The major contenders when it comes to mobile operating systems are Android, iOS (more commonly known as iPhone, iPad and iPod), and Windows Phone 7 – all fantastic mobile operating systems, it is hard to even begin to compare them to their predecessors.

But why were we suddenly (these past few years) imbued with these brilliant new OS’es?

The answer of course is advances in hardware – lower cost, more computation power, high resolution displays and multi-touch, more storage, faster wireless networks, longer battery life… and on top of all that, advances in nanotechnology has made everything smaller and lighter, too.

My point with this little article, is to share with you an observation that has surfaced in a few of my conversations lately: that these new mobile operating systems are part of a transition towards “real” operating systems running on mobile devices. In fact, I’ve taken to referring to them as “transition operating systems” myself.

The evolution of mobile hardware does not cease. What made these new OS’es possible, is the fact that mobile devices are now almost as fast as “real” computers – and that same progress will put an end to them, too.

Soon, mobile devices will be fast enough to run “real” operating systems – and when that time comes, why would you want a dedicated mobile OS, or even a mobile device dedicated to wireless communications, such as your phone? If you could run a real Windows, OSX or Linux OS on your device, why wouldn’t you? At least two of the major players in mobile hardware, NVidia and QualComm, are currently racing to bring quad-core processors to market this year, so it may be more imminent than you think.

I suspect certain companies, such as Apple, are already having the same realization – it was recently rumored that certain features are being migrated from iOS to OSX. My guess is, they’re getting ready to add support for iOS apps to OSX, with the intent of running OSX on a mobile device in the no-too-distant future.

This is all speculation, of course – and either way, it doesn’t diminish the value of the mobile “transition” operating systems, which paved the way for new advances in user interface / user experience development, and have set new standards for human-machine interfaces overall.

And it certainly doesn’t mean that you should hold out on your business ideas – waiting for real operating systems to hit your cell phones – the new mobile platforms are already embedded in our lives, and they are inevitably here to stay, in some form or another.

Rasmus Schultz has worked for web development companies, advertising agencies and a music software company during his extensive development career. His main strengths are software development and database design. Rasmus has more than a decade of experience with many development platforms, languages and standards.
©2013 GORGES - All rights reserved
where programming meets design and lives happily ever after