Configuring a GitLab CI pipeline for Rails, PostgreSQL, rspec, and rubocop
While setting up a new side project using rails 5, I wanted a quick-and-easy CI service to help verify my code quality. GitLab has a CI service built into their (free) private git repository service, so it seemed worth giving a shot. The verdict? It’s easy to use and straightforward to configure, but it’s a lot slower than having your own CI machine. That’s good enough for my use case.
For this project, I have two requirements for my CI service:
- Run my rspec test suite and ensure the tests pass
- Run static code analysis against the ruby code (with rubocop) and fail for serious violations
Running rspec test suite with PostgreSQL as the database
To use the GitLab CI, you need to add a .gitlab-ci.yml
file to your project. This file tells the CI build system:
- How to set up the VM — which packages to install, installing ruby, how to bundle your Gemfile, create your test databases, etc.
- Which checks to run: your test suite, static code analysis tools, etc.
The GitLab docs were helpful for configuring the CI for rspec, but switching the database to postgresql required a couple changes. Here’s a complete .gitlab-ci.yml
that installs ruby 2.3, the required packages, sets up a blank test database, then runs rspec.
image: "ruby:2.3"services:
- postgres:latestvariables:
POSTGRES_DB: test_db
POSTGRES_USER: runner
POSTGRES_PASSWORD: ""before_script:
- apt-get update -qq && apt-get install -y -qq postgresql postgresql-contrib libpq-dev cmake
- ruby -v
- which ruby
- gem install bundler --no-ri --no-rdoc
- RAILS_ENV=test bundle install --jobs $(nproc) "${FLAGS[@]}"
- cp config/database.yml.gitlab config/database.yml
- RAILS_ENV=test bundle exec rake db:create db:schema:loadrspec:
script:
- RAILS_ENV=test bundle exec rspec
Take note of this line:
- cp config/database.yml.gitlab config/database.yml
This expects you to have a file in your project config/database.yml.gitlab
which stores the CI database connection info. It should match the info you have specified in the variables
section of this file. e.g.:
test:
adapter: postgresql
encoding: unicode
pool: 5
timeout: 5000
host: postgres
username: runner
password: ""
database: test_db
That’s it!
Rubocop
Besides rspec, I like to run rubocop against my code to ensure a consistent coding style. Rubocop only provides a list of violations for the entire project, so it’s not useful as a merge request linting tool alone. The gem pronto allows you to output only violations that are on lines of code changed in a given merge request.
We won’t cover setting up rubocop and pronto — but they’re both straightforward. Install the gems (including pronto-rubocop
), and create a .rubocop.yml
with your configuration.
Once you have the gems installed, you may add an entry to your CI pipeline:
pronto:
script:
- bundle exec pronto run -c=origin/master --exit-code
This tells pronto to run rubocop against the lines of code that are different from origin/master. exit-code
tells pronto to fail the build if any serious violations are found.
Summary
That’s it! You now have CI running your test suite and code analysis for your GitLab MRs. Here’s the complete .gitlab-ci.yml
:
image: "ruby:2.3"
services:
- postgres:latest
variables:
POSTGRES_DB: test_db
POSTGRES_USER: runner
POSTGRES_PASSWORD: ""
before_script:
- apt-get update -qq && apt-get install -y -qq postgresql postgresql-contrib libpq-dev cmake
- ruby -v
- which ruby
- gem install bundler --no-ri --no-rdoc
- RAILS_ENV=test bundle install --jobs $(nproc) "${FLAGS[@]}"
- cp config/database.yml.gitlab config/database.yml
- RAILS_ENV=test bundle exec rake db:create db:schema:load
rspec:
script:
- RAILS_ENV=test bundle exec rspec
pronto:
script:
- bundle exec pronto run -c=origin/master --exit-code