Rails, Shippable and PostgreSQL

  • Mar 5

I code on cloud most of time using Nitrous.io and use Bitbucket as git repositories. The Rails application is deployed to Heroku. You can connect to Nitrous via SSH through Secure Shell and it feels like a regular Unix environment. Bitbucket is of good quality as Github and allows private repostories, which is important for some personal projects. Free service is not without limit. I have limited memory and disk space on Nitrous.io, even though it is already more generous than other cloud development environment and you can use your N2O to trade disk space with memory. To make test more efficient and take less resource, I decide to use Shippable for regular testing.

It is related easy to set it up. First, sign up with your bitbucket account. Then you can choice the project for shippable. To begin with, you need a shippable.yml at root environment like this:

language: ruby
rvm:
  - 2.1.2
script:
  - bundle exec rake test

It is a bare minimum setup. If you need to do something before the Rails is installed, you can use before_install section in shippable.yml.

Once you commit new code to bitbucket, shippable will start to run and you can fix the problem one-by-one at shippable console. It is very straight forward and easy.

I use Figaro for secret token and the application.yml is not in the git repository, shippable will complain. Since I currently only use shippable for test, I decode to hard-code the secret for test environment like this:

# config/secrets.yml 
development:
  secret_key_base: <%= ENV["RAILS_SECRET_KEY"] %>

test:
  secret_key_base: 'Put our secret token for test environment here.'

production:
  secret_key_base: <%= ENV["RAILS_SECRET_KEY"] %>

And in devise initializer

# config/initializers/devise.rb
Devise.setup do |config|
  if Rails.env.test?
    config.secret_key = 'Put our devise token for test environment here.'
  else
    config.secret_key = ENV['DEVISE_SECRET_TOKEN']
  end
  ...

You can always use rake secret to generate new token.

If you have problem related to PostgreSQL:

PG::ConnectionBad: FATAL:  Peer authentication failed for user "xxx"

You can fix it based on this article

#config/database.shippable.yml 
development:
  adapter: postgresql
  encoding: unicode
  database: app_development
  pool: 5
  username: postgres
  password:

test:
  adapter: postgresql
  encoding: unicode
  database: app_test
  pool: 5
  username: postgres
  password:
  min_messages: warning

production:
  adapter: postgresql
  encoding: unicode
  database: app_production
  pool: 5
  username: postgres
  password:

Here is the final shippable.yml:

language: ruby
rvm:
  - 2.1.2
before_script:
  - cp config/database.shippable.yml config/database.yml
  - bundle exec rake db:setup
script:
  - bundle exec rake test

Note the use of db:setup to set up database is better than migration.

Now, it should runs as what you have in a console.

Shippable supports test visualization in JUnit format. To use it, you need minitest-reporters:

# Gemfile

group :development, :test do
  gem 'minitest-reporters'
end
# test/test_helper.rb 
ENV['RAILS_ENV'] ||= 'test'
require File.expand_path('../../config/environment', __FILE__)
require 'rails/test_help'
require 'minitest/reporters'

MiniTest::Reporters.use!([
  MiniTest::Reporters::DefaultReporter.new,
  MiniTest::Reporters::JUnitReporter.new(
    ENV["CI_REPORTS"] || "log/ci"
  )
])
...
# shippable.yml 
language: ruby
rvm:
  - 2.1.2
before_install:
  - sed '/ruby ENV/d' Gemfile > Gemfile.out; mv Gemfile.out Gemfile;
before_script:
  - cp config/database.shippable.yml config/database.yml
  - bundle exec rake db:setup
script:
  - bundle exec rake test
env:
  - CI_REPORTS=shippable/testresults

I put local JUnit result under log to avoid being tracked by git and I generally don't read JUnit result on console. Now, it should work as expected.