How I learned to stop worrying and love Trac

It’s hard to believe only a week has passed since we’ve integrated the project blog into Trac – with the Timeline view displaying both source code changes and blog entries, it now became really convenient to just keep Trac open and refresh it every time we want to get an update on the state of the project. The first thing that bothered me was the looks – Trac comes with a lovely warm coloured skin – the Trac team has done an excellent job designing the interface, but next to the rest of our web-based tools (which all conform to the same colour scheme as this very blog) Trac just looked a bit out of place. Also, with so many Trac installations on the web it started being a bit confusing. I thought I’d have a stab at customizing Trac’s look.

It ain’t no sin, to take off your skin…

First, I grabbed the logo and favourites icon from our website, placed them in the htdocs/ directory of our Trac installation, and changed the entries pointing to the in the Trac configuration file.

In order to change the colour scheme I changed the template site_css.cs in the project’s templates directory, and added a directive to pull a CSS file I had prepared based on our standard css (the template is being pulled into each and every page that Trac renders, so it’s better not to put the css directly in it – using a separate css file allows browser to cache the code). Getting the CSS selectors right was mostly straightforward, though I do think the HTML templates could have been better designed for customization.

Getting rid of the ticketing system

While we already make use of Trac’s source browser, timeline and wiki, we don’t need the ticketing system (we use Bugzilla for bug-tracking). I wondered whether I could make Trac hide the navigation and search items for tickets. Turns out it’s easier than I hoped – since all Trac components inherit from the Component class, it’s easy to tell Trac which components to load based on the package they’re in – All I have to do is add the following to trac.ini :

[components] trac.ticket.* = disabled

With View Tickets, New Ticket and Roadmap gone from the Trac menu the system looks much less cluttered, and there’s no risk that anyone would try to use these features, that are incompatible with our existing bug-tracking system.

Bugs, not Tickets

I still found myself switching between Trac and Bugzilla all the time, and that can be very frustrating – so frustrating it can ruin even days like this, when the weather is so fine. Something had to be done – it was time to integrate our project’s bug-list from Bugzilla into Trac.

Bugzilla is notorious for having very sparse documentation, but the clues are there if you want to read them. For every bug-list you get from bugzilla you can pull an RSS feed, and for the detailed bug views you can request the data to be sent in Bugzilla’s proprietary XML format. Retrieving information from Bugzilla is possible using a combination of the two.

First you must authenticate – Bugzilla uses cookies to keep track of your login, so it’s easy to fool it by posting the username and password to the login form, capturing the cookie and sending it back to Bugzilla in all future requests.

To search for bugs I build a query string (based on what I learned from playing with the standard web interface) and add the parameter ctype=rss . I parse the result with feedparser and extract the id from all the bugs in the result by parsing the bug url.

With the list of bug ids I can initiate a call to show_bug.cgi , passing the ids and the parameter ctype=xml . I parse the result using xmltramp and iterate over it, building a neat little list of dictionaries which can be easily used from Python code and from templates.

Integration with Trac

As we’ve seen last week, integrating new functionality into Trac is easy peasy – all you have to do is write classes that inherit from Component and implement interfaces – the documentation is not great but the Trac source code is very easy to read and pretty self-documenting.

First, I added a new navigation item (implementing INavigationContributor ) which reads Bugs and points to /bugs . I added a new template (which I placed inside my Python package) and implemented IRequestHandler so that it reads all of the project’s bugs out of bugzilla and uses the template to render them, linking each bug to its corresponding page on Bugzilla.

One of the advantages of having a centralized system for project management is that you can search over all of it’s components – by implementing ISearchSource I could provide a hook into Bugzilla’s search – by simply forwarding the search terms to the short desc and long desc parameters in Bugzilla you get pretty good coverage.

Finally, bugs are a moving target, they just keep changing all the time as participants in the project add comments and change the bug’s status, so it would be useful to see these changes interleaved with the rest of the chronological list in the timeline view. After last week’s little adventure with the blog I am already an ITimelineEventProvider pro – it only took a couple of minutes before I had bug changes in the list.

The code

You can get the plugin from here. It’s buggy, and extremely inefficient. It authenticates before each and every request, thus making the interface to Bugzilla even slower than it needs to be. The entries in the timeline indicate that the bug changed, but not why it changed – you’ll have to follow to Bugzilla if you’re curious enough, the bug list doesn’t sort the bugs by anything, doesn’t allow any report except for the list of all bugs, and it doesn’t look very nice either. If you do decide to give it a try, don’t forget to send us some patches 🙂