GitHub Actions入門:CI/CDパイプラインをゼロから構築する実践ガイド
目次
CI/CDとは何か
CI(継続的インテグレーション) とは、コードをリポジトリにプッシュするたびに自動でテストを実行し、バグを早期に発見する仕組みです。
CD(継続的デリバリー/デプロイ) とは、テストが通ったコードを自動で本番環境やステージング環境にデプロイする仕組みです。
CI/CDがない開発の問題点:
- テストを手動で実行し忘れてバグを本番にリリースする
- デプロイ手順をドキュメント化しても、手順を間違える
- チームメンバー全員がデプロイできないため、特定の人に依存する
GitHub Actionsを使えば、これらをコード(YAML)で定義して自動化できます。
GitHub Actionsの基本概念
ワークフロー(Workflow)
.github/workflows/ディレクトリに置くYAMLファイルです。「何をトリガーに」「どのような処理を」実行するかを定義します。
トリガー(on)
ワークフローを起動するイベントです。代表的なものは以下のとおりです。
| トリガー | 説明 |
|---|---|
push | 指定ブランチへのプッシュ時 |
pull_request | プルリクエストの作成・更新時 |
workflow_dispatch | 手動でワークフローを起動 |
schedule | cronで定期実行 |
ジョブ(jobs)
ワークフロー内の処理単位です。デフォルトで並列実行されますが、needsで依存関係を定義して順次実行もできます。
ステップ(steps)
ジョブ内の個々の処理です。シェルコマンドの実行(run)またはアクション(uses)を指定します。
アクション(Action)
再利用可能なステップのテンプレートです。GitHubが公式に提供するもの(actions/checkoutなど)や、コミュニティが公開するものがあります。
Node.jsプロジェクトのCI設定
まず最もよく使われる構成、Node.jsプロジェクトのテスト自動実行を構築します。
# .github/workflows/ci.yml
name: CI
# トリガー:mainへのプッシュ、またはすべてのPR作成・更新時
on:
push:
branches: [main]
pull_request:
branches: [main]
# 同じブランチで新しいワークフローが起動したら古いものをキャンセル
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
test:
name: Lint & Test
runs-on: ubuntu-latest
# Node.jsの複数バージョンでテスト(マトリックス戦略)
strategy:
matrix:
node-version: [20, 22]
steps:
# ① リポジトリのコードをチェックアウト
- name: Checkout repository
uses: actions/checkout@v4
# ② Node.jsのセットアップ(npmキャッシュも有効化)
- name: Setup Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v4
with:
node-version: ${{ matrix.node-version }}
cache: 'npm'
# ③ 依存パッケージをインストール(package-lock.jsonに従い完全再現)
- name: Install dependencies
run: npm ci
# ④ リントチェック
- name: Run ESLint
run: npm run lint
# ⑤ 型チェック(TypeScriptプロジェクトの場合)
- name: Type check
run: npm run type-check
# ⑥ テスト実行(カバレッジも計測)
- name: Run tests
run: npm run test -- --coverage
# ⑦ カバレッジレポートをアーティファクトとして保存
- name: Upload coverage report
uses: actions/upload-artifact@v4
if: matrix.node-version == 20 # Node 20の場合のみ
with:
name: coverage-report
path: coverage/
retention-days: 7
package.jsonのスクリプト設定
上記のワークフローに対応するnpmスクリプトです。
{
"scripts": {
"dev": "vite",
"build": "tsc && vite build",
"lint": "eslint . --ext .ts,.tsx",
"type-check": "tsc --noEmit",
"test": "vitest run",
"test:watch": "vitest",
"test:coverage": "vitest run --coverage"
}
}
ビルドとデプロイの自動化
テストが通ったら本番にデプロイするパイプラインを構築します。ここではCloudflare Pagesへのデプロイを例にします。
# .github/workflows/deploy.yml
name: Deploy to Cloudflare Pages
on:
push:
branches: [main] # mainへのプッシュ時のみデプロイ
jobs:
# ジョブ1: テスト(先に実行)
test:
name: Run Tests
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 20
cache: 'npm'
- run: npm ci
- run: npm test
# ジョブ2: ビルドとデプロイ(testジョブが成功した場合のみ実行)
deploy:
name: Build & Deploy
runs-on: ubuntu-latest
needs: test # testジョブの完了を待つ
steps:
- name: Checkout repository
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
run: npm run build
env:
# GitHub Secretsから環境変数を注入
PUBLIC_API_URL: ${{ secrets.PUBLIC_API_URL }}
- name: Deploy to Cloudflare Pages
uses: cloudflare/wrangler-action@v3
with:
apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }}
accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
command: pages deploy dist/ --project-name=my-project
# デプロイ完了をSlackに通知
- name: Notify Slack
if: always() # 成功・失敗どちらでも実行
uses: slackapi/slack-github-action@v1
with:
channel-id: 'C0123456789'
slack-message: |
${{ job.status == 'success' && '✅ デプロイ成功' || '❌ デプロイ失敗' }}
Branch: ${{ github.ref_name }}
Commit: ${{ github.sha }}
env:
SLACK_BOT_TOKEN: ${{ secrets.SLACK_BOT_TOKEN }}
シークレットの設定方法
APIトークンなどの機密情報はGitHub Secretsに保存します。
- GitHubリポジトリの「Settings」→「Secrets and variables」→「Actions」を開く
- 「New repository secret」をクリック
- 名前(例:
CLOUDFLARE_API_TOKEN)と値を入力して保存
ワークフロー内では${{ secrets.CLOUDFLARE_API_TOKEN }}のように参照します。シークレットの値はログに表示されずマスクされます。
PRにテスト結果を自動コメント
プルリクエスト時にテスト結果や差分カバレッジをPRコメントとして自動投稿することで、レビューが効率化します。
# .github/workflows/pr-check.yml
name: PR Check
on:
pull_request:
branches: [main]
jobs:
test:
runs-on: ubuntu-latest
# PRへのコメント権限を付与
permissions:
pull-requests: write
steps:
- uses: actions/checkout@v4
with:
# PR のベースブランチも取得(差分カバレッジ計算に必要)
fetch-depth: 0
- uses: actions/setup-node@v4
with:
node-version: 20
cache: 'npm'
- run: npm ci
- name: Run tests with coverage
run: npm run test -- --coverage --reporter=json
continue-on-error: true # テスト失敗でもPRコメントを投稿する
- name: Post coverage comment
uses: davelosert/vitest-coverage-report-action@v2
with:
json-summary-path: ./coverage/coverage-summary.json
json-final-path: ./coverage/coverage-final.json
定期実行(cron)でのスケジュール実行
毎日深夜に依存パッケージの脆弱性チェックを行う例です。
# .github/workflows/security-scan.yml
name: Security Scan
on:
schedule:
# 毎日 UTC 00:00(JST 09:00)に実行
- cron: '0 0 * * *'
workflow_dispatch: # 手動でも実行できるようにする
jobs:
audit:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 20
cache: 'npm'
- run: npm ci
- name: Run npm audit
run: npm audit --audit-level=high
# 高リスク以上の脆弱性があればワークフローが失敗する
- name: Check for outdated packages
run: npm outdated || true # 旧バージョンがあっても失敗扱いにしない
キャッシュを活用してビルドを高速化
npm ciは毎回node_modulesを再インストールするため時間がかかります。setup-nodeのcache: 'npm'オプションを使うと、package-lock.jsonのハッシュをキーにしてキャッシュが効きます。
手動でキャッシュを設定する場合は以下のようにします。
- name: Cache node_modules
uses: actions/cache@v4
with:
path: ~/.npm
key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
restore-keys: |
${{ runner.os }}-node-
hashFiles('**/package-lock.json')はpackage-lock.jsonのハッシュ値を計算します。ファイルが変わらなければ同じキャッシュが再利用され、変わった場合は新しくキャッシュが作成されます。
よくあるつまずきポイント
YAML のインデントエラー
GitHubActions のワークフローはYAMLの書式に厳密です。タブではなくスペースを使い、インデントを2または4スペースに統一してください。yamllintコマンドで事前チェックできます。
# yamllintのインストールと検証
pip install yamllint
yamllint .github/workflows/ci.yml
パーミッションエラー
デフォルトではワークフローのパーミッションは読み取り専用です。PRへのコメント投稿やリリースの作成など書き込みが必要な場合は明示的にpermissionsを指定します。
permissions:
contents: read
pull-requests: write
issues: write
GitHub CI/CD実践ガイド 持続可能なソフトウェア開発を支えるGitHub Actionsの設計と運用
GitHub Actionsの設計思想から実践的なCI/CDパイプライン構築まで体系的に学べる一冊。再利用可能なワークフローや大規模運用のノウハウも収録されています。
※ アフィリエイトリンクを含みます
まとめ
GitHub Actionsの核心は「コードとして定義された自動化」です。
- .github/workflows/にYAMLを置くだけでCI/CDが動く
- トリガー(on) でいつ実行するかを定義する
- ジョブ(jobs) を
needsで連鎖させてパイプラインを作る - シークレット でAPIトークンなどを安全に管理する
- キャッシュ を活用して実行時間を短縮する
まずはnpm testを自動実行するシンプルなCI設定から始め、慣れてきたら自動デプロイやSlack通知を追加していくことをおすすめします。