Ruby on Rails GitHub Actions Workflow Template
Last updated
This is a working .github/workflows/ci.yml for a Rails app on Postgres. It caches gems with ruby/setup-ruby, starts a Postgres service container, prepares the test database and runs RuboCop and your tests.
The workflow
name: CI
on:
push:
branches: [main]
pull_request:
permissions:
contents: read
concurrency:
group: ci-${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: ${{ github.event_name == 'pull_request' }}
jobs:
test:
runs-on: ubuntu-latest
timeout-minutes: 20
services:
postgres:
image: postgres:16
env:
POSTGRES_USER: postgres
POSTGRES_PASSWORD: postgres
ports:
- 5432:5432
options: >-
--health-cmd "pg_isready -U postgres"
--health-interval 5s
--health-timeout 5s
--health-retries 10
env:
RAILS_ENV: test
DATABASE_URL: postgres://postgres:postgres@localhost:5432/app_test
steps:
- uses: actions/checkout@v4
- uses: ruby/setup-ruby@v1
with:
ruby-version: .ruby-version
bundler-cache: true
- run: bundle exec rubocop --parallel
- run: bin/rails db:create db:schema:load
- run: bin/rails test
What the non-obvious parts do
ruby-version: .ruby-versionreads the version from your repository file, so CI and local development cannot drift. If you do not have the file, write a version such as"3.3"instead.bundler-cache: truerunsbundle installand caches the gems, keyed onGemfile.lockand the Ruby version. You do not need a separateactions/cachestep.services.postgresruns Postgres next to the job atlocalhost:5432. The--health-*options make GitHub wait until it accepts connections.DATABASE_URLoverridesconfig/database.ymlin Rails, so the same file can serve local and CI use. The database nameapp_testis created bydb:create.db:schema:loadbuilds the database fromdb/schema.rbin one step, which is faster than replaying every migration. Usedb:structure:loadif you usestructure.sql.rubocop --parallellints on all cores. Remove the step if you do not use RuboCop.bin/rails testruns Minitest. Replace it withbundle exec rspecfor RSpec.
Variants
System tests and JavaScript
Rails apps with JavaScript need Node. Add actions/setup-node@v4 with cache: yarn or npm, and run bin/rails assets:precompile or yarn build before the tests. System tests need Chrome, already present on ubuntu-latest.
Parallel tests
Rails can parallelise tests with parallelize(workers: :number_of_processors) in test_helper.rb. For several machines, use test sharding, and give each shard its own database.
Redis or Sidekiq
Add a redis:7 service with --health-cmd "redis-cli ping".
Deploy job
Add a second job with needs: test on main only. Use OIDC to reach your cloud.
macOS
Not needed for a server app. Stay on Linux; service containers do not run on macOS runners.
Run it on faster machines
Rails suites spend most of their time in database setup and test execution. Change one line:
runs-on: [self-hosted, Linux, compiler-ci]
The job then runs on a fresh 8 vCPU machine from compiler.dev, with automatic fallback. For a full tuning list, see speed up Rails on GitHub Actions. Prices are on the pricing page.
FAQ
Why not use actions/cache for gems?
bundler-cache: true does it for you with a correct key. Manual caching often misses the Ruby version in the key.
My tests fail only in CI with a connection error. Why?
Check that DATABASE_URL host is localhost and that the health check options are present.
Can I use MySQL instead?
Yes. Swap the service for mysql:8, use --health-cmd "mysqladmin ping", and change the DATABASE_URL scheme to mysql2://.
How do I debug a failure?
Upload log/test.log and tmp/screenshots as an artifact with if: failure().
Related
- Speed Up Rails in GitHub ActionsSpeed up Rails CI in GitHub Actions: gem caching, bootsnap, Postgres and Redis services, parallel_tests splitting, and assets. Working YAML.
- .NET GitHub Actions Workflow TemplateCopy-paste GitHub Actions CI for .NET with NuGet caching, restore, build and test steps, a SQL Server service option, concurrency and permissions.
- Django GitHub Actions Workflow TemplateCopy-paste GitHub Actions CI for Django with a Postgres service container, pip caching, migrations check and tests, plus concurrency and permissions.
- Docker Build GitHub Actions Workflow TemplateCopy-paste GitHub Actions workflow to build Docker images with Buildx, GitHub cache layers and a push to GHCR on main, with minimal permissions.