Github Actionsを使ってRails×PostgreSQL環境のCIを作りました。
Github Actionsは普段触らなかったので、作ったCIについてコードの解説をここに書いていきます。
まずはCIでやっていることと、そのコードの全体像を書いていきます。そのあとにCIのコードについて説明を書いていきます。
今回のCIでやっていること
- Pull Requestが作られたタイミングで、RSpecによるテスト
- Masterブランチにマージされたタイミングで、Herokuにデプロイ
- テストが完了したら、Slackに通知する
書いたCI
name: Build And Test
on:
pull_request:
push:
branches:
- master
jobs:
build_and_test:
name: Exec RSpec rubocop brakeman
runs-on: ubuntu-latest
services:
postgres:
image: postgres:11.5
ports:
- 5432:5432
options: >-
--health-cmd pg_isready
--health-interval 10s
--health-timeout 5s
--health-retries 5
env:
RAILS_ENV: test
BUNDLE_PATH: ./vendor/bundle
DATABASE_NAME: covid19_line_bot_test
DATABASE_USER: postgres
DATABASE_PASSWORD: ""
DATABASE_HOST: 127.0.0.1
DATABASE_PORT: 5432
TZ: Asia/Tokyo
RAILS_MASTER_KEY: ${{ secrets.RAILS_MASTER_KEY }}
steps:
- name: Check out code
uses: actions/checkout@v2
- name: Cache Gemfile.lock
uses: actions/cache@v2
with:
path: ./vendor/bundle
key: ${{ runner.os }}-rails-bundle-v1-${{ hashFiles('**/Gemfile.lock') }}
restore-keys: |
${{ runner.os }}-rails-bundle-v1-
- name: Ruby 2.6.5のセットアップ
uses: ruby/setup-ruby@v1
with:
ruby-version: 2.6.5
- name: pg gem の依存関係のインストール
run: |
sudo apt-get update; sudo apt-get install libpq-dev
- name: node v10のセットアップ
uses: actions/setup-node@v1
with:
node-version: '10.x'
- name: yarn install
run: |
yarn install --check-files
- name: gem install
run: |
gem install bundler -v 1.17.3
- name: bundler install
run: |
bundle check || bundle install --path vendor/bundle --jobs 4 --retry 3
- name: Setup Database
run: |
bundle exec rails db:create db:schema:load --trace
- name: Exec RSpec
run: |
bundle exec rspec --format documentation --force-color --backtrace
- name: Exec Brakeman
run: |
bundle exec brakeman -A
- name: Exec rubocop
run: |
bundle exec rubocop --extra-details --display-style-guide --parallel --display-cop-names
test_slack_notification:
name: 【Test Result】Slack Notification by Github Actions
runs-on: ubuntu-latest
needs: build_and_test
env:
SLACK_WEBHOOK: ${{ secrets.SLACK_WEBHOOK_URL }}
SLACK_USERNAME: Github Actions Result
steps:
- name: Slack Notification on Success
uses: rtCamp/action-slack-notify@v2
if: success()
env:
SLACK_MESSAGE: Pass rubocop, rspec, brakeman
SLACK_TITLE: Test Complete!🎉✨
- name: Slack Notification on Failure
uses: rtCamp/action-slack-notify@v2
if: failure()
env:
SLACK_MESSAGE: Fail rubocop, rspec, brakeman
SLACK_TITLE: Test Failure!👾
SLACK_COLOR: "#dc3545"
deploy_production:
name: Herokuにデプロイ
needs: build_and_test
runs-on: ubuntu-latest
if: github.ref == 'refs/heads/master'
steps:
- name: Check out code
uses: actions/checkout@v2
- name: Deploy to Heroku Production
uses: akhileshns/heroku-deploy@v3.6.8
with:
heroku_api_key: ${{ secrets.HEROKU_API_KEY }}
heroku_app_name: ${{ secrets.HEROKU_APP_NAME }}
heroku_email: ${{ secrets.HEROKU_EMAIL }}
解説
name
name: Build And Test
ワークフローの名前GitHub リポジトリの [Actions] タブに表示されるワークフローの名前
on
ワークフローを実行するタイミングを指定
on:
pull_request:
push:
branches:
- master
上記の例では、以下のタイミングでワークフローが走ります。
- Pull Requestが作られたとき
- MasterブランチにPushされたとき
他にもデプロイがされたとき、ブランチが作られたとき、プルリクにレビューが投げられたとき、など様々なタイミングを指定することが可能。
参考:Events that trigger workflows
jobs
ワークフローは1つ以上のJobからなる。
複数のジョブはデフォルトでは、並行に実行される。
jobs.job_id
JobにはJobを一意に判別するIDが必要
jobs:
build_and_test:
name: Exec RSpec rubocop brakeman
runs-on: ubuntu-latest
services: ~~~
[省略]
test_slack_notification:
name: 【Test Result】Slack Notification by Github Actions
runs-on: ubuntu-latest
needs: build_and_test
env:
SLACK_WEBHOOK: ${{ secrets.SLACK_WEBHOOK_URL }}
SLACK_USERNAME: Github Actions Result
steps: ~~
[省略]
deploy_production:
name: Herokuにデプロイ
needs: build_and_test
runs-on: ubuntu-latest
if: github.ref == 'refs/heads/master'
[省略]
上記のコードではこれらがJobのIDのキーに該当します。
- build_and_test
- test_slack_notification
- deploy_production
jobs.job_name
Jobの名前
build_and_test:
name: Exec RSpec rubocop brakeman
test_slack_notification:
name: 【Test Result】Slack Notification by Github Actions
deploy_production:
name: Herokuにデプロイ
jobs.runs_on
Jobを実行するマシンを指定します。
build_and_test:
name: Exec RSpec rubocop brakeman
runs-on: ubuntu-latest
2020年12月16日現在は、このような環境が用意されています
Virtual environment | YAML workflow label |
---|---|
Windows Server 2019 | windows-latest or windows-2019 |
Ubuntu 20.04 | ubuntu-20.04 |
Ubuntu 18.04 | ubuntu-latest or ubuntu-18.04 |
Ubuntu 16.04 | ubuntu-16.04 |
macOS Big Sur 11.0 | macos-11.0 |
macOS Catalina 10.15 | macos-latest or macos-10.15 |
参考:Github Actions Supported runners and hardware resources
jobs.services
ジョブのためのサービスコンテナをホストするために使用
[サービスコンテナ]
Jobを実行するのに必要になるDBやRedisなどのサービスを提供できるDockerコンテナ
jobs:
build_and_test:
name: Exec RSpec rubocop brakeman
runs-on: ubuntu-latest
services:
postgres:
image: postgres:11.5
ports:
- 5432:5432
# ↓postgresが起動するまで待つヘルスチェックの設定
options: >-
--health-cmd pg_isready
--health-interval 10s
--health-timeout 5s
--health-retries 5
jobs.env
Job中で使える環境変数を定義
Stepの中に書けば、そのStepでのみ利用可能な環境変数を定義できる
jobs:
build_and_test:
name: Exec RSpec rubocop brakeman
[省略]
env:
RAILS_ENV: test
BUNDLE_PATH: ./vendor/bundle
DATABASE_NAME: covid19_line_bot_test
DATABASE_USER: postgres
DATABASE_PASSWORD: ""
DATABASE_HOST: 127.0.0.1
DATABASE_PORT: 5432
TZ: Asia/Tokyo
RAILS_MASTER_KEY: ${{ secrets.RAILS_MASTER_KEY }}
jobs.needs
ジョブの実行前に正常に完了する必要があるジョブを指定できる
以下の例だと、 build_and_test
が正常に完了しないと、test_slack_notification
も deploy_production
も実行され
jobs:
[省略]
test_slack_notification:
name: 【Test Result】Slack Notification by Github Actions
runs-on: ubuntu-latest
needs: build_and_test
deploy_production:
name: Herokuにデプロイ
needs: build_and_test
jobs.if
ジョブを実行する条件を書くことができる
deploy_production:
name: Herokuにデプロイ
needs: build_and_test
runs-on: ubuntu-latest
if: github.ref == 'refs/heads/master'
github.refとは
ワークフローの実行をトリガーしたブランチまたはタグ ref。 ブランチの場合、これはrefs/heads/ の形式で、タグの場合は refs/tags/ です
参考:GitHub Actions のコンテキストおよび式の構文
steps
Jobで実行するコマンドなどを書いていく
steps:
- name: Check out code
uses: actions/checkout@v2
- name: Cache Gemfile.lock
uses: actions/cache@v2
with:
path: ./vendor/bundle
key: ${{ runner.os }}-rails-bundle-v1-${{ hashFiles('**/Gemfile.lock') }}
restore-keys: |
${{ runner.os }}-rails-bundle-v1-
- name: Ruby 2.6.5のセットアップ
uses: ruby/setup-ruby@v1
with:
ruby-version: 2.6.5
- name: pg gem の依存関係のインストール
run: |
sudo apt-get update; sudo apt-get install libpq-dev
- name: node v10のセットアップ
uses: actions/setup-node@v1
with:
node-version: '10.x'
- name: yarn install
run: |
yarn install --check-files
- name: gem install
run: |
gem install bundler -v 1.17.3
- name: bundler install
run: |
bundle check || bundle install --path vendor/bundle --jobs 4 --retry 3
- name: Setup Database
run: |
bundle exec rails db:create db:schema:load --trace
- name: Exec RSpec
run: |
bundle exec rspec --format documentation --force-color --backtrace
- name: Exec Brakeman
run: |
bundle exec brakeman -A
- name: Exec rubocop
run: |
bundle exec rubocop --extra-details --display-style-guide --parallel --display-cop-names
steps.name
GitHubで表示されるステップの名前
steps:
- name: Check out code
uses: actions/checkout@v2
steps.uses
ステップとして実行するアクションを選択
steps:
- name: Check out code
uses: actions/checkout@v2
- name: Cache Gemfile.lock
uses: actions/cache@v2
with:
path: ./vendor/bundle
key: ${{ runner.os }}-rails-bundle-v1-${{ hashFiles('**/Gemfile.lock') }}
restore-keys: |
${{ runner.os }}-rails-bundle-v1-
- name: Ruby 2.6.5のセットアップ
uses: ruby/setup-ruby@v1
with:
ruby-version: 2.6.5
使っているusersの説明
actions/checkout@v2
リポジトリをチェックアウトする
- name: Check out code
uses: actions/checkout@v2
参考:https://github.com/actions/checkout
actions/cache@v2
キャッシュできる
- name: Cache Gemfile.lock
uses: actions/cache@v2
with:
path: ./vendor/bundle
key: ${{ runner.os }}-rails-bundle-v1-${{ hashFiles('**/Gemfile.lock') }}
restore-keys: |
${{ runner.os }}-rails-bundle-v1-
path: ~~
はキャッシュする、復元するファイルやディレクトリを指定する
key: ~~
はキャッシュを保存/復元するためのキー
restore-keys: ~~
はキーのキャッシュヒットが発生しなかった場合にキャッシュを復元するために使用するキーの順序付きリスト
参考:https://github.com/actions/cache
ruby/setup-ruby@v1
- name: Ruby 2.6.5のセットアップ
uses: ruby/setup-ruby@v1
with:
ruby-version: 2.6.5
ruby-version:~~
で使用するRubyのバージョンを指定できる
参考:https://github.com/ruby/setup-ruby
actions/setup-node@v1
- name: node v10のセットアップ
uses: actions/setup-node@v1
with:
node-version: '10.x'
node-version:~~
で使用するNodeのバージョンを指定できる
参考:https://github.com/actions/setup-node
rtCamp/action-slack-notify@v2
Slackに通知を送ることができる
- name: Slack Notification on Success
uses: rtCamp/action-slack-notify@v2
if: success()
env:
SLACK_MESSAGE: Pass rubocop, rspec, brakeman
SLACK_TITLE: Test Complete!🎉✨
SLACK_WEBHOOK:$ {{secrets.SLACK_WEBHOOK}}
SlackのWebHockのURL設定は必須
参考:https://github.com/rtCamp/action-slack-notify
akhileshns/heroku-deploy@v3.6.8
Herokuにデプロイできる
- name: Deploy to Heroku Production
uses: akhileshns/heroku-deploy@v3.6.8
with:
heroku_api_key: ${{ secrets.HEROKU_API_KEY }}
heroku_app_name: ${{ secrets.HEROKU_APP_NAME }}
heroku_email: ${{ secrets.HEROKU_EMAIL }}
heroku_api_key:、heroku_app_name:、heroku_emailは必須
参考:https://github.com/AkhileshNS/heroku-deploy
steps.run
コマンドラインプログラムを実行する
- name: yarn install
run: |
yarn install --check-files
- name: gem install
run: |
gem install bundler -v 1.17.3
- name: bundler install
run: |
bundle check || bundle install --path vendor/bundle --jobs 4 --retry 3
- name: Exec RSpec
run: |
bundle exec rspec --format documentation --force-color --backtrace
runの中では、bundle installやyarn install、Rspecの実行などを行うようにしました。
終わりに
Rails×PostgreSQL環境を使うことが多くていままでCircleCIを利用していましたが今回GithubActionsを書いてみました。CIとしてそれほど大きな違いはなく感じたので、個人的には学習コストは低かったです。
ドキュメントも非常に分かりやすく日本語で書かれていてよかったです。