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よりわかりやすい?
- 実行速度はプロジェクト規模が違うので比較は出来なかった。どうだろ。早い気もしてくる。