This guide is intended for a Rails
application that uses PostgreSQL
and is tested, developed, and deployed using Docker
. The following link is a setup guide for a Rails
+ PostgreSQL
application using Docker
:
https://gist.github.com/iEv0lv3/17e33bc8d3ad4132d317ba5a1cf62d9b
The guide assumes the above Docker
+ Rails
setup is complete. The approach in this guide creates a new Rails
environment: staging
, and the only responsibility of the staging
environment is to be used with CircleCI
for CI/CD
testing. The environment name can be whatever you'd like, ci
, cd
, or circleci
would all work as environment names as well. Why I prefer this approach is because it allows the use of standard CircleCI
environments for the build
and test
jobs that utilize native CircleCI
images for Ruby
and PostgreSQL
. It also allows for a high degree of customization for CircleCI
without affecting Docker
test, development, and production deployments.
Completing the entire guide is required to ensure all functionality works as expected, but the primary factor that makes this build work is overwriting the default host: db
in config/database.yml
...
# config/database.yml
staging:
<<: *default
database: my_app_staging
host: 127.0.0.1
Updating the config/database.yml
file with the above code enables CircleCI
to use the standard PostgreSQL
image: circleci/postgres:12.3
, and run it locally on 127.0.0.1
. This guide requires Rails 6
in order to use credentials
.
There is an alternative approach that creates a Linux
environment in the .circleci/config.yml
setup using an Ubuntu
image, and then adds all necessary dependencies to run Docker
and Docker Compose
within that environment. The alternative approach allows for the use of docker-compose build
to build a test
environment in CircleCI
, which creates containers based on the project's Dockerfile
. The images built from the Dockerfile
are used in place of standard images from CircleCI
. A standard image configuartion for CircleCI
and a Rails
app generally includes:
# .circleci/config.yml
docker:
- image: cimg/ruby:2.7.1-node
- image: circleci/postgres:12.3
With my current level of Docker
knowledge I find the alternative approach to be more cumbersome and prone to errors, but it is a valid solution to use with CircleCI
.
- Open
Gemfile
- Add
gem ‘rspec_junit_formatter’
- Add
- Result
- Solves a test formatting error when running RSpec tests
The following steps create the staging
environment in Rails
- Add
staging.rb
toconfig/environments
- Copy contents of
config/environments/test.rb
intoconfig/environments/staging.rb
Here is a resource to help understand creating new Rails
environments
- Open
Gemfile
- Add
:staging
environment to Gem group that also includes:test
and:development
- Add
- Open
database.yml
and add
...
staging:
<<: *default
database: my_app_staging
host: 127.0.0.1
...
- Open
webpacker.yml
and add
...
staging:
<<: *default
compile: true
# Compile test packs to a separate directory
public_output_path: packs-test
...
- Run
rails c
Rails.application.credentials.config
- Copy
secret_key_base
and it’s value - Close
rails c
- Edit
staging
environment credentials in terminalEDITOR=“code --wait” bin/rails credentials:edit --environment staging
- In the above command replace
code
with yourIDE
of choice
- In the above command replace
- A file will open that can be edited
- Add
secret_key_base: <paste value>
to file - Close file and it will save and encrypt
Here are some resources to help understand Rails
credentials
- https://guides.rubyonrails.org/security.html#environmental-security
- https://blog.saeloun.com/2019/10/10/rails-6-adds-support-for-multi-environment-credentials.html
- Open
.gitignore
- Add
/config/credentials/staging.key
- Add
- Open
.circleci/config.yml
and ensure these environment variables are set correctly
jobs:
test:
docker:
- image: circleci/postgres:12.3
environment:
POSTGRES_DB: my_app_staging
environment:
RAILS_ENV: staging
PGHOST: 127.0.0.1
- Open project on
CircleCI.com
- Open project options
- Add Environment Variable
RAILS_MASTER_KEY: <staging.key value>
version: 2.1 # Use 2.1 to enable using orbs and other features.
# Declare the orbs that we'll use in our config.
orbs:
ruby: circleci/[email protected]
node: circleci/[email protected]
jobs:
build: # our first job, named "build"
docker:
- image: cimg/ruby:2.7.1-node # use a tailored CircleCI docker image.
steps:
- checkout # pull down our git code.
- ruby/install-deps # use the ruby orb to install dependencies
# use the node orb to install our packages
# specifying that we use `yarn` and to cache dependencies with `yarn.lock`
# learn more: https://circleci.com/docs/2.0/caching/
- node/install-packages:
pkg-manager: yarn
test: # our next job, called "test"
# we run "parallel job containers" to enable speeding up our tests;
# this splits our tests across multiple containers.
parallelism: 3
# here we set TWO docker images.
docker:
- image: cimg/ruby:2.7.1-node # this is our primary docker image, where step commands run.
- image: circleci/postgres:12.3
environment: # add POSTGRES environment variables.
POSTGRES_USER: postgres
POSTGRES_PASSWORD: password
POSTGRES_DB: my_app_staging
# environment variables specific to Ruby/Rails, applied to the primary container.
environment:
BUNDLE_JOBS: "3"
BUNDLE_RETRY: "3"
PGHOST: 127.0.0.1
PGUSER: postgres
PGPASSWORD: password
RAILS_ENV: staging
# A series of steps to run, some are similar to those in "build".
steps:
- checkout
- ruby/install-deps
- node/install-packages:
pkg-manager: yarn
# Here we make sure that the secondary container boots
# up before we run operations on the database.
- run:
name: Wait for DB
command: dockerize -wait tcp://localhost:5432 -timeout 1m
- run:
name: Database setup
command: bundle exec rails db:schema:load --trace
# Run rspec in parallel
- ruby/rspec-test
# We use workflows to orchestrate the jobs that we declared above.
workflows:
version: 2
build_and_test: # The name of our workflow is "build_and_test"
jobs: # The list of jobs we run as part of this workflow.
- build # Run build first.
- test: # Then run test,
requires: # Test requires that build passes for it to run.
- build