Integrating Ruby on Rails Static Analysis with Codeship

Written by: Taylor Jones
5 min read

Every development team has their own preferences for what kind of checks they want to run on newly committed code. One specific flavor of tools that developers use is static analysis. Static analysis tools are programs that preform checks “statically” on code. This means that they determine the correctness or validity of code without executing it.

In nonprogramming terms, static analysis is a lot like checking a sentence for errors before speaking it out loud. There is a wide range of problems and insights that static analysis can discover. However, since these tools don’t execute our code, they can’t catch any error that’s unique to the execution runtime. In the same way that we check sentences for grammatical errors, some problems don’t become apparent until we speak (or execute) the words in sequence.

Today, I want to run through an example using static analysis on a Ruby on Rails project and integrating those checks into our Codeship CI process.

To accomplish this, we’ll need a few tools:

  1. A source-control connected version of a Ruby on Rails application like this

  2. A Codeship account

We’ll start developing our CI process locally and then look to translating it to a Codeship configuration.

Staying in Style with Rubocop

Rubocop is the first Ruby static analysis tool I want to explore. While there are a variety of purposes that this library covers, I’ve found it's most commonly used as a means to enforce the Ruby Style Guide in your project.

There’s a lot to be said about having a consistent style across your application. Sandi Metz wrote a really good blog about it recently. One of Sandi’s points that resonated with me was:

Code is read many more times than it is written, which means that the ultimate cost of code is in its reading.

In larger teams of developers, having them create the same kind of consistently readable code is crucial for efficient collaboration. Rubocop helps remind us how our code fits a specific coding style.

We can install Rubocop via:

gem install rubocop

This will give you the ability to run the Rubocop CLI by simply running:

rubocop app

Rubocop will then run some checks that will either come back successful or with errors. We can treat no errors as a “successful” check and a run with any errors as an “unsuccessful” check.

In a sense, our testing and audit process might eventually look something like this:

bundle exec rspec spec # or whatever testing framework you use
rubocop app

As mentioned before, please note that if Rubocop finds any error in its analysis, the build will fail. This might be somewhat annoying as your test suite and code base grows. However, you can configure Rubocop’s preferred ruleset with a .rubocop.yml file.

Having a consistent style and formatting is certainly nice. However, I’d love to talk a bit about some static analysis libraries that dive a bit deeper than just checking for consistent style.

Detecting Code Smells with Reek

Next we’re going to talk about Reek, a static analysis tool that detects code smells in your application.

If you’re not familiar with the idea of code smells, Jeff Atwood (@codinghorror) has an excellent rundown of them. I’ve found Reek to be incredibly useful for helping me understand if my newly created code exhibits some of these smells.

We can install Reek via:

gem install reek

With Reek installed, we can run an audit on our codebase locally. I like to target specific aspects of my application for code smells. Because of this, I tend to just run Reek on my app directory.

You can execute this audit by running:

reek app

Reek will then run some checks that will either come back successful or with errors. We can treat no errors as a “successful” check and a run with any errors as an “unsuccessful” check.

In a sense, our testing and audit process might eventually look something like this:

bundle exec rspec spec # or whatever testing framework you use
reek app

As mentioned before, please note that if Reek finds any error in its analysis, the build will fail. This might be somewhat annoying as your test suite and code base grows. However, you can configure Reek’s preferred ruleset with a .reek file.

We’ve talked about using Rubocop to make our style consistent and Reek to make our code smell better. However, how do we implement these kind of checks on Codeship?

!Sign up for a free Codeship Account

Codeship Setup

To kick things off, log into your Codeship account and navigate to Create New Project. You’ll then need to connect your Source Control provider of choice and point Codeship toward your hosted project.

Once everything is connected, you’ll be presented with the Test deployment pipeline setup. Depending on how complex your CI pipeline is, you may just want to write a custom solution. However, I’ve found that selecting the Ruby on Rails option as a starting point is incredibly helpful.

Our project will have a Test pipeline that looks something like the following:

Setup Commands

rvm use 2.4.0 # Or whatever Ruby version you're using
bundle install
gem install reek # Used to execute Reek
gem install rubocop # Used to execute Rubocop
rake db:create
rake db:migrate

Our setup commands help prepare our application for testing, but we’re also installing Reek and Rubocop outside of our application bundle. This is because we’ll be executing them outside of Bundler in our next step.

Test Commands

bundle exec rspec spec
rubocop app
reek app

With these elements all in place, we now have a CI pipeline that allows us to test and audit our application code with every new push.

Looking to the Future

Using static analysis tools for local development is incredibly useful for getting more information on the code you’ve written. However, adding static analysis checks into your pipeline is even more of a commitment. You might find yourself becoming frustrated by certain failures and smells as your codebase grows. Yet the benefit of having somewhat of a “cleaner” codebase will benefit you immensely in the future.

Stay up to date

We'll never share your email address and you can opt out at any time, we promise.