GitHubActions에서 Ruby on Rails RSpec 테스트 실행

Ruby on Rails의 RSpec 테스트를 GitHubActions에서 실행하려고하면 어려웠기 때문에 메모에 남겨 둡니다.

GitHubActions란?



GitHub에서 실행되는 서버리스 실행 환경입니다.
리포지토리 내의 파일에 설정을 기술하는 것으로, GitHub의 각종 조작에 트리거해 임의의 액션을 실행할 수 있는 구조입니다.
공공 리포지토리라면 무료로 사용할 수 있습니다.

이번에는 Pull Request의 작성에 묶어 RSpec을 실행함으로써 Rails용 CI로 하려고 합니다.

결론



Rails를 실행할 수있는 Docker 이미지를 DockerHub에 업로드하고 DockerPull하여 테스트를 실행하는 것이 좋습니다.

환경


  • 우분투 16.04 LTS
  • Ruby on Rails 6.0
  • Ruby 2.6.6

  • OS 이외는 달라도 쉽게 대응할 수 있습니다.

    Docker 이미지를 만들어 DockerHub에 업로드



    Dockerfile



    기본적인 환경입니다.
    필요한 라이브러리가 있으면 추가하십시오.

    tools/ci/Dockerfile
    FROM ubuntu:16.04
    
    SHELL ["/bin/bash", "-c"]
    
    ENV RUBY_VERSION="2.6.6"
    ENV BUNDLER_VERSION="2.1.4"
    ENV DEBIAN_FRONTEND="noninteractive"
    ENV PATH=/root/.rbenv/bin:/root/.rbenv/shims:$PATH
    
    WORKDIR /app
    
    COPY Gemfile .
    COPY Gemfile.lock .
    
    RUN set -x \
      && apt update \
      && apt install -y \
        build-essential \
        curl \
        git \
        libssl-dev \
        libreadline-dev \
        libmysqlclient-dev \
        mysql-client \
        mysql-server \
        tzdata \
        zlib1g-dev \
      # Install rbenv and ruby
      && git clone https://github.com/sstephenson/rbenv.git ~/.rbenv \
      && git clone https://github.com/sstephenson/ruby-build.git ~/.rbenv/plugins/ruby-build \
      && CONFIGURE_OPTS='--disable-install-rdoc' /root/.rbenv/bin/rbenv install ${RUBY_VERSION} -s \
      && /root/.rbenv/bin/rbenv global ${RUBY_VERSION} \
      # Install bundler
      && echo 'gem: --no-rdoc --no-ri' > /root/.gemrc \
      && /root/.rbenv/shims/gem install bundler -v ${BUNDLER_VERSION} \
      # bundle install
      && /root/.rbenv/shims/bundle config set without development \
      && /root/.rbenv/shims/bundle install \
      # delete unused file
      && rm -rf /var/lib/apt/lists/* \
      && rm Gemfile Gemfile.lock
    

    RUN을 복수 써 Docker의 레이어를 겹치면 MySQL 주위에서 런타임에 에러가 나오므로 1개의 커멘드로 전체 환경을 구축합니다.

    Docker 빌드


    docker build -t utyosu/build-rails:latest . -f tools/ci/Dockerfile
    

    Docker 이미지 업로드



    DockerHub 계정이 필요합니다.
    처음 DockerHub 리포지토리 등록 근처가 참고가 될 것 같습니다.
    docker push utyosu/build-rails:latest
    

    GitHubActions 트리거 설정



    프로젝트 리포지토리에 GitHubAction용 파일을 만듭니다.

    .github\workflows\build.yml
    name: build
    
    # Pull Requestをトリガにする
    on: [pull_request]
    
    jobs:
      build:
        # Ubuntuの最新版をベースにする
        runs-on: ubuntu-latest
    
        # DockerHubからイメージをPullする
        container:
          image: utyosu/build-rails:latest
    
        # このブランチをcheckoutする
        steps:
        - uses: actions/checkout@v1
    
        # test.shを実行する
        - name: run test
          run: . tools/ci/test.sh
    

    테스트 스크립트



    테스트하고 싶은 것을 설명합니다.
    이 스크립트가 실패하면 빌드 실패가 발생합니다.

    tools/ci/test.sh
    #!/bin/bash
    
    # プロセスが何も起動してないので、まずはMySQLを立ち上げておく
    service mysql start
    
    # MySQLユーザの作成と権限の付与
    mysql -e 'create user "user_name";'
    mysql -e 'grant all on *.* to "user_name";'
    
    export RAILS_ENV=test
    bundle config set without development
    
    # Gemをインストールする。
    # 何もない状態から
    bundle install
    
    # Capistranoが動いているか確認する
    # (バージョンの不一致で動かないときがあるので念の為チェックしている)
    bundle exec cap -T
    
    # Rubocopによる静的解析
    bundle exec rubocop
    
    # railsで定義されているデータベースを作成する
    bundle exec rails db:create
    
    # ridgepoleによるデータベースのスキーマ作成
    # ridgepoleを使っていない人は代わりに bundle exec rails db:schema:load を実行する
    bundle exec ridgepole -c config/database.yml --apply -f db/schema -E test
    
    # RSpecの実行
    bundle exec rspec
    

    실제로 해보자



    PullRequest를 만들면 Some checks haven't completed yet가 표시됩니다.



    Details를 클릭하면 CI의 진행 상황을 볼 수 있습니다.



    조금 기다리면 콘솔 출력이 표시됩니다.



    잠시 후 완료됩니다.



    PullRequest로 돌아가면 All checks have passed가 표시되고 문제없이 테스트가 통과되었음을 알 수 있습니다.



    경위



    GitHub 표준 Ruby 실행 환경이 준비되어 있기 때문에 처음에는 그것을 기반으로 시도했습니다.
    그러나 Rails나 Gem의 인스톨로 30분 이상 걸려 버리기 때문에, 가벼운 프로젝트에 있어서의 CI에는 적합하지 않다고 생각했습니다.
    DockerHub에서 이미지를 Pull하여 실행하는 방법이라면 40초 정도로 테스트 실행을 시작할 수 있다는 것을 알았으므로 이 방법을 사용하고 있습니다.

    메모



    다른 컨테이너에 MySQL이라든지 준비해 컨테이너끼리 교환하는 방법도 있는 것 같습니다만 구조가 너무 어려워 실현할 수 없었습니다.
    Rails 환경에서 잘 실현할 수 있으면 좋겠다고 생각합니다.

    좋은 웹페이지 즐겨찾기