Rails + RSpec + postgresをGitHub Actionsで自動テスト

GitHub上でCI/CDが完結するツールであるGitHub Actionsを触ってみた。

今回書いたのは、Ruby on RailsのRSpecで書かれているテストを実行する設定なので、.github/workflows/ruby.ymlに書く。
ちなみにデータベースはpostgres。herokuで動かしているアプリなので。

設定内容は次の状態にしたら無事に動いた。

name: RSpec
on: [push]
jobs:
  test:
    runs-on: ubuntu-latest
    if: "!contains(github.event.head_commit.message, 'ci skip')"
    services:
      postgres:
        image: postgres:12
        env:
          POSTGRES_USER: postgres
          POSTGRES_PASSWORD: postgres
          POSTGRES_DB: my_database
        options: >-
          --health-cmd pg_isready
          --health-interval 10s
          --health-timeout 5s
          --health-retries 5
        ports:
          - 5432:5432
    steps:
    - uses: actions/checkout@v2
    - name: Set up Ruby
      uses: ruby/setup-ruby@ec106b438a1ff6ff109590de34ddc62c540232e0
      with:
        ruby-version: 2.7.1
    - name: Cache gems
      uses: actions/cache@v1
      with:
        path: vendor/bundle
        key: ${{ runner.os }}-gem-${{ hashFiles('**/Gemfile.lock') }}
        restore-keys: |
          ${{ runner.os }}-gem-
    - name: Cache node modules
      uses: actions/cache@v1
      with:
        path: node_modules
        key: ${{ runner.os }}-node-${{ hashFiles('**/yarn.lock') }}
        restore-keys: |
          ${{ runner.os }}-node-
    - name: Install dependencies
      run: |
        gem install bundler
        bundle install --path vendor/bundle --without production
        yarn install
    - name: Set env
      run: |
        echo '::set-env name=RAILS_ENV::test'
        echo '::set-env name=DATABASE_URL::postgres://postgres:postgres@localhost:5432/my_database'
    - name: setup DB
      run: |
        bundle exec rails db:schema:load
    - name: Run tests
      run: bundle exec rspec

解説していく

name

name: RSpec

これはGitHub Acttionsのweb上に表示される名前なので、何のワークフローなのかわかりやすい名前を好きに付けていい。

on

on: [push]

最初はpushとpullrequestを両方使っていたのだけれど、いざPRを出してみたらなんか2重でテストが実行されたのでpushにしておいた。
pullrequestの用途は要調査ですね。

jobs

jobs:
  test:

jobを何個も好きに増やせる。
たとえばテストと並列してrubocopなどのlintをしたければ、test: の他に lint: を増やす。みたいな。

if

    if: "!contains(github.event.head_commit.message, 'ci skip')"

gitのコミットメッセージの一行目にci skipが存在する場合は、このjobをキャンセルする。
GitHub Actionsの無料枠は月2000分なので、節約しようかなと。

postgres

    services:
      postgres:
        image: postgres:12
        env:
          POSTGRES_USER: postgres
          POSTGRES_PASSWORD: postgres
          POSTGRES_DB: my_database
        options: >-
          --health-cmd pg_isready
          --health-interval 10s
          --health-timeout 5s
          --health-retries 5
        ports:
          - 5432:5432

postgresの設定。
POSTGRES_DBにRails側のdatabase.ymlに書かれているtest DB名を指定しておけば、自動で作ってくれる。つまり、rails側でdb:createを実行する必要がない。
optionsは公式のヘルプとまったく一緒。

DB名間違えたら、実行時に次のエラーが出たりした。

could not translate host name "postgress" to address: Name or service not known
Couldn't create 'my_database' database. Please check your configuration.

キャッシュ

    - name: Cache gems
      uses: actions/cache@v1
      with:
        path: vendor/bundle
        key: ${{ runner.os }}-gem-${{ hashFiles('**/Gemfile.lock') }}
        restore-keys: |
          ${{ runner.os }}-gem-
    - name: Cache node modules
      uses: actions/cache@v1
      with:
        path: node_modules
        key: ${{ runner.os }}-node-${{ hashFiles('**/yarn.lock') }}
        restore-keys: |
          ${{ runner.os }}-node-

bundlerとyarnのインストール結果をキャシュした。
キャッシュは成功時にのみ作られるっぽい。

環境変数の設定

    - name: Set env
      run: |
        echo '::set-env name=RAILS_ENV::test'
        echo '::set-env name=DATABASE_URL::postgres://postgres:postgres@localhost:5432/my_database'

set-envを使うことにより、これ以降のコマンド全てに適応する環境変数を設定することができる。
コマンド毎にenvでRAILS_ENV=testを設定するのが面倒なので使った。

DATABSE_URLはrails側でdatabase.ymlが次のようになっているのと対応している。

test:
  <<: *default
  url: <%= ENV['DATABASE_URL'].presence %>
  database: my_database

localhostを使わなかったり、ポートを間違えたりして次のエラーが出まくって苦しめられた・・・。

could not connect to server: Connection refused
    Is the server running on host "localhost" (127.0.0.1) and accepting
    TCP/IP connections on port 5432?
Couldn't create 'my_database' database. Please check your configuration.

感想

  • CircleCIを普段使っているけど、並列が無料プランでも大量にできるのはすごい
  • cacheがCIrcleCIよりわかりやすい?
  • 実行速度はプロジェクト規模が違うので比較は出来なかった。どうだろ。早い気もしてくる。
タイトルとURLをコピーしました