はじめに
CircleCIとGitHub Actionsは、どちらも自動的にコードのビルド、テスト、公開、リリース、デプロイを行うワークフローを作成できます。 CircleCIとGitHub Actionsは、ワークフローの設定において似ているところがあります。
- ワークフローの設定ファイルはYAMLで書かれ、リポジトリに保存されます。
- ワークフローには1つ以上のジョブが含まれます。
- ジョブには1つ以上のステップもしくは個別のコマンドが含まれます。
- ステップもしくはタスクは、再利用とコミュニティとの共有が可能です。
詳しくは、「GitHub Actions を理解する」を参照してください。
主要な相違点
CircleCIから移行する際には、以下の差異を考慮してください。
- CircleCIの自動テストの並列性は、ユーザが指定したルールもしくは過去のタイミングの情報に基づいて、自動的にテストをグループ化します。 この機能はGitHub Actionsには組み込まれていません。
- コンテナはユーザのマッピングが異なるので、Dockerコンテナ内で実行されるアクションは、権限の問題に敏感です。 Dockerfile で
USER
命令を使わなければ、これらの問題の多くを回避できます。 GitHub Enterprise Cloud でホストされるランナー上の Docker フィルシステムの詳細については、「GitHub ホステッド ランナーの使用」を参照してください。
ワークフローとジョブの移行
CircleCI によって、config.yml ファイルに workflows
が定義されます。これにより、1 つ以上のワークフローを構成できるようになります。 GitHub Enterprise Cloud は、ワークフローごとに 1 つのワークフロー ファイルを必要とするので、workflows
を宣言する必要はありません。 config.yml に構成されている各ワークフローに対して、新しいワークフロー ファイルを作成する必要があります。
CircleCI と GitHub Actions のどちらを使っても、同様の構文を使って、構成ファイル内に jobs
が構成されます。 CircleCI ワークフロー内で requires
を使ってジョブ間に依存関係を構成する場合は、同様の GitHub Actions needs
構文を使うことができます。 詳しくは、「GitHub Actions のワークフロー構文」を参照してください。
orbsからアクションへの移行
CircleCIとGitHub Actionsは、どちらもワークフロー中のタスクを再利用し、共有するための仕組みを提供しています。 CircleCIはorbsという概念を利用します。これはYAMLで書かれ、ワークフロー中で再利用できるタスクを提供します。 GitHub Actionsはアクションと呼ばれる強力で柔軟な再利用できるコンポーネントを持っており、これはJavaScriptファイルもしくはDockerイメージで構築できます。 GitHub Enterprise Cloud の API やパブリックに利用可能なサードパーティ API との統合など、リポジトリと相互作用するカスタムコードを書いてアクションを作成することができます。 たとえば、アクションで npm モジュールを公開したり、緊急の問題が発生したときに SMS アラートを送信したり、実稼働可能なコードをデプロイしたりできます。 詳しくは、「自動化の共有」を参照してください。
CircleCIは、YAMLのアンカーとエイリアスでワークフローの部分を再利用できます。 GitHub Actions は、マトリックスを使って、再利用性についてのほとんどのニーズをサポートしています。 マトリックスの詳細については、「ワークフローでのジョブのバリエーションの実行」を参照してください。
Dockerイメージの利用
CircleCIとGitHub Actionsは、どちらもDockerイメージ内でのステップの実行をサポートします。
CircleCIは、共通の依存関係を持つ一連のビルド済みのイメージを提供します。 これらのイメージでは、USER
が circleci
に設定されていますが、これにより、権限が GitHub Actions と競合します。
GitHub Actionsへの移行に際しては、CircleCIの構築済みイメージから離脱することをおすすめします。 多くの場合、必要な追加の依存関係のインストールにアクションを使うことができます。
Docker ファイルシステムの詳細については、「GitHub ホステッド ランナーの使用」を参照してください。
GitHub ホステッド ランナー イメージで使用できるツールとパッケージの詳細については、「GitHub ホステッド ランナーの使用」を参照してください。
変数とシークレットの利用
CircleCI と GitHub Actions は、設定ファイル内での変数の設定と、CircleCI もしくは GitHub Enterprise Cloud の UI を使ったシークレットの作成をサポートしています。
詳細については、「変数に情報を格納する」および「GitHub Actions でのシークレットの使用」を参照してください。
キャッシュ
CircleCIとGitHub Actionsは、設定ファイル中で手動でファイルをキャッシュする方法を提供しています。
以下は、それぞれのシステムにおける構文の例です。
キャッシュの CircleCI 構文
- restore_cache:
keys:
- v1-npm-deps-{{ checksum "package-lock.json" }}
- v1-npm-deps-
キャッシュの GitHub Actions 構文
- name: Cache node modules
uses: actions/cache@v3
with:
path: ~/.npm
key: v1-npm-deps-${{ hashFiles('**/package-lock.json') }}
restore-keys: v1-npm-deps-
GitHub Actionsは、CircleCIのDocker Layer Caching(DLC)に相当する機能を持っていません。
ジョブ間でのデータの永続化
CircleCIとGitHub Actionsは、どちらもジョブ間でデータを永続化するための仕組みを提供しています。
以下は、CircleCIとGitHub Actionsの設定構文の例です。
ジョブ間でデータを永続化するための CircleCI 構文
- persist_to_workspace:
root: workspace
paths:
- math-homework.txt
...
- attach_workspace:
at: /tmp/workspace
ジョブ間でデータを永続化するための GitHub Actions 構文
- name: Upload math result for job 1
uses: actions/upload-artifact@v4
with:
name: homework
path: math-homework.txt
...
- name: Download math result for job 1
uses: actions/download-artifact@v4
with:
name: homework
詳しくは、「ワークフローからのデータの格納と共有」を参照してください。
データベースとサービスコンテナの利用
どちらのシステムでも、データベース、キャッシング、あるいはその他の依存関係のための追加コンテナを含めることができます。
CircleCI では、config.yaml で最初に示されているイメージが、コマンドの実行で主に使用されているイメージです。 GitHub Actions では、明示的なセクションを使います。主要なコンテナーには container
を使い、追加のコンテナーのリストを services
に表示します。
以下は、CircleCIとGitHub Actionsの設定構文の例です。
データベースとサービス コンテナーを使うための CircleCI 構文
---
version: 2.1
jobs:
ruby-26:
docker:
- image: circleci/ruby:2.6.3-node-browsers-legacy
environment:
PGHOST: localhost
PGUSER: administrate
RAILS_ENV: test
- image: postgres:10.1-alpine
environment:
POSTGRES_USER: administrate
POSTGRES_DB: ruby26
POSTGRES_PASSWORD: ""
working_directory: ~/administrate
steps:
- checkout
# Bundle install dependencies
- run: bundle install --path vendor/bundle
# Wait for DB
- run: dockerize -wait tcp://localhost:5432 -timeout 1m
# Setup the environment
- run: cp .sample.env .env
# Setup the database
- run: bundle exec rake db:setup
# Run the tests
- run: bundle exec rake
workflows:
version: 2
build:
jobs:
- ruby-26
...
- attach_workspace:
at: /tmp/workspace
データベースとサービス コンテナーを使うための GitHub Actions 構文
name: Containers
on: [push]
jobs:
build:
runs-on: ubuntu-latest
container: circleci/ruby:2.6.3-node-browsers-legacy
env:
PGHOST: postgres
PGUSER: administrate
RAILS_ENV: test
services:
postgres:
image: postgres:10.1-alpine
env:
POSTGRES_USER: administrate
POSTGRES_DB: ruby25
POSTGRES_PASSWORD: ""
ports:
- 5432:5432
# Add a health check
options: --health-cmd pg_isready --health-interval 10s --health-timeout 5s --health-retries 5
steps:
# This Docker file changes sets USER to circleci instead of using the default user, so we need to update file permissions for this image to work on GH Actions.
# See https://docs.github.com/actions/using-github-hosted-runners/about-github-hosted-runners#docker-container-filesystem
- name: Setup file system permissions
run: sudo chmod -R 777 $GITHUB_WORKSPACE /github /__w/_temp
- uses: actions/checkout@v4
- name: Install dependencies
run: bundle install --path vendor/bundle
- name: Setup environment configuration
run: cp .sample.env .env
- name: Setup database
run: bundle exec rake db:setup
- name: Run tests
run: bundle exec rake
詳しくは、「サービスコンテナについて」を参照してください。
コード例全体
以下は実際の例です。 左側には、thoughtbot/administrator リポジトリの実際の CircleCI config.yml が表示されています。 右は、同等のGitHub Actionsを示しています。
CircleCI の完全なサンプル コード
---
version: 2.1
commands:
shared_steps:
steps:
- checkout
# Restore Cached Dependencies
- restore_cache:
name: Restore bundle cache
key: administrate-{{ checksum "Gemfile.lock" }}
# Bundle install dependencies
- run: bundle install --path vendor/bundle
# Cache Dependencies
- save_cache:
name: Store bundle cache
key: administrate-{{ checksum "Gemfile.lock" }}
paths:
- vendor/bundle
# Wait for DB
- run: dockerize -wait tcp://localhost:5432 -timeout 1m
# Setup the environment
- run: cp .sample.env .env
# Setup the database
- run: bundle exec rake db:setup
# Run the tests
- run: bundle exec rake
default_job: &default_job
working_directory: ~/administrate
steps:
- shared_steps
# Run the tests against multiple versions of Rails
- run: bundle exec appraisal install
- run: bundle exec appraisal rake
jobs:
ruby-25:
<<: *default_job
docker:
- image: circleci/ruby:2.5.0-node-browsers
environment:
PGHOST: localhost
PGUSER: administrate
RAILS_ENV: test
- image: postgres:10.1-alpine
environment:
POSTGRES_USER: administrate
POSTGRES_DB: ruby25
POSTGRES_PASSWORD: ""
ruby-26:
<<: *default_job
docker:
- image: circleci/ruby:2.6.3-node-browsers-legacy
environment:
PGHOST: localhost
PGUSER: administrate
RAILS_ENV: test
- image: postgres:10.1-alpine
environment:
POSTGRES_USER: administrate
POSTGRES_DB: ruby26
POSTGRES_PASSWORD: ""
workflows:
version: 2
multiple-rubies:
jobs:
- ruby-26
- ruby-25
GitHub Actions の完全なサンプル コード
# このワークフローはGitHubによって認定されていないアクションを使用します。
# それらはサードパーティによって提供され、
# 別個の利用規約、プライバシーポリシー、
# ドキュメントを参照してください。
# GitHub では、コミット SHA にアクションをピン留めすることが推奨されます。
# 新しいバージョンを取得するには、SHA を更新する必要があります。
# タグまたはブランチを参照することもできますが、アクションは警告なしに変更される可能性があります。
name: Containers
on: [push]
jobs:
build:
strategy:
matrix:
ruby: ['2.5', '2.6.3']
runs-on: ubuntu-latest
env:
PGHOST: localhost
PGUSER: administrate
RAILS_ENV: test
services:
postgres:
image: postgres:10.1-alpine
env:
POSTGRES_USER: administrate
POSTGRES_DB: ruby25
POSTGRES_PASSWORD: ""
ports:
- 5432:5432
# Add a health check
options: --health-cmd pg_isready --health-interval 10s --health-timeout 5s --health-retries 5
steps:
- uses: actions/checkout@v4
- name: Setup Ruby
uses: eregon/use-ruby-action@ec02537da5712d66d4d50a0f33b7eb52773b5ed1
with:
ruby-version: ${{ matrix.ruby }}
- name: Cache dependencies
uses: actions/cache@v3
with:
path: vendor/bundle
key: administrate-${{ matrix.image }}-${{ hashFiles('Gemfile.lock') }}
- name: Install postgres headers
run: |
sudo apt-get update
sudo apt-get install libpq-dev
- name: Install dependencies
run: bundle install --path vendor/bundle
- name: Setup environment configuration
run: cp .sample.env .env
- name: Setup database
run: bundle exec rake db:setup
- name: Run tests
run: bundle exec rake
- name: Install appraisal
run: bundle exec appraisal install
- name: Run appraisal
run: bundle exec appraisal rake