Minitest on Rails.

GitHub Actions with more than 2 cores

Cover Image for GitHub Actions with more than 2 cores
Dwight Watson
Dwight Watson

Rails provides parallel testing out of the box but GitHub Actions only gives you 2 cores as standard. With Rails 8 planning to ship with GitHub CI files it's worthwhile learning how to use more cores when required. Especially as your app (and test suite) grow the time benefits of increasing your parallelization compound.

Requirements: in order to use larger runners you will need to be using paid GitHub teams or an enterprise plan. It's also worth noting that the free minutes you get do not apply to larger runners.

Create a GitHub-hosted runner

Visit your organization settings - github.com/organizations/{YOUR_ORGANIZATION}/settings/actions/runners} and select New runner, followed by new GitHub-hosted runner.

Give your runner a name - it should be something simple as you will reference it in your GitHub workflows. You can leave everything else as default, but select the Runner size that meets your requiements. You can test how many cores work best for your suite and choose appropriately.

Use your new GitHub-hosted runner

Update your workflows to change the runs-on parameter. This defaults to ubuntu-latest which is the runner with 2 cores.

name: CI

on:
  push:
    branches: [main]
  pull_request:
    branches: [main]

jobs:
  test:
    runs-on: your_runner_name

    services:
      postgres:
        image: postgres
        env:
          POSTGRES_USER: postgres
          POSTGRES_PASSWORD: postgres
        ports:
          - 5432:5432
        options: --health-cmd="pg_isready" --health-interval=10s --health-timeout=5s --health-retries=3

    steps:
      - name: Install packages
        run: sudo apt-get update && sudo apt-get install --no-install-recommends -y google-chrome-stable postgresql-client libpq-dev libvips

      - name: Checkout code
        uses: actions/checkout@v4

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

      - name: Run Tests
        env:
          RAILS_ENV: test
          DATABASE_URL: postgres://postgres:postgres@localhost:5432
        run: bin/rails db:setup test test:system

For the other features of the default CI - namely Brakeman and Rubocop - you're worth leaving it on the default runner. They will not benefit from parallelization and you'll pay more for no reason.

Be sure to check the pricing for these runners but note that you are only charged for the time they are used - not when they are inactive.