How Santa's Elves Keep their Workshop Tidy

Code::TidyAll - 2014-12-16

Code::TidyAll bills itself as Your all-in-one code tidier and validator. Many people do not know this, but tidyall has become an indispensable part of the toolkit in Santa's workshop. It makes it trivial for the elves to keep their code formatting consistent and clean.

Perl::Tidy

Many of us are familiar with Perl::Tidy (the Perl module for reformatting your source code in a consistent manner according to a set of rules,) so we'll start with it as an example. Since the elves work as a team, it's easiest for them to add their common .perltidyrc to their Git repository. Next they create an rc file for the tidyall command line utility. They add this to the top level of their repository and call it .tidyallrc:

Each section of a .tidyallrc file begins by specifying the tidier/formatter which is being configured. In this case it's the Code::TidyAll::Plugin::PerlTidy plugin which plugs Perl::Tidy into tidyall. The select args accept File::Zglob patterns (i.e. shell glob pattern). This allows the elves to configure which files the plugin should be applied to. Similarly, they can also add ignore patterns to exclude arbitrary files and patterns.

The argv param lets the elves specify a set of arguments to pass to Perl::Tidy. In this case the elves use the profile arg, which tells perltidy where to find a valid .perltidyrc file. $ROOT is a special variable provided by tidyall which means the top level of the repository it has been added to.

Now, they're all set. tidyall -a will tidy everything which matches the select statements in the configuration. tidyall -g is much like tidyall -a but it is restricted to all files which have been changed but not yet committed to the git repository they're currently working in.

Let's have a look at an example. This is the repository the elves are working on:

We have one modified file, lib/Acme/Claus.pm. So, let's constrain this further and use the -g flag. This should mean that only one file gets checked and possibly tidied.

tidyall -g
[tidied] lib/Acme/Claus.pm

It worked! At this point the elves essentially have a wrapper around perltidy, which lets them restrict which files the transformations are applied to. Helpful, right? Let's take it a step further. Two of the elves on the gifting geolocation team, Holly and Max, are pretty good about tidying their files before they commit them to the workshop's main repo. However, the other half of the team, Buddy and Peppermint aren't quite so disciplined. How can Holly and Max ensure that Buddy and Peppermint work together with the rest of the team? Well, since they're using Git, there are a few things they can do. (This would be a good time to note that tidyall has Subversion support too.)

No Untidy Code Makes it Past this Hook

The first thing Holly and Max can try is using a pre-commit hook. Setting it up is easy.

Now, all Holly and Max need to do is tell Buddy and Peppermint to check out the latest commits from master and run the following command:

sh git/setup.sh

This will set up a hook which runs before any git commit in the local repo is finalized. Note that the hook will not tidy your files. It will merely warn you about untidy code and prevent the commit. (You can get the same behaviour at the command line by supplying the --check-only arg). At this point you can check what the problems are and then run tidyall -g as appropriate. Then be sure to perform your tidying before you commit. If you don't, tidyall will be fooled into thinking that your commits are clean, even if you haven't staged the tidied bits.

In a traditional git setup it's also possible to install similar pre-receive hooks that run on the main repository whenever someone pushes code to it. However, since Santa's workshop runs Github Enterprise - where pre-receive hooks aren't possible without some wrangling - pre-commit hooks and a strong lecture on always installing them clientside will have to do.

Testing to Keep Buddy and Peppermint in Line

Now, it's entirely possible that someone will forget to enable the hook or even intentionally bypass it. (You can do this with git commit --no-verify). Let's put another safeguard in place to catch the naughty elves.

Let's create a file called t/tidyall.t and add the following lines:

1: 2: 3:

#!/usr/bin/perluseTest::Code::TidyAll;tidyall_ok();

Now we'll have a failing test whenever something untidy makes it into the master branch. Holly and Max are now safe in the knowledge that whenever untidy code is tested via their CS (continuous santagration) that the test suite will curse loudly and the perpetrator(s) will be exposed. In fact, it should look a little bit like this:

With this much plugin support tidyall can be used for front end as well as back end development. As mentioned above, it works with Subversion as well as Git. It helps Santa's elves keep their workshop clean and tidy. Maybe it can help your workshop as well.