Quick guide on Ruby on Rails Continuous Integration with GitlabCI - why it's worth and how to get it running.

hixdevs

hix.dev

Posted on January 30, 2020

Quick guide on Ruby on Rails Continuous Integration with GitlabCI - why it's worth and how to get it running.

This is the ultimate guide for your next Ruby on Rails project setup on Gitlab with GitlabCI for continuous integration in 2020.

You can find original, 1:1 version on our website - feel invited!

Let's get started.

What is Gitlab?

Gitlab is, among all the other DevOps related features, one of the top git remote hosting cloud providers, next to Microsoft's Github and Atlassian's Bitbucket.

It can be both self-hosted or used via provided web UI on an official website. Like the other two giants, it offers an unlimited amount of public and private repositories, with limited users access extendable with a paid plan.

Fun fact is that both Ruby and Ruby on Rails are a big part of the Gitlab's tech stack.

Alt Text

Gitlab allows its users to integrate various pipelines into the code lifecycle, providing powerful GitlabCI, which should be rather called GitlabCD, for Continuous Delivery, as it equips developers with everything that's necessary to deliver code from their workstations straight to the production servers.

Why use Gitlab for Ruby on Rails app?

Creating constant backups of your code without using git or any other version control system would be true horror. Gitlab's biggest advantage for Ruby on Rails and projects written with any other frameworks is that on top of checkpoints in your codebase saved locally, you can host them in the cloud.

An ability to roll back to the older version of the code in case of introducing bugs in newer releases is yet another life-saving feature of Gitlab and other git remote hosting providers.

Another advantage is that with its massive usage as a self-hosted remote git repository solution there's a big chance that anybody that is going to collaborate with your code is going to know how to use Gitlab, so statistically, a learning curve is gone.

Thanks to its intuitive UI, Merge Requests, Code Review and Forks, Gitlab allows developers to easily work together.

On top of all that, it introduces its own, very advanced git branching strategy called GitLab flow.

Continuous Integration for Ruby on Rails

Continuous Integration (CI) in a programming world is a widely accepted practice that requires developers to push their work to the shared codebase continuously, ideally several times a day.

On top of general usages such as building programs and running the test suite against new features, new code might be verified against static code analysis tools knowledge base, pinpointing security vulnerabilities, common stylistic mistakes and all different kinds of inaccuracies.

Continuous Integration pipelines are a great place to ensure high code quality, well, continuously, which is good for both programmers and software itself.

There are multiple open-source static code analysis tools available for both Ruby and Ruby on Rails.

Most of them can be set up on the CI server to audit the code of Ruby on Rails project every time it's pushed, or nightly.

Why use GitlabCI for Ruby on Rails app?

GitlabCI is Gitlab's own solution for Continuous Integration and Delivery, hosted in its cloud.

It is tightly integrated with Gitlab repository hosting, turned on by default, so every time you create a new repository on Gitlab all you need to do in order to turn on its Continuous Integration solution for your project is providing a correct configuration file, .gitlab-ci.yml.

There are several shared runners available, so there's no need for your custom CI server maintenance (hello Jenkins), just one YAML file and you're all set.

No credit card information required, a perfect combination to start small with your project and pay for what you use as you grow.

GitlabCI provides an intuitive, well-organized UI with all the information required to establish the problem that occurs when the new code was integrated into the Gitlab hosted codebase.

It is crucial to set up the Continuous Integration system for any project, let alone Ruby on Rails, from the first day of the development.

This is a great way to avoid a lot of technical debt, protect yourself from common mistakes and enforce certain standards that make working with Ruby on Rails codebase pleasing and its maintenance much, much easier.

Create Ruby on Rails project on Gitlab

Follow the instructions below to create your Gitlab account and set up the Ruby on Rails project.

1.Sign up on the official Gitlab website.

Alt Text

2.Verify your email and complete the simple account creation wizard.
3.When successfully logged in, select "Create project".

Alt Text

4.Provide a project name and click "Create project".

Alt Text

5.Copy your new project's URL to the clipboard.

Alt Text

6.If you are using Hix on Rails, that's all you are going to need for now, just paste the address into the CLI when asked for it.
7.Navigate to the Ruby on Rails project root directory in the command line and enter git remote add origin YOUR_REPOSITORY_URL

Ruby on Rails project with GitlabCI pipelines

If you are using Hix on Rails - that's it. Your pipeline will run with all the code quality checks selected in the installation wizard upon the first push the remote. Beware that it will initially fail unless you create any database migration, as it is necessary for the database to be created.

Otherwise, if you still on the copy/paste duty instead of automating that part of your life, follow the steps below for Ruby on Rails project configuration on the GitlabCI.

In your project root, create the required GitlabCI configuration file.

cd path/to/your/project/root
touch .gitlab-ci.yml
Enter fullscreen mode Exit fullscreen mode

Open the GitlabCI configuration file with a text editor of your choice and paste the basic code required, depending on which database you use.

Ruby on Rails with PostgreSQL on GitlabCI

PostgreSQL is the most popular choice for Ruby on Rails projects.

For the GitlabCI to test your application along with PostgreSQL you are going to need a specific setup in the config/database.yml file. We use the dotenv-rails gem.

config/database.yml

default: &default
  adapter: postgresql
  encoding: unicode
  pool: <%= ENV['DB_POOL'] %>
  username: <%= ENV['DB_USERNAME'] %>
  password: <%= ENV['DB_PASSWORD'] %>
  host: <%= ENV['DB_HOST'] %>
  port: 5432

development:
  <<: *default
  database: hix_postgresql_development

test:
  <<: *default
  database: hix_postgresql_test

production:
  <<: *default
  database: hix_postgresql_development
Enter fullscreen mode Exit fullscreen mode

If you decided to go with it, here's the basic GitlabCI configuration for the Ruby on Rails project build with the PostgreSQL database.

.gitlab-ci.yml

stages:
  - build
  - test

.build:
  image: ruby:2.6.5
  cache:
    key: rat-app-name
    paths:
      - apt-cache/
      - vendor/ruby
      - node_modules/
    policy: pull
  before_script:
    - gem install bundler --no-document
    - bundle install --jobs $(nproc) "${FLAGS[@]}" --path=vendor

.db:
  extends: .build
  services:
    - postgres:12.0
  variables:
    POSTGRES_USER: hix_postgresql
    POSTGRES_PASSWORD: hixonrails
    DB_USERNAME: hix_postgresql
    DB_PASSWORD: hixonrails
    DB_HOST: postgres
    RAILS_ENV: test
    DISABLE_SPRING: 1
    BUNDLE_PATH: vendor/bundle
  before_script:
    - export APT_CACHE_DIR=`pwd`/apt-cache && mkdir -pv $APT_CACHE_DIR
    - apt update -qq && apt -o dir::cache::archives="$APT_CACHE_DIR" install -yqq nodejs
    - gem install bundler --no-document
    - bundle install --jobs $(nproc) "${FLAGS[@]}" --path=vendor
    - bundle exec rails db:create db:schema:load --trace
Enter fullscreen mode Exit fullscreen mode

As is, this file will fail the pipeline, it is only a strong foundation for further jobs presented in the guide.

Adjust the configuration file for this code to work with your project:

  1. In the build Ruby image, line 6, adjust your Ruby version. At the time of writing this article the last stable version is used, 2.6.5.
  2. In the database PostgreSQL image, line 20, adjust your PostgreSQL version. At the time of writing this article, the last stable version is used, 12.0.
  3. You can freely change corresponding user and password values, respectively in lines 22 - 24 and 23 - 25, however it's not mandatory.
  4. Replace all occurrences of the "hix_postgresql" with your Ruby on Rails project name.

It is important for the Continuous Integration suite to run on an environment as close to your production as possible.

To check your local PostgreSQL version, run the following command in the CLI.

psql -V
Enter fullscreen mode Exit fullscreen mode

If you are developing some serious Ruby on Rails project, it is the best moment to install the latest stable version of the PostgreSQL database. If not, find the Docker PostgreSQL image corresponding to your local database version and adjust the GitlabCI configuration file accordingly.

Follow the next steps to actually use defined images in your continuous integration workflow.

Ruby on Rails with MySQL on GitlabCI

MySQL is the second most popular choice for Ruby on Rails applications, just behind the PostgreSQL.

For the MySQL to work you, same as with PostgreSQL, you are going to need a setup in the config/database.yml file adjusted to the one configuring the GitlabCI.

default: &default
  adapter: mysql2
  encoding: utf8
  pool: <%= ENV['DB_POOL'] %>
  username: <%= ENV['DB_USERNAME'] %>
  password: <%= ENV['DB_PASSWORD'] %>
  host: <%= ENV['DB_HOST'] %>
  port: 3306

development:
  <<: *default
  database: hix_mysql_development

test:
  <<: *default
  database: hix_mysql_test

production:
  <<: *default
  database: hix_mysql_production
Enter fullscreen mode Exit fullscreen mode

If that's your choice, here's the basic GitlabCI configuration for the Ruby on Rails project build with the MySQL database.

stages:
  - build
  - test

.build:
  image: ruby:2.6.5
  cache:
    key: rat-app-name
    paths:
      - apt-cache/
      - vendor/ruby
      - node_modules/
    policy: pull
  before_script:
    - gem install bundler --no-document
    - bundle install --jobs $(nproc) "${FLAGS[@]}" --path=vendor

.db:
  extends: .build
  services:
    - name: mysql:8.0.18
      command: ['--default-authentication-plugin=mysql_native_password']
  variables:
    MYSQL_ROOT_PASSWORD: hixonrails
    DB_USERNAME: root
    DB_PASSWORD: hixonrails
    DB_HOST: mysql
    RAILS_ENV: test
    DISABLE_SPRING: 1
    BUNDLE_PATH: vendor/bundle
  before_script:
    - export APT_CACHE_DIR=`pwd`/apt-cache && mkdir -pv $APT_CACHE_DIR
    - apt update -qq && apt -o dir::cache::archives="$APT_CACHE_DIR" install -yqq nodejs
    - gem install bundler --no-document
    - bundle install --jobs $(nproc) "${FLAGS[@]}" --path=vendor
    - bundle exec rails db:create db:schema:load --trace
Enter fullscreen mode Exit fullscreen mode

It needs a few tweaks in order to work with your particular project. Do the following:

  1. In the build Ruby image, line 6, adjust your Ruby version. At the time of writing this article the last stable version is used, 2.6.5.
  2. In the database MySQL image, line 21, adjust your MySQL version. At the time of writing this article, the last stable version is used, 12.0.
  3. You can freely change corresponding root password values, respectively in lines 24 - 26, however, it's not mandatory.
  4. Replace all occurrences of the "hix_postgresql" with your Ruby on Rails project name.

Be aware that those are only images to extend in order to use them for the jobs to follow and they do nothing by themselves, as they do not belong to any of the stages defined at the beginning of the GitlabCI configuration file.

I am going to state that again, in case you skipped the PostgreSQL section: it is important for the Continuous Integration suite to run on an environment as close to your production as possible.

Take a moment now to check your local MySQL version. In your local CLI, type:

mysql -V
Enter fullscreen mode Exit fullscreen mode

and do one of the following:

  1. Best: Update your local MySQL version to the latest stable one.
  2. Good: Update your GitlabCI docker image to the one matching your local version - check an official Docker MySQL images
  3. Bad: Do nothing (in case versions differ, because if they don't your technically in point 2).

If you went with the local update alternative, your future self is smiling at you right now. The second point is probably the most common choice, as all it takes is editing the configuration file.

The third option is plain wrong and it will cost you more time than it's worth it, eventually - go back to point 2.

Now that we have the installed bundle with our Ruby on Rails applications database ready to use, let's see what we can use them to run.

Ruby on Rails with RSpec on GitlabCI

RSpec is the favorite choice of the Ruby and Ruby on Rails community for writing tests.

It is important to check if newly developed features did not break older parts of the codebase and the Continuous Integration flow is a great place to do it. If you enforce the full test suite run from the Ruby on Rails application day one and agree with your team on some rational test coverage you will not regret it.

Speaking of the code coverage, there are great tools like SimpleCov, the Ruby gem for generating test coverage reports that hooked up with a Coveralls always tell you what's codebase code coverage at a glance, from the README.md badge level.

The Continuous Integration part of checking Ruby on Rails application tests health is really easy, all it takes is to store the results in the CI environment after the suite run. Reporting part comes in the RSpec configuration, you can read about it in the Ruby on Rails tested with RSpec article.

Overall, running the test suite of the Ruby on Rails project is the perfect job for the GitlabCI, so let's get to it.

Edit your GitlabCI configuration file with the following.

rspec:
  extends: .db
  stage: test
  cache:
    policy: pull-push
  artifacts:
    name: coverage
    paths:
      - coverage/
  script:
    - bundle exec rspec --profile 10 --format progress
Enter fullscreen mode Exit fullscreen mode

You can skip the artifacts part of the job if you did not bother with SimpleCov configuration, but you don't have to. It is always possible to browse the coverage results from the GitlabCI level.

Another thing that's happening here is the profiling flag of our RSpec script - given the integer 10, it will show us the ten slowest unit tests in the whole suite.

Ruby on Rails with RuboCop on GitlabCI

RuboCop is the Ruby and Ruby on Rails community favorite linting tool. It checks the code against almost four hundred rules in its default configuration.

Along with the default gem corresponding to a Ruby Styleguide website, there are RuboCop extensions encapsulated in the separated gems for some of the most popular Ruby frameworks, including Ruby on Rails and RSpec.

On top of that, there's another gem authored by RuboCop Headquarters specifically checking the Ruby code performance, called, you guessed it, rubocop-performance.

If you decided to use the RuboCop in your Ruby on Rails project, the GitlabCI continuous integration suite is the place to do it - this way you can always be sure that your code is kept up to the RuboCop standard.

Edit the GitlabCI configuration file of your Ruby on Rails project with the following code.

rubocop:
  extends: .build
  stage: build
  cache:
    policy: pull-push
  script:
    - bundle exec rubocop
Enter fullscreen mode Exit fullscreen mode

The RuboCop job does not require a Docker database image. We simply extend bare build, in which the gems bundle is installed - this way your CI runs faster every time.

For the complete RuboCop setup for Ruby on Rails applications using RSpec, please read the Ruby on Rails project RuboCop setup with RSpec.

Ruby on Rails with Brakeman on GitlabCI

If you keep the security of the Ruby on Rails project in mind, Brakeman is the way to go.

It is a simple command-line tool that checks the Ruby on Rails codebase against known security vulnerabilities, including SQL Injection and Cross-Site Scripting.

The GitlabCI Continuous Integration suite is the best place to check your code against Brakeman's knowledge of breaking Ruby on Rails stuff. If you decided to use it, edit your configuration file with the following.

brakeman:
  extends: .build
  stage: build
  cache:
    policy: pull-push
  script:
    - bundle exec brakeman --rails6 -A
Enter fullscreen mode Exit fullscreen mode

Same as the RuboCop job, Brakeman does not need the Docker database image in order to run, so we save ourselves a few seconds every time and extend the bare build one.

Remember, that using any security audit tool does not guarantee that your Ruby on Rails application is 100% safe. Please read the Open Web Application Security Project Top 10 Project and on top of other things, audit your website regularly with tools like Mozilla Observatory.

Ruby on Rails with Fasterer on GitlabCI

Fasterer is a static Ruby code analysis command-line tool that corresponds to the open-source project called Fast Ruby.

It is the single biggest website with up-to-date benchmarks of various Ruby methods that are able to achieve the same goal, which allows programmers to find the fastest tool for a lot of stuff done with Ruby.

If you decide to use the Fasterer in your Ruby on Rails project, here's the GitlabCI Continuous Integration configuration for running the static performance analysis against the codebase.

fasterer:
  extends: .build
  stage: build
  cache:
    policy: pull-push
  script:
    - bundle exec fasterer
Enter fullscreen mode Exit fullscreen mode

One configuration tweak worth pointing out and included in the example fasterer repository configuration file is to turn off each.with_index vs a while loop comparison when using with Ruby on Rails applications.

Ruby on Rails with Rails Best Practices on GitlabCI

Rails Best Practices is a Ruby on Rails blog by Xinmin Labs, with its last article written in 2014. Do not give up on it though, as most of its wisdom is still applicable now, and it is safe to say that it will be for a long time.

Next to the old but gold read, there's a static code analysis tool with the same "Rails Best Practices" name. It reports all the code violating the guidelines thoroughly explained on the website.

If you decide to follow the Rails Best Practices, your GitlabCI Continuous Integration suite for the Ruby on Rails project is the best place to do so.

rails_best_practices:
  extends: .build
  stage: build
  cache:
    policy: pull-push
  script:
    - bundle exec rails_best_practices
Enter fullscreen mode Exit fullscreen mode

With this small additional GitlabCI configuration comes a lot of good stuff that will keep your Ruby on Rails codebase safe and sound, pointing out common mistakes that are otherwise easy to forget.

Conclusion

Gitlab is a very popular choice for Ruby on Rails applications remote version control and it comes with many benefits, one of which is its tremendous help in the DevOps world.

GitlabCI is a powerful yet very easy to set up cloud suite for Continuous Integration and Delivery, and it comes built-in and ready to use with every new Gitlab repository, for free.

A lot of Ruby on Rails community knowledge about how to do things correctly was forged into static code analysis tools.

Enforcing the standardized style guide for your Ruby on Rails application via GitlabCI jobs and pipelines is a great way to both learn the framework better and save yourself some trouble in the future.

Again, if you wish to help us in growing our tutorial base, please share this article to your dev friends! Kudos!

You can also take a look at Hix which we've made with love for Rails developers.

💖 💪 🙅 🚩
hixdevs
hix.dev

Posted on January 30, 2020

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related