概要
以前の記事でも書きましたが、業務ではGitLab CI
を使用しています。しかし、個人開発などではGitHub
を使いたかったので、今回はGitHub Actions
を試してみました。
GitHub Actionsとは
GitLab CI
と同様にbuilt in、つまりGitHubだけでCI/CD環境が構築出来るサービスです。
詳しくはこの記事を見てください。とてもわかり易いです。
試してみる
環境構築
リポジトリを作ります。
$ mkdir ~/sample_pj $ cd ~/sample_pj $ touch Dockerfile docker-compose.yml Gemfile Gemfile.lock
Dockerfile
とdocker-compose.yml
とGemfile
とGemfile.lock
を用意します。
FROM ruby:2.6.5 RUN apt-get update -y && apt-get install curl RUN curl -sL https://deb.nodesource.com/setup_12.x | bash - RUN apt-get install -y nodejs RUN npm install -g yarn RUN mkdir /myapp WORKDIR /myapp COPY Gemfile /myapp/Gemfile COPY Gemfile.lock /myapp/Gemfile.lock RUN bundle install RUN yarn install COPY . /myapp
docker-compose.yml
では3つのコンテナを定義しました。
railsなのでweb
とdb
はおなじみですが、今回はSystem Spec
を扱いたいのでwebdriver_chrome
というコンテナを定義しました。
version: "3" services: db: image: mysql:5.7 volumes: - db-volume:/var/lib/mysql environment: MYSQL_ROOT_PASSWORD: password web: build: . command: rails s -p 3000 -b '0.0.0.0' volumes: - .:/myapp ports: - "3000:3000" environment: SELENIUM_REMOTE_URL: http://webdriver_chrome:4444/wd/hub depends_on: - db - webdriver_chrome webdriver_chrome: image: selenium/standalone-chrome volumes: db-volume:
source "https://rubygems.org" git_source(:github) {|repo_name| "https://github.com/#{repo_name}" } gem "rails", '6.0.0'
railsアプリケーションを作成します。
$ docker-compose run web rails new . -f -d=mysql
config/database.yml
を編集します。
default: &default adapter: mysql2 encoding: utf8mb4 pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %> username: root password: password <-- 追記 host: db <--- 追記
編集したらbuildし直します。
$ docker-compose build
データベースを作成して、サーバーを立ち上げます。
$ docker-compose run web rails db:create $ docker-compose up -d
http://localhost:3000/にアクセスしていかのようになっていれば環境構築は終了です。
適当に機能を作成する
scaffoldで簡単なブログ的な機能を実装します。
$ docker-compose exec web /bin/bash root@c6e2afbc1f47:/myapp# rails g scaffold Post title:string content:text root@c6e2afbc1f47:/myapp# rails db:migrate
テストを書く準備をする
テストを書くのに必要なgem(factory-bot-rails
とrspec-rails
)をインストールします。
group :development, :test do # Call 'byebug' anywhere in the code to stop execution and get a debugger console gem 'byebug', platforms: [:mri, :mingw, :x64_mingw] gem 'factory_bot_rails' <-- 追記 end group :test do # Adds support for Capybara system testing and selenium driver gem 'capybara', '>= 2.15' gem 'selenium-webdriver' # Easy installation and use of web drivers to run system tests with browsers gem 'webdrivers', require: !ENV['SELENIUM_REMOTE_URL'] <--- 編集 gem 'rspec-rails', '~> 4.0.0' <-- 追記 end
$ docker-compose exec web /bin/bash root@c6e2afbc1f47:/myapp# bundle root@c6e2afbc1f47:/myapp# rails g rspec:install
webdrivers
でrequire: !ENV['SELENIUM_REMOTE_URL']
としているのはSystem Spec
実行時にFailed to find Chrome binaryというエラーが出るのを防ぐための処理です。
spec/rails_helper.rb
にdriverの設定とFactoryBotの設定を追記します。
Capybara.server_host = Socket.ip_address_list.detect{|addr| addr.ipv4_private?}.ip_address Capybara.server_port = 3000 Capybara.register_driver :selenium_remote do |app| url = "http://chrome:4444/wd/hub" opts = { desired_capabilities: :chrome, browser: :remote, url: url } driver = Capybara::Selenium::Driver.new(app, opts) end RSpec.configure do |config| # Remove this line if you're not using ActiveRecord or ActiveRecord fixtures config.before(:each, type: :system) do driven_by :rack_test end config.before(:each, type: :system, js: true) do driven_by :selenium_remote host! "http://#{Capybara.server_host}:#{Capybara.server_port}" end config.include FactoryBot::Syntax::Methods ・ ・ ・ end
.rspec
にformatの設定を追記します
--require spec_helper --format documentation
FactoryBotでpost
のテストデータを作成します。
FactoryBot.define do factory :post do title { "test" } content { "test" } end end
適当にRSpec(model spec、system spec)を書く
root@c6e2afbc1f47:/myapp# rails g rspec:model Post root@c6e2afbc1f47:/myapp# rails g rspec:system posts
require 'rails_helper' RSpec.describe Post, type: :model do describe "データ" do it("テストデータは有効"){ expect(build(:post)).to be_valid } end describe "CRUD機能" do describe "ポスト作成" do let(:post) { build(:post) } it { expect{post.save}.to change { Post.count }.by(1)} end describe "ポスト削除" do let!(:post) { create(:post) } it { expect{post.destroy}.to change { Post.count }.by(-1) } end describe "ポスト更新" do let(:post) { Post.new(title: "test", content: "test") } it "更新に成功する" do post.update(title: "updated") expect(post.title).to eq "updated" end end end end
require 'rails_helper' RSpec.describe "Posts", type: :system do before { visit new_post_path } describe "create new post" do subject do fill_in "Title", with: "New Post" fill_in "Content", with: "New Post" click_on "Create Post" end context "正しく入力したとき" do it "Postの数は1つ増える" do expect{ subject }.to change { Post.count }.by(1) end end context "Postの作成に成功したとき" do it "詳細ページに飛んでフラッシュメッセージが表示される" do subject expect(page).to have_current_path post_path(Post.first) expect(page).to have_selector "#notice", text: "Post was successfully created." end end end end
root@c6e2afbc1f47:/myapp# rm -rf test root@c6e2afbc1f47:/myapp# bundle exec rspec Post データ テストデータは有効 CRUD機能 ポスト作成 is expected to change `Post.count` by 1 ポスト削除 is expected to change `Post.count` by -1 ポスト更新 更新に成功する Posts create new post 正しく入力したとき Postの数は1つ増える Postの作成に成功したとき 詳細ページに飛んでフラッシュメッセージが表示される Finished in 35.55 seconds (files took 9.6 seconds to load) 6 examples, 0 failures
上記のようにテストがパスすればOKです。
rubocopの設定をする
Gemfileにrubocop
を追記してインストールします。
gem 'rubocop', require: false
root@c6e2afbc1f47:/myapp# bundle root@c6e2afbc1f47:/myapp# bundle exec rubocop --auto-gen-config
今回はrubocopがCIで動くのが確認できればいいので、.rubocop.yml
の中身を.rubocop-todo.yml
のファイルの中身に置き換えます。
root@c6e2afbc1f47:/myapp# bundle exec rubocop
上の画像のようにrubocopがパスすればrubocopの準備は終了です。
GitHub Actionの設定をする
設定ファイルを作成します。公式サイトによると設定ファイルは.github/workflows
配下に置きます。
root@c6e2afbc1f47:/myapp# mkdir .github && mkdir .github/workflows && touch .github/workflows/.github-ci.yml
name: Test on: [push] jobs: rspec: runs-on: ubuntu-latest services: db: image: mysql:5.7 env: MYSQL_USER: root MYSQL_ROOT_PASSWORD: password options: --health-cmd="mysqladmin ping" --health-interval=10s --health-timeout=5s --health-retries=3 container: image: ruby:2.6.5 steps: - uses: actions/checkout@v2 - name: setup bundle run: bundle install - name: install chorme run: | curl -sS -L https://dl.google.com/linux/linux_signing_key.pub | apt-key add - echo "deb [arch=amd64] http://dl.google.com/linux/chrome/deb/ stable main" > /etc/apt/sources.list.d/google.list apt-get update -q -y apt-get install -y google-chrome-stable - name: setup yarn run: | curl -sL https://deb.nodesource.com/setup_12.x | bash - apt-get install -y nodejs npm install -g yarn yarn install - name: setup migrate run: | rails db:create RAILS_ENV=test rails db:migrate RAILS_ENV=test - name: run spec run: bundle exec rspec rubocop: runs-on: ubuntu-latest container: image: ruby:2.6.5 steps: - uses: actions/checkout@v2 - name: setup bundle run: bundle install - name: run rubocop run: bundle exec rubocop
実行
Githubにリポジトリを作って、pushします。
実行結果
RSpec、RubocopどちらもPassしました。
今回試したリポジトリはこちらです。
GitHubに詳しくなりたいので、次はこの本を読んでみたいと思います。