Skip to main content

Rubyでのビルドとテスト

Rubyプロジェクトのビルドとテストのための継続的インテグレーション(CI)ワークフローを作成できます。

はじめに

このガイドでは、Rubyアプリケーションのビルドとテストを行う継続的インテグレーション(CI)ワークフローの作成方法を紹介します。 CIテストにパスしたなら、コードをデプロイしたりgemを公開したりすることになるでしょう。

前提条件

Ruby、YAML、ワークフローの設定オプションと、ワークフローファイルの作成方法についての基本的な知識を持っておくことをおすすめします。 詳細については、次を参照してください。

Ruby スターター ワークフローの使用

すぐに開始するには、リポジトリの .github/workflows ディレクトリにスターター ワークフローを追加します。

GitHub では、ほとんどの Ruby プロジェクトで使用できる Ruby 用のスターター ワークフローが提供されています。 このガイドの以降のセクションでは、このスターター ワークフローをカスタマイズする方法の例を示します。

  1. GitHub.com で、リポジトリのメイン ページへ移動します。

  2. リポジトリ名の下にある [アクション] をクリックします。

    "github/docs" リポジトリのタブのスクリーンショット。 [アクション] タブがオレンジ色の枠線で強調表示されています。

  3. ワークフローが既にリポジトリ内にある場合は、 [新しいワークフロー] をクリックします。

  4. 「ワークフローの選択」ページには、推奨されるスターター ワークフローの選択内容が表示されます。 「ruby」を検索します。

  5. [継続的インテグレーション] をクリックして、ワークフローの選択をフィルター処理します。

  6. 「Ruby」ワークフローで、[設定] をクリックします。

  7. 必要に応じてワークフローを編集します。 たとえば、使用する Ruby のバージョンを変更します。

    注:

    • このスターター ワークフローでは、GitHub によって認定されていないアクションが使われます。 サード パーティによって提供されるアクションには、個別のサービス使用条件、プライバシー ポリシー、およびサポート ドキュメントが適用されます。
    • サード パーティのアクションを使用するには、コミット SHA で指定されたバージョンを使用する必要があります。 アクションが変更された新しいバージョンを使用する場合は、SHA を更新する必要があります。 タグまたはブランチを参照してバージョンを指定できますが、アクションは警告なしに変更される可能性があります。 詳しくは、「GitHub Actions のセキュリティ強化」を参照してください。
  8. [変更をコミットする] をクリックします。

ruby.yml ワークフロー ファイルがリポジトリの .github/workflows ディレクトリに追加されます。

Rubyのバージョンの指定

Ruby のバージョンを指定する最も簡単な方法は、Ruby 組織によって GitHub で提供されている ruby/setup-ruby アクションを使用することです。 このアクションにより、ワークフロー内の各ジョブ実行に対する PATH に、サポートされている Ruby のバージョンが追加されます。 詳細と使用可能な Ruby のバージョンについては、ruby/setup-ruby を参照してください。

GitHub Actions で Ruby を使用する場合、Ruby の ruby/setup-ruby アクションを使用すると、異なるランナーおよび 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によって認定されていないアクションを使用します。
# それらはサードパーティによって提供され、
# 別個の利用規約、プライバシーポリシー、
# ドキュメントを参照してください。

# GitHub では、コミット SHA にアクションをピン留めすることが推奨されます。
# 新しいバージョンを取得するには、SHA を更新する必要があります。
# タグまたはブランチを参照することもできますが、アクションは警告なしに変更される可能性があります。

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 アクションにより、バンドルが自動的にインストールされます。 バージョンは 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

これにより、gem を vendor/cache にインストールするように Bundler が構成されます。 ワークフローの実行が成功するたびに、このフォルダーは 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

コードのマトリクステスト

以下の例のマトリクスは、すべての安定リリースとヘッドバージョンのMRI、JRuby、TruffleRubyをUbuntu及びmacOSでテストします。

# このワークフローはGitHubによって認定されていないアクションを使用します。
# それらはサードパーティによって提供され、
# 別個の利用規約、プライバシーポリシー、
# ドキュメントを参照してください。

# GitHub では、コミット SHA にアクションをピン留めすることが推奨されます。
# 新しいバージョンを取得するには、SHA を更新する必要があります。
# タグまたはブランチを参照することもできますが、アクションは警告なしに変更される可能性があります。

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 を構成することができます。

# このワークフローはGitHubによって認定されていないアクションを使用します。
# それらはサードパーティによって提供され、
# 別個の利用規約、プライバシーポリシー、
# ドキュメントを参照してください。

# GitHub では、コミット SHA にアクションをピン留めすることが推奨されます。
# 新しいバージョンを取得するには、SHA を更新する必要があります。
# タグまたはブランチを参照することもできますが、アクションは警告なしに変更される可能性があります。

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

gemの公開

CIテストにパスしたなら、Rubyパッケージを任意のパッケージレジストリに公開するようにワークフローを設定できます。

パッケージを公開するのに必要なアクセストークンや認証情報は、リポジトリシークレットを使って保存できます。 次の例では、パッケージが作成されて、GitHub Package RegistryRubyGems に発行されます。

# このワークフローはGitHubによって認定されていないアクションを使用します。
# それらはサードパーティによって提供され、
# 別個の利用規約、プライバシーポリシー、
# ドキュメントを参照してください。

# GitHub では、コミット SHA にアクションをピン留めすることが推奨されます。
# 新しいバージョンを取得するには、SHA を更新する必要があります。
# タグまたはブランチを参照することもできますが、アクションは警告なしに変更される可能性があります。

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}}"