When I tried to run the RSpec test of Ruby on Rails with GitHub Actions, it was quite difficult, so I will write it down.
It is a serverless execution environment that runs on GitHub. By describing the settings in the file in the repository, it is a mechanism that can trigger various operations on GitHub and execute arbitrary actions. You can use it for free if it is a public repository.
This time, I will make it a CI for Rails by executing RSpec in association with the creation of Pull Request.
It seems good to upload a Docker image that can run Rails to Docker Hub, pull Docker and run the test.
It can be easily handled even if it is different from the OS.
Dockerfile
It's a basic environment. If you have the required library, please add it.
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
If you write multiple RUNs and overlap Docker layers, an error will occur at runtime around MySQL, so build the entire environment with one command.
docker build -t utyosu/build-rails:latest . -f tools/ci/Dockerfile
You will need a Docker Hub account. Registering the Docker Hub repository for the first time seems to be helpful.
docker push utyosu/build-rails:latest
Create a file for GitHub Action in your project's repository.
:.github\workflows\build.yml
name: build
#Trigger a Pull Request
on: [pull_request]
jobs:
build:
#Based on the latest version of Ubuntu
runs-on: ubuntu-latest
#Pull the image from Docker Hub
container:
image: utyosu/build-rails:latest
#Check out this branch
steps:
- uses: actions/checkout@v1
# test.run sh
- name: run test
run: . tools/ci/test.sh
Describe what you want to test. If this script fails, the build will fail.
tools/ci/test.sh
#!/bin/bash
#Since no process is started, start MySQL first
service mysql start
#Create a MySQL user and grant permissions
mysql -e 'create user "user_name";'
mysql -e 'grant all on *.* to "user_name";'
export RAILS_ENV=test
bundle config set without development
#Install Gem.
#From nothing
bundle install
#Check if Capistrano is running
#(I check it just in case because it may not work due to version mismatch)
bundle exec cap -T
#Static analysis with Rubocop
bundle exec rubocop
#Create a database defined in rails
bundle exec rails db:create
#Database schema creation with ridgepole
#For those who are not using ridgepole, bundle exec rails db instead:schema:Run load
bundle exec ridgepole -c config/database.yml --apply -f db/schema -E test
#Run RSpec
bundle exec rspec
When I make a Pull Request, it says Some checks haven't completed yet
.
You can check the progress of CI by clicking Details.
After a short wait, you will see the console output.
It will be completed after a while.
When you return to the Pull Request, ʻAll checks have passed` is displayed, indicating that the test passed without any problems.
Since the GitHub standard Ruby execution environment is prepared, I tried it based on it at first. However, installing Rails and Gem takes more than 30 minutes, so I thought it was not suitable for CI in a light project. If you pull the image from DockerHub and execute it, I found that the test execution can be started in about 40 seconds, so I use this method.
There seems to be a way to prepare MySQL in another container and exchange between containers, but the mechanism was too difficult to realize. I wish I could do it well in the Rails environment.
Recommended Posts