Ruby 빌드 및 테스트하기

Ruby 빌드 및 테스트하기

Ruby 프로젝트를 빌드하고 테스트하는 지속적 통합(CI) 워크플로를 만들 수 있어요. CI 테스트가 통과하면 코드를 배포하거나 gem을 게시할 수 있어요.

출처: 문서

본문

Ruby 프로젝트를 빌드하고 테스트하는 지속적 통합(CI) 워크플로를 만드는 방법을 알아봅니다. CI 테스트가 통과하면 코드를 배포하거나 gem을 게시할 수 있습니다.

사전 요구 사항

Ruby, YAML, 워크플로 구성 옵션, 워크플로 파일 작성 방법에 대한 기본적인 이해를 권장합니다. 자세한 내용은 다음을 참고하세요:

Ruby 워크플로 템플릿 사용하기

빠르게 시작하려면 저장소의 .github/workflows 디렉터리에 워크플로 템플릿을 추가하세요.

GitHub는 대부분의 Ruby 프로젝트에서 작동하는 Ruby용 워크플로 템플릿을 제공합니다. 이 가이드의 이후 섹션은 이 워크플로 템플릿을 사용자 지정하는 방법의 예시를 제공합니다.

  1. GitHub에서 저장소의 메인 페이지로 이동합니다.

  2. 저장소 이름 아래에서 Actions를 클릭합니다.

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

  3. 저장소에 이미 워크플로가 있다면 New workflow를 클릭합니다.

  4. "Choose a workflow" 페이지에 추천 워크플로 템플릿 목록이 표시됩니다. "ruby"를 검색하세요.

  5. Continuous integration을 클릭해서 워크플로 선택을 필터링합니다.

  6. "Ruby" 워크플로에서 Configure를 클릭합니다.

  7. 필요에 따라 워크플로를 편집합니다. 예를 들어 사용할 Ruby 버전을 변경합니다.

    [!NOTE]

    • 이 워크플로 템플릿에는 GitHub가 인증하지 않은 액션이 포함되어 있습니다. 제3자가 제공하는 액션은 별도의 서비스 약관, 개인정보 보호 정책, 지원 문서의 적용을 받습니다.
    • 제3자의 액션을 사용한다면 커밋 SHA로 지정된 버전을 사용해야 합니다. 액션이 수정되고 최신 버전을 사용하려면 SHA를 업데이트해야 합니다. 태그나 브랜치를 참조해서 버전을 지정할 수도 있지만 액션이 경고 없이 변경될 수 있습니다. 자세한 내용은 Secure use reference를 참고하세요.
  8. Commit changes를 클릭합니다.

    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 버전을 입력으로 받아 러너에 해당 버전을 구성합니다.

# 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.
steps:
- uses: actions/checkout@v6
- 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 }} 컨텍스트를 사용해서 현재 잡의 버전에 접근합니다. 매트릭스 전략과 컨텍스트에 대한 자세한 내용은 Workflow syntax for GitHub ActionsContexts reference를 참고하세요.

매트릭스 전략이 포함된 완전히 업데이트된 워크플로는 다음과 같을 수 있습니다:

# 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@v6
      - 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 파일에 의해 결정됩니다. 잠금 파일에 버전이 없으면 최신 호환 버전이 설치됩니다.

# 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.
steps:
- uses: actions/checkout@v6
- uses: ruby/setup-ruby@ec02537da5712d66d4d50a0f33b7eb52773b5ed1
  with:
    ruby-version: '3.1'
- run: bundle install

의존성 캐싱하기

setup-ruby 액션은 실행 간에 gems의 캐싱을 자동으로 처리하는 방법을 제공합니다.

캐싱을 활성화하려면 다음을 설정합니다.

# 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.
steps:
- uses: ruby/setup-ruby@ec02537da5712d66d4d50a0f33b7eb52773b5ed1
  with:
    bundler-cache: true

이렇게 하면 bundler가 gems를 vendor/cache에 설치하도록 구성됩니다. 워크플로의 각 성공적인 실행마다 이 폴더는 GitHub Actions에 의해 캐시되고 이후 워크플로 실행을 위해 다시 다운로드됩니다. gemfile.lock의 해시와 Ruby 버전이 캐시 키로 사용됩니다. 새 gems를 설치하거나 버전을 변경하면 캐시가 무효화되고 bundler가 새로 설치합니다.

setup-ruby 없이 캐싱하기

캐싱을 더 세밀하게 제어하려면 actions/cache 액션을 직접 사용할 수 있습니다. 자세한 내용은 Dependency caching reference를 참고하세요.

steps:
- uses: actions/cache@v4
  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@v4
  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의 모든 안정 릴리스와 head 버전을 테스트합니다.

# 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@v6
      - 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@v6
      - uses: ruby/setup-ruby@ec02537da5712d66d4d50a0f33b7eb52773b5ed1
        with:
          ruby-version: '2.6'
      - run: bundle install
      - name: Rubocop
        run: rubocop -f github

-f github를 지정하면 RuboCop 출력이 GitHub의 주석(annotation) 형식이 됩니다. 린팅 오류가 있으면 이를 도입한 풀 리퀘스트의 Files changed 탭에 인라인으로 표시됩니다.

Gems 게시하기

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

더 알아보기 (Learn more)