Rails 5.x and PostgreSQL configuration for CircleCI 2.0

Revised November 17, 2017

There is a better way to solve this without removing the CircleCI TEST_FILES section and preserve parallel container. I've updated the configuration below. Thanks to Jason Milkins for posting the fix to the rspec github.

Getting Rails (or Ruby) running on CircleCI's new 2.0 platform provides a sample configuration for Rails apps that does not work out-of-the-box. I figured I would save some folks the pain and provide an updated sample configuration.

No PG configuration and RSpec error

This configuration focuses on fixing two things:

  • Rails does not have access to the PostgreSQL container (skip if your only concerned with a Ruby app)
  • Running bundle exec rspec on CircleCI results in the following error:
#!/bin/bash -eo pipefail
mkdir /tmp/test-results  
TEST_FILES="$(circleci tests glob "spec/**/*_spec.rb" | circleci tests split --split-by=timings)"

bundle exec rspec --format progress \  
                --format RspecJunitFormatter \
                --out /tmp/test-results/rspec.xml \
                --format progress \
                "${TEST_FILES}"
bundler: failed to load command: rspec (/home/circleci/repo/vendor/bundle/ruby/2.4.0/bin/rspec)  
NoMethodError: undefined method `captures' for nil:NilClass  
  /home/circleci/repo/vendor/bundle/ruby/2.4.0/gems/rspec-core-3.6.0/lib/rspec/core/example.rb:124:in `parse_id'
  /home/circleci/repo/vendor/bundle/ruby/2.4.0/gems/rspec-core-3.6.0/lib/rspec/core/configuration.rb:2026:in `extract_location'
  /home/circleci/repo/vendor/bundle/ruby/2.4.0/gems/rspec-core-3.6.0/lib/rspec/core/configuration.rb:1965:in `block in get_files_to_run'
  /home/circleci/repo/vendor/bundle/ruby/2.4.0/gems/rspec-core-3.6.0/lib/rspec/core/flat_map.rb:7:in `each'
  /home/circleci/repo/vendor/bundle/ruby/2.4.0/gems/rspec-core-3.6.0/lib/rspec/core/flat_map.rb:7:in `flat_map'
  /home/circleci/repo/vendor/bundle/ruby/2.4.0/gems/rspec-core-3.6.0/lib/rspec/core/flat_map.rb:7:in `flat_map'
  /home/circleci/repo/vendor/bundle/ruby/2.4.0/gems/rspec-core-3.6.0/lib/rspec/core/configuration.rb:1963:in `get_files_to_run'
  /home/circleci/repo/vendor/bundle/ruby/2.4.0/gems/rspec-core-3.6.0/lib/rspec/core/configuration.rb:976:in `files_to_run'
  /home/circleci/repo/vendor/bundle/ruby/2.4.0/gems/rspec-core-3.6.0/lib/rspec/core/configuration.rb:1492:in `load_spec_files'
  /home/circleci/repo/vendor/bundle/ruby/2.4.0/gems/rspec-core-3.6.0/lib/rspec/core/runner.rb:100:in `setup'
  /home/circleci/repo/vendor/bundle/ruby/2.4.0/gems/rspec-core-3.6.0/lib/rspec/core/runner.rb:86:in `run'
  /home/circleci/repo/vendor/bundle/ruby/2.4.0/gems/rspec-core-3.6.0/lib/rspec/core/runner.rb:71:in `run'
  /home/circleci/repo/vendor/bundle/ruby/2.4.0/gems/rspec-core-3.6.0/lib/rspec/core/runner.rb:45:in `invoke'
  /home/circleci/repo/vendor/bundle/ruby/2.4.0/gems/rspec-core-3.6.0/exe/rspec:4:in `<top (required)>'
  /home/circleci/repo/vendor/bundle/ruby/2.4.0/bin/rspec:23:in `load'
  /home/circleci/repo/vendor/bundle/ruby/2.4.0/bin/rspec:23:in `<top (required)>'
Exited with code 1  

Revised .circleci/config.yml

Below is a tweaked version that supports PostgreSQL and resolves the error above running bundle exec rspec. Unfortunately I am stuck to the free version of CircleCI and do not have multiple containers. This configuration does not support split tests across multiple containers.

# Ruby CircleCI 2.0 configuration file
#
# Check https://circleci.com/docs/2.0/language-ruby/ for more details
#
version: 2  
jobs:  
  build:
    docker:
      # specify the version you desire here
      - image: circleci/ruby:2.4.1-node-browsers
        environment:
          RAILS_ENV: test
          PGHOST: 127.0.0.1
          DATABASE_URL: postgres://myapp-user@127.0.0.1/myapp-test


      # Specify service dependencies here if necessary
      # CircleCI maintains a library of pre-built images
      # documented at https://circleci.com/docs/2.0/circleci-images/
      - image: circleci/postgres:9.6-alpine
        POSTGRES_DB: myapp-test
        POSTGRES_USER: myapp-user


    working_directory: ~/myapp

    steps:
      - checkout

      # Download and cache dependencies
      - restore_cache:
          keys:
          - v1-dependencies-{{ checksum "Gemfile.lock" }}
          # fallback to using the latest cache if no exact match is found
          - v1-dependencies-

      - run:
          name: install dependencies
          command: |
            bundle install --without development --jobs=4 --retry=3 --path vendor/bundle

      - save_cache:
          paths:
            - ./venv
          key: v1-dependencies-{{ checksum "Gemfile.lock" }}

      # Database setup
      - run: bundle exec rake db:create
      - run: bundle exec rake db:schema:load

      # run tests!
      - run:
          name: run tests
          command: |
            mkdir /tmp/test-results
            TEST_FILES="$(circleci tests glob "spec/**/*_spec.rb" | circleci tests split --split-by=timings)"

            bundle exec rspec --format documentation \
                            --format RspecJunitFormatter \
                            --out /tmp/test-results/rspec.xml \
                            -- $(sed -e 's/\n/\\n/' -e 's/ /\ /' <<< "${TEST_FILES}")

      # collect reports
      - store_test_results:
          path: /tmp/test-results
      - store_artifacts:
          path: /tmp/test-results
          destination: test-results