Ruby on Rails 的 CI:GitHub Actions
Ruby on Rails 的 CI:GitHub Actions 与 CircleCI
Ruby on Rails 的 CI:GitHub Actions 与 CircleCI
这是由三部分组成的系列文章的一部分,我将引导您使用 GitHub Actions、CircleCI 设置您的 CI 套件,然后比较如果您要为 Rails 应用程序设置持续集成,您可能需要使用哪个套件。
第 1 部分:GitHub Actions
1. 设置操作名称
name: Run Tests & Linters
2. 设置触发操作运行的事件
name: Run Tests & Linters
on:
pull_request:
branches:
- '*'
push:
branches:
- master
这意味着,只要在任何分支上更新 pull_request 并且推送到 master 时,此操作就会运行。
3. 创建您的作业,并选择要运行操作的对象
jobs:
build:
runs-on: ubuntu-latest
这告诉我们的操作我们想要在 Ubuntu 上运行该操作,并使用 GitHub 提供的最新版本,即 Ubuntu 18.04。
4. 定义服务
对于典型的 Rails 应用,您可能使用 Redis 来缓存像 Sidekiq 这样的工具,并且可能还拥有一个数据库。在操作中定义服务允许我们使用额外的容器来运行这些类型的工具。
services:
postgres: # The name of the service
image: postgres:11 # A docker image
env: # Environment variables you want to use inside the service
POSTGRES_USER: postgres
POSTGRES_PASSWORD: postgres
POSTGRES_DB: postgres
ports: ['5432:5432'] # The port that you can access the service on
options: >- # Options for the service, in this case we want to make sure that the Postgres container passes a health check
--health-cmd pg_isready
--health-interval 10s
--health-timeout 5s
--health-retries 5
redis: # The name of the service
image: redis # A docker image
ports: ['6379:6379'] # The ports that you can access the service on
options: --entrypoint redis-server # Options for the service
5. 设置依赖项并检出分支
对我来说,这有点棘手。如果你搜索“在 Rails 中使用 GitHub Actions”,你可能会看到类似这样的内容:
- uses: actions/checkout@v1
- name: Setup Ruby
uses: actions/setup-ruby@v1
with:
ruby-version: 2.6.x
- uses: borales/actions-yarn@v2.0.0
with:
cmd: install
这个特殊的例子来自我的朋友Chris Oliver,他负责Go Rails(看看吧!!)。
这个解决方案本来很棒,但除了:
- GitHub 上提供的最新 Ruby 版本是 Ruby 2.6.3
- GitHub 上提供的最新 Node 版本是 Node 12.13.1
在CodeFund,我们使用的是 Ruby 2.6.5(即将升级到 2.7)和 Node 13.0.1。针对这个问题,已经提出了一些解决方案,比如使用ruby build从源代码安装所需的 Ruby 版本,或者使用nvm之类的工具。这些方法可能对你有用,但速度可能很慢,而且对于我以后遇到的问题也不起作用。因此,我编写了自己的 Docker 镜像,其中已经内置了我需要的一切。Ruby 2.6.5、Node 13.0.1、Postgres 所需的附加软件包、用于系统测试的 Chrome、Bundler 2.0.2 以及我的通用环境变量。
我不会在这里解释所有的细节,我知道我可以稍微缩小尺寸,但这是该图像的第一次迭代:
FROM ruby:2.6.5
LABEL "name"="Locomotive"
LABEL "version"="0.0.1"
ENV APT_KEY_DONT_WARN_ON_DANGEROUS_USAGE=DontWarn
ENV BUNDLE_PATH='/bundle/vendor'
ENV LANG=en_US.UTF-8
ENV LANGUAGE=en_US.UTF-8
ENV LC_ALL=C.UTF-8
ENV PG_HOST='postgres'
ENV PG_PASSWORD='postgres'
ENV PG_USERNAME='postgres'
ENV RACK_ENV='test'
ENV RAILS_ENV='test'
ENV REDIS_CACHE_URL='redis://redis:6379/0'
ENV REDIS_QUEUE_URL='redis://redis:6379/0'
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 && \
curl -sL https://deb.nodesource.com/setup_13.x | bash - && \
wget -q -O - https://dl-ssl.google.com/linux/linux_signing_key.pub | apt-key add - && \
echo "deb [arch=amd64] http://dl.google.com/linux/chrome/deb/ stable main" | tee /etc/apt/sources.list.d/google-chrome.list && \
apt-get update && \
apt-get install -y google-chrome-stable && \
echo "CHROME_BIN=/usr/bin/google-chrome" | tee -a /etc/environment && \
wget -q -O - 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-get -yqq install libpq-dev && \
apt-get install -qq -y google-chrome-stable yarn nodejs postgresql postgresql-contrib
RUN gem install bundler:2.0.2
6. 使用Docker容器
container:
image: andrewmcodes/locomotive:v0.0.1 # my image name
env: # additional environment variables I want to have access to
DEFAULT_HOST: app.codefund.io
注意:如果您未设置容器,则所有步骤将直接在指定的主机上运行,如果您还记得的话,该主机是 Ubuntu 18.04。
截至目前,我们的行动如下:
name: Run Tests & Linters
on:
pull_request:
branches:
- '*'
push:
branches:
- master
jobs:
build:
runs-on: ubuntu-latest
services:
postgres:
image: postgres:11
env:
POSTGRES_USER: postgres
POSTGRES_PASSWORD: postgres
POSTGRES_DB: postgres
ports: ['5432:5432']
options: >-
--health-cmd pg_isready
--health-interval 10s
--health-timeout 5s
--health-retries 5
redis:
image: redis
ports: ['6379:6379']
options: --entrypoint redis-server
container:
image: andrewmcodes/locomotive:v0.0.1
env:
DEFAULT_HOST: app.codefund.io
7.添加步骤
现在是时候在容器内运行命令了。我们先来检查一下代码。
steps:
- uses: actions/checkout@v2
8.缓存
值得庆幸的是,GitHub 提供了一些示例,可以帮助你开始使用你选择的缓存依赖项工具。我建议你查看这些示例以及文档。
注意:单个缓存的最大大小为 400MB,单个仓库最多可拥有 2GB 的缓存。达到 2GB 的限制后,较旧的缓存将根据上次访问的时间进行清除。过去一周内未访问的缓存也将被清除。
- name: Get Yarn Cache
id: yarn-cache
run: echo "::set-output name=dir::$(yarn cache dir)"
- name: Node Modules Cache
id: node-modules-cache
uses: actions/cache@v1
with:
path: ${{ steps.yarn-cache.outputs.dir }}
key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }}
restore-keys: |
${{ runner.os }}-yarn-
- name: Gems Cache
id: gem-cache
uses: actions/cache@v1
with:
path: vendor/bundle
key: ${{ runner.os }}-gem-${{ hashFiles('**/Gemfile.lock') }}
restore-keys: |
${{ runner.os }}-gem-
- name: Assets Cache
id: assets-cache
uses: actions/cache@v1
with:
path: public/packs-test
key: ${{ runner.os }}-assets-${{ steps.extract_branch.outputs.branch }}
restore-keys: |
${{ runner.os }}-assets-
9. 捆绑、Yarn 和预编译资产
接下来,如果我们的依赖项没有从缓存中恢复,我们将运行 Bundler 和 Yarn 来安装它们,并预编译我们的资产。
- name: Bundle Install
run: bundle check || bundle install --path vendor/bundle --jobs 4 --retry 3
- name: Yarn Install
run: yarn check || bin/rails yarn:install
- name: Compile Assets
run: |
if [[ ! -d public/packs-test ]]; then
bin/rails webpacker:compile
else
echo "No need to compile assets."
fi
注意:您可能可以跳过资产编译,这取决于您。
10.更新一些文件
为了使其正常工作,我必须对项目中的某些文件进行一些更新。
config/database.yml
更新测试主机为:host: <%= ENV.fetch("PG_HOST", "localhost") %>
- 更新
test/application_system_test_case.rb
require "test_helper"
class ApplicationSystemTestCase < ActionDispatch::SystemTestCase
driven_by :selenium, using: :headless_chrome, screen_size: [1400,1400] do |driver_options|
driver_options.add_argument("--disable-dev-shm-usage")
driver_options.add_argument("--no-sandbox")
end
end
11.设置数据库
在运行测试和检查之前我们需要注意的最后一件事是设置数据库。
- name: Setup DB
run: bin/rails db:drop db:create db:structure:load --trace
12. 运行测试和 Linters
现在我们终于可以运行测试和检查了。
- name: Run Rails Tests
run: |
bin/rails test
bin/rails test:system
- name: Zeitwerk Check
run: bundle exec rails zeitwerk:check
- name: StandardRB Check
run: bundle exec standardrb --format progress
- name: ERB Lint
run: bundle exec erblint app/views_redesigned/**/*.html.erb
- name: Prettier-Standard Check
run: yarn run --ignore-engines prettier-standard --check 'app/**/*.js'
至此,您的操作就完成了!
这是我完成的操作文件:
name: Run Tests & Linters
on:
pull_request:
branches:
- '*'
push:
branches:
- master
jobs:
build:
runs-on: ubuntu-latest
services:
postgres:
image: postgres:11
env:
POSTGRES_USER: postgres
POSTGRES_PASSWORD: postgres
POSTGRES_DB: postgres
ports: ['5432:5432']
options: >-
--health-cmd pg_isready
--health-interval 10s
--health-timeout 5s
--health-retries 5
redis:
image: redis
ports: ['6379:6379']
options: --entrypoint redis-server
container:
image: andrewmcodes/locomotive:v0.0.1
env:
DEFAULT_HOST: app.codefund.io
steps:
- uses: actions/checkout@v1
- name: Get Yarn Cache
id: yarn-cache
run: echo "::set-output name=dir::$(yarn cache dir)"
- name: Cache Node Modules
id: node-modules-cache
uses: actions/cache@v1
with:
path: ${{ steps.yarn-cache.outputs.dir }}
key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }}
restore-keys: |
${{ runner.os }}-yarn-
- name: Cache Gems
id: gem-cache
uses: actions/cache@v1
with:
path: vendor/bundle
key: ${{ runner.os }}-gem-${{ hashFiles('**/Gemfile.lock') }}
restore-keys: |
${{ runner.os }}-gem-
- name: Cache Assets
id: assets-cache
uses: actions/cache@v1
with:
path: public/packs-test
key: ${{ runner.os }}-assets-${{ steps.extract_branch.outputs.branch }}
restore-keys: |
${{ runner.os }}-assets-
- name: Bundle Install
run: bundle install --path vendor/bundle --jobs 4 --retry 3
- name: Yarn Install
run: bin/rails yarn:install
- name: Compile Assets
shell: bash
run: |
if [[ ! -d public/packs-test ]]; then
bundle exec rails webpacker:compile
else
echo "No need to compile assets."
fi
- name: Setup DB
run: bin/rails db:drop db:create db:structure:load --trace
- name: Run Rails Tests
run: |
bin/rails test
bin/rails test:system
- name: Zeitwerk Check
run: bundle exec rails zeitwerk:check
- name: StandardRB Check
run: bundle exec standardrb --format progress
- name: ERB Lint
run: bundle exec erblint app/views_redesigned/**/*.html.erb
- name: Prettier-Standard Check
run: yarn run --ignore-engines prettier-standard --check 'app/**/*.js'
如你所见,为你的 CI 设置 GitHub Actions 可能相当复杂,需要大量的初始设置。如果你正在考虑在你的 Rails 应用上尝试使用它们,希望这篇文章能对你有所帮助。本周晚些时候,请回来查看第二部分:设置 CircleCI!
文章来源:https://dev.to/codefund/ci-for-ruby-on-rails-github-actions-3mn1