mcpField
G
github-actions-templates

github-actions-templates

github.com/ckorhonenクラウド・DevOps2244 回インストール5 週間前に更新
リポジトリ

github-actions-templates について

github-actions-templates は、アプリケーションのテスト、ビルド、デプロイを行うチーム向けの GitHub Actions ワークフローパターンガイドです。一般的なテンプレートに加え、シークレットや権限、マトリックスビルド、キャッシュ、失敗への対処も扱います。

主な機能

  1. 01テストとデプロイのワークフローパターン
  2. 02Docker のビルドとプッシュ用テンプレート
  3. 03Kubernetes デプロイとマトリックスビルド
  4. 04シークレットと権限の指針
  5. 05キャッシュとワークフローのトラブルシューティング

活用シーン

  1. 01プロジェクトの CI とデプロイ設定
  2. 02Docker イメージの自動ビルドとプッシュ
  3. 03Kubernetes へのアプリケーションデプロイ
  4. 04ワークフローの権限やキャッシュ問題の調査

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/ckorhonen/claude-skills --skill github-actions-templates

インストール後、Claude Code で/github-actions-templatesを入力して読み込まれたか確認します。

詳細

GitHub Actions テンプレート

アプリケーションのテスト、ビルド、デプロイに対応した、本番環境ですぐに使える GitHub Actions ワークフローパターンです。

目的

さまざまな技術スタックで継続的インテグレーションとデプロイを行うための、効率的で安全な GitHub Actions ワークフローを作成します。

使用する場面

  • テストとデプロイを自動化する
  • Docker イメージをビルドしてレジストリにプッシュする
  • Kubernetes クラスターにデプロイする
  • セキュリティスキャンを実行する
  • 複数の環境向けにマトリックスビルドを実装する

よく使われるワークフローパターン

パターン 1:テストワークフロー
name: Test

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

jobs:
  test:
    runs-on: ubuntu-latest

    strategy:
      matrix:
        node-version: [18.x, 20.x]

    steps:
      - uses: actions/checkout@v4

      - name: Use 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 tests
        run: npm test

      - name: Upload coverage
        uses: codecov/codecov-action@v3
        with:
          files: ./coverage/lcov.info
パターン 2:Docker イメージのビルドとプッシュ
name: Build and Push

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

env:
  REGISTRY: ghcr.io
  IMAGE_NAME: ${{ github.repository }}

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

    steps:
      - uses: actions/checkout@v4

      - name: Log in to Container Registry
        uses: docker/login-action@v3
        with:
          registry: ${{ env.REGISTRY }}
          username: ${{ github.actor }}
          password: ${{ secrets.GITHUB_TOKEN }}

      - name: Extract metadata
        id: meta
        uses: docker/metadata-action@v5
        with:
          images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
          tags: |
            type=ref,event=branch
            type=ref,event=pr
            type=semver,pattern={{version}}
            type=semver,pattern={{major}}.{{minor}}

      - name: Build and push
        uses: docker/build-push-action@v5
        with:
          context: .
          push: true
          tags: ${{ steps.meta.outputs.tags }}
          labels: ${{ steps.meta.outputs.labels }}
          cache-from: type=gha
          cache-to: type=gha,mode=max
パターン 3:Kubernetes へのデプロイ
name: Deploy to Kubernetes

on:
  push:
    branches: [main]

jobs:
  deploy:
    runs-on: ubuntu-latest

    steps:
      - uses: actions/checkout@v4

      - name: Configure AWS credentials
        uses: aws-actions/configure-aws-credentials@v4
        with:
          aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
          aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
          aws-region: us-west-2

      - name: Update kubeconfig
        run: |
          aws eks update-kubeconfig --name production-cluster --region us-west-2

      - name: Deploy to Kubernetes
        run: |
          kubectl apply -f k8s/
          kubectl rollout status deployment/my-app -n production
          kubectl get services -n production

      - name: Verify deployment
        run: |
          kubectl get pods -n production
          kubectl describe deployment my-app -n production
パターン 4:マトリックスビルド
name: Matrix Build

on: [push, pull_request]

jobs:
  build:
    runs-on: ${{ matrix.os }}

    strategy:
      matrix:
        os: [ubuntu-latest, macos-latest, windows-latest]
        python-version: ["3.9", "3.10", "3.11", "3.12"]

    steps:
      - uses: actions/checkout@v4

      - name: Set up Python
        uses: actions/setup-python@v5
        with:
          python-version: ${{ matrix.python-version }}

      - name: Install dependencies
        run: |
          python -m pip install --upgrade pip
          pip install -r requirements.txt

      - name: Run tests
        run: pytest

ワークフローのベストプラクティス

  1. 特定のアクションバージョンを使用する(@latest ではなく @v4)
  2. 依存関係をキャッシュすることでビルドを高速化する
  3. 機密データにはシークレットを使用する
  4. PR でステータスチェックを実装する
  5. 複数バージョンのテストにはマトリックスビルドを使用する
  6. 適切な権限を設定する
  7. 共通パターンには再利用可能なワークフローを使用する
  8. 本番環境には承認ゲートを実装する
  9. 失敗時の通知ステップを追加する
  10. 機密性の高いワークロードにはセルフホストランナーを使用する

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

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

on:
  workflow_call:
    inputs:
      node-version:
        required: true
        type: string
    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
      - run: npm test

再利用可能なワークフローの使用:

jobs:
  call-test:
    uses: ./.github/workflows/reusable-test.yml
    with:
      node-version: "20.x"
    secrets:
      NPM_TOKEN: ${{ secrets.NPM_TOKEN }}

セキュリティスキャン

name: Security Scan

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

jobs:
  security:
    runs-on: ubuntu-latest

    steps:
      - uses: actions/checkout@v4

      - name: Run Trivy vulnerability scanner
        uses: aquasecurity/trivy-action@master
        with:
          scan-type: "fs"
          scan-ref: "."
          format: "sarif"
          output: "trivy-results.sarif"

      - name: Upload Trivy results to GitHub Security
        uses: github/codeql-action/upload-sarif@v2
        with:
          sarif_file: "trivy-results.sarif"

      - name: Run Snyk Security Scan
        uses: snyk/actions/node@master
        env:
          SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }}

承認を伴うデプロイ

name: Deploy to Production

on:
  push:
    tags: ["v*"]

jobs:
  deploy:
    runs-on: ubuntu-latest
    environment:
      name: production
      url: https://app.example.com

    steps:
      - uses: actions/checkout@v4

      - name: Deploy application
        run: |
          echo "Deploying to production..."
          # Deployment commands here

      - name: Notify Slack
        if: success()
        uses: slackapi/slack-github-action@v1
        with:
          webhook-url: ${{ secrets.SLACK_WEBHOOK }}
          payload: |
            {
              "text": "Deployment to production completed successfully!"
            }

よくある落とし穴

このセクションでは、GitHub Actions ワークフローが予期せず、または何も通知せずに失敗する原因となる、実際に発生した失敗パターンとアンチパターンを説明します。

1. ワークフローの構文エラー

問題: YAML のインデント、引用符、式の構文は、何も通知されない失敗の最も一般的な原因です。

よくあるエラー:

インデントの誤り
# ❌ WRONG - Missing indentation
on: push
jobs:
test:
  runs-on: ubuntu-latest
  steps:
  - run: npm test

# ✅ CORRECT
on: push
jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - run: npm test

エラーメッセージ: "unexpected mapping value" or "mapping values are not allowed here" 修正方法: YAML ではインデントに厳密に 2 つのスペースを使用します。ワークフローで yamllint のような YAML リンターを使用してください。

式の構文に関する混乱
# ❌ WRONG - Using $ without github context
- run: echo ${{ matrix.node-version }}

# ❌ WRONG - Missing quotes on complex expressions
env:
  MY_VAR: ${{ github.event.pull_request.title }}

# ✅ CORRECT
- run: echo "${{ matrix.node-version }}"

# ✅ CORRECT with quotes for strings
env:
  MY_VAR: "${{ github.event.pull_request.title }}"

エラーメッセージ: "Unable to process template language" or "unrecognized named value" 修正方法: シェルコマンド内や文字列として使う式は、必ず引用符で囲んでください。安全に展開するには、GitHub Actions で適切な引用符が必要です。

パイプ構文を使わない複数行文字列
# ❌ WRONG - Multiline without | or >
- run: echo "Line 1
Line 2"

# ✅ CORRECT using pipe (preserves newlines)
- run: |
  npm install
  npm run build
  npm test

# ✅ CORRECT using >  (folds newlines)
- name: Summary
  run: >
    This is a long
    command that spans
    multiple lines

エラーメッセージ: "expected '<block end>', but found '\\n'" 修正方法: リテラルブロック(改行を保持)には | を、折りたたみブロック(改行をスペースに置き換え)には > を使用してください。


2. シークレットの取り扱いミス

問題: シークレットは、最も頻繁に誤って扱われる要素です。GitHub Actions では、シークレットを使用できる状況について特定のルールがあります。

重大なミス:

ワークフローファイルにシークレットをハードコードする
# ❌ ABSOLUTELY WRONG - Secret is now in git history
- run: |
  aws s3 sync . s3://my-bucket \
    --aws-access-key-id AKIA1234567890ABCDEF \
    --aws-secret-access-key wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY

エラーメッセージ: 最初はありませんが、これは重大なセキュリティ上の脆弱性です。 修正方法: 必ず ${{ secrets.SECRET_NAME }} を使用し、GitHub リポジトリの設定でシークレットを定義してください。

シークレットを使用できないコンテキストでアクセスする
# ❌ WRONG - Secrets not available in if: conditionals
if: ${{ secrets.DEPLOY_KEY != '' }}

# ✅ CORRECT - Secrets work in env: blocks at job and step level
jobs:
  deploy:
    runs-on: ubuntu-latest
    env:
      MESSAGE: ${{ secrets.MY_SECRET }} # ← Works at job level
    steps:
      - name: Deploy
        env:
          DEPLOY_KEY: ${{ secrets.DEPLOY_KEY }} # ← Works at step level
        run: |
          # Now DEPLOY_KEY is available here
          ./deploy.sh

エラーメッセージ: シークレットは ***(マスク済み)と表示されますが、if: 条件内で使用すると、実際には空または未定義です。 修正方法: ジョブレベルまたはステップレベルの env: ブロックでシークレットを使用してください。if: 条件ではシークレットを使用しないでください。そこでシークレットは使用できません。

出力を機密情報として扱う指定を忘れる
# ❌ WRONG - Logs leak credentials
- name: Get credentials
  run: |
    TOKEN=$(curl -s https://api.example.com/token)
    echo "TOKEN=$TOKEN" >> $GITHUB_OUTPUT
    echo "Got token: $TOKEN"  # ← Logged!

# ✅ CORRECT - Mark as secret in action output
- name: Get credentials
  id: creds
  run: |
    TOKEN=$(curl -s https://api.example.com/token)
    echo "token=$TOKEN" >> $GITHUB_OUTPUT  # ← Set output
  # Then reference as:
  # ${{ steps.creds.outputs.token }}

エラーメッセージ: ワークフローログに認証情報が平文で表示されます。 修正方法: 機密値には $GITHUB_OUTPUT を使用し、値を直接 echo しないでください。

再利用可能なワークフローでシークレットのコンテキストを誤る
# ❌ WRONG - Parent secrets aren't automatically passed
jobs:
  call-workflow:
    uses: ./.github/workflows/deploy.yml
    # secrets: inherit not specified!

# ✅ CORRECT
jobs:
  call-workflow:
    uses: ./.github/workflows/deploy.yml
    secrets: inherit  # ← Pass all parent secrets

エラーメッセージ: ワークフローは実行されますが、呼び出されたワークフローではシークレットが未定義です。 修正方法: シークレットが必要な再利用可能なワークフローを呼び出すときは、secrets: inherit を指定してください。


3. 権限の問題

問題: デフォルトで GITHUB_TOKEN のスコープは制限されており、権限の設定を誤りやすいです。

よくある問題:

トークンの権限不足
# ❌ WRONG - Trying to write packages with default permissions
- name: Push to Docker registry
  run: |
    docker push ghcr.io/${{ github.repository }}:latest
    # Fails with "permission denied" because GITHUB_TOKEN lacks 'packages: write'

# ✅ CORRECT - Explicitly grant permissions
jobs:
  build:
    runs-on: ubuntu-latest
    permissions:
      contents: read        # Read repo code
      packages: write       # Write Docker images
      id-token: write       # For OIDC token exchange
    steps:
    - uses: actions/checkout@v4
    - name: Push to Docker registry
      run: docker push ghcr.io/${{ github.repository }}:latest

エラーメッセージ: API から "authentication failed, permission denied" または "Insufficient permissions" が返されます 修正方法: 必要なスコープ(contents、packages、id-token、pull-requests、issues、deployments など)を指定し、必ずジョブレベルで permissions: を明示的に宣言してください。

GITHUB_TOKEN では実行できない操作に使用しようとする
# ❌ WRONG - GITHUB_TOKEN can't trigger other workflows
- name: Trigger deployment
  run: |
    curl -X POST https://api.github.com/repos/${{ github.repository }}/dispatches \
      -H "Authorization: token ${{ secrets.GITHUB_TOKEN }}" \
      -d '{"event_type":"deploy"}'
    # Fails silently - GITHUB_TOKEN lacks workflow permissions

# ✅ CORRECT - Use a PAT (Personal Access Token) or GitHub App token
- name: Trigger deployment
  run: |
    curl -X POST https://api.github.com/repos/${{ github.repository }}/dispatches \
      -H "Authorization: token ${{ secrets.WORKFLOW_PAT }}" \
      -d '{"event_type":"deploy"}'

エラーメッセージ: "Resource not accessible by integration"(HTTP 403) 修正方法: GITHUB_TOKEN ではワークフロー(repository_dispatch)をトリガーできません。代わりに、シークレットに保存した PAT を使用してください。

リポジトリ間のアクセス失敗
# ❌ WRONG - GITHUB_TOKEN only has access to current repo
- name: Clone another repo
  run: |
    git clone https://github.com/other-org/private-repo.git
    # Fails - GITHUB_TOKEN has no access

# ✅ CORRECT - Use a PAT with repo access
- name: Clone another repo
  run: |
    git clone https://x-access-token:${{ secrets.CROSS_REPO_PAT }}@github.com/other-org/private-repo.git

エラーメッセージ: "fatal: could not read Username for 'https://github.com': terminal prompts disabled" 修正方法: リポジトリ間のアクセスには、repo または read:repo_hook スコープを持つ Personal Access Token(PAT)を使用してください。


4. マトリックス戦略の失敗

問題: マトリックスビルドは強力ですが、組み合わせが誤っていたり、exclude/include の使い方を誤ったりすると、何も通知されずに失敗します。

よくある落とし穴:

ステップでの未定義のマトリックスコンテキスト
# ❌ WRONG - Using matrix variables that don't exist
jobs:
  build:
    runs-on: ${{ matrix.os }}
    strategy:
      matrix:
        os: [ubuntu-latest, macos-latest]
        # No 'version' defined here
    steps:
    - run: echo "Version is ${{ matrix.version }}"  # ← Empty!

# ✅ CORRECT - Define all matrix variables used
jobs:
  build:
    runs-on: ${{ matrix.os }}
    strategy:
      matrix:
        os: [ubuntu-latest, macos-latest]
        version: ['1.0', '2.0']
    steps:
    - run: echo "Building for ${{ matrix.os }} v${{ matrix.version }}"

エラーメッセージ: ログでマトリックス変数が空、または未定義として表示されます。 修正方法: ステップで参照するすべての変数を strategy.matrix で定義する必要があります。

壊れた exclude/include 構文
# ❌ WRONG - Invalid exclude syntax
jobs:
  build:
    runs-on: ${{ matrix.os }}
    strategy:
      matrix:
        os: [ubuntu-latest, macos-latest, windows-latest]
        node-version: ['18', '20']
      exclude:
        - os: windows-latest, node-version: '18'  # ← Comma not allowed here

# ✅ CORRECT - Proper exclude syntax
jobs:
  build:
    runs-on: ${{ matrix.os }}
    strategy:
      matrix:
        os: [ubuntu-latest, macos-latest, windows-latest]
        node-version: ['18', '20']
      exclude:
        - os: windows-latest
          node-version: '18'

# ✅ Using include for specific combinations
jobs:
  build:
    runs-on: ${{ matrix.os }}
    strategy:
      matrix:
        os: [ubuntu-latest, macos-latest]
        include:
          - os: windows-latest
            node-version: '20'  # ← Only windows + node 20

エラーメッセージ: 検証フェーズ中にワークフローの解析に失敗します。 修正方法: exclude と include では YAML のリスト構文を使用し、プロパティごとに個別の行を指定します。

直積による組み合わせの爆発
# ❌ WRONG - Creates 4 × 3 × 2 × 5 = 120 jobs unexpectedly
jobs:
  build:
    runs-on: ${{ matrix.os }}
    strategy:
      matrix:
        os: [ubuntu-latest, macos-latest, windows-latest, linux-arm64]
        node-version: ['16', '18', '20']
        npm-version: ['8', '9']
        python-version: ['3.8', '3.9', '3.10', '3.11', '3.12']
        # This is excessive and wastes CI minutes

# ✅ CORRECT - Use include for specific combinations
jobs:
  build:
    runs-on: ${{ matrix.os }}
    strategy:
      matrix:
        include:
          - os: ubuntu-latest
            node-version: '20'
            npm-version: '9'
          - os: macos-latest
            node-version: '20'
            npm-version: '9'
          - os: windows-latest
            node-version: '18'
            npm-version: '8'

エラーメッセージ: 何もありませんが、CI の費用が突然 4 倍になります。 修正方法: マトリックスで直積を作成するのではなく、include を使用して特定の組み合わせを定義します。


5. キャッシュに関するミス

問題: GitHub Actions のキャッシュは保守的です。古いキャッシュが何カ月も残り、原因不明のビルド失敗を引き起こすことがあります。

重大な問題:

古いキャッシュによる失敗の繰り返し
# ❌ WRONG - Cache key doesn't change, stale deps stay cached
- uses: actions/cache@v3
  with:
    path: node_modules
    key: deps-${{ runner.os }} # ← Never changes!
    restore-keys: |
      deps-${{ runner.os }}

# ✅ CORRECT - Include lockfile hash in cache key
- uses: actions/cache@v3
  with:
    path: node_modules
    key: deps-${{ runner.os }}-${{ hashFiles('**/package-lock.json') }}
    restore-keys: |
      deps-${{ runner.os }}-

エラーメッセージ: ローカルではビルドが成功するのに、CI では解読しにくいモジュールエラーで失敗します。 修正方法: キャッシュキーには依存関係ロックファイルのハッシュを必ず含めてください。npm では ${{ hashFiles('**/package-lock.json') }}、pip では ${{ hashFiles('**/requirements.txt') }} を使用します。

言語ランタイムのキャッシュパスの誤り
# ❌ WRONG - Caching wrong path, cache misses happen
- name: Setup Node
  uses: actions/setup-node@v4
  with:
    node-version: "20.x"
- uses: actions/cache@v3
  with:
    path: /tmp/node_modules # ← Wrong path!
    key: deps-${{ hashFiles('package-lock.json') }}

# ✅ CORRECT - Let action handle caching, or use right path
- name: Setup Node
  uses: actions/setup-node@v4
  with:
    node-version: "20.x"
    cache: "npm" # ← Let the action handle caching

# OR if manual caching:
- uses: actions/cache@v3
  with:
    path: ~/.npm # ← Correct npm cache location
    key: npm-${{ hashFiles('package-lock.json') }}

エラーメッセージ: ワークフローの実行が遅く、依存関係を繰り返しダウンロードします。 修正方法: setup-node@v4 の組み込みの cache: パラメーターを使用するか、言語ランタイムの公式キャッシュディレクトリ(例:~/.npm、~/.pip-cache)をキャッシュします。

キャッシュ無効化の競合状態
# ❌ WRONG - Multiple branches writing to same cache
branches:
  - main
  - develop
  - '*'

jobs:
  test:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/cache@v3
      with:
        path: dist
        key: build-${{ hashFiles('package.json') }}
        # develop branch builds with old deps, overwrites cache
        # main branch then gets develop's stale build artifacts

# ✅ CORRECT - Include branch in cache key or read-only on non-main
- uses: actions/cache@v3
  with:
    path: dist
    key: build-${{ github.ref }}-${{ hashFiles('package.json') }}
    restore-keys: |
      build-refs/heads/main-
      build-refs/heads/develop-

エラーメッセージ: マージ後に原因不明のテスト失敗が発生します(別のブランチからキャッシュが汚染されています)。 修正方法: ブランチごとにキャッシュを分離するには、キャッシュキーに ${{ github.ref }} を含めるか、main 以外のブランチでは読み取り専用モードを使用します。

Docker レイヤーキャッシュが保持されない
# ❌ WRONG - Rebuilds every layer despite cache-from
- uses: docker/build-push-action@v5
  with:
    context: .
    push: true
    tags: myimage:latest
    # cache-from: type=gha missing!

# ✅ CORRECT - Use GitHub Actions cache backend
- uses: docker/build-push-action@v5
  with:
    context: .
    push: true
    tags: myimage:latest
    cache-from: type=gha
    cache-to: type=gha,mode=max

エラーメッセージ: ローカルではキャッシュが正常に機能しているのに、Docker ビルドが非常に遅くなります。 修正方法: 実行をまたいでレイヤーをキャッシュするには、docker/build-push-action に cache-from: type=gha と cache-to: type=gha,mode=max を必ず含めてください。


ワークフローのデバッグ

ワークフローが失敗したときに役立つテクニック:

  1. デバッグログを有効にする: リポジトリ設定で ACTIONS_STEP_DEBUG=true シークレットを設定し、詳細なログを確認します
  2. 権限を確認する: API 呼び出しが失敗した場合は、ジョブの permissions: ブロックを確認します
  3. YAML を検証する: プッシュする前に、ワークフローファイルに対してローカルで yamllint を実行します
  4. マトリックスをローカルでテストする: ローカルのテストスクリプトでマトリックスの組み合わせをシミュレートします
  5. キャッシュを調べる: GitHub UI の「Actions」→「Caches」でキャッシュエントリーを確認します
  6. シークレットを確認する: すべての ${{ secrets.NAME }} がリポジトリ設定で定義されていることを確認します

関連スキル

  • gitlab-ci-patterns - GitLab CI ワークフローについて
  • deployment-pipeline-design - パイプラインアーキテクチャについて
  • secrets-management - シークレットの取り扱いについて

コメント