Help us understand the problem. What is going on with this article?

Rails on GitHub Actions チュートリアル

More than 1 year has passed since last update.

Github Actions 使ってますか?
まだβ版ですし本稼働させている人は多くないと思いますが、 2019年11月中旬頃にようやくキャッシュ機構が実装されるそうなので、 CircleCI 非課金勢としては非常に楽しみにしています。
宣言通り実装されたので追記しました!

Rails の CI を Github Actions で動かすにあたって、システムテスト周りで少しハマったので、導入方法をまとめてみました。

Rails プロジェクトの初期化

いつも通り rails new していきます。
今回は Rails 標準の minitest を使っていますが RSpec の場合でもほぼ変わりません。

$ mkdir rails_on_github_actions
$ bundle init
Gemfile
# frozen_string_literal: true
source "https://rubygems.org"
git_source(:github) {|repo_name| "https://github.com/#{repo_name}" }
gem "rails"
$ bundle
$ bundle exec rails new .
$ bin/rails db:migrate

テストをするために user リソースを追加しておきます。

$ bin/rails g scaffold users
$ bin/rails db:migrate
$ bin/rails test

Workflow の作成

Github Actions でテストを走らせるために、 workflow を作っていきます。
scaffold によってシステムテストも作られていますが、一旦ここではブラウザを使わないテストだけ扱います。

.github/workflows/test.yml
name: Test
on: [push]
jobs:
  build:
    runs-on: ubuntu-latest
    container:
      image: ruby:2.6.4
    steps:
    - uses: actions/checkout@v1
    - name: Set up node and yarn
      run: |
        curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | apt-key add -
        echo "deb https://dl.yarnpkg.com/debian/ stable main" | tee /etc/apt/sources.list.d/yarn.list
        curl -sL https://deb.nodesource.com/setup_12.x | bash -
        apt install -y nodejs yarn
    - name: Build and setup
      run: |
        bundle -j 4
        bin/rails yarn:install db:setup assets:precompile
        bin/rails test

これを push すると workflow が自動的に走ります。

System Test

Github Actions で system test を実行するため、 Chrome をインストールするスクリプトを workflow に追加しています。

.github/workflows/test.yml
name: Test
on: [push]
jobs:
  build:
    runs-on: ubuntu-latest
    container:
      image: ruby:2.6.4
    steps:
    - uses: actions/checkout@v1
    - name: Set up YARN and NodeJS
      run: |
        curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | apt-key add -
        echo "deb https://dl.yarnpkg.com/debian/ stable main" | tee /etc/apt/sources.list.d/yarn.list
        curl -sL https://deb.nodesource.com/setup_12.x | bash -
        apt install -y yarn nodejs
    - name: Install chrome
      run: |
        wget -q -O - https://dl.google.com/linux/linux_signing_key.pub | apt-key add -
        echo 'deb http://dl.google.com/linux/chrome/deb/ stable main' | tee /etc/apt/sources.list.d/google-chrome.list
        apt update -y
        apt install -y google-chrome-stable
    - name: Build
      run: |
        bundle -j 4
        bin/rails yarn:install db:setup assets:precompile
    - name: Run test
      run: |
        bin/rails test
    - name: Run system test
      run: |
        bin/rails test:system

ローカル環境なら driven_by :selenium_chrome_headless だけで Headless Chrome を使ってテストできますが、 Github Actions のような Docker 環境だと /dev/shm のサイズ割り当てが小さいため、それを使わないようにするため disable-dev-shm-usage という起動オプションを追加しています。また、 no-sandbox は Docker 環境のように root 権限で Chrome を立ち上げるのに必要なオプションです。

test/application_system_test_case.rb
require "test_helper"

class ApplicationSystemTestCase < ActionDispatch::SystemTestCase
  driven_by :selenium, using: :headless_chrome, screen_size: [1400, 1400] do |driver_options|
    driver_options.add_argument('--disable-dev-shm-usage')
    driver_options.add_argument('--no-sandbox')
  end
end

これを push すると Github Actions で system test も無事に成功します。

MySQL

実際のアプリケーションでは SQLite を使うことはほぼ無いと思うので、 Github Actions でも MySQL を使ってみます。

Gemfile に mysql2 を追加

Gemfile
gem 'mysql2'

database.yml を MySQL 用に更新します。ほぼデフォルトですが、ホスト名とパスワードを環境変数で設定できるようにしています。

config/database.yml
default: &default
  adapter: mysql2
  pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
  username: root
  charset: utf8mb4
  collation: utf8mb4_bin
  encoding: utf8mb4
  password: <%= ENV.fetch('MYSQL_ROOT_PASSWORD', '') %>
  host: <%= ENV.fetch('MYSQL_HOST', 'localhost') %>

development:
  <<: *default
  database: rails_on_github_actions_development
test:
  <<: *default
  database: rails_on_github_actions_test
production:
  <<: *default
  database: rails_on_github_actions_production

テストが正常に動くかローカルで確認しておきます。

$ bin/rails db:create
$ bin/rails test
$ bin/rails test:system

workflow の services に MySQL を追加します。root のパスワードは環境変数で設定します。
services で追加したコンテナのホスト名はサービス名と同じになるようです。

.github/workflows/test.yml
name: Test
on: [push]
jobs:
  build:
    runs-on: ubuntu-latest
    services:
      mysql:
        image: mysql:5.7
        env:
          MYSQL_ROOT_PASSWORD: password
    container:
      image: ruby:2.6.4
      env:
        MYSQL_HOST: mysql
        MYSQL_ROOT_PASSWORD: password
    steps:
    - uses: actions/checkout@v1
    - name: Set up yarn and node
      run: |
        curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | apt-key add -
        echo "deb https://dl.yarnpkg.com/debian/ stable main" | tee /etc/apt/sources.list.d/yarn.list
        curl -sL https://deb.nodesource.com/setup_12.x | bash -
        apt install -y yarn nodejs
    - name: Install chrome
      run: |
        wget -q -O - https://dl.google.com/linux/linux_signing_key.pub | apt-key add -
        echo 'deb http://dl.google.com/linux/chrome/deb/ stable main' | tee /etc/apt/sources.list.d/google-chrome.list
        apt update -y
        apt install -y google-chrome-stable
    - name: Build
      run: |
        bundle -j 4
        bin/rails yarn:install db:setup assets:precompile
    - name: Run test
      run: |
        bin/rails test
    - name: Run system test
      run: |
        bin/rails test:system

これを push すると Github Actions で MySQL を使ったテストが無事に成功します。
services と環境変数を書き換えれば postgres などの他のデータベースも使用できるかと思います。

キャッシュ

Actions リリース当時はキャッシュ機構が実装されておらず、自前でキャッシュ機構を用意しない限りビルド毎に gem や Node モジュールのインストールが必要でしたが、actions/cache が2019年11月に提供され、一般的な CI サービスと同等レベルに使えるサービスになりました。

ここでは前回の MySQL のサンプルをベースにして、Gemflie.lock と yarn.lock のハッシュ値をキャッシュのキーとして使用し、ライブラリに変更がなければ余計なダウンロードが行われないようにしてみます。

.github/workflows/test.yml
name: Test
on: [push]
jobs:
  build:
    runs-on: ubuntu-latest
    services:
      mysql:
        image: mysql:5.7
        env:
          MYSQL_ROOT_PASSWORD: password
    container:
      image: ruby:2.6.4
      env:
        MYSQL_HOST: mysql
        MYSQL_ROOT_PASSWORD: password
    steps:
    - uses: actions/checkout@v1
    - uses: actions/cache@v1
      with:
        path: vendor/bundle
        key: bundle-${{ hashFiles('**/Gemfile.lock') }}
    - uses: actions/cache@v1
      with:
        path: node_modules
        key: yarn-${{ hashFiles('**/yarn.lock') }}
    - name: Set up yarn and node
      run: |
        curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | apt-key add -
        echo "deb https://dl.yarnpkg.com/debian/ stable main" | tee /etc/apt/sources.list.d/yarn.list
        curl -sL https://deb.nodesource.com/setup_12.x | bash -
        apt install -y yarn nodejs
    - name: Install chrome
      run: |
        wget -q -O - https://dl.google.com/linux/linux_signing_key.pub | apt-key add -
        echo 'deb http://dl.google.com/linux/chrome/deb/ stable main' | tee /etc/apt/sources.list.d/google-chrome.list
        apt update -y
        apt install -y google-chrome-stable
    - name: Build
      run: |
        bundle -j 4 --path vendor/bundle
        bin/rails yarn:install db:setup assets:precompile
    - name: Run test
      run: |
        bin/rails test
    - name: Run system test
      run: |
        bin/rails test:system

詳細なドキュメントはこちらになります。上限2GBってなかなか太っ腹ですね。
https://help.github.com/en/actions/automating-your-workflow-with-github-actions/caching-dependencies-to-speed-up-workflows

今回作ったサンプルプロジェクトは Github に置いてますので良かった参考にしてみてください。
https://github.com/d-mato/rails_on_github_actions

d-mato
魚屋でエンジニアやってます。
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away