GitHub Actions入門|CI/CDパイプラインを自動構築する基本と実践

kento_morota 17分で読めます

コードをプッシュするたびにテストを手動で実行し、本番環境に手作業でデプロイする――こうしたワークフローは、チームの生産性を大きく損ないます。GitHub Actionsを使えば、CI(継続的インテグレーション)とCD(継続的デリバリー)のパイプラインをGitHub上で完結して自動構築できます。

この記事では、GitHub Actionsの基本概念から実践的なCI/CDパイプラインの構築方法まで、コード例とともに解説します。

GitHub Actionsとは?基本概念を理解する

GitHub Actionsは、GitHubに統合されたCI/CDおよびワークフロー自動化プラットフォームです。リポジトリ内にYAMLファイルを配置するだけで、コードのプッシュ、プルリクエスト、スケジュールなど、さまざまなイベントをトリガーに処理を自動実行できます。

主要な構成要素

GitHub Actionsの構成要素を理解しましょう。

  • Workflow(ワークフロー):自動化プロセス全体の定義。YAMLファイルで記述
  • Event(イベント):ワークフローを起動するトリガー(push、pull_request等)
  • Job(ジョブ):ワークフロー内の実行単位。複数のジョブは並列実行可能
  • Step(ステップ):ジョブ内の個々の処理。コマンドの実行やActionの利用
  • Action(アクション):再利用可能な処理パーツ。Marketplaceで公開されているものも利用可能
  • Runner(ランナー):ワークフローを実行するサーバー環境

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

ワークフローファイルは、リポジトリの.github/workflows/ディレクトリに配置します。

my-project/
├── .github/
│   └── workflows/
│       ├── ci.yml        # テスト・リント
│       ├── cd.yml        # デプロイ
│       └── codeql.yml    # セキュリティスキャン
├── src/
├── package.json
└── README.md

最初のワークフローを作成する

まずは最もシンプルなワークフローから始めましょう。コードがプッシュされたらテストを実行する基本的なCIワークフローです。

Hello Worldワークフロー

# .github/workflows/hello.yml
name: Hello World

on:
  push:
    branches: [main]
  pull_request:
    branches: [main]

jobs:
  greeting:
    runs-on: ubuntu-latest
    steps:
      - name: Say Hello
        run: echo "Hello, GitHub Actions!"

      - name: Show environment info
        run: |
          echo "Event: ${{ github.event_name }}"
          echo "Branch: ${{ github.ref }}"
          echo "Repository: ${{ github.repository }}"
          echo "Runner OS: ${{ runner.os }}"

Node.jsプロジェクトのCIワークフロー

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

on:
  push:
    branches: [main, develop]
  pull_request:
    branches: [main]

jobs:
  test:
    runs-on: ubuntu-latest

    strategy:
      matrix:
        node-version: [18, 20, 22]

    steps:
      - name: Checkout code
        uses: actions/checkout@v4

      - name: Setup Node.js ${{ matrix.node-version }}
        uses: actions/setup-node@v4
        with:
          node-version: ${{ matrix.node-version }}
          cache: 'npm'

      - name: Install dependencies
        run: npm ci

      - name: Run linter
        run: npm run lint

      - name: Run type check
        run: npm run type-check

      - name: Run tests
        run: npm run test -- --coverage

      - name: Upload coverage
        if: matrix.node-version == 20
        uses: actions/upload-artifact@v4
        with:
          name: coverage-report
          path: coverage/

このワークフローのポイントを解説します。

  • strategy.matrix:Node.jsの複数バージョンで並列テストを実行
  • actions/setup-node@v4のcacheオプション:npm依存関係をキャッシュして高速化
  • if: matrix.node-version == 20:特定の条件でのみステップを実行
  • actions/upload-artifact@v4:テスト結果をアーティファクトとして保存

実践的なCI/CDパイプラインの構築

実際のプロジェクトでは、テスト・ビルド・デプロイを段階的に実行するパイプラインが必要です。

テスト → ビルド → デプロイのパイプライン

# .github/workflows/pipeline.yml
name: CI/CD Pipeline

on:
  push:
    branches: [main]
  pull_request:
    branches: [main]

jobs:
  # ジョブ1: テスト
  test:
    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 lint
      - run: npm run test

  # ジョブ2: ビルド(テスト成功後に実行)
  build:
    needs: test
    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
      - uses: actions/upload-artifact@v4
        with:
          name: build-output
          path: dist/

  # ジョブ3: デプロイ(mainブランチのpushのみ)
  deploy:
    needs: build
    if: github.ref == 'refs/heads/main' && github.event_name == 'push'
    runs-on: ubuntu-latest
    environment: production
    steps:
      - uses: actions/download-artifact@v4
        with:
          name: build-output
          path: dist/

      - name: Deploy to production
        env:
          DEPLOY_TOKEN: ${{ secrets.DEPLOY_TOKEN }}
        run: |
          echo "Deploying to production..."
          # デプロイスクリプトをここに記述

needsキーワードでジョブ間の依存関係を定義し、if条件で特定の条件でのみジョブを実行できます。

Dockerイメージのビルドとプッシュ

# .github/workflows/docker.yml
name: Docker Build & Push

on:
  push:
    branches: [main]
    tags: ['v*']

jobs:
  docker:
    runs-on: ubuntu-latest
    permissions:
      contents: read
      packages: write

    steps:
      - uses: actions/checkout@v4

      - name: Set up Docker Buildx
        uses: docker/setup-buildx-action@v3

      - name: Login to GitHub Container Registry
        uses: docker/login-action@v3
        with:
          registry: ghcr.io
          username: ${{ github.actor }}
          password: ${{ secrets.GITHUB_TOKEN }}

      - name: Extract metadata
        id: meta
        uses: docker/metadata-action@v5
        with:
          images: ghcr.io/${{ github.repository }}
          tags: |
            type=sha,prefix=
            type=ref,event=branch
            type=semver,pattern={{version}}

      - name: Build and push
        uses: docker/build-push-action@v6
        with:
          context: .
          push: true
          tags: ${{ steps.meta.outputs.tags }}
          labels: ${{ steps.meta.outputs.labels }}
          cache-from: type=gha
          cache-to: type=gha,mode=max

Secretsと環境変数の管理

APIキーやデプロイトークンなどの機密情報は、GitHub Secretsで安全に管理します。

Secretsの設定と使用

# GitHubリポジトリの Settings > Secrets and variables > Actions で設定

# ワークフローでの参照
jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - name: Deploy
        env:
          AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
          AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
          DATABASE_URL: ${{ secrets.DATABASE_URL }}
        run: |
          # 環境変数としてSecretsを利用
          npm run deploy

Environment(環境)の活用

# 環境ごとにSecretsを分ける
jobs:
  deploy-staging:
    runs-on: ubuntu-latest
    environment: staging  # staging環境のSecretsを使用
    steps:
      - name: Deploy to staging
        env:
          API_URL: ${{ vars.API_URL }}  # 環境変数(非機密)
          API_KEY: ${{ secrets.API_KEY }}  # 機密情報
        run: npm run deploy

  deploy-production:
    needs: deploy-staging
    runs-on: ubuntu-latest
    environment: production  # production環境のSecretsを使用
    steps:
      - name: Deploy to production
        env:
          API_URL: ${{ vars.API_URL }}
          API_KEY: ${{ secrets.API_KEY }}
        run: npm run deploy

Environment機能を使うと、本番環境へのデプロイに承認フローを設定することも可能です。

キャッシュ戦略による高速化

CI/CDパイプラインの実行時間を短縮するには、キャッシュの活用が不可欠です。

依存関係のキャッシュ

# setup-nodeの組み込みキャッシュ(推奨)
- uses: actions/setup-node@v4
  with:
    node-version: 20
    cache: 'npm'

# 手動でキャッシュを設定する場合
- name: Cache node_modules
  uses: actions/cache@v4
  with:
    path: node_modules
    key: ${{ runner.os }}-node-${{ hashFiles('package-lock.json') }}
    restore-keys: |
      ${{ runner.os }}-node-

ビルドキャッシュ

# Next.jsのビルドキャッシュ
- name: Cache Next.js build
  uses: actions/cache@v4
  with:
    path: |
      .next/cache
    key: ${{ runner.os }}-nextjs-${{ hashFiles('package-lock.json') }}-${{ hashFiles('**/*.ts', '**/*.tsx') }}
    restore-keys: |
      ${{ runner.os }}-nextjs-${{ hashFiles('package-lock.json') }}-
      ${{ runner.os }}-nextjs-

再利用可能なワークフロー

複数のリポジトリや複数のワークフローで同じ処理を繰り返す場合、再利用可能なワークフロー(Reusable Workflows)を活用しましょう。

再利用可能なワークフローの定義

# .github/workflows/reusable-test.yml
name: Reusable Test Workflow

on:
  workflow_call:
    inputs:
      node-version:
        required: false
        type: string
        default: '20'
      working-directory:
        required: false
        type: string
        default: '.'
    secrets:
      CODECOV_TOKEN:
        required: false

jobs:
  test:
    runs-on: ubuntu-latest
    defaults:
      run:
        working-directory: ${{ inputs.working-directory }}
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: ${{ inputs.node-version }}
          cache: 'npm'
          cache-dependency-path: ${{ inputs.working-directory }}/package-lock.json
      - run: npm ci
      - run: npm run test -- --coverage

再利用可能なワークフローの呼び出し

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

on:
  push:
    branches: [main]
  pull_request:

jobs:
  test-frontend:
    uses: ./.github/workflows/reusable-test.yml
    with:
      node-version: '20'
      working-directory: './frontend'

  test-backend:
    uses: ./.github/workflows/reusable-test.yml
    with:
      node-version: '20'
      working-directory: './backend'

コスト管理とベストプラクティス

GitHub Actionsは無料枠がありますが、使い方によっては想定以上のコストが発生することがあります。

無料枠と料金体系

  • パブリックリポジトリ:無制限に無料
  • プライベートリポジトリ(Freeプラン):月2,000分(Linux)
  • プライベートリポジトリ(Teamプラン):月3,000分(Linux)
  • macOSランナー:Linuxの10倍の消費レート
  • Windowsランナー:Linuxの2倍の消費レート

コスト削減のテクニック

# 1. 不要なトリガーを減らす
on:
  push:
    branches: [main]
    paths-ignore:
      - '**.md'        # ドキュメントの変更ではCIを実行しない
      - '.gitignore'
      - 'LICENSE'
  pull_request:
    paths:
      - 'src/**'       # ソースコードの変更時のみ実行
      - 'package*.json'

# 2. ジョブの並列実行を活用
# 3. concurrencyで重複実行をキャンセル
concurrency:
  group: ${{ github.workflow }}-${{ github.ref }}
  cancel-in-progress: true  # 同じブランチの古い実行をキャンセル

# 4. タイムアウトを設定
jobs:
  test:
    runs-on: ubuntu-latest
    timeout-minutes: 15  # 最大15分で打ち切り

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

# 1. Actionsのバージョンをピン留め(SHA指定推奨)
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683  # v4.2.2

# 2. 最小限のパーミッション
permissions:
  contents: read
  pull-requests: write

# 3. GITHUB_TOKENの権限を制限
# リポジトリ Settings > Actions > General >
# "Workflow permissions" を "Read repository contents" に設定

まとめ:GitHub Actionsを始めるためのステップ

GitHub Actionsは、GitHubを使っている開発チームにとって最も手軽に始められるCI/CDプラットフォームです。段階的に導入することで、無理なく自動化の恩恵を受けられます。

  • ステップ1:プッシュ時にリントとテストを自動実行するCIワークフローを作成
  • ステップ2:キャッシュを設定してビルド時間を短縮
  • ステップ3:ステージング環境への自動デプロイ(CD)を追加
  • ステップ4:本番環境へのデプロイに承認フローを設定
  • ステップ5:セキュリティスキャンや依存関係の自動更新を追加

最初から完璧なパイプラインを目指す必要はありません。まずはシンプルなCIワークフローから始め、プロジェクトの成長に合わせて段階的に機能を追加していきましょう。自動化に投資した時間は、長期的に何倍もの生産性向上として返ってきます。

#GitHub Actions#CI/CD#自動化
共有:
無料メルマガ

週1回、最新の技術記事をお届け

AI・クラウド・開発の最新記事を毎週月曜にメールでお届けします。登録は無料、いつでも解除できます。

プライバシーポリシーに基づき管理します

起業準備に役立つ情報、もっとありますよ。

まずは話だけ聞いてもらう