GitHub Actionsとは

GitHub Actionsは、GitHubで動作するCI/CDプラットフォームです。コードのプッシュやPR作成をトリガーに、自動でテストやデプロイを実行できます。

GitHub Actionsでできること

  • ✅ 自動テスト実行
  • ✅ コードの自動ビルド
  • ✅ 自動デプロイ
  • ✅ コードフォーマット・Lint
  • ✅ セキュリティスキャン
  • ✅ Issue・PR の自動管理

基本概念

主要な構成要素

  • Workflow: 自動化プロセス全体(YAMLファイル)
  • Job: Workflowを構成するタスクグループ
  • Step: Job内の個別の処理
  • Action: 再利用可能な処理単位
  • Runner: Workflowを実行する環境

ディレクトリ構造

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

最初のWorkflow

Hello World Workflow

# .github/workflows/hello.yml

name: Hello World

on:
  push:
    branches: [main]

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

実行

1. ファイルをコミット・プッシュ
git add .github/workflows/hello.yml
git commit -m "Add hello workflow"
git push origin main

2. GitHub > Actions タブで確認

トリガー(on)

Push トリガー

on:
  push:
    branches:
      - main
      - develop
    paths:
      - 'src/**'      # srcディレクトリ内のみ
      - '!src/test/**' # テストは除外

Pull Request トリガー

on:
  pull_request:
    types: [opened, synchronize, reopened]
    branches:
      - main

スケジュール実行

on:
  schedule:
    - cron: '0 0 * * *'  # 毎日午前0時(UTC)
    - cron: '0 */6 * * *' # 6時間ごと

手動実行

on:
  workflow_dispatch:
    inputs:
      environment:
        description: 'Deploy environment'
        required: true
        default: 'staging'
        type: choice
        options:
          - staging
          - production

複数トリガー

on:
  push:
    branches: [main]
  pull_request:
    branches: [main]
  schedule:
    - cron: '0 0 * * 0'  # 毎週日曜日

実用的なCI Workflow

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: [16, 18, 20]
    
    steps:
      - name: Checkout code
        uses: actions/checkout@v3
      
      - name: Setup Node.js ${{ matrix.node-version }}
        uses: actions/setup-node@v3
        with:
          node-version: ${{ matrix.node-version }}
          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
      
      - name: Upload coverage
        uses: codecov/codecov-action@v3
        with:
          token: ${{ secrets.CODECOV_TOKEN }}

Python プロジェクトのCI

name: Python CI

on: [push, pull_request]

jobs:
  test:
    runs-on: ubuntu-latest
    
    strategy:
      matrix:
        python-version: ['3.9', '3.10', '3.11']
    
    steps:
      - uses: actions/checkout@v3
      
      - name: Set up Python
        uses: actions/setup-python@v4
        with:
          python-version: ${{ matrix.python-version }}
      
      - name: Install dependencies
        run: |
          python -m pip install --upgrade pip
          pip install -r requirements.txt
      
      - name: Lint with flake8
        run: |
          pip install flake8
          flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics
      
      - name: Test with pytest
        run: |
          pip install pytest pytest-cov
          pytest --cov=./ --cov-report=xml
      
      - name: Upload coverage
        uses: codecov/codecov-action@v3

Actionsの使用

公式Actions

# コードのチェックアウト
- uses: actions/checkout@v3

# Node.js セットアップ
- uses: actions/setup-node@v3
  with:
    node-version: '18'

# Python セットアップ
- uses: actions/setup-python@v4
  with:
    python-version: '3.11'

# キャッシュ
- uses: actions/cache@v3
  with:
    path: ~/.npm
    key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}

サードパーティActions

# Docker ビルド・プッシュ
- uses: docker/build-push-action@v4
  with:
    push: true
    tags: user/app:latest

# Slack 通知
- uses: 8398a7/action-slack@v3
  with:
    status: ${{ job.status }}
    webhook_url: ${{ secrets.SLACK_WEBHOOK }}

Secrets の管理

Secretsの設定

Settings > Secrets and variables > Actions > New repository secret

Name: API_KEY
Value: sk_test_xxxxxxxxxxxx

Workflowでの使用

steps:
  - name: Deploy
    env:
      API_KEY: ${{ secrets.API_KEY }}
      DATABASE_URL: ${{ secrets.DATABASE_URL }}
    run: |
      echo "Deploying with API_KEY"
      deploy.sh

環境別Secrets

Settings > Environments > New environment

environment名: production
Secrets: PROD_API_KEY, PROD_DB_URL

# Workflowで使用
jobs:
  deploy:
    runs-on: ubuntu-latest
    environment: production
    steps:
      - run: echo ${{ secrets.PROD_API_KEY }}

並列実行とマトリックス

マトリックス戦略

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

並列Jobsと依存関係

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - run: npm run build
  
  test:
    needs: build  # buildの完了後に実行
    runs-on: ubuntu-latest
    steps:
      - run: npm test
  
  deploy:
    needs: [build, test]  # 両方完了後に実行
    runs-on: ubuntu-latest
    steps:
      - run: npm run deploy

成果物(Artifacts)

アップロード

- name: Build app
  run: npm run build

- name: Upload build
  uses: actions/upload-artifact@v3
  with:
    name: build-files
    path: dist/
    retention-days: 7

ダウンロード

- name: Download build
  uses: actions/download-artifact@v3
  with:
    name: build-files
    path: dist/

条件付き実行

if 条件

jobs:
  deploy:
    runs-on: ubuntu-latest
    if: github.ref == 'refs/heads/main'
    steps:
      - run: echo "Deploying to production"
  
  notify:
    runs-on: ubuntu-latest
    if: failure()
    steps:
      - run: echo "Tests failed!"

Step レベルの条件

steps:
  - name: Deploy to staging
    if: github.event_name == 'pull_request'
    run: deploy-staging.sh
  
  - name: Deploy to production
    if: github.ref == 'refs/heads/main'
    run: deploy-production.sh

Docker を使ったWorkflow

Dockerコンテナでの実行

jobs:
  test:
    runs-on: ubuntu-latest
    container:
      image: node:18
    steps:
      - uses: actions/checkout@v3
      - run: npm install
      - run: npm test

サービスコンテナ

jobs:
  test:
    runs-on: ubuntu-latest
    
    services:
      postgres:
        image: postgres:15
        env:
          POSTGRES_PASSWORD: postgres
        options: >-
          --health-cmd pg_isready
          --health-interval 10s
          --health-timeout 5s
          --health-retries 5
    
    steps:
      - uses: actions/checkout@v3
      - name: Run tests
        env:
          DATABASE_URL: postgres://postgres:postgres@postgres:5432/testdb
        run: npm test

自動デプロイ

Vercel へのデプロイ

name: Deploy to Vercel

on:
  push:
    branches: [main]

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      
      - name: Deploy to Vercel
        uses: amondnet/vercel-action@v20
        with:
          vercel-token: ${{ secrets.VERCEL_TOKEN }}
          vercel-org-id: ${{ secrets.ORG_ID }}
          vercel-project-id: ${{ secrets.PROJECT_ID }}
          vercel-args: '--prod'

AWS へのデプロイ

name: Deploy to AWS

on:
  push:
    branches: [main]

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      
      - name: Configure AWS credentials
        uses: aws-actions/configure-aws-credentials@v2
        with:
          aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
          aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
          aws-region: ap-northeast-1
      
      - name: Deploy to S3
        run: |
          npm run build
          aws s3 sync dist/ s3://my-bucket --delete

再利用可能なWorkflow

呼び出し可能なWorkflow

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

on:
  workflow_call:
    inputs:
      node-version:
        required: true
        type: string

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

呼び出し側

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

on: [push]

jobs:
  call-test:
    uses: ./.github/workflows/reusable-test.yml
    with:
      node-version: '18'

トラブルシューティング

デバッグログ

Settings > Secrets and variables > Actions > Variables

Name: ACTIONS_STEP_DEBUG
Value: true

# または Workflow内で
env:
  ACTIONS_RUNNER_DEBUG: true

ローカルでのテスト

# act をインストール
brew install act

# Workflowをローカル実行
act push
act pull_request

ベストプラクティス

1. キャッシュの活用

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

2. タイムアウトの設定

jobs:
  test:
    runs-on: ubuntu-latest
    timeout-minutes: 10  # 10分でタイムアウト

3. 並列実行で高速化

strategy:
  matrix:
    shard: [1, 2, 3, 4]
steps:
  - run: npm test -- --shard=${{ matrix.shard }}/4

まとめ

GitHub Actionsで開発プロセスを自動化し、品質と生産性を向上できます。

重要ポイント

  • YAMLでWorkflowを定義
  • トリガーで自動実行
  • 公式・サードパーティActionsを活用
  • SecretsでCIトークン管理
  • マトリックスで並列テスト

次のステップ

  • カスタムActionの作成
  • セルフホストRunnerの構築
  • 高度なデプロイ戦略