Stitching it all together: Rails, PostgreSQL, Webpack, Gitlab-CI, Docker

Rails/Webpacker project using GitLab CI and Docker can be a daunting task. This article explains how to set up CI for your project using GitLab CI.

Here is what we’ll be setting up:

  • Set up your own Runner on Docker
  • Configure your .gitlab-ci.yml
  • Setting up a PostgreSQL for running test

Step 1: Set up your own Runner on Docker

GitLab has built-in continuous integration to allow you to run a number of tasks as you prepare to deploy your software. Typical tasks might be to build a software package or to run tests as specified in a YAML file. These tasks need to run by something, and in GitLab this something is called a Runner; an application that processes builds. Let’s use the Docker executor since it has the most supported features according to the GitLab Runner executor compatibility chart. For this, we will need to install Docker on the server that will host the GitLab Runner. Fortunately, DigitalOcean has a one-click image with Docker pre-installed on Ubuntu 16.04.

Create a droplet:

Login to DigitalOcean and from the Control Panel, click on the “Create” button on the page. Under the “Choose an image” section, select the “One-click Apps” tab and click the “Docker” image (the version might differ). The next step is to choose the droplet size and the region you would like to use. You are advised to use the 1 GB /1 CPU droplet for quicker builds. Choose the datacenter region and your SSH Keys(*Optional) and click the “Create” button to complete your droplet creation.

Install the GitLab Runner:

First, login to the new droplet via SSH and verify that Docker is installed. To verify the Docker, run
docker info
This should show a bunch of information about the Docker version, the number of images and containers, etc. With that set, we’re ready to install GitLab Runner. GitLab provides a repository where you can easily install and update GitLab Runner. The supported distros as Debian, Ubuntu and CentOS. run
curl -L https://packages.gitlab.com/install/repositories/runner/gitlab-runner/script.deb.sh | sudo
bash
Now let’s install GitLab Runner, run
sudo apt-get install gitlab-runner
And verify it’s installed, run
gitlab-runner --version
This should show a bunch of information about the gitlab-runner. And now, we’re now ready to start using it.

Register the GitLab Runner:

Registering a Runner is the process of tying it with a specific GitLab project. Each project on GitLab has a unique token that is used by the Runner in order to be able to talk to GitLab via its API. To register a Runner we first need to know the project’s token. Go to your newly created project or pick one that already uses GitLab.com’s shared Runners. Navigate to the project’s Settings > Runners and notice that the shared Runners are enabled. In the left side you get detailed information on the steps needed to register a new Runner. Now let’s register the runner, run
sudo gitlab-runner register
This will be asked the following information needed to register a new Runner.
    • The gitlab-ci coordinator URL
    • The gitlab-ci token for this
    • The gitlab-ci description for this runner
    • The gitlab-ci tags for this runner (comma separated)
    • Whether to run untagged jobs [true/false]
    • Whether to lock Runner to current project [true/false]
    • Please enter the executor: ssh, docker+machine, docker-ssh+machine, kubernetes, docker, parallels, virtualbox, docker-ssh, shell: docker
    • Please enter the Docker image (eg. ruby:2.1):
Once answered all questions, you can verify that the Runner is registered, run
sudo gitlab-runner list
This should show a list of configured runners . Now if you head back in your project’s Settings > Runners you will see that the Runner appeared in the list. Now you have successfully set up your own runner on docker.

Step 2: Configure your .gitlab-ci.yml

GitLab CI uses a YAML file (.gitlab-ci-yml) to define the project configuration, which includes a definition of all the stages that need to be run after a CI/CD pipeline is triggered in response to a git push/merge. If you are using Webpack for managing your Front-end dependencies, choosing a ruby-node Docker image over a plain ruby image will spare you from setting up Nodejs and other dependencies manually in `before_script`.
image: starefossen/ruby-node:latest
before_script:
  - bundle install
  - yarn install
job1:
  script: "execute-script-for-job1"

Step 3: Setting up a PostgreSQL for running test

The GitLab docs were helpful for configuring the CI for you test suit, but switching the database to PostgreSQL required a couple changes in .gitlab-ci.yml file and also you have to add a new file config/database.yml.gitlab in your project, which stores the CI database connection info. It should match the info you have specified in the variables section of the .gitlab-ci.yml file. Here’s a complete .gitlab-ci.yml that installs ruby 2.4 and node 8.9, the required packages, sets up a blank test database, then runs your test suit.
image: starefossen/ruby-node:latest
services:
  - postgres:latest
variables:
  POSTGRES_DB: test_db
  POSTGRES_USER: username
  POSTGRES_PASSWORD: password
before_script:
  - 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
  - yarn install
test:
  script: "execute-script-for-job1"
And your config/database.yml.gitlab should be looks like ,
test:
  adapter: postgresql
  encoding: unicode
  pool: 5
  timeout: 1000
  host: postgres
  username: username
  password: password
  database: test_db
That’s it!

Summary

That’s it! You now have CI running your test suite and code analysis for your Rails /Webpacker project. Here’s the complete .gitlab-ci.yml file for running the unit test for front-end components using Jest + Enzyme, feature test using Cucumber and Minitest for your rails integration test.
image: starefossen/ruby-node:latest
cache:
  paths:
    - node_modules/
    - .yarn
services:
  - postgres:latest
variables:
  POSTGRES_DB: test_db
  POSTGRES_USER: runner
  POSTGRES_PASSWORD: ""
before_script:
  - 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
  - yarn install
test:
  script:
  - bundle exec rake test
  - yarn jest
  - bundle exec cucumber
Happy coding :-)]]>