rubocop, erblint, rspecをGitHub Actionsで回したいと思い、GitHub Actionsについて学習したことをここに整理します。
用語について
-
on
: トリガーを指定。例)push
-
job
: 同一のruuner
上で実行される。steps
の集まり。 -
runs-on
: ランナーのOSを指定。例)ubuntu-latest
- ランナー: ワークフローがトリガーされると実行されるサーバー。各ランナーあたりひとつの
job
を実行
- ランナー: ワークフローがトリガーされると実行されるサーバー。各ランナーあたりひとつの
-
step
: シェルスクリプトoraction
。同一job内のstep
ではデータを共有できる。 -
action
:step
内の個々のタスク。GitHub公式のアクションやサードパーティのアクション、独自作成したアクションを使用可能。- GitHub公式の
action
の例:actions/checkout@v2
- サードパーティの
action
の例:ruby/setup-ruby@v1
-
uses:
でaction
指定
- GitHub公式の
-
services
: サービスコンテナ。runner
からサービスコンテナへのアクセスはポート番号を指定。コンテナからサービスコンテナへのアクセスはラベル(今回ならmysql
)を指定。 -
container
: ジョブの実行場所となるコンテナ -
uses
: アクションを指定。(=用意されたものを利用)
例)actions/checkout@v2
: ランナー上にソースコードをチェックアウトし、自身のコードに対してスクリプトやアクションを実行できるようにする。自身のコードに対してスクリプト・アクションを実行する際はcheckoutアクションは常に必要。 -
run
: ランナー上で実行したいコマンド・スクリプト -
bats
: テスティングフレームワーク。Bash Automated Testing System。
実際に作成したGitHub Actionsの設定ファイル
name: Test
on: push
jobs:
rspec:
runs-on: ubuntu-latest
timeout-minutes: 10
env:
RAILS_ENV: test
DB_HOST: 127.0.0.1 # mysqlの仕様でlocalhostだとソケット通信しようとしてしまう
DB_PORT: 33060
services:
mysql:
image: mysql:8.0.31
ports:
- 33060:3306
env:
TZ: "Asia/Tokyo"
MYSQL_ALLOW_EMPTY_PASSWORD: yes
BIND-ADDRESS: 0.0.0.0 # 設定しないとホストサーバーから接続できない
options: --health-cmd="mysqladmin ping" --health-interval=5s --health-timeout=2s --health-retries=3
container:
image: ruby:3.1.2
steps:
- uses: actions/checkout@v2
- name: Install chrome
run: |
wget -qO - 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 libvips
- name: bundler config
run: bundle config set path 'vendor/bundle'
- name: cache gems
id: cache-gems
uses: actions/cache@v2
with:
path: vendor/bundle
key: ${{ runner.os }}-gems-${{ hashFiles('**/Gemfile.lock') }}
- name: setup bundle
if: steps.cache-gems.outputs.cache-hit != 'true'
run: |
bundle install --jobs 4 --retry 3
- name: set database.yml
run: cp -v config/database.ci.yml config/database.yml
- name: setup db schema
run: |
bundle exec rails db:create db:schema:load --trace
- name: run spec
run: bundle exec rspec
- name: archive rspec result screenshots
if: failure()
uses: actions/upload-artifact@v3
with:
name: rspec result screenshots
path: |
tmp/screenshots/
tmp/capybara/
rubocop:
runs-on: ubuntu-latest
container:
image: ruby:3.1.2
steps:
- uses: actions/checkout@v2
- name: bundler config
run: bundle config set path 'vendor/bundle'
- name: cache gems
id: cache-gems
uses: actions/cache@v2
with:
path: vendor/bundle
key: ${{ runner.os }}-gems-${{ hashFiles('**/Gemfile.lock') }}
- name: setup bundle
if: steps.cache-gems.outputs.cache-hit != 'true'
run: bundle install --jobs 4 --retry 3
- name: run rubocop
run: bundle exec rubocop
erblint:
runs-on: ubuntu-latest
container:
image: ruby:3.1.2
steps:
- uses: actions/checkout@v2
- name: bundler config
run: bundle config set path 'vendor/bundle'
- name: Cache gems
id: cache-gems
uses: actions/cache@v2
with:
path: vendor/bundle
key: ${{ runner.os }}-gems-${{ hashFiles('**/Gemfile.lock') }}
- name: setup bundle
if: steps.cache-gems.outputs.cache-hit != 'true'
run: bundle install --jobs 4 --retry 3
- name: run erblint
run: bundle exec erblint .
GitHub Actionsで何を実行しているか
-
rspec
-
ソースコードのチェックアウト
自分のコードに対してスクリプトorアクションを実行するための準備 -
Chromeのインストール
テストにブラウザを使うため。
run
の中身:chromeのlinux用認証鍵を取得→鍵のリストファイルに取得した認証鍵を追加→aptのアップデート→chromeのインストール -
gemのインストール先のパスを設定(
vendor/bundle
に) -
gemのキャッシュの設定
bundle install
の高速化が目的。-
key
が既存のキャッシュと完全一致した場合:cache-hit
がtrue
になり、path
に指定された場所vendor/bundle
にキャッシュファイルが復元される。 - 完全一致しなかった場合:
cache-hit
がfalse
になり、ジョブが正常に完了後に新しいkey
の値をキーとして持つpath
内のファイルのキャッシュが作成される。
-
-
gemのインストール(キャッシュがなかった場合)
-
CI用のデータベースの設定ファイルをコンテナにコピー
-
データベースのセットアップ(DBを新規作成→
schema.rb
からテーブル作成) -
rspecを実行
-
rspec失敗時にスクリーンショットを保存
-
-
rubocop
- ソースコードのチェックアウト
- gemのインストール先パスの設定
- gemのキャッシュの設定
- キャッシュがない場合にgemをインストール
- rubocopを実行
-
erblint
- ソースコードのチェックアウト
- gemのインストール先パスの設定
- gemのキャッシュの設定
- キャッシュがない場合にgemをインストール
- erblintを実行
課題
ソースコードのチェックアウト〜gemのインストールのstepは3つのjobで共通しているため、まとめたい。
参考になりそうな記事:GitHub Actionsを使い始めて、Stepsの共通化で詰まった話
余談
- "チェックアウト"の意味:リポジトリからドキュメントを取り出すこと。図書館やレンタル店で本などを借りるようなイメージ。(参考)