Automating code checks with overcommit

Automating code checks with overcommit

A few months ago, I was looking for something to prevent me to commit/push code with a debugger call, byebug for example. Then I found something that I didn't know at the moment: Git Hooks. Git Hooks allow running custom scripts when certain actions occur, for example: commit, push, merge, checkout, etc.

You can put whatever you want in these custom scripts, including to check if you did something not so clever, for example, push code with a byebug call. And if you search in Google, you'll find a couple of Git hook scripts to prevent you from doing that.

But then, as a Ruby developer, I thought: Hey, there's always a gem, right!?. Right! And it's called overcommit. Overcommit is a Ruby gem which allows you to easily manage and configure your Git hooks.

To start using overcommit is very simple:

$ gem install overcommit
$ overcommit --install

The overcommit --install command will create a .overcommit.yml settings file in the current folder and also back up existing hooks. The default settings file includes the following hooks:

  • CapitalizedSubject: Ensures commit message subject lines start with a capital letter
  • EmptyMessage: Checks that the commit message is not empty
  • SingleLineSubject: Ensures commit message subject lines are followed by a blank line
  • TextWidth: Ensures the number of columns the subject and commit message lines occupy is under the preferred limits
  • TrailingPeriod: Ensures commit message subject lines do not have a trailing period
  • AuthorEmail: Checks the format of an author's email address
  • AuthorName: Ensures that a commit author has a name with at least first and last names
  • BrokenSymlinks: Checks for broken symlinks
  • CaseConflicts: Checks for files that would conflict in case-insensitive filesystems

Of course, you can easily disable any of these hooks:

  CapitalizedSubject:
    enabled: false

Every time you perform changes in the settings file, you also need to update the signature running overcommit --sign. You can also disable signature checking by setting verify_signatures: false in your .overcommit.yml file. However, please read the security implications before doing that.

Recommended built-in hooks

The hooks described in this section are the ones I'm currently using and recommend. You can also find, between parenthesis in the hook title, in which action the hooks are being executed.

RuboCop (PreCommit)

Runs RuboCop against any modified Ruby files.

  RuboCop:
    enabled: true
    on_warn: fail
    problem_on_unmodified_line: ignore
    command: ['bundle', 'exec', 'rubocop']
  • on_warn: fail: blocks the commit in case of warnings
  • problem_on_unmodified_line: ignore: ignore problems in lines of code you did not add/change

BundleAudit (PreCommit)

Checks for vulnerable versions of gems in Gemfile.lock.

  BundleAudit:
    enabled: true
    flags: ['--update']
  • flags: ['--update']: force BundleAudit to update before checking

BundleCheck (PreCommit)

Check if local Gemfile.lock matches Gemfile when either changes, unless Gemfile.lock is ignored by git.

  BundleCheck:
    enabled: true

ForbiddenBranches (PreCommit and PrePush)

Prevents commits to branches matching one of the configured patterns.

  ForbiddenBranches:
    enabled: true
    branch_patterns: ['master']

Fasterer (PreCommit)

Runs fasterer against any modified Ruby files.

  Fasterer:
    enabled: true
    exclude:
      - 'vendor/**/*.rb'
      - 'db/schema.rb'

CustomScript (PreCommit)

Runs a custom command/script before commit.

  CustomScript:
    quiet: true
    enabled: true
    command: ['i18n-tasks', 'normalize']

The previous hook will run i18n-tasks normalize before commit. normalize is a task of the i18n-tasks gem.

BundleInstall (PostCheckout, PostMerge and PostRewrite)

Runs bundle install when a change is detected in the repository's dependencies.

  BundleInstall:
    enabled: true

Other (probably) useful built-in hooks

These are the hooks I'm not currently using but I'm willing to give a try.

  • Foodcritic: linting tool for writing better and safer code
  • RailsBestPractices: code metric tool to check the quality of Rails code
  • RailsSchemaUpToDate: Check to see whether the schema file is in line with the migrations
  • Reek: Code smell detector for Ruby
  • Brakeman: Vulnerability scanner designed for Rails applications. It statically analyzes code to find security issues
  • FixMe: Check for "token" (TODO, FIXME, etc.) strings before commit
  • BundleOutdated: List installed gems with newer versions available