GitHub ActionsでRuby on Railsのテストを実行する(CIの構築) 2020-12版
はじめに
今まではCircleCIかWerckerを使っていたけど、GitHub Actionsが安定してきているようなので使い始めてみることにした。
CircleCIのWeb UIもそれほど使いやすいとは思ってなかったのも理由の1つ。
コスト比較
かなり安いとの記事を発見。
無料プランで比較すると、
月あたりCircleCIが約1000分、GHAは 2000分 のマシン時間が使える。(どちらも 2 cpu)
テンプレートを使ってみる
こちらの記事を参考に、GitHubのテンプレートでやってみる
GitHubのWebから全てできるので10分程度で完了。
設定内容としては、
- GitHubのコードをチェックアウト
- Ruby をセットアップ
- Rspecを実行
実行すると、DBへの接続エラーとなる。このGitHubのテンプレートはRubyを実行する設定だけなのでRailsに必要なDBなどの設定などがないため。
RailsのRspecを実行するための設定を作る
GitHub Actions公式のドキュメント を見ると、CircleCIが分かっていれば比較的分かりやすい
このあたりの2次情報を見て、イメージを補足
以下の方向性で設定ファイルを作成
- DB, Cacheサーバーはservices(Dockerコンテナ)で構築
- メインの実行環境もDockerコンテナで Rubyイメージを使う
- GitHub ActionsのRuby Setupは長期的なサポートとActionsのセキュリティに懸念があるので使わない
- npm, gem をキャッシュする
作成した設定ファイル
name: Test
on: [push]
jobs:
run:
runs-on: ubuntu-latest
services:
postgres:
image: postgres:10
options: --health-cmd pg_isready --health-interval 10s --health-timeout 5s --health-retries 5
env:
POSTGRES_HOST_AUTH_METHOD: 'trust'
redis:
image: redis:alpine
options: --health-cmd "redis-cli -h localhost ping" --health-interval 10s --health-timeout 5s --health-retries 15
container:
image: ruby:2.6.2
env:
RAILS_ENV: test
DATABASE_HOST: postgres
REDIS_URL: redis://redis:6379/1
steps:
- uses: actions/checkout@v2
- name: Cache node modules
uses: actions/cache@v2
env:
cache-name: cache-node-modules
with:
# npm キャッシュファイルは Linux/macOS の「~/.npm」に保存される
path: ~/.npm
key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ hashFiles('**/yarn.lock') }}
restore-keys: |
${{ runner.os }}-build-${{ env.cache-name }}-
${{ runner.os }}-build-
${{ runner.os }}-
- name: Cache bundle gems
uses: actions/cache@v2
with:
path: vendor/bundle
key: ${{ runner.os }}-gem-${{ hashFiles('**/Gemfile.lock') }}
restore-keys: |
${{ runner.os }}-gem-${{ env.cache-name }}-
${{ runner.os }}-gem-
${{ runner.os }}-
- name: Install Node.js and Yarn
run: |
# https://github.com/nodesource/distributions/blob/master/README.md#installation-instructions
curl -sL https://deb.nodesource.com/setup_12.x | bash -
apt-get install -y nodejs
# https://classic.yarnpkg.com/en/docs/install#debian-stable
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
apt update && apt install yarn
- name: Install Bundler
run: gem install bundler --no-document -v $(grep "BUNDLED WITH" -1 Gemfile.lock | tail -n 1)
- name: Bundle install
run: bundle install --path=vendor/bundle --jobs 4 --retry 3
- name: Yarn install
run: bundle exec rails yarn:install
- name: DB setup
run: bundle exec rails db:setup
- name: Run rspec
run: bundle exec rspec
設定ファイル解説
name: Test
ワークフローの名前。好みで変えてOK
run:
ジョブの名前。好みで変えてOK
この設定だと、Test.run
のように表示されます。 build
と記述する例が多かったのですが、 Test.build
となるので、個人的には冗長に感じました。
runs-on: ubuntu-latest
ジョブを実行するホストマシンの指定。 ubuntu-latest
は今はUbuntu 18.04
services:
別コンテナで起動するミドルウェアなどを定義します。Docker-compose の service
と同じ感じ。
postgres:
image: postgres:10
options: --health-cmd pg_isready --health-interval 10s --health-timeout 5s --health-retries 5
env:
POSTGRES_HOST_AUTH_METHOD: 'trust'
PostgreSQLを Dockerイメージで起動します。
optionsの起動チェックはこのあたりを参考にしています。
redis:
image: redis:alpine
options: --health-cmd "redis-cli -h localhost ping" --health-interval 10s --health-timeout 5s --health-retries 15
RedisをDockerイメージで起動します。
こちらも optionsの起動チェックは公式を参考にしています。
container:
image: ruby:2.6.2
env:
RAILS_ENV: test
DATABASE_HOST: postgres
REDIS_URL: redis://redis:6379/1
Ruby 2.6.2のDockerイメージでジョブを実行します。
DATABASE_HOST
はRailsの設定(database.ymlなど)で指定できるようにしあります。Docker-composeと同じくコンテナ同士のネットワークが構築されるので、Postgreのサービス名を指定しています。
REDIS_URL
も同じく redisの接続先を設定しています。
- uses: actions/checkout@v2
GitHubのコードをコンテナにチェックアウトします。
- name: Cache node modules
uses: actions/cache@v2
env:
cache-name: cache-node-modules
with:
# npm キャッシュファイルは Linux/macOS の「~/.npm」に保存される
path: ~/.npm
key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ hashFiles('**/yarn.lock') }}
restore-keys: |
${{ runner.os }}-build-${{ env.cache-name }}-
${{ runner.os }}-build-
${{ runner.os }}-
node moduleのキャッシュです。以下を参考にしてます。
CirclCIと比較すると cache actionsを使うことで、キャッシュの保存を記述しなくてもジョブ完了後に自動的に保存されるようです。
- name: Cache bundle gems
uses: actions/cache@v2
with:
path: vendor/bundle
key: ${{ runner.os }}-gem-${{ hashFiles('**/Gemfile.lock') }}
restore-keys: |
${{ runner.os }}-gem-${{ env.cache-name }}-
${{ runner.os }}-gem-
${{ runner.os }}-
node modulesと同じですが、パスなどを変えてます。
- name: Install Node.js and Yarn
run: |
# https://github.com/nodesource/distributions/blob/master/README.md#installation-instructions
curl -sL https://deb.nodesource.com/setup_12.x | bash -
apt-get install -y nodejs
# https://classic.yarnpkg.com/en/docs/install#debian-stable
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
apt update && apt install yarn
結構ハマるポイントなので、公式のドキュメントを見てバージョン決めてインストールしました。
- name: Install Bundler
run: gem install bundler --no-document -v $(grep "BUNDLED WITH" -1 Gemfile.lock | tail -n 1)
- name: Bundle install
run: bundle install --path=vendor/bundle --jobs 4 --retry 3
- name: Yarn install
run: bundle exec rails yarn:install
- name: DB setup
run: bundle exec rails db:setup
- name: Run rspec
run: bundle exec rspec
このあたりは、通常のRailsでの実行と同じなので説明は割愛
感想
- GitHubがテンプレートを用意してくれているものは最初の一歩としては優秀。Rubyの実行だけなら5分かからずできる
- Circle CIなどの外部サービスと比べて、GitHubの画面の中に
Actions
として表示されるので見やすい。追加でログインするのとか地味にストレス。ワークフローの開始も遅延が少ない気がする(数秒の違いですが) - 小さいRspecが5つくらいのRailsプロジェクトを実行したところ、実行に5分程度かかった。2回目以降にキャッシュが効くと2分弱で完了。他のサービスと比べても多分有意差はなさそう。
Discussion