Introduction

How do you ensure code quality, automate testing, and deploy Rails applications effortlessly? πŸš€

CI/CD (Continuous Integration & Continuous Deployment) automates the entire build, test, and deployment process, reducing errors and ensuring fast, reliable releases.

In this guide, we will cover:
βœ… Setting up Continuous Integration (CI) with GitHub Actions
βœ… Running automated tests on every push
βœ… Building Docker containers for deployment
βœ… Using Capistrano for zero-downtime releases

By the end, you’ll have a fully automated pipeline to ship high-quality Rails code faster. πŸš€


1. Understanding CI/CD in Rails

What is Continuous Integration (CI)?

CI ensures each code commit is tested automatically before merging.

πŸ’‘ Example Workflow:

  1. Developer pushes code β†’ GitHub Actions triggers
  2. Run RSpec & RuboCop tests
  3. If tests pass, merge to main branch
What is Continuous Deployment (CD)?

CD automates deploying tested code to production.

πŸ’‘ Example Workflow:

  1. Code is merged β†’ Build a Docker image
  2. Deploy to Heroku, AWS, or DigitalOcean
  3. Capistrano ensures zero-downtime deployment

Let’s set this up step by step.


2. Setting Up Continuous Integration with GitHub Actions

GitHub Actions automates CI for Rails projects.

πŸ“Œ Create a .github/workflows/ci.yml File
name: CI

on:
push:
branches:
- main
pull_request:

jobs:
test:
runs-on: ubuntu-latest

    services:
      postgres:
        image: postgres:13
        env:
          POSTGRES_USER: postgres
          POSTGRES_PASSWORD: password
        ports:
          - 5432:5432

    steps:
      - name: Checkout code
        uses: actions/checkout@v3

      - name: Set up Ruby
        uses: ruby/setup-ruby@v1
        with:
          ruby-version: 3.1
          bundler-cache: true

      - name: Install dependencies
        run: bundle install

      - name: Set up database
        run: |
          cp config/database.yml.ci config/database.yml
          bin/rails db:create db:migrate

      - name: Run tests
        run: bundle exec rspec

βœ… Triggers on every commit & PR
βœ… Runs tests inside GitHub’s cloud environment
βœ… Uses PostgreSQL service for DB testing


3. Automating Deployment with Docker & Capistrano

Once CI tests pass, we deploy using Docker and Capistrano for zero downtime.

πŸ“Œ Dockerize Your Rails App

Create a Dockerfile:

FROM ruby:3.1

WORKDIR /app
COPY . .
RUN bundle install
CMD ["rails", "server", "-b", "0.0.0.0"]

Build & push the image:

docker build -t myrailsapp .
docker tag myrailsapp myrepo/myrailsapp:latest
docker push myrepo/myrailsapp:latest

Now, let’s automate deployment with Capistrano.

πŸ“Œ Install Capistrano
bundle add capistrano capistrano-rails capistrano-passenger

Run:

bundle exec cap install

Modify config/deploy.rb:

set :application, "myrailsapp"
set :repo_url, "git@github.com:yourusername/myrailsapp.git"
set :deploy_to, "/var/www/myrailsapp"

Now, deploy with:

cap production deploy

πŸš€ Your Rails app is now deployed automatically!


4. Automating Deployment with GitHub Actions

Instead of manual deployment, trigger Docker builds & Capistrano deploys automatically.

πŸ“Œ Create a .github/workflows/deploy.yml File
name: Deploy

on:
push:
branches:
- main

jobs:
deploy:
runs-on: ubuntu-latest

    steps:
      - name: Checkout code
        uses: actions/checkout@v3

      - name: Log in to DockerHub
        run: echo "$" | docker login -u "$" --password-stdin

      - name: Build and push Docker image
        run: |
          docker build -t myrepo/myrailsapp:latest .
          docker push myrepo/myrailsapp:latest

      - name: Deploy with Capistrano
        run: |
          ssh deploy@myserver "cd /var/www/myrailsapp && cap production deploy"

πŸ”Ή Automatically deploys on git push
πŸ”Ή Ensures fresh Docker images are deployed
πŸ”Ή Uses GitHub Secrets for security


5. Best Practices for CI/CD in Rails

βœ… Run tests on every commit β†’ Prevents broken code from reaching production
βœ… Use Docker for consistency β†’ Eliminates β€œworks on my machine” issues
βœ… Automate deployment β†’ Avoids manual errors and downtime
βœ… Secure secrets β†’ Use environment variables instead of hardcoding API keys
βœ… Monitor deployments β†’ Use tools like New Relic or Datadog to track performance


Conclusion

With this setup, your Rails app now has:
βœ… Continuous Integration (CI) with GitHub Actions
βœ… Automated Testing (RSpec, RuboCop, Postgres)
βœ… Containerized Deployment with Docker
βœ… Zero-Downtime Deployments with Capistrano

This streamlines development, increases reliability, and makes scaling easier. πŸš€

πŸ”Ή What CI/CD tools do you use for Rails? Drop a comment below!