1
/
5

Github Actionsに入門してみた(CI編)

 株式会社チュートリアルでWebエンジニアを担当しています有賀です。
この記事は『Tutorial Advent Calendar 2020』の13日目です。

はじめに

 チュートリアルでは以前からCI/CDのサービスとしてCloud Buildを使用していたのですが、Production用GCPの権限の問題もあり、例えテストが落ちていても一部のメンバー以外すぐに気づけない問題がありました。そのため、Cloud Buildに加えて、Github ActionsをCIツールとして新たに採用することになりました。そこで、普段業務で中々触ることの少ないCI/CDパイプラインの構築にGithub Actionsを使ってチャレンジしてみようと思います!

前提知識

  • Rails開発に関する入門レベルの知識
  • CI/CDに関する入門レベルの知識
  • yamlファイルに関する入門レベルの知識
  • コンテナに関する入門レベルの知識

各種環境、バージョン

  • MacOS Catalina 10.15.4
  • Ruby 2.6.6
  • Rails 6.0.3
  • Docker 19.03.8
  • docker-compose 1.25.5
  • MySQL 5.7

概要

Github Actionsとは

 Githubが提供するCI/CDサービスであり、Circle CIやTravis CIなどその他のCI/CDツールと同様にリポジトリと連携しながら、リポジトリへのプッシュやマージ、プルリクエストなどをトリガーにして、アプリのビルドやテスト、デプロイといった様々な処理を実行できるようになっています。
 Github自身が開発、提供するCI/CDツールということで、他のサービスには実現できないUI、UXや便利な機能の実現も十分に期待されるため、機能の拡充に伴ってシェアを伸ばしていくのではないかと個人的に期待しています。詳しく知りたい方は以下のドキュメントを参照ください。

参考


まずはアプリの環境構築

 テスト用のアプリの作成には、docker、docker-composeを活用していきます。今回はCI/CDに関する紹介ということでDockerfileやコマンドの解説は行いませんので、気になる方は「Docker rails 環境構築」とググってみれば先人の方の記事がたくさんヒットするので参考にしてみてください。


1.各種ファイルの作成

任意のディレクトリとそのディレクトリ内にDockerfile、docker-compose.yml、Gemfile、Gemfile.lock、entrypoint.shを作成します。

$ mkdir cicd-test
$ cd cicd-test



Dockerfile

FROM ruby:2.6
RUN 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-get update -qq \
    && apt-get install -y nodejs yarn \
    && mkdir /cicd-test
WORKDIR /cicd-test
COPY Gemfile /cicd-test/Gemfile
COPY Gemfile.lock /cicd-test/Gemfile.lock
RUN bundle install
COPY . /cicd-test

COPY entrypoint.sh /usr/bin/
RUN chmod +x /usr/bin/entrypoint.sh
ENTRYPOINT ["entrypoint.sh"]
EXPOSE 3000

CMD ["rails", "server", "-b", "0.0.0.0"]

docker-compose.yml

version: '3'
services:
  web:
    build: .
    command: bash -c "rm -f tmp/pids/server.pid && bundle exec rails s -p 3000 -b '0.0.0.0'"
    volumes:
      - .:/cicd-test
      - /cicd-test/tmp
    ports:
      - "3000:3000"
    depends_on:
      - db
    stdin_open: true
    tty: true
  db:
    image: mysql:5.7
    environment:
      MYSQL_USERNAME: dbuser
      MYSQL_ROOT_PASSWORD: dbpass
    ports:
      - '3306:3306'
    volumes:
      - mysql-data:/var/lib/mysql
volumes:
  mysql-data:
    driver: local

Gemfile

source 'https://rubygems.org'
gem 'rails', '~>6'

Gemfile.lock

空ファイルで作成する

entrypoint.sh

#!/bin/bash
set -e

# Remove a potentially pre-existing server.pid for Rails.
rm -f /cicd-test/tmp/pids/server.pid
# Then exec the container's main process (what's set as CMD in the Dockerfile).
exec "$@"

2.Railsアプリの作成、起動

まずは、アプリの雛形を作成します。

docker-compose run --rm --no-deps web rails new . --force --database=mysql --webpacker

その後、イメージをビルドします。

docker-compose build

database.ymlを編集して、データベースの設定まで完了させます。

default: &default
  adapter: mysql2
  encoding: utf8mb4
  pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
  username: <%= ENV.fetch("MYSQL_USERNAME", "dbuser") %>
  password: <%= ENV.fetch("MYSQL_ROOT_PASSWORD", "dbpass") %>
  host: <%= ENV.fetch("MYSQL_HOST", "db") %>

development:
  <<: *default
  database: cicd_test_development

test:
  <<: *default
  database: cicd_test_test

production:
  <<: *default
  database: cicd_test_production
  username: cicd_test
  password: <%= ENV['CICD_TEST_DATABASE_PASSWORD'] %>

以下のコマンドでDBを作成します。

docker-compose run --rm web rails db:create

 以下のコマンドでアプリを起動後、http://localhost:3000にアクセスすることでおなじみのあの画面が表示されることを確認できます!

docker-compose up -d

3.ローカルでテストを実行

まずはscaffoldで簡単なCRUD機能とテストコードを自動生成します。

docker-compose exec web rails g scaffold User name:string age:integer

マイグレーションファイルなどが作成されるので、以下のコマンドでその変更を反映させます。

docker-compose exec web rails db:migrate

自動生成されたテストコードを実行して、パスするか確認します。

docker-compose exec web rails test

テストケースが全て通ることが確認できたらここまでの準備はOKです!


4.Github Actionsの設定、実行


まずは設定から

 まずは設定ファイルを作成します。公式ドキュメントによると設定ファイルは.github/workflows配下に置きます。

mkdir .github && mkdir .github/workflows && touch .github/workflows/.rails-test.yml
name: RailsTest
on: [push]
jobs:
  build:
    runs-on: ubuntu-latest
    services:
      db:
        image: mysql:5.7
        env:
          MYSQL_USERNAME: dbuser
          MYSQL_ROOT_PASSWORD: dbpass
    container:
      image: ruby:2.6
      env:
        RAILS_ENV: test
        MYSQL_HOST: db
        MYSQL_USERNAME: dbuser
        MYSQL_ROOT_PASSWORD: dbpass
    steps:
    - uses: actions/checkout@v2
    - uses: actions/cache@v1
      with:
        path: vendor/bundle
        key: bundle-${{ hashFiles('**/Gemfile.lock') }}
    - uses: actions/cache@v1
      with:
        path: node_modules
        key: yarn-${{ hashFiles('**/yarn.lock') }}
    - name: Setup yarn and node
      run: |
        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-get update -qq
        apt-get install -y nodejs yarn
        yarn install
    - name: Setup bundles
      run: bundle install
    - name: Setup Database
      run: |
        bundle exec rails db:create
        bundle exec rails db:migrate
    - name: Run tests
      run: |
        bundle exec rails test

設定ファイルの説明

 まずはnameプロパティでワークフロー名を指定します。ワークフローとは1つ以上のジョブで構成された実行する処理とその処理を実行する条件を定義したもので、このワークフロー内で様々な処理を指定していくことで、自動でGitHub上でプロジェクトをビルド、テスト、デプロイなどをすることができます。

name: RailsTest  # ワークフロー名を指定

 次にワークフローをトリガーするためのイベントについて紹介します。このイベントを設定することで誰かがリポジトリにpushした時、issueやプルリクエストが作成された時などに予め登録しておいた手順で処理を実行することができます。今回はコミットをリポジトリにpushしたタイミングで、自動ビルド、テストが走るようにします。

on: [push] # リポジトリへpushしたタイミングで、ワークフローを実行するよう指定

 次にjobsと呼ばれる実行する一連の処理群について設定していきます。基本的にjobsの各ジョブは並列で実行されますが、特定の順序で実行することも可能です。

jobs:   # ここで実行するジョブを指定する
  build:   # 「build」という名前のジョブを定義

次に処理を実行する環境を指定します。ここではubuntuの最新環境を指定しておきます。

runs-on: ubuntu-latest # コンテナはLinuxベースのOS内で実行するように指定

 続いて、servicesを使って、各ステップとは独立して動作するコンテナを指定することができます。テスト用のWebサーバーやデータベースが必要になる時に指定します。ここではdbというサービス名でテスト用のデータベースの実行コンテナを指定しています。

services:
  db:    # サービス名を指定
    image: mysql:5.7  # 使用するコンテナイメージの指定
    env:      # 環境変数の設定
      MYSQL_USERNAME: dbuser
      MYSQL_ROOT_PASSWORD: dbpass

 次に一連のbuildジョブが実行されるメインのイメージを指定していきます。ここではrubyのイメージを指定しています。

container:
      image: ruby:2.6  # jobが実行されるDockerHubイメージを指定
      env:  # 環境変数の設定
        RAILS_ENV: test
        MYSQL_HOST: db
        MYSQL_USERNAME: dbuser
        MYSQL_ROOT_PASSWORD: dbpass

 ここからはstepsを使用してテスト実行までの一連の処理を書いていきます。GitHubの提供しているuses: actions/checkout@v2とuses: actions/cache@v1を使用して、ソースコードをチェックアウトするアクションと依存関係をキャッシュするアクションを指定することでソースコードをチェックアウトし、ワークフロー内で頻繁に使われる依存関係をキャッシュして処理にかかる時間を大幅に短縮することができます。lockファイルから算出されるハッシュ値をcacheの検索keyに指定することで、依存関係に変更がなければ保存したcacheを使用することができます。

steps:
    - uses: actions/checkout@v2 # ソースコードをチェックアウトするアクション
    - uses: actions/cache@v1  # 依存関係をキャッシュするアクション
      with:
        path: vendor/bundle  # キャッシュあるいはリストアをするファイルパス
        key: bundle-${{ hashFiles('**/Gemfile.lock') }} # cacheの検索キー
    - uses: actions/cache@v1
      with:
        path: node_modules # キャッシュあるいはリストアをするファイルパス
        key: yarn-${{ hashFiles('**/yarn.lock') }}  # cacheの検索キー

Railsの動作にnode.jsとyarnが必須のためインストールしていきます。

- name: Setup yarn and node
      run: |
        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-get update -qq
        apt-get install -y nodejs yarn
        yarn install

bundle installでgemをインストールしていきます。

- name: Setup bundles
      run: bundle install

DBの作成とマイグレーションもテストに必要なため、行っていきます。

- name: Setup Database
      run: |
        bundle exec rails db:create
        bundle exec rails db:migrate

最後にテストが実行されます。

- name: Run tests
      run: |
        bundle exec rails test

いよいよ実行してみる

 適当にhtmlファイルを編集して、リポジトリにpushしてみます。Actionsタブから確認できる実行履歴で以下の画面のような緑のチェックマークが確認できたら成功です。もし失敗していたら、実行履歴からエラーログを確認できるので適宜修正が必要になります。


終わりに

 今回はGithub Actionsを題材にrailsアプリのpushをトリガーにして自動でビルド、テストするまでの流れを紹介してきました。今回使用したGithub Actionsの設定ファイルやDockerfileなどはテスト用のもので、そのままでは本番運用に耐えうるものではないかと思いますが、記事をよんだ方がとりあえずGithub Actionsを体験したり、今後カスタマイズしていくベースになれば幸いです。
 次の私の記事ではGithub Actions CD編を予定しているのですが、どのような構成にするかはまだ未定です…(早く決めないとやばい)

オートロ株式会社's job postings
6 Likes
6 Likes

Weekly ranking

Show other rankings
Invitation from オートロ株式会社
If this story triggered your interest, have a chat with the team?