Pre-commit static code analysis with Rubocop

Oct 24, 2015

On a medium to large sized development team, code consistency can become an issue. Every developer has their own style and text editor settings, so maintaining readability can be quite the effort. There were a number of options on the table:

An editor code linter, like SublimeLinter or Rubocop for RubyMine. These work well, but do they not enforce properly formatted code. This might be a good addition to another solution.

A pre-commit code linter. These are nice, but they can be a pain to configure on multiple dev environments (the .git directory is not checked in to source control, and is thus not shared by developers working on a shared remote repository).

A post-push code linter, like HoundCI. I’ve used HoundCI in the past, and I found it quite useful. However, if a developer hasn’t been following best practices while writing a large feature, when it comes time to code review, it can simply be too much work to go back and refactor a large amount of code.

We eventually decided on option #2, a pre-commit code linter. Why? Well, it would literally block developers from committing bad code (so its effective), while remaining easy to bypass in an emergency (git commit --no-verify will not run pre-commit hooks). Also, its very configurable, so you can customize it as you see fit.

I didn’t find any existing scripts that were to my liking, so I decided to write my own. This is a very simple Ruby script, and I commented it so it should be understandable.

(Note, we’re a Ruby shop, so this script uses a Ruby code linter, Rubocop). It should be easy to replace it with any other code linter.

To use this script, you’ll need to add it to your pre-commit hook. Drop it into .git/hooks/pre-commit in your git repository. pre-commit must be executable (chmod +x pre-commit). Just as a bit of background, if the execution of pre-commit results in a non-zero exit code, the commit will be blocked. This script returns a non-zero exit code if any of the Rubocop rules fail.

Remember that the .git directory is not checked into source control or pushed up to any remote repositories. It is completely local. If you want to share this pre-commit script between development machines or repositories, I would recommend storing it in a separate repository and symlinking it to the proper locations across your repositories.

Hope this helps you stop your codebase from being overrun with bad code!