メインコンテンツへスキップ
Code & Craft
ツール比較 約7分で読めます

GitHub Actions で CI/CD を組む実践ガイド|ワークフロー・シークレット・再利用

GitHub Actions の使い方を実例付きで完全解説。CI/CD ワークフローの基礎、再利用可能ワークフロー、シークレット管理、キャッシュ活用まで実務に使えるテクニック。

GitHub Actions は、GitHub が提供する CI/CD プラットフォームです。リポジトリへの push、Pull Request、Issue の更新、時間スケジュールなど、あらゆるイベントをトリガーに自動処理を実行できます。公開リポジトリでは無料、プライベートでも月2000分まで無料と、コストパフォーマンスも優秀です。

GitHub Actions の基本

ワークフローファイルの配置

.github/
└── workflows/
    ├── ci.yml
    ├── deploy.yml
    └── release.yml

.github/workflows/ 以下に YAML ファイルを置くだけで、自動的に認識されます。

最小のワークフロー

# .github/workflows/ci.yml
name: CI

on: [push]

jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - run: echo "Hello, GitHub Actions!"

ワークフローの構成要素

Workflow (ci.yml)
  └ Job (test)
    └ Step (checkout)
    └ Step (run command)
  • Workflow: 1つの YAML ファイル = 1つのワークフロー
  • Job: 並行実行される処理単位
  • Step: Job 内の各ステップ

トリガー(on)

# push 時
on: push

# 特定ブランチのみ
on:
  push:
    branches: [main, develop]
  pull_request:
    branches: [main]

# 特定ファイル変更時のみ
on:
  push:
    paths:
      - 'src/**'
      - 'package.json'

# タグが付いた時
on:
  push:
    tags:
      - 'v*.*.*'

# 手動実行
on:
  workflow_dispatch:
    inputs:
      environment:
        description: '環境'
        required: true
        type: choice
        options: [dev, staging, prod]

# 定時実行(cron)
on:
  schedule:
    - cron: '0 9 * * *'  # 毎日 9:00 UTC

# 複数トリガーの組み合わせ
on:
  push:
    branches: [main]
  pull_request:
  schedule:
    - cron: '0 0 * * 0'

Node.js プロジェクトの CI 例

name: CI

on:
  push:
    branches: [main]
  pull_request:

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 linter
        run: npm run lint

      - name: Run tests
        run: npm test

      - name: Build
        run: npm run build

マトリックスビルド(複数環境テスト)

複数の OS / バージョンで並行テスト:

jobs:
  test:
    runs-on: ${{ matrix.os }}
    strategy:
      matrix:
        os: [ubuntu-latest, macos-latest, windows-latest]
        node-version: [18, 20, 22]
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: ${{ matrix.node-version }}
      - run: npm ci
      - run: npm test

上記は 3 OS × 3 Node.js バージョン = 9 並列ジョブが実行されます。

シークレットの管理

シークレットの追加

GitHub リポジトリの Settings → Secrets and variables → Actions で追加。

ワークフローでの使用

- name: Deploy
  run: ./deploy.sh
  env:
    API_KEY: ${{ secrets.API_KEY }}
    DATABASE_URL: ${{ secrets.DATABASE_URL }}

重要: シークレットはログに自動マスクされますが、echo "${{ secrets.API_KEY }}" のようにログ出力しないよう注意。

環境別シークレット

jobs:
  deploy:
    environment: production  # production 環境のシークレットを使用
    steps:
      - run: echo "Deploying..."
        env:
          DEPLOY_KEY: ${{ secrets.PROD_DEPLOY_KEY }}

Settings → Environments で本番・ステージング等の環境を定義できます。承認ルール(レビュー必須)も設定可能です。

キャッシュで高速化

Node.js 依存関係のキャッシュ

actions/setup-node@v4 には cache オプションが組み込まれています。

- uses: actions/setup-node@v4
  with:
    node-version: 20
    cache: 'npm'  # または 'yarn', 'pnpm'

手動キャッシュ

- uses: actions/cache@v4
  with:
    path: |
      ~/.npm
      node_modules
    key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
    restore-keys: |
      ${{ runner.os }}-node-

Next.js ビルドキャッシュ

- uses: actions/cache@v4
  with:
    path: |
      ~/.npm
      ${{ github.workspace }}/.next/cache
    key: ${{ runner.os }}-nextjs-${{ hashFiles('**/package-lock.json') }}-${{ hashFiles('**/*.js', '**/*.jsx', '**/*.ts', '**/*.tsx') }}

並行実行の制御

concurrency

同じブランチの前のワークフローをキャンセル:

concurrency:
  group: ${{ github.workflow }}-${{ github.ref }}
  cancel-in-progress: true

これにより、プッシュを連続した時も最新のものだけが実行されます。

Job の依存関係

jobs:
  test:
    runs-on: ubuntu-latest
    steps: [...]

  build:
    needs: test  # test が成功したら実行
    runs-on: ubuntu-latest
    steps: [...]

  deploy:
    needs: [test, build]  # 両方成功したら実行
    runs-on: ubuntu-latest
    if: github.ref == 'refs/heads/main'
    steps: [...]

再利用可能ワークフロー

複数のリポジトリで共通処理を使う場合、再利用可能ワークフローを定義できます。

定義側(共通リポジトリ)

# .github/workflows/reusable-ci.yml
name: Reusable CI

on:
  workflow_call:
    inputs:
      node-version:
        type: string
        default: '20'
    secrets:
      NPM_TOKEN:
        required: true

jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: ${{ inputs.node-version }}
      - run: npm ci
        env:
          NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
      - run: npm test

呼び出し側

# .github/workflows/ci.yml
jobs:
  call-reusable:
    uses: your-org/shared-workflows/.github/workflows/reusable-ci.yml@main
    with:
      node-version: '22'
    secrets:
      NPM_TOKEN: ${{ secrets.NPM_TOKEN }}

Composite Action(複合アクション)

一連のステップを1つの Action としてまとめられます。

# .github/actions/setup/action.yml
name: Setup
description: Node.js と依存関係のセットアップ

inputs:
  node-version:
    description: Node.js version
    default: '20'

runs:
  using: composite
  steps:
    - uses: actions/setup-node@v4
      with:
        node-version: ${{ inputs.node-version }}
        cache: 'npm'

    - run: npm ci
      shell: bash

使用例:

- uses: ./.github/actions/setup
  with:
    node-version: '22'

デプロイの実例

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
      - run: npm run build

      - name: Deploy to Cloudflare Pages
        uses: cloudflare/pages-action@v1
        with:
          apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }}
          accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
          projectName: my-project
          directory: dist

Vercel へのデプロイ

- uses: amondnet/vercel-action@v25
  with:
    vercel-token: ${{ secrets.VERCEL_TOKEN }}
    vercel-org-id: ${{ secrets.VERCEL_ORG_ID }}
    vercel-project-id: ${{ secrets.VERCEL_PROJECT_ID }}
    vercel-args: '--prod'

通知の設定

Slack 通知

- name: Slack Notification
  if: failure()
  uses: rtCamp/action-slack-notify@v2
  env:
    SLACK_WEBHOOK: ${{ secrets.SLACK_WEBHOOK }}
    SLACK_TITLE: CI Failed
    SLACK_COLOR: danger

Discord 通知

- name: Discord Notification
  if: always()
  uses: sarisia/actions-status-discord@v1
  with:
    webhook: ${{ secrets.DISCORD_WEBHOOK }}

デバッグテクニック

デバッグログの有効化

リポジトリの Secrets に以下を追加:

ACTIONS_RUNNER_DEBUG = true
ACTIONS_STEP_DEBUG = true

詳細なログが出力されるようになります。

SSH での接続デバッグ

- name: SSH Debug
  if: failure()
  uses: mxschmitt/action-tmate@v3

ワークフローが失敗した時に、SSH で接続してデバッグできます(パブリックリポジトリのみ)。

ログをファイル出力

- run: npm test 2>&1 | tee test-output.log

- uses: actions/upload-artifact@v4
  if: always()
  with:
    name: test-output
    path: test-output.log

コスト管理

GitHub Actions の無料枠:

プラン月間無料分
Free2,000分
Team3,000分
Enterprise50,000分

コスト削減のコツ:

  1. 並列実行を減らす: マトリックスを必要最小限に
  2. 不要なジョブを削除: draft PR では CI を実行しない
  3. パスフィルタ: 関係ないファイル変更では実行しない
  4. キャッシュ活用: セットアップ時間を削減
  5. self-hosted runner: 大規模プロジェクトでは自前ホスティング
# draft PR では実行しない
if: github.event.pull_request.draft == false

セキュリティのベストプラクティス

1. サードパーティ Action の固定

# 悪い例: タグで指定
- uses: some-action@v1

# 良い例: コミットハッシュで固定
- uses: some-action@abc123def456

タグは後から変更可能です。セキュリティ重視ならコミットハッシュで固定しましょう。

2. 最小権限の原則

permissions:
  contents: read
  pull-requests: write

GITHUB_TOKEN に必要最低限の権限のみ付与します。

3. Pull Request からのシークレット保護

外部からの PR ではシークレットが利用できないよう、デフォルトで制限されています。pull_request_target の使用は慎重に。

まとめ

GitHub Actions は、CI/CD 入門として最も簡単かつ強力な選択肢です。

導入のステップ:

  1. 基本の CI: Lint、Test、Build の自動化から
  2. デプロイ自動化: main マージ時の自動デプロイ
  3. マトリックスビルド: 複数環境でのテスト
  4. 再利用可能ワークフロー: 共通処理の切り出し
  5. セキュリティ強化: シークレット管理、権限最小化

まずは既存プロジェクトの npm test を GitHub Actions で自動化するところから始めてみましょう。数分で効果を実感できます。

参考リンク

#GitHub Actions #CI/CD #DevOps #自動化
シェア: