【GitHub Actions】実務で使えるCI/CDパイプライン設計パターン
はじめに
現代のソフトウェア開発において、CI/CD(継続的インテグレーション/継続的デリバリー)は、品質の高いソフトウェアを迅速に提供するために不可欠なプラクティスとなっています。GitHubに統合されたCI/CDサービスである GitHub Actions は、その手軽さと強力な機能から、多くの開発現場で採用されています。
しかし、プロジェクトの規模や特性によって、最適なCI/CDパイプラインの形は異なります。「とりあえず動く」だけのパイプラインから一歩進んで、より効率的で堅牢なパイプラインを設計することが、開発プロセス全体の生産性を大きく左右します。
この記事では、実務で頻繁に利用されるGitHub Actionsの代表的な設計パターンを4つ紹介し、それぞれのユースケースと実装のポイントを解説します。基本的な使い方から、モノレポ対応のような応用的なトピックまで、幅広くカバーします。
GitHub Actionsの基本アーキテクチャ
設計パターンを見る前に、まずはGitHub Actionsの基本的な構成要素をおさらいしましょう。これらの関係性を理解することが、パイプライン設計の第一歩です。

GitHub Actionsの基本アーキテクチャ
| 要素 | 説明 |
|---|---|
| Workflow(ワークフロー) | 1つ以上のジョブを含む自動化プロセスの全体定義。.github/workflows/ ディレクトリに配置されるYAMLファイルです。 |
| Event(イベント) | ワークフローを起動するきっかけとなる特定のアクション。push や pull_request、schedule(定時実行)などがあります。 |
| Job(ジョブ) | ワークフローを構成する実行単位。複数のステップを含み、デフォルトでは並列に実行されます。 |
| Step(ステップ) | ジョブ内の個々のタスク。シェルコマンドを実行したり、特定のアクション(再利用可能なコード)を実行したりします。 |
| Action(アクション) | ワークフローで利用できる再利用可能なコマンドの集まり。自作も可能ですし、Marketplaceで公開されているものを利用することもできます。 |
これらの要素が連携し、コードのプッシュからテスト、ビルド、デプロイまでの一連の流れを自動化します。
設計パターン1:シンプルなテスト&ビルドパイプライン
これは最も基本的かつ重要なパターンです。主にmainブランチへのプルリクエスト時やマージ時に、コードの品質を担保することを目的とします。
ユースケース
- ライブラリや小規模なWebアプリケーション
- すべてのプルリクエストで基本的な静的解析と単体テストを実行したい場合
ワークフロー例
name: CI
on:
push:
branches: [ main ]
pull_request:
branches: [ main ]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'npm'
- name: Install dependencies
run: npm ci
- name: Run lint
run: npm run lint
- name: Run tests
run: npm test
build:
needs: test # testジョブが成功したら実行
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'npm'
- name: Install dependencies
run: npm ci
- name: Build application
run: npm run build
- name: Upload artifact
uses: actions/upload-artifact@v4
with:
name: build-artifact
path: dist/
ポイント
-
needsディレクティブ:buildジョブがtestジョブの成功に依存することを示します。これにより、テストが失敗した場合はビルドが実行されず、リソースを節約できます。 -
キャッシュ:
actions/setup-nodeのcacheオプションを利用して、npmのパッケージをキャッシュし、2回目以降の実行を高速化します。 -
upload-artifact: ビルド成果物を保存し、後続のジョブ(デプロイなど)で利用できるようにします。
設計パターン2:マトリクスビルド
複数のバージョンの言語やOS、依存関係の組み合わせでテストやビルドを実行したい場合に強力なパターンです。同じジョブ定義を、パラメータを変えながら並列実行できます。
ユースケース
- OSSライブラリで、複数のNode.jsやPythonのバージョンをサポートする必要がある場合
- Windows, macOS, Linuxの各OSで動作確認が必要なデスクトップアプリ
ワークフロー例
name: Matrix Build
on:
pull_request:
jobs:
test:
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [18, 20, 22]
os: [ubuntu-latest, windows-latest, macos-latest]
steps:
- uses: actions/checkout@v4
- name: Setup Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v4
with:
node-version: ${{ matrix.node-version }}
- name: Run tests on ${{ matrix.os }}
run: |
npm ci
npm test
ポイント
-
strategy.matrix: テストしたいバージョンの組み合わせを配列で定義します。この例では、3(Node) x 3(OS) = 9通りのジョブが並列で実行されます。 -
${{ matrix.os }}: マトリクスで定義した変数を、ジョブの各ステップで参照できます。
設計パターン3:段階的デプロイメント
開発(Dev)、ステージング(Staging)、本番(Production)といった複数の環境へ、段階的にアプリケーションをデプロイするためのパターンです。特に、本番環境へのデプロイ前に手動での承認を挟むことで、安全性を高めます。

段階的デプロイメントのフロー
ユースケース
- WebサービスやSaaSアプリケーションの本番リリースフロー
- インフラの変更を安全に本番環境へ適用したい場合
ワークフロー例
name: Staged Deployment
on:
push:
branches:
- main
jobs:
build:
runs-on: ubuntu-latest
steps:
# ... ビルドとアーティファクトのアップロード ...
deploy-staging:
needs: build
runs-on: ubuntu-latest
environment:
name: staging
url: https://staging.example.com
steps:
# ... アーティファクトをダウンロードしてステージング環境へデプロイ ...
approve-production:
needs: deploy-staging
runs-on: ubuntu-latest
environment:
name: production
steps:
- name: Manual approval for production deployment
uses: trstringer/manual-approval@v1
with:
secret: ${{ secrets.GITHUB_TOKEN }}
approvers: shineos
minimum-approvals: 1
deploy-production:
needs: approve-production
runs-on: ubuntu-latest
environment:
name: production
url: https://example.com
steps:
# ... アーティファクトをダウンロードして本番環境へデプロイ ...
ポイント
-
environment: デプロイ対象の環境を定義します。環境ごとにシークレットを設定したり、保護ルール(手動承認など)を適用したりできます。 -
手動承認:
trstringer/manual-approvalのようなアクションを使うことで、特定のユーザーの承認があるまでワークフローを一時停止させることができます。これにより、意図しない本番デプロイを防ぎます。
設計パターン4:モノレポ対応
モノレポ(単一リポジトリ)では、複数のプロジェクトやサービスが同じリポジトリに存在します。すべての変更で全プロジェクトのCIを動かすのは非効率なため、変更があったプロジェクトに関連するワークフローのみを実行するパターンです。
ユースケース
- フロントエンドとバックエンドが同じリポジトリにある
- 複数のマイクロサービスをモノレポで管理している
ワークフロー例
name: Monorepo CI
on:
pull_request:
jobs:
run-frontend-ci:
if: contains(github.event.pull_request.labels.*.name, 'frontend')
runs-on: ubuntu-latest
steps:
# ... フロントエンドのテストとビルド ...
run-backend-ci:
if: contains(github.event.pull_request.labels.*.name, 'backend')
runs-on: ubuntu-latest
steps:
# ... バックエンドのテストとビルド ...
# パスベースでの実行
run-docs-ci:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: dorny/paths-filter@v3
id: changes
with:
filters: |
docs:
- 'docs/**'
- if: steps.changes.outputs.docs == 'true'
run: echo "Documentation has changed!"
ポイント
-
if条件: ラベルやコミットメッセージ、変更されたファイルのパスに基づいてジョブの実行を制御します。 -
dorny/paths-filterアクション: 変更されたファイルのパスに基づいて、特定のジョブやステップを実行するかどうかを簡単に判定できます。この例ではdocs/ディレクトリ配下に差分がある場合のみ後続のステップが実行されます。
まとめとベストプラクティス
この記事では、4つの代表的なCI/CD設計パターンを紹介しました。実際のプロジェクトでは、これらのパターンを組み合わせることで、より洗練されたパイプラインを構築できます。
最後に、効率的で安全なパイプラインを維持するためのベストプラクティスをいくつか紹介します。
-
キャッシュを積極的に利用する:
actions/cacheアクションなどを使い、依存関係やビルドの中間生成物をキャッシュして、実行時間を短縮しましょう。 - シークレットの管理: APIキーやパスワードは、GitHubの暗号化されたシークレットに保存し、コードに直接書き込まないようにします。
- 再利用可能なワークフロー: 複数のワークフローで共通の処理がある場合は、「Callable Workflow」や「Composite Action」を使って処理を共通化し、メンテナンス性を高めましょう。
-
最小権限の原則: ワークフローに与える権限(
permissionsキー)は、必要最小限に設定し、セキュリティリスクを低減します。
GitHub Actionsは非常に柔軟で強力なツールです。ぜひこれらのパターンを参考に、あなたのプロジェクトに最適なCI/CDパイプラインを設計してみてください。
Discussion