跳至主要内容

构建和测试 Ruby

您可以创建一个持续集成 (CI) 工作流来构建和测试您的 Ruby 项目。

简介

本指南将向您展示如何创建一个持续集成 (CI) 工作流,用于构建和测试 Ruby 应用程序。如果您的 CI 测试通过,您可能希望部署代码或发布 gem。

先决条件

我们建议您对 Ruby、YAML、工作流配置选项以及如何创建工作流文件有基本了解。有关更多信息,请参阅

使用 Ruby 初始工作流

要快速入门,请将初始工作流添加到存储库的 .github/workflows 目录中。

GitHub 提供了一个适用于大多数 Ruby 项目的 Ruby 初始工作流。本指南的后续部分将提供如何自定义此初始工作流的示例。

  1. 在 GitHub.com 上,导航到存储库的主页。

  2. 在您的存储库名称下,单击 操作.

    Screenshot of the tabs for the "github/docs" repository. The "Actions" tab is highlighted with an orange outline.

  3. 如果您在存储库中已有工作流,请单击 **新建工作流**。

  4. "选择工作流" 页面显示了推荐的初始工作流选择。搜索 "ruby"。

  5. 通过单击 **持续集成** 过滤工作流选择。

  6. 在 "Ruby" 工作流上,单击 **配置**。

  7. 根据需要编辑工作流。例如,更改要使用的 Ruby 版本。

    注意:

    • 此初始工作流包含一个未经 GitHub 认证的操作。第三方提供的操作受单独的服务条款、隐私政策和支持文档的约束。
    • 如果您使用来自第三方的操作,您应该使用由提交 SHA 指定的版本。如果操作被修改,并且您想使用更新的版本,您需要更新 SHA。您可以通过引用标签或分支来指定版本,但是操作可能会在没有警告的情况下发生变化。有关更多信息,请参阅 "GitHub Actions 安全加固"。
  8. 点击 **提交更改**。

    ruby.yml 工作流程文件将添加到您的仓库的 .github/workflows 目录中。

指定 Ruby 版本

指定 Ruby 版本的最简单方法是使用 GitHub 上 Ruby 组织提供的 ruby/setup-ruby 操作。该操作将任何支持的 Ruby 版本添加到每个工作流程中运行的作业的 PATH 中。有关更多信息和可用的 Ruby 版本,请参阅 ruby/setup-ruby

使用 Ruby 的 ruby/setup-ruby 操作是使用 Ruby 与 GitHub Actions 的推荐方法,因为它确保了不同运行器和不同版本的 Ruby 之间的行为一致性。

setup-ruby 操作将 Ruby 版本作为输入,并在运行器上配置该版本。

steps:
- uses: actions/checkout@v4
- uses: ruby/setup-ruby@ec02537da5712d66d4d50a0f33b7eb52773b5ed1
  with:
    ruby-version: '3.1' # Not needed with a .ruby-version file
- run: bundle install
- run: bundle exec rake

或者,您可以将 .ruby-version 文件检入到您的仓库的根目录中,setup-ruby 将使用该文件中定义的版本。

使用多个版本的 Ruby 进行测试

您可以添加矩阵策略,使用多个版本的 Ruby 运行您的工作流程。例如,您可以针对版本 3.1、3.0 和 2.7 的最新补丁版本测试您的代码。

strategy:
  matrix:
    ruby-version: ['3.1', '3.0', '2.7']

ruby-version 数组中指定的每个版本的 Ruby 都会创建一个运行相同步骤的作业。${{ matrix.ruby-version }} 上下文用于访问当前作业的版本。有关矩阵策略和上下文的更多信息,请参阅 "GitHub Actions 的工作流程语法" 和 "上下文"。

具有矩阵策略的完整更新工作流程可能如下所示

# This workflow uses actions that are not certified by GitHub.
# They are provided by a third-party and are governed by
# separate terms of service, privacy policy, and support
# documentation.

# GitHub recommends pinning actions to a commit SHA.
# To get a newer version, you will need to update the SHA.
# You can also reference a tag or branch, but the action may change without warning.

name: Ruby CI

on:
  push:
    branches: [ main ]
  pull_request:
    branches: [ main ]

jobs:
  test:

    runs-on: ubuntu-latest

    strategy:
      matrix:
        ruby-version: ['3.1', '3.0', '2.7']

    steps:
      - uses: actions/checkout@v4
      - name: Set up Ruby ${{ matrix.ruby-version }}
        uses: ruby/setup-ruby@ec02537da5712d66d4d50a0f33b7eb52773b5ed1
        with:
          ruby-version: ${{ matrix.ruby-version }}
      - name: Install dependencies
        run: bundle install
      - name: Run tests
        run: bundle exec rake

使用 Bundler 安装依赖项

setup-ruby 操作将自动为您安装 bundler。版本由您的 gemfile.lock 文件决定。如果您的锁定文件中没有版本,则将安装最新的兼容版本。

steps:
- uses: actions/checkout@v4
- uses: ruby/setup-ruby@ec02537da5712d66d4d50a0f33b7eb52773b5ed1
  with:
    ruby-version: '3.1'
- run: bundle install

缓存依赖项

setup-ruby 操作提供了一种方法,可以在运行之间自动处理 gem 的缓存。

要启用缓存,请设置以下内容。

steps:
- uses: ruby/setup-ruby@ec02537da5712d66d4d50a0f33b7eb52773b5ed1
  with:
    bundler-cache: true

这将配置 bundler 将您的 gem 安装到 vendor/cache。对于您的工作流程的每次成功运行,此文件夹将由 GitHub Actions 缓存并在后续工作流程运行中重新下载。您的 gemfile.lock 和 Ruby 版本的哈希值将用作缓存键。如果您安装了任何新的 gem 或更改了版本,缓存将失效,bundler 将进行全新安装。

在没有 setup-ruby 的情况下进行缓存

为了更好地控制缓存,您可以直接使用 actions/cache 操作。有关更多信息,请参阅“缓存依赖项以加快工作流程速度”。

steps:
- uses: actions/cache@v3
  with:
    path: vendor/bundle
    key: ${{ runner.os }}-gems-${{ hashFiles('**/Gemfile.lock') }}
    restore-keys: |
      ${{ runner.os }}-gems-
- name: Bundle install
  run: |
    bundle config path vendor/bundle
    bundle install --jobs 4 --retry 3

如果您使用的是矩阵构建,您需要将矩阵变量包含在您的缓存键中。例如,如果您对不同的 Ruby 版本(matrix.ruby-version)和不同的操作系统(matrix.os)有一个矩阵策略,您的工作流程步骤可能如下所示

steps:
- uses: actions/cache@v3
  with:
    path: vendor/bundle
    key: bundle-use-ruby-${{ matrix.os }}-${{ matrix.ruby-version }}-${{ hashFiles('**/Gemfile.lock') }}
    restore-keys: |
      bundle-use-ruby-${{ matrix.os }}-${{ matrix.ruby-version }}-
- name: Bundle install
  run: |
    bundle config path vendor/bundle
    bundle install --jobs 4 --retry 3

对您的代码进行矩阵测试

以下示例矩阵测试了 Ubuntu 和 macOS 上所有稳定版本和 MRI、JRuby 和 TruffleRuby 的头部版本。

# This workflow uses actions that are not certified by GitHub.
# They are provided by a third-party and are governed by
# separate terms of service, privacy policy, and support
# documentation.

# GitHub recommends pinning actions to a commit SHA.
# To get a newer version, you will need to update the SHA.
# You can also reference a tag or branch, but the action may change without warning.

name: Matrix Testing

on:
  push:
    branches: [ main ]
  pull_request:
    branches: [ main ]

jobs:
  test:
    runs-on: ${{ matrix.os }}-latest
    strategy:
      fail-fast: false
      matrix:
        os: [ubuntu, macos]
        ruby: [2.5, 2.6, 2.7, head, debug, jruby, jruby-head, truffleruby, truffleruby-head]
    continue-on-error: ${{ endsWith(matrix.ruby, 'head') || matrix.ruby == 'debug' }}
    steps:
      - uses: actions/checkout@v4
      - uses: ruby/setup-ruby@ec02537da5712d66d4d50a0f33b7eb52773b5ed1
        with:
          ruby-version: ${{ matrix.ruby }}
      - run: bundle install
      - run: bundle exec rake

对您的代码进行代码风格检查

以下示例安装了 rubocop 并使用它来检查所有文件。有关更多信息,请参阅 RuboCop。您可以 配置 RuboCop 来决定具体的代码风格检查规则。

# This workflow uses actions that are not certified by GitHub.
# They are provided by a third-party and are governed by
# separate terms of service, privacy policy, and support
# documentation.

# GitHub recommends pinning actions to a commit SHA.
# To get a newer version, you will need to update the SHA.
# You can also reference a tag or branch, but the action may change without warning.

name: Linting

on: [push]

jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: ruby/setup-ruby@ec02537da5712d66d4d50a0f33b7eb52773b5ed1
        with:
          ruby-version: '2.6'
      - run: bundle install
      - name: Rubocop
        run: rubocop -f github

指定 -f github 表示 RuboCop 输出将采用 GitHub 的注释格式。任何代码风格检查错误都将在引入它们的拉取请求的“已更改的文件”选项卡中内联显示。

发布 Gem

您可以配置您的工作流程,以便在您的 CI 测试通过时将您的 Ruby 包发布到您想要的任何包注册表。

您可以使用存储库机密存储发布您的包所需的任何访问令牌或凭据。以下示例创建并发布一个包到 GitHub Package RegistryRubyGems

# This workflow uses actions that are not certified by GitHub.
# They are provided by a third-party and are governed by
# separate terms of service, privacy policy, and support
# documentation.

# GitHub recommends pinning actions to a commit SHA.
# To get a newer version, you will need to update the SHA.
# You can also reference a tag or branch, but the action may change without warning.

name: Ruby Gem

on:
  # Manually publish
  workflow_dispatch:
  # Alternatively, publish whenever changes are merged to the `main` branch.
  push:
    branches: [ main ]
  pull_request:
    branches: [ main ]

jobs:
  build:
    name: Build + Publish
    runs-on: ubuntu-latest
    permissions:
      packages: write
      contents: read

    steps:
      - uses: actions/checkout@v4
      - name: Set up Ruby 2.6
        uses: ruby/setup-ruby@ec02537da5712d66d4d50a0f33b7eb52773b5ed1
        with:
          ruby-version: '2.6'
      - run: bundle install

      - name: Publish to GPR
        run: |
          mkdir -p $HOME/.gem
          touch $HOME/.gem/credentials
          chmod 0600 $HOME/.gem/credentials
          printf -- "---\n:github: ${GEM_HOST_API_KEY}\n" > $HOME/.gem/credentials
          gem build *.gemspec
          gem push --KEY github --host https://rubygems.pkg.github.com/${OWNER} *.gem
        env:
          GEM_HOST_API_KEY: "Bearer ${{secrets.GITHUB_TOKEN}}"
          OWNER: ${{ github.repository_owner }}

      - name: Publish to RubyGems
        run: |
          mkdir -p $HOME/.gem
          touch $HOME/.gem/credentials
          chmod 0600 $HOME/.gem/credentials
          printf -- "---\n:rubygems_api_key: ${GEM_HOST_API_KEY}\n" > $HOME/.gem/credentials
          gem build *.gemspec
          gem push *.gem
        env:
          GEM_HOST_API_KEY: "${{secrets.RUBYGEMS_AUTH_TOKEN}}"