GitHub Actions CI/CD:ゼロからビルド・テスト・デプロイのワークフローを構築する
継続的インテグレーションとデプロイのためのGitHub Actionsのセットアップ方法を解説します。トリガー、ジョブ、マトリックス、シークレット、キャッシュ、Docker、実践的なワークフロー例を網羅しています。
GitHub Actionsは、プッシュ・プルリクエスト・マージのたびに自動化されたパイプラインを起動し、テストの実行、アーティファクトのビルド、脆弱性のスキャン、本番環境へのデプロイを行います。インフラ管理が一切不要で、リポジトリの中に直接組み込まれたCI/CDプラットフォームです。
GitHub Actionsの仕組み
すべてのワークフローは.github/workflows/内のYAMLファイルです。トリガーイベントが発生すると、GitHubが新しい仮想マシンを起動してジョブを実行し、結果を報告します。これらはすべて数秒以内に完了します。
mainへのプッシュ
↓
ワークフローが起動
↓
ジョブ: ビルド & テスト (ubuntu-latest)
├── ステップ 1: コードのチェックアウト
├── ステップ 2: Node.jsのインストール
├── ステップ 3: npm ci
├── ステップ 4: npm test
└── ステップ 5: npm run build
↓
✅ すべてのチェックが完了
最初のワークフロー
.github/workflows/ci.ymlを作成します:
name: CI
on:
push:
branches: [main]
pull_request:
branches: [main]
jobs:
build:
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
- run: npm run build
これだけです。mainへのプッシュとすべてのPRで、テストスイートが自動的に実行されるようになります。
トリガー:ワークフローが実行されるタイミング
コードイベント
on:
push:
branches: [main, develop]
paths: ['src/**', 'package.json'] # 変更があった場合のみ実行
pull_request:
types: [opened, synchronize]
スケジュール(cron)
on:
schedule:
- cron: '0 6 * * 1' # 毎週月曜日 UTC 6:00
手動実行
on:
workflow_dispatch:
inputs:
environment:
description: 'デプロイ先'
required: true
type: choice
options: [staging, production]
これにより、GitHub UIにパラメーターを選択できる「Run workflow」ボタンが追加されます。
再利用可能なワークフロー
on:
workflow_call:
inputs:
node-version:
type: string
default: '20'
別のワークフローからuses: ./.github/workflows/reusable.ymlで呼び出せます。
ジョブとステップ
並列ジョブ
ジョブはデフォルトで並列に実行されます:
jobs:
lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: npm run lint
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: npm test
build:
runs-on: ubuntu-latest
needs: [lint, test] # 両方が完了するまで待機
steps:
- uses: actions/checkout@v4
- run: npm run build
マトリックス戦略 — 複数バージョンでテスト
複数の設定で同じジョブを実行します:
jobs:
test:
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [18, 20, 22]
os: [ubuntu-latest, windows-latest]
fail-fast: false
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: ${{ matrix.node-version }}
- run: npm ci
- run: npm test
これにより、6つの並列ジョブ(3バージョン × 2オペレーティングシステム)が作成されます。
シークレットと環境変数
シークレットの使用
機密情報はSettings → Secrets and variables → Actionsに保存します:
steps:
- name: Deploy
env:
API_KEY: ${{ secrets.API_KEY }}
DATABASE_URL: ${{ secrets.DATABASE_URL }}
run: ./deploy.sh
シークレットはログでマスクされ、フォークには公開されません。
環境変数
# ワークフローレベル
env:
NODE_ENV: production
jobs:
build:
# ジョブレベル
env:
CI: true
steps:
- name: Build
# ステップレベル
env:
VITE_API_URL: https://api.example.com
run: npm run build
高速ビルドのためのキャッシュ
キャッシュを使用しない場合、毎回すべての依存関係をゼロからダウンロードします。キャッシュを使うとビルド時間を50〜80%短縮できます:
- uses: actions/setup-node@v4
with:
node-version: 20
cache: npm # 組み込みのnpmキャッシュ
# 他のツール向けの手動キャッシュ
- uses: actions/cache@v4
with:
path: ~/.cache/pip
key: ${{ runner.os }}-pip-${{ hashFiles('requirements.txt') }}
restore-keys: |
${{ runner.os }}-pip-
アーティファクト:ジョブ間でのデータ共有
あるジョブのビルド出力をアップロードし、別のジョブでダウンロードします:
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: npm run build
- uses: actions/upload-artifact@v4
with:
name: dist
path: dist/
deploy:
needs: build
runs-on: ubuntu-latest
steps:
- uses: actions/download-artifact@v4
with:
name: dist
- run: ./deploy.sh
実践的なワークフロー例
Dockerのビルドとプッシュ
name: Docker
on:
push:
tags: ['v*']
permissions:
packages: write
jobs:
docker:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- uses: docker/build-push-action@v5
with:
push: true
tags: ghcr.io/${{ github.repository }}:${{ github.ref_name }}
cache-from: type=gha
cache-to: type=gha,mode=max
Cloudflare Pagesへのデプロイ
name: Deploy
on:
push:
branches: [main]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 20
cache: npm
- run: npm ci && npm run build
- uses: cloudflare/wrangler-action@v3
with:
apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }}
command: pages deploy dist --project-name=my-site
変更ログ付きリリース
name: Release
on:
push:
tags: ['v*.*.*']
permissions:
contents: write
jobs:
release:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: 変更ログを生成
run: |
git log $(git describe --tags --abbrev=0 HEAD^)..HEAD \
--pretty=format:"- %s" > CHANGELOG.md
- uses: softprops/action-gh-release@v2
with:
body_path: CHANGELOG.md
generate_release_notes: true
条件付き実行
ステップとジョブの実行タイミングを制御します:
steps:
- name: 本番環境へデプロイ
if: github.ref == 'refs/heads/main'
run: ./deploy-prod.sh
- name: ステージング環境へデプロイ
if: github.event_name == 'pull_request'
run: ./deploy-staging.sh
- name: 失敗時に通知
if: failure()
run: curl -X POST ${{ secrets.SLACK_WEBHOOK }} -d '{"text":"Build failed!"}'
セキュリティのベストプラクティス
1. アクションのバージョンをSHAに固定する
# ❌ 変更可能なタグ — 侵害される可能性あり
- uses: actions/checkout@v4
# ✅ 正確なコミットSHAに固定
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11
2. 最小権限の原則を使用する
permissions:
contents: read # 必要なものだけ
packages: write
3. シークレットをechoしない
# ❌ 絶対にやってはいけない
- run: echo ${{ secrets.API_KEY }}
# ✅ 環境変数を使用する
- env:
API_KEY: ${{ secrets.API_KEY }}
run: ./script-that-uses-api-key.sh
4. フォークからのPRの権限を制限する
on:
pull_request_target: # ベースブランチのコンテキストで実行
types: [opened, synchronize]
失敗したワークフローのデバッグ
- ログを確認する — 失敗したステップをクリックして全出力を確認
- デバッグログを追加する — シークレット
ACTIONS_STEP_DEBUGをtrueに設定 actをローカルで使用する — nektos/actでマシン上のワークフローを実行- ランナーにSSH接続する — インタラクティブなデバッグには
mxschmitt/action-tmateを使用
ワークフローをビジュアルで構築する
YAMLを手書きしたくない場合は、**GitHub Actions Generator**を使いましょう。Node.js、Python、Docker、デプロイメントなどのテンプレートを使ってワークフローをビジュアルで構築し、本番環境対応のYAMLをダウンロードできます。
まとめ
GitHub Actionsは、リポジトリの中に直接組み込まれたCI/CDを提供します:
- シンプルに始める — ビルド + テストを含む1つのワークフローファイル
- キャッシュを追加する —
actions/cacheや組み込みの言語キャッシュでビルド時間を短縮 - マトリックスを使用する — 複数のバージョンとオペレーティングシステムでテスト
- シークレットを保護する — ハードコーディングせず、常に暗号化されたシークレットを使用
- すべてを自動化する — リリース、デプロイ、セキュリティスキャン、スケジュールタスク
最高のCI/CDパイプラインは、あなたが意識することなくすべてのコミットで実行されるものです。一度セットアップすれば、あとはGitHubに任せておけます。