GitHub Actionsで始める継続的デリバリー(CD)入門
継続的デリバリー(CD)は、ソフトウェア開発ライフサイクルにおいて、変更を自動的に本番環境へリリース可能にするためのプラクティスです。これにより、開発チームは頻繁に、そして確実にソフトウェアを顧客に届けることができるようになります。GitHub Actionsは、GitHubに統合された強力な自動化プラットフォームであり、CI/CDパイプラインの構築と実行を容易にします。
本稿では、GitHub Actionsを用いた継続的デリバリーの基礎から応用までを、具体的な例を交えながら詳細に解説します。読者は、この記事を通して、CDの概念を理解し、GitHub Actionsを効果的に活用して、自身のプロジェクトにCDパイプラインを実装できるようになることを目指します。
1. 継続的デリバリー(CD)とは?
継続的デリバリー(Continuous Delivery: CD)は、ソフトウェア開発における重要な概念であり、継続的インテグレーション(CI)の拡張として位置づけられます。CIがコードの変更を頻繁に統合し、自動テストを通じて品質を保証するのに対し、CDはこれらの変更を自動的に本番環境にリリース可能な状態にするプロセス全体を指します。
1.1. なぜCDが必要なのか?
CDを導入することで、以下のようなメリットが得られます。
- リリース頻度の向上: 開発チームは、手動の介入を最小限に抑え、頻繁に、そしてより迅速にソフトウェアをリリースできます。
- リスクの軽減: 小さな変更を頻繁にリリースすることで、個々のリリースに伴うリスクを軽減し、問題が発生した場合の影響範囲を小さく抑えることができます。
- フィードバックサイクルの短縮: 頻繁なリリースにより、ユーザーからのフィードバックを迅速に収集し、製品の改善に繋げることができます。
- 開発者の生産性向上: リリース作業の自動化により、開発者はより価値の高いタスクに集中できるようになります。
- ビジネス価値の向上: 迅速なリリースにより、顧客への価値提供を加速し、競争優位性を確立することができます。
1.2. CDの主要な要素
CDを実現するためには、以下の要素が重要となります。
- 自動化されたビルドプロセス: コードのコンパイル、パッケージング、および必要な依存関係のインストールを自動化します。
- 自動テスト: ユニットテスト、統合テスト、エンドツーエンドテストなど、様々なテストを自動化し、コードの品質を保証します。
- 環境の一貫性: 開発、テスト、ステージング、本番など、すべての環境で構成を一致させ、予期せぬ問題を回避します。
- 自動デプロイ: テストが成功した場合、自動的にソフトウェアをターゲット環境にデプロイします。
- モニタリングとアラート: アプリケーションのパフォーマンスを監視し、問題が発生した場合に自動的にアラートを発行します。
- ロールバック戦略: 問題が発生した場合、迅速に以前のバージョンにロールバックできる仕組みを準備します。
1.3. CDと継続的デプロイメント(Continuous Deployment)の違い
CDと継続的デプロイメント(Continuous Deployment: CD)は、しばしば混同されますが、明確な違いがあります。CDは、変更を自動的に本番環境にリリース可能な状態にするまでを指すのに対し、継続的デプロイメントは、自動的に本番環境にリリースするまでを含みます。つまり、継続的デプロイメントは、CDの延長線上にあると言えます。
継続的デプロイメントを導入するには、高度な自動化と徹底的なテストが不可欠です。すべての変更が自動的に本番環境にデプロイされるため、テストの信頼性が非常に重要となります。
2. GitHub Actionsとは?
GitHub Actionsは、GitHubに統合された自動化プラットフォームであり、ソフトウェア開発ワークフローの自動化を可能にします。これを使用することで、CI/CDパイプラインの構築、タスクの自動化、およびGitHubイベントへの対応を容易に行うことができます。
2.1. GitHub Actionsの主要なコンポーネント
GitHub Actionsを理解するためには、以下の主要なコンポーネントを理解する必要があります。
- Workflow: 自動化されたプロセスの定義です。YAMLファイルとして定義され、リポジトリの
.github/workflows
ディレクトリに保存されます。Workflowは、一つまたは複数のJobで構成されます。 - Job: Workflowの中で実行される一連のステップです。Jobは、単一の仮想マシンまたはコンテナ上で実行されます。
- Step: Jobの中で実行される個々のタスクです。Stepは、シェルスクリプトの実行、GitHub Actionの実行、またはDockerコンテナの実行など、様々な処理を行うことができます。
- Action: 再利用可能なコンポーネントであり、特定のタスクを実行するために使用されます。GitHub Marketplaceで公開されているActionを使用することも、独自にActionを作成することもできます。
- Runner: Jobを実行するサーバーです。GitHubが提供するRunnerを使用することも、独自のRunnerをセットアップすることもできます。
- Event: Workflowの実行をトリガーするイベントです。GitHubイベント(コードのプッシュ、プルリクエストの作成など)や、スケジュールされた時間などが利用できます。
2.2. GitHub Actionsの利点
GitHub Actionsを利用することで、以下のような利点が得られます。
- GitHubとの統合: GitHubに完全に統合されているため、GitHubリポジトリのイベントに直接対応できます。
- 柔軟性: 様々なプログラミング言語やツールをサポートしており、多様なワークフローを構築できます。
- 拡張性: GitHub Marketplaceで公開されているActionを利用することで、既存の機能を拡張できます。
- コスト効率: GitHubが提供する無料枠を利用することで、小規模なプロジェクトであれば無料で利用できます。
- オープンソース: Actionはオープンソースとして公開されているものが多く、コミュニティのサポートを受けやすいです。
3. GitHub Actionsを用いたCDパイプラインの構築
ここでは、GitHub Actionsを用いて、Node.jsアプリケーションのCDパイプラインを構築する例を具体的に解説します。
3.1. サンプルアプリケーションの準備
まず、簡単なNode.jsアプリケーションを作成します。
“`javascript
// index.js
const express = require(‘express’);
const app = express();
const port = process.env.PORT || 3000;
app.get(‘/’, (req, res) => {
res.send(‘Hello, World!’);
});
app.listen(port, () => {
console.log(Server listening on port ${port}
);
});
“`
json
// package.json
{
"name": "node-cd-example",
"version": "1.0.0",
"description": "Node.js application for CD example",
"main": "index.js",
"scripts": {
"start": "node index.js",
"test": "echo \"Error: no test specified\" && exit 1"
},
"dependencies": {
"express": "^4.17.1"
}
}
このアプリケーションは、localhost:3000
にアクセスすると “Hello, World!” と表示するシンプルなものです。
3.2. GitHubリポジトリの作成
作成したアプリケーションをGitHubリポジトリにプッシュします。
3.3. Workflowファイルの作成
リポジトリの.github/workflows
ディレクトリに、cd.yml
という名前のWorkflowファイルを作成します。
“`yaml
.github/workflows/cd.yml
name: Continuous Delivery
on:
push:
branches:
– main
jobs:
build:
runs-on: ubuntu-latest
steps:
– uses: actions/checkout@v3
– name: Set up Node.js
uses: actions/setup-node@v3
with:
node-version: ’16’
– name: Install dependencies
run: npm install
– name: Run tests
run: npm test
deploy:
needs: build
runs-on: ubuntu-latest
steps:
– uses: actions/checkout@v3
– name: Deploy to Heroku
uses: akhileshns/[email protected]
with:
heroku_api_key: ${{secrets.HEROKU_API_KEY}}
heroku_app_name: ${{secrets.HEROKU_APP_NAME}}
heroku_email: ${{secrets.HEROKU_EMAIL}}
“`
このWorkflowファイルは、以下の処理を行います。
name: Continuous Delivery
: Workflowの名前を定義します。on:
: Workflowの実行をトリガーするイベントを定義します。ここでは、main
ブランチへのpush
イベントをトリガーとしています。jobs:
: Workflow内で実行されるJobを定義します。ここでは、build
とdeploy
という2つのJobを定義しています。build:
: アプリケーションのビルドとテストを行います。runs-on: ubuntu-latest
: Jobを実行するRunnerを指定します。ここでは、Ubuntuの最新バージョンを使用します。steps:
: Jobの中で実行されるStepを定義します。uses: actions/checkout@v3
: リポジトリのコードをRunnerにチェックアウトします。name: Set up Node.js
: Node.jsの環境をセットアップします。uses: actions/setup-node@v3
: Node.jsのバージョンを指定します。ここでは、バージョン16を使用します。name: Install dependencies
: アプリケーションの依存関係をインストールします。run: npm install
:npm install
コマンドを実行します。name: Run tests
: アプリケーションのテストを実行します。run: npm test
:npm test
コマンドを実行します。
deploy:
: アプリケーションをHerokuにデプロイします。needs: build
:build
Jobが成功した場合のみ、deploy
Jobを実行します。runs-on: ubuntu-latest
: Jobを実行するRunnerを指定します。ここでは、Ubuntuの最新バージョンを使用します。steps:
: Jobの中で実行されるStepを定義します。uses: actions/checkout@v3
: リポジトリのコードをRunnerにチェックアウトします。name: Deploy to Heroku
: アプリケーションをHerokuにデプロイします。uses: akhileshns/[email protected]
: Herokuへのデプロイを行うためのActionを使用します。with:
: Actionに渡すパラメータを定義します。heroku_api_key: ${{secrets.HEROKU_API_KEY}}
: Heroku APIキーを指定します。APIキーは、GitHubリポジトリのSecretsに登録する必要があります。heroku_app_name: ${{secrets.HEROKU_APP_NAME}}
: Herokuアプリケーションの名前を指定します。heroku_email: ${{secrets.HEROKU_EMAIL}}
: Herokuアカウントのメールアドレスを指定します。
3.4. GitHub Secretsの設定
Workflowファイルで使用しているsecrets.HEROKU_API_KEY
、secrets.HEROKU_APP_NAME
、secrets.HEROKU_EMAIL
は、GitHubリポジトリのSecretsに登録する必要があります。
- リポジトリのSettingsタブを開きます。
- 左側のメニューからSecrets > Actionsを選択します。
-
“New repository secret”ボタンをクリックし、それぞれのSecretを登録します。
HEROKU_API_KEY
: Herokuのダッシュボードから取得できます。HEROKU_APP_NAME
: Herokuアプリケーションの名前です。HEROKU_EMAIL
: Herokuアカウントのメールアドレスです。
3.5. コードのプッシュとデプロイの確認
main
ブランチにコードをプッシュすると、GitHub Actionsが自動的に実行され、アプリケーションがHerokuにデプロイされます。GitHubリポジトリのActionsタブで、Workflowの実行状況を確認できます。
3.6. 自動テストの追加
上記の例では、テストを実行するStepを追加していますが、テスト自体は実装されていません。ここでは、jestを用いて自動テストを追加してみましょう。
まず、jestをインストールします。
bash
npm install --save-dev jest
次に、テストファイルを作成します。
“`javascript
// index.test.js
const request = require(‘supertest’);
const app = require(‘./index’);
describe(‘GET /’, () => {
it(‘responds with “Hello, World!”‘, async () => {
const response = await request(app).get(‘/’);
expect(response.text).toBe(‘Hello, World!’);
});
});
“`
package.json
のscripts
に、テストを実行するためのコマンドを追加します。
json
// package.json
{
"scripts": {
"start": "node index.js",
"test": "jest"
}
}
最後に、Workflowファイルを更新します。
“`yaml
.github/workflows/cd.yml
name: Continuous Delivery
on:
push:
branches:
– main
jobs:
build:
runs-on: ubuntu-latest
steps:
– uses: actions/checkout@v3
– name: Set up Node.js
uses: actions/setup-node@v3
with:
node-version: ’16’
– name: Install dependencies
run: npm install
– name: Run tests
run: npm test
“`
これで、main
ブランチにコードをプッシュすると、自動的にテストが実行され、テストが成功した場合のみ、アプリケーションがHerokuにデプロイされるようになります。
4. GitHub Actionsの応用的な使い方
ここでは、GitHub Actionsのより応用的な使い方について解説します。
4.1. 環境変数の利用
Workflowファイル内で環境変数を利用することで、設定値を柔軟に変更することができます。環境変数は、GitHubリポジトリのSecretsに登録することも、Workflowファイル内で直接定義することもできます。
“`yaml
.github/workflows/cd.yml
name: Continuous Delivery
on:
push:
branches:
– main
jobs:
build:
runs-on: ubuntu-latest
steps:
– uses: actions/checkout@v3
– name: Set up Node.js
uses: actions/setup-node@v3
with:
node-version: ’16’
– name: Install dependencies
run: npm install
– name: Run tests
run: npm test
env:
NODE_ENV: test
deploy:
needs: build
runs-on: ubuntu-latest
steps:
– uses: actions/checkout@v3
– name: Deploy to Heroku
uses: akhileshns/[email protected]
with:
heroku_api_key: ${{secrets.HEROKU_API_KEY}}
heroku_app_name: ${{secrets.HEROKU_APP_NAME}}
heroku_email: ${{secrets.HEROKU_EMAIL}}
env:
HEROKU_API_KEY: ${{secrets.HEROKU_API_KEY}}
“`
上記の例では、build
JobでNODE_ENV
環境変数をtest
に設定しています。また、deploy
JobでHEROKU_API_KEY
環境変数を設定しています。
4.2. Dockerコンテナの利用
GitHub Actionsでは、Dockerコンテナを利用してJobを実行することができます。これにより、特定の依存関係や環境が必要なアプリケーションのビルドやデプロイを容易に行うことができます。
“`yaml
.github/workflows/cd.yml
name: Continuous Delivery
on:
push:
branches:
– main
jobs:
build:
runs-on: ubuntu-latest
container:
image: node:16
steps:
– uses: actions/checkout@v3
– name: Install dependencies
run: npm install
– name: Run tests
run: npm test
deploy:
needs: build
runs-on: ubuntu-latest
steps:
– uses: actions/checkout@v3
– name: Deploy to Heroku
uses: akhileshns/[email protected]
with:
heroku_api_key: ${{secrets.HEROKU_API_KEY}}
heroku_app_name: ${{secrets.HEROKU_APP_NAME}}
heroku_email: ${{secrets.HEROKU_EMAIL}}
“`
上記の例では、build
Jobをnode:16
というDockerイメージで実行しています。これにより、RunnerにNode.jsをインストールする必要がなくなり、より安定した環境でビルドを行うことができます。
4.3. 環境に応じたデプロイ戦略
本番環境だけでなく、ステージング環境や開発環境など、複数の環境にデプロイする必要がある場合、ブランチやタグに基づいてデプロイ先を切り替えることができます。
“`yaml
.github/workflows/cd.yml
name: Continuous Delivery
on:
push:
branches:
– main
pull_request:
branches:
– develop
jobs:
build:
runs-on: ubuntu-latest
steps:
– uses: actions/checkout@v3
– name: Set up Node.js
uses: actions/setup-node@v3
with:
node-version: ’16’
– name: Install dependencies
run: npm install
– name: Run tests
run: npm test
deploy:
needs: build
runs-on: ubuntu-latest
steps:
– uses: actions/checkout@v3
– name: Deploy to Heroku
uses: akhileshns/[email protected]
with:
heroku_api_key: ${{secrets.HEROKU_API_KEY}}
heroku_app_name: ${{secrets.HEROKU_APP_NAME}}
heroku_email: ${{secrets.HEROKU_EMAIL}}
env:
HEROKU_API_KEY: ${{secrets.HEROKU_API_KEY}}
if: github.ref == ‘refs/heads/main’
“`
上記の例では、push
イベントの対象ブランチがmain
の場合にのみ、deploy
Jobを実行するようにしています。develop
ブランチへのpull_request
イベントは、build
Jobのみを実行するように設定されています。
4.4. 手動承認ワークフロー
完全な自動デプロイが困難な場合や、特定の段階で人間の承認が必要な場合、手動承認ワークフローを組み込むことができます。
“`yaml
.github/workflows/cd.yml
name: Continuous Delivery
on:
push:
branches:
– main
jobs:
build:
runs-on: ubuntu-latest
steps:
– uses: actions/checkout@v3
– name: Set up Node.js
uses: actions/setup-node@v3
with:
node-version: ’16’
– name: Install dependencies
run: npm install
– name: Run tests
run: npm test
approve:
needs: build
runs-on: ubuntu-latest
outputs:
approved: ${{ job.status == ‘success’ }}
steps:
– name: Request approval
id: approval
uses: actions/github-script@v6
with:
script: |
github.rest.actions.createWorkflowDispatch({
owner: context.repo.owner,
repo: context.repo.repo,
workflow_id: ‘cd.yml’,
ref: context.ref,
inputs: {
approved: ‘true’
}
})
– name: Wait for approval
uses: actions/github-script@v6
with:
script: |
console.log(‘Waiting for approval…’)
deploy:
needs: approve
runs-on: ubuntu-latest
if: needs.approve.outputs.approved == ‘true’
steps:
– uses: actions/checkout@v3
– name: Deploy to Heroku
uses: akhileshns/[email protected]
with:
heroku_api_key: ${{secrets.HEROKU_API_KEY}}
heroku_app_name: ${{secrets.HEROKU_APP_NAME}}
heroku_email: ${{secrets.HEROKU_EMAIL}}
env:
HEROKU_API_KEY: ${{secrets.HEROKU_API_KEY}}
“`
この例では、approve
Jobを追加し、GitHub ActionsのAPIを使用して手動でWorkflowをディスパッチしています。deploy
Jobは、approve
Jobが成功した場合のみ実行されます。
5. GitHub Actionsにおけるベストプラクティス
GitHub Actionsを効果的に活用するためには、以下のベストプラクティスを遵守することが重要です。
- Workflowファイルを簡潔に保つ: Workflowファイルを複雑にしすぎないように、必要最小限のステップで構成するように心がけましょう。
- Actionのバージョンを固定する: Actionのバージョンを固定することで、予期せぬ変更による問題を防ぐことができます。
- Secretsを適切に管理する: Secretsは暗号化された状態で保存されますが、誤って公開しないように注意が必要です。
- テストを徹底的に行う: 自動テストは、CDパイプラインの信頼性を高めるために不可欠です。
- モニタリングとアラートを設定する: アプリケーションのパフォーマンスを監視し、問題が発生した場合に自動的にアラートを発行するように設定しましょう。
- コードレビューを徹底する: Workflowファイルもコードと同様に、レビューを行うことで、品質を向上させることができます。
6. まとめ
本稿では、GitHub Actionsを用いた継続的デリバリーの基礎から応用までを解説しました。GitHub Actionsは、柔軟性と拡張性に優れた自動化プラットフォームであり、CI/CDパイプラインの構築を容易にします。この記事を参考に、GitHub Actionsを活用して、自身のプロジェクトにCDパイプラインを実装し、より迅速かつ確実にソフトウェアをリリースできるようにしましょう。継続的な学習と改善を通じて、CDパイプラインを最適化し、より効率的な開発プロセスを確立していくことが重要です。