rails Travis CI Multi Database Rails

27 Sep 2013
I started to use Travis CI for continous integration. They have a free plan for open source which makes a good opportunity to try out the service. Travis supports various runtimes and databases and I was going to test my app against ruby 1.9 and ruby 2 and 3 different databases: sqlite, mysql, postgres. To setup these runtimes I created a travis.yml config file like this:
language: ruby
rvm:
  - 2.0.0
  - 1.9.3
env:
  - DB=sqlite
  - DB=mysql
  - DB=postgresql
We need a bit more work to make this work though as we need to specify the database config for each runtime. In my Gemfile I decide which database gem to bundle from the database config but on travis that won't exists so the bundle command will fail. Travis sets a DB environment variable which we can use to determine which gem to bundle:
require 'yaml'

env = ENV["RAILS_ENV"] || 'development'
dbconfig = File.expand_path("../config/database.yml", __FILE__)

raise "You need to configure config/database.yml first" unless File.exists?(dbconfig)
require 'erb'
config = YAML.load(ERB.new(File.read(dbconfig)).result)

environment = config[env]

adapter = environment['adapter'] if environment
raise "Please set an adapter in database.yml for #{env} environment" if adapter.nil?
case adapter
when 'sqlite3'
  gem 'sqlite3'
when 'postgresql'
  gem 'pg'
when 'mysql2'
  gem 'mysql2'
else
  raise "Not supported database adapter: #{adapter}"
end
Note that we process the database.yml with ERB first. It needs because we use the ENV['DB'] variable in the yaml file. I don't have a database.yml in source control just an example for the different database options and I thought the best way would be to keep all the travis related db config in a separate file so I created a database.travis.yml file:
sqlite: &sqlite
  adapter: sqlite3
  database: db/<%= ENV['RAILS_ENV'] %>.sqlite3

mysql: &mysql
  adapter: mysql2
  username: root
  password:
  database: invoicer_<%= ENV['RAILS_ENV'] %>

postgresql: &postgresql
  adapter: postgresql
  username: postgres
  password:
  database: invoicer_<%= ENV['RAILS_ENV'] %>
  min_messages: ERROR

defaults: &defaults
  pool: 5
  timeout: 5000
  host: localhost
  <<: *<%= ENV['DB'] || "sqlite" %>

development:
  <<: *defaults

test:
  <<: *defaults

production:
  <<: *defaults
With this in place we just need to extend the travis config to set the rails environment and run a before script:
language: ruby
rvm:
  - 2.0.0
  - 1.9.3
env:
  - DB=sqlite
  - DB=mysql
  - DB=postgresql
before_install: cp config/database.travis.yml config/database.yml
script:
  - export RAILS_ENV=test
  - bundle exec rake db:create db:migrate
  - bundle exec rake db:test:prepare
Now we just need to push a commit and wait for the build result.

I run an indie startup providing vulnerability scanning for your Ruby on Rails app. It is free to use at the moment, and I am grateful for any feedback about it.
If you would like to give it a spin, you can do it here: Vulnerability Scanning for your Ruby on Rails app!

Did you enjoy reading this? Follow me on Twitter or sign up to my newsletter for more content like this!

Related posts