GitHub Actions 完全ガイド【2026年最新】|workflow 構文・Matrix・Secrets・OIDC・Environments・Concurrency・Reusable Workflows・Artifacts v4・Custom Runner Images までを実戦パターンで解説

GitHub Actions 完全ガイド【2026年最新】|workflow 構文・Matrix・Secrets・OIDC・Environments・Concurrency・Reusable Workflows・Artifacts v4・Custom Runner Images までを実戦パターンで解説 Git

GitHub Actions は「リポジトリのイベント(push / PR / release / schedule など)をトリガーに YAML で宣言したジョブを実行する」CI/CD プラットフォームです。テスト・ビルド・デプロイだけでなく、ドキュメント生成・Issue トリアージ・週次レポート・外部 API 連携まで、GitHub 上で完結するあらゆる自動化の基盤になっています。

2025〜2026 年に入って機能がさらに成熟しました。Artifacts v4(非圧縮アップロード対応)、Reusable Workflows(最大 10 段ネスト・50 ワークフロー呼び出しに拡張)、OIDC の custom properties 対応(2026-04 GA)、Custom Runner Images(2026-04 GA)、Runner Scale Set Client(K8s / VM / ベアメタルのマルチ label スケーリング)、M2 powered macOS runner など、セキュリティ・スケーラビリティ・柔軟性の全軸でアップデートが続いています。

この記事では 2026 年 4 月時点の仕様を前提に、workflow 構文、on トリガー、jobs / steps、Matrix Strategy、Secrets / Variables、OIDC 認証、Environments、Concurrency、Permissions、Cache、Artifacts v4、Reusable Workflows、Composite Actions、Custom Runner Images、セキュリティ強化、Vercel / Cloudflare / Docker / AWS への典型的デプロイパターン、落とし穴まで実戦で使える形で解説します。

スポンサーリンク

2026 年 4 月時点のアップデート総覧

機能 状態 要点
Artifacts v4 GA 非圧縮アップロード対応、ダウンロード高速化、upload 当たり 1 つの artifact(同名統合廃止)
Reusable Workflows 制限緩和 GA 最大 10 段ネスト(旧 4 段)・1 実行で 50 呼び出し(旧 20)
OIDC: Repository Custom Properties 2026-04 GA OIDC claims にカスタムプロパティを含め、ABAC による細粒度 IAM 制御
Custom Runner Images 2026-04 GA 依存を焼き込んだ再利用 VM イメージ。snapshot キーワードでバージョン固定
Runner Scale Set Client 2026-02 Preview K8s / VM / ベアメタルで自前ランナーをマルチ label で自動スケール
macOS M2 Larger Runner GA macos-latest-xlarge 系で Apple Silicon ビルドが高速化
Service Containers の entrypoint/command 2026-04 Docker Compose と同等の上書き構文
Azure VNet Failover Preview Private Networking で Secondary サブネットの手動フェイルオーバー
2026 年の主戦場:OIDC × Reusable Workflows × Custom Runner Images」の 3 点セットで、長期保管シークレット不要ワークフローロジックの DRY 化ビルド時間の短縮を同時に実現するのが標準構成になりました。

workflow の基本構造

ワークフローは .github/workflows/*.yml に置きます。最小構成は「トリガー(on)」「ジョブ(jobs)」「ステップ(steps)」の 3 階層です。

.github/workflows/ci.yml ── 最小構成
name: CI

on:
  push:
    branches: [main]
  pull_request:

jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v5
      - uses: actions/setup-node@v5
        with:
          node-version: 22
          cache: npm
      - run: npm ci
      - run: npm test
ファイル名と name: ファイル名(例: ci.yml)が内部識別子、name: が UI で表示される名前。name を省略するとファイルパスがそのまま表示されて読みにくいので、明示推奨です。

on ── イベントトリガー

主要なトリガーパターン
on:
  # コードの push(ブランチ・パス・タグフィルタ)
  push:
    branches: [main, "release/**"]
    branches-ignore: [gh-pages]
    paths: ["src/**", "package.json"]
    paths-ignore: ["**.md"]
    tags: ["v*.*.*"]

  # Pull Request(どのアクションで走るか細かく指定)
  pull_request:
    types: [opened, synchronize, reopened, ready_for_review]
    branches: [main]

  # 手動実行(入力フォーム付き)
  workflow_dispatch:
    inputs:
      environment:
        description: "デプロイ先"
        required: true
        default: staging
        type: choice
        options: [staging, production]
      dry_run:
        type: boolean
        default: true

  # スケジュール(cron)
  schedule:
    - cron: "0 3 * * *"     # 毎日 03:00 UTC

  # 他ワークフローの完了をトリガーに
  workflow_run:
    workflows: [CI]
    types: [completed]
    branches: [main]

  # Issue / PR コメント・ラベル変更など
  issues:
    types: [opened, labeled]
  issue_comment:
    types: [created]

  # 外部トリガー(REST API / GitHub Apps)
  repository_dispatch:
    types: [deploy-prod]
fork PR の secrets 制限: fork からの PR では secrets が空文字になります(プルリクエスト攻撃対策)。外部 PR で実行する必要がある場合は pull_request_target を使いますが、このトリガーは base ブランチの workflow が動く点で強力すぎるため、コード実行の前に必ず permissions を絞り、untrusted な PR チェックアウトでは persist-credentials: false を設定してください。

jobs と steps ── 並列・順序制御

jobs の依存関係・条件・環境変数
jobs:
  lint:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v5
      - run: npm ci
      - run: npm run lint

  test:
    runs-on: ubuntu-latest
    needs: lint                             # lint が成功したらだけ走る
    timeout-minutes: 15                     # 15 分で強制終了
    env:
      CI: true
      NODE_ENV: test
    steps:
      - uses: actions/checkout@v5
      - run: npm ci
      - run: npm test -- --coverage
      - name: カバレッジ閾値チェック
        if: always()                        # test 失敗でも実行
        run: |
          node scripts/check-coverage.mjs

  build:
    runs-on: ubuntu-latest
    needs: [lint, test]                     # 両方成功後に並列実行可能
    if: github.ref == 'refs/heads/main'     # main だけ
    steps:
      - uses: actions/checkout@v5
      - run: npm ci
      - run: npm run build

条件式(if)とステップ成功状態

step 単位の条件制御
steps:
  - name: テスト
    id: test-step
    run: npm test
    continue-on-error: true       # 失敗しても次に進む

  - name: 失敗時のみ通知
    if: failure() && steps.test-step.outcome == 'failure'
    run: ./scripts/notify-slack.sh

  - name: 成功時のみアーティファクト収集
    if: success()
    uses: actions/upload-artifact@v4
    with: { name: report, path: coverage/ }

  - name: どんな結果でも実行(cleanup)
    if: always()
    run: rm -rf /tmp/build-cache

Matrix Strategy ── 並列バリエーション実行

Matrix は「同じジョブを複数の変数組合せで走らせる」仕組み。複数 Node.js / OS / DB バージョンのテストなど、組合せ爆発を YAML 数行で表現できます。

基本の matrix(Node × OS)
jobs:
  test:
    runs-on: ${{ matrix.os }}
    strategy:
      fail-fast: false                     # ある組合せが失敗しても他を続行
      max-parallel: 6
      matrix:
        os: [ubuntu-latest, macos-latest, windows-latest]
        node: [20, 22, 24]
    steps:
      - uses: actions/checkout@v5
      - uses: actions/setup-node@v5
        with: { node-version: "${{ matrix.node }}", cache: npm }
      - run: npm ci
      - run: npm test
include / exclude でピンポイント制御
strategy:
  matrix:
    os: [ubuntu-latest, macos-latest]
    node: [20, 22, 24]
    include:
      # Windows は Node 22 だけ追加で試す
      - os: windows-latest
        node: 22
        extra-flag: --no-color
      # ubuntu + node 24 のときだけ追加の環境変数
      - os: ubuntu-latest
        node: 24
        db: postgres-17
    exclude:
      # macOS + node 20 は除外
      - os: macos-latest
        node: 20
fail-fast の使い分け: ライブラリ開発やフレームワーク互換性テストでは fail-fast: false(全組合せの失敗を見たい)、アプリケーションの通常テストでは fail-fast: true(1 つでも失敗したら節約のため中断)が基本です。

Secrets と Variables

repository / organization / environment の 3 層
jobs:
  deploy:
    runs-on: ubuntu-latest
    environment: production              # environment secrets / protection rule が効く
    env:
      # Variables(機密でない設定値。Settings > Actions > Variables)
      API_BASE: ${{ vars.API_BASE }}
      REGION:   ${{ vars.AWS_REGION }}
    steps:
      - uses: actions/checkout@v5

      - name: デプロイ
        env:
          # Secrets(暗号化、ログマスクあり)
          DATABASE_URL: ${{ secrets.DATABASE_URL }}
          SLACK_TOKEN:  ${{ secrets.SLACK_WEBHOOK }}
        run: ./scripts/deploy.sh
Secrets はログでマスクされるが echo には注意: GitHub は一致する文字列を *** に置換しますが、base64 / JSON にエンコードして出力すると素抜けることがあります。ログに出す必要があるデバッグでも、echo "::add-mask::$SECRET" で明示マスクしつつ、原則 secret は出力しない習慣を徹底してください。また secret は必ず env: か step の with: で渡し、コマンド引数(--token=${{ secrets.X }})に直接埋めないでください(プロセス一覧に出る)。

OIDC ── 長期保管 secret を置かないクラウド認証

GitHub Actions は OpenID Connect (OIDC) トークンを発行でき、AWS・GCP・Azure 側で信頼設定をするとシークレットを持たずに一時クレデンシャルで認証できます。2026-04 からは OIDC claims にリポジトリの custom propertiesも含められるようになり、ABAC(属性ベースアクセス制御)がより細粒度になりました。

AWS への OIDC 認証(role-to-assume)
permissions:
  id-token: write              # OIDC トークン発行に必須
  contents: read

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v5

      - uses: aws-actions/configure-aws-credentials@v5
        with:
          role-to-assume: arn:aws:iam::123456789012:role/gh-deploy
          aws-region: ap-northeast-1

      # この時点で aws CLI / SDK が使える(期限付き STS 認証情報)
      - run: aws s3 sync ./dist s3://my-bucket/
AWS 側の Trust Policy 例: token.actions.githubusercontent.com を OIDC Provider として登録し、Role の Trust Relationship で StringEqualsrepo:OWNER/REPO:ref:refs/heads/main を指定します。2026-04 からは custom_properties.tier のようなリポジトリ属性も使えるため、「環境 tier が production のリポジトリのみ本番権限付与」のような ABAC が書けます。Claude Code の GitHub Actions 連携は Claude Code GitHub Actions 完全ガイド を参照。

Environments ── デプロイ承認とブランチ保護

環境ごとに secrets / ルール / URL を分離
jobs:
  deploy-staging:
    runs-on: ubuntu-latest
    environment:
      name: staging
      url: https://staging.example.com

    steps:
      - run: ./deploy.sh

  deploy-production:
    runs-on: ubuntu-latest
    needs: deploy-staging
    environment:
      name: production                 # 承認者設定・待機時間・ブランチ制限が効く
      url: https://example.com

    steps:
      - run: ./deploy.sh
Environment の「デプロイ保護ルール」: Settings > Environments > 環境名 から、①必須レビュアー指定(人間承認)②wait-timer(デプロイ前の待機時間)③許可ブランチ(main だけ等)④Deployment branch policy(protected branches のみ)を設定できます。「本番デプロイは必ず誰かのレビューを挟む」運用を YAML ではなく UI で設定できるため、ワークフロー改変では突破できないゲートになります。

Concurrency ── 重複実行の制御

concurrency で古い実行をキャンセル
# PR に対して新しい push が来たら古いジョブをキャンセル
concurrency:
  group: ci-${{ github.ref }}
  cancel-in-progress: true

# デプロイは直列(cancel しない、順次キューイング)
jobs:
  deploy:
    concurrency:
      group: deploy-${{ github.ref }}
      cancel-in-progress: false    # デプロイ途中でキャンセルすると壊れるため
    runs-on: ubuntu-latest
    steps:
      - run: ./deploy.sh
料金削減への効果: 公式ベンチマークでは cancel-in-progress: true + group: github.ref月次利用分の 30〜50% 削減例があります。PR で連続 push するチームほど効果が大きく、設定 3 行で効くため全プロジェクト推奨です。

Permissions ── 最小権限の鉄則

トップレベルで全体を read-only にし、必要な job だけ書込権限
# デフォルトを最小に
permissions:
  contents: read

jobs:
  test:
    runs-on: ubuntu-latest
    # test は読むだけでいい(contents: read のまま)
    steps:
      - uses: actions/checkout@v5
      - run: npm test

  release:
    runs-on: ubuntu-latest
    # リリースでタグを打つ時だけ書込権限を付与
    permissions:
      contents: write        # タグ push に必要
      id-token: write        # OIDC 発行(パッケージ署名等)
    steps:
      - uses: actions/checkout@v5
      - run: npm version patch && git push --tags
GITHUB_TOKEN のデフォルト権限: 組織 / リポジトリ設定で「Default permissions for GITHUB_TOKEN」を Read repository contents permission にしておくのが 2026 年の推奨です。古いリポジトリは「Read and write」が既定のままのことが多く、workflow が compromised された時の被害範囲が広くなります。workflow 側で permissions: contents: read を明示すると、組織設定より緩くならない形で制御できます。

Cache ── ビルド高速化の核

setup-* の cache オプション(推奨)
steps:
  - uses: actions/checkout@v5

  # Node + npm
  - uses: actions/setup-node@v5
    with:
      node-version: 22
      cache: npm                       # package-lock.json から自動でキー生成
      cache-dependency-path: "**/package-lock.json"   # monorepo

  # Python + pip
  - uses: actions/setup-python@v5
    with:
      python-version: "3.12"
      cache: pip

  # Bun
  - uses: oven-sh/setup-bun@v2
    with: { bun-version: 1.3 }

  # Deno(setup-deno は cache を明示)
  - uses: denoland/setup-deno@v2
    with: { deno-version: v2.7.x }
actions/cache ── 任意のディレクトリをキャッシュ
- uses: actions/cache@v5
  with:
    path: |
      ~/.cache/puppeteer
      ~/.cache/next
      .next/cache
    key: ${{ runner.os }}-next-${{ hashFiles('package-lock.json') }}-${{ hashFiles('**/*.ts', '**/*.tsx') }}
    restore-keys: |
      ${{ runner.os }}-next-${{ hashFiles('package-lock.json') }}-
      ${{ runner.os }}-next-
key と restore-keys の設計: key完全一致したらヒット(そのまま使う)、restore-keysプリフィックス一致で最新を復元(保存は新キーで行う)。この 2 段構えで「lock ファイルが変わった時も前回のキャッシュを部分活用できる」動作になります。BunDeno 2 はパッケージインストールが速いため、lock 不一致時でもフル再インストールで十分な場合も多いです。

Artifacts v4 ── ビルド成果物の受け渡し

upload-artifact@v4 / download-artifact@v4
jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v5
      - run: npm ci && npm run build
      - uses: actions/upload-artifact@v4
        with:
          name: dist-${{ matrix.os }}-${{ matrix.node }}   # 一意にする
          path: dist/
          retention-days: 7
          compression-level: 6                 # 0=無圧縮 ... 9=最大
          if-no-files-found: error

  release:
    runs-on: ubuntu-latest
    needs: build
    steps:
      - uses: actions/download-artifact@v4
        with:
          pattern: dist-*                      # 複数の artifact をまとめて DL
          merge-multiple: true
          path: all-dists/
      - run: ls -la all-dists/
v3 からの破壊的変更: Artifacts v4 では 同名 artifact の上書きが禁止されました(Matrix で同じ名前を使うと 409 Conflict)。Matrix で分けて上げる場合は name: dist-${{ matrix.os }} のように一意化するか、overwrite: true を付けます。v3 の workflow を v4 にアップグレードする時、この点で失敗するケースが頻発します。

Reusable Workflows ── ワークフロー自体を DRY 化

.github/workflows/reusable-deploy.yml ── 呼び出される側
name: Reusable Deploy

on:
  workflow_call:
    inputs:
      environment:
        type: string
        required: true
      node-version:
        type: string
        default: "22"
    secrets:
      DATABASE_URL:
        required: true
    outputs:
      url:
        description: デプロイ先 URL
        value: ${{ jobs.deploy.outputs.url }}

jobs:
  deploy:
    runs-on: ubuntu-latest
    environment: ${{ inputs.environment }}
    outputs:
      url: ${{ steps.do-deploy.outputs.url }}
    steps:
      - uses: actions/checkout@v5
      - uses: actions/setup-node@v5
        with: { node-version: "${{ inputs.node-version }}", cache: npm }
      - id: do-deploy
        env: { DATABASE_URL: "${{ secrets.DATABASE_URL }}" }
        run: |
          ./scripts/deploy.sh
          echo "url=https://${{ inputs.environment }}.example.com" >> $GITHUB_OUTPUT
.github/workflows/release.yml ── 呼び出す側
name: Release

on:
  push:
    branches: [main]

jobs:
  stg:
    uses: ./.github/workflows/reusable-deploy.yml
    with:
      environment: staging
    secrets:
      DATABASE_URL: ${{ secrets.STAGING_DB_URL }}

  prod:
    needs: stg
    uses: ./.github/workflows/reusable-deploy.yml
    with:
      environment: production
    secrets:
      DATABASE_URL: ${{ secrets.PROD_DB_URL }}

  notify:
    needs: [stg, prod]
    runs-on: ubuntu-latest
    steps:
      - run: echo "stg=${{ needs.stg.outputs.url }} prod=${{ needs.prod.outputs.url }}"
2026 年の制限緩和: Reusable Workflows は最大 10 段までネスト可能、1 実行あたり50 ワークフロー呼び出しまで拡張されました(旧 4 段・20 呼び出し)。大規模モノレポで「パッケージごとに共通 reusable を呼ぶ → 共通 reusable が内部でさらに reusable を呼ぶ」構成が組みやすくなっています。Claude Code × モノレポ完全ガイドの Turborepo / Nx 構成と合わせると威力絶大です。

Composite Actions ── 複数ステップを 1 つの Action に

.github/actions/setup-app/action.yml
name: Setup App
description: Checkout + Node + 依存インストール + キャッシュの決まり切った一連処理

inputs:
  node-version:
    default: "22"
  frozen:
    default: "true"

runs:
  using: composite
  steps:
    - uses: actions/checkout@v5

    - uses: actions/setup-node@v5
      with: { node-version: "${{ inputs.node-version }}", cache: npm }

    - if: inputs.frozen == 'true'
      shell: bash
      run: npm ci

    - if: inputs.frozen != 'true'
      shell: bash
      run: npm install
呼び出し側で 1 行
jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: ./.github/actions/setup-app
        with: { node-version: 22 }
      - run: npm test
Composite vs Reusable Workflow: Composite Action は「ステップの束を 1 つの step に圧縮」する用途(uses: の中身を抽象化)。Reusable Workflow は「job 全体を別ワークフローに切り出す」用途(並列ジョブ・matrix・environment 込み)。共通セットアップ手順なら Composite、デプロイ全体なら Reusable、と使い分けます。

Custom Runner Images(2026-04 GA)

ビルド専用の依存パッケージをあらかじめ焼き込んだ VM イメージを作成し、ランナー起動時間を数十秒 → 数秒に短縮できます。snapshot キーワードでバージョン固定した再現性のあるビルド環境が作れます。

runs-on: で custom image を指定
jobs:
  build:
    runs-on:
      group: my-custom-pool
      labels: [ubuntu-24.04, prebuilt-cxx, node-22]     # 事前にイメージに焼いた label
    steps:
      # apt-get install も npm install も最小限に
      - uses: actions/checkout@v5
      - run: npm run build
snapshot キーワード: カスタムイメージにバージョンタグ(snapshot)を打てるようになり、「本番と同じ状態のイメージで CI を回す」運用が実現します。更新時は snapshot を差し替えるだけで全ワークフローが新しいイメージに切り替わります。

セキュリティ強化の 5 原則

  1. Actions を SHA で pin する(タグ @v5 は書き換え可能。信頼できるリポジトリ以外は SHA 固定が推奨)
  2. permissions は read-only をデフォルトに。必要な job だけ write 付与
  3. secret は env か with で渡し、コマンド引数・echo に出さない
  4. クラウド接続は OIDC を使い、長期保管 secret(AWS アクセスキー等)を置かない
  5. fork PR は pull_request_target を安易に使わない。使うなら permissions: contents: readpersist-credentials: false
Action を SHA で pin する例
steps:
  - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683  # v5.0.0
  - uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020  # v5.0.0
  # ファーストパーティ(actions/*)は @v5 でも許容範囲だが、
  # サードパーティのアクションは SHA 必須にするのが 2026 年の標準
最近の GitHub Actions サプライチェーン攻撃: 2024〜2025 年にかけて、popular な action が改竄される事件が数件発生しました。タグは常に書き換え可能なため、セキュリティ重視プロジェクトではSHA pinning + Dependabot の weekly updateが鉄則。Dependabot が「新しい SHA」として PR を出してくれるので、レビューしてマージする運用になります。

よく使うデプロイパターン

Vercel / Netlify(フロント SSG / SSR)

Vercel 公式 action で Preview / Production
name: Vercel Deploy
on:
  push:
    branches: [main]
  pull_request:

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v5
      - 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: ${{ github.ref == 'refs/heads/main' && '--prod' || '' }}

Cloudflare Workers / Pages

wrangler deploy
name: Cloudflare
on: { push: { branches: [main] } }

jobs:
  deploy:
    runs-on: ubuntu-latest
    permissions: { contents: read, id-token: write }
    steps:
      - uses: actions/checkout@v5
      - uses: actions/setup-node@v5
        with: { node-version: 22, cache: npm }
      - run: npm ci && npm run build
      - uses: cloudflare/wrangler-action@v3
        with:
          apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }}
          accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}

Docker イメージを GHCR に push

GitHub Container Registry 連携
name: Docker
on:
  push:
    branches: [main]
    tags: ["v*.*.*"]

jobs:
  build:
    runs-on: ubuntu-latest
    permissions:
      contents: read
      packages: write              # GHCR に push するのに必要
      id-token: write              # 署名用(cosign 連携)
    steps:
      - uses: actions/checkout@v5
      - uses: docker/setup-buildx-action@v3
      - uses: docker/login-action@v3
        with:
          registry: ghcr.io
          username: ${{ github.actor }}
          password: ${{ secrets.GITHUB_TOKEN }}
      - uses: docker/metadata-action@v5
        id: meta
        with:
          images: ghcr.io/${{ github.repository }}
      - 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
          platforms: linux/amd64,linux/arm64

AWS に OIDC 経由でデプロイ

ECS Fargate デプロイ例(抜粋)
permissions:
  id-token: write
  contents: read

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v5

      - uses: aws-actions/configure-aws-credentials@v5
        with:
          role-to-assume: arn:aws:iam::123456789012:role/gh-actions
          aws-region: ap-northeast-1

      - uses: aws-actions/amazon-ecr-login@v2
        id: login-ecr

      - run: |
          docker build -t $ECR_REGISTRY/app:${{ github.sha }} .
          docker push   $ECR_REGISTRY/app:${{ github.sha }}
        env:
          ECR_REGISTRY: ${{ steps.login-ecr.outputs.registry }}

      - uses: aws-actions/amazon-ecs-deploy-task-definition@v2
        with:
          task-definition: infra/task-def.json
          service: prod-app
          cluster: prod-cluster
          wait-for-service-stability: true

落とし穴と注意点

タグを pin せずに @main を使う

uses: some/action@main のように main を使うと、次回実行時にコードが変わっている可能性があります。意図しない挙動変更・サプライチェーン攻撃の入口になるので、必ずバージョンタグ(@v5)または SHA で固定してください。

secrets を echo / printf でデバッグ

マスクを回避する方法を使わなくても、base64 / JSON でラップした文字列は一致しないためマスクされないことがあります。Secret を「ちょっと見て確認」は絶対にやらないでください。代わりに steps.x.outputs の長さだけ確認する、ダミー値で動作確認するなどの方法を使います。

Matrix で fail-fast を有効にしてビルドログが見えない

デフォルト fail-fast: true だと、1 組合せで失敗した瞬間に他がキャンセルされ、その失敗の原因を切り分けるための情報が得られないことがあります。デバッグ中は fail-fast: false に切り替え、原因特定後に true に戻すのが楽です。

GITHUB_TOKEN の write 権限で workflow 書き換え

GITHUB_TOKEN に actions: write があると、compromised な action がworkflow ファイル自体を書き換える攻撃が可能になります。permissions: contents: read を default にし、actions: write は本当に必要な job(ワークフロー自動更新など)にだけ限定してください。

concurrency のグループ設計ミスで本番デプロイが勝手にキャンセル

concurrency: { group: deploy, cancel-in-progress: true } を本番デプロイに適用すると、次の push で前のデプロイが途中でキャンセルされ、不整合な本番状態になる危険があります。デプロイジョブは cancel-in-progress: false で直列キューイングが鉄則です。

Cache ヒットしているのに再ダウンロードされている

lock ファイルの hash を key に入れずに restore-keys だけで復元すると、見かけはヒットしていても古いキャッシュを使い続けることがあります。lock ファイルが変わったら必ず新しいキーで save される設計(hashFiles("**/package-lock.json") を key に入れる)にしてください。

Artifacts v4 で同名アップロードの 409 Conflict

v3 までは同名で上書きできましたが、v4 は同一 run 内で同じ name は禁止。Matrix ジョブでそのまま v4 にアップグレードすると最初の 1 件以外が失敗します。name: dist-${{ matrix.os }}-${{ matrix.node }} のように一意化してください。

よくある質問

QGitHub-hosted runner と self-hosted runner はどう使い分けますか?
AGitHub-hosted は運用不要・料金が分かりやすい・すぐ使える。公開リポジトリは無料で、プライベートも月 2,000 分の無料枠。self-hosted は「社内ネットワーク内のリソースにアクセスする」「GPU / 特殊ハードを使う」「社内コンプライアンスで社外実行禁止」といったケースで選びます。2026 年は Runner Scale Set Client(Preview)で K8s / VM に自動スケールする self-hosted 群が組みやすくなり、中間的なハイブリッド運用が増えています。
QOIDC で AWS に繋ぐときの IAM Role の信頼ポリシーはどう書きますか?
A基本は Principal に GitHub OIDC Provider、ConditionStringEquals / StringLiketoken.actions.githubusercontent.com:subrepo:OWNER/REPO:ref:refs/heads/main 等)を指定します。ワイルドカード(repo:OWNER/*)は避け、厳密なブランチ/環境単位に絞るのが鉄則。2026-04 からは custom_properties.* を使った ABAC も可能になり、リポジトリ単位で柔軟に権限分離できるようになりました。
QPR から走るジョブで secrets が使えないのはなぜですか?
Afork からの PR ではセキュリティ上 secrets が空になる仕様です(任意の第三者のコードに自社シークレットを渡さないため)。同リポジトリ内ブランチの PR では使えます。どうしても fork PR で何かデプロイしたい場合は、fork 側でワークフローを走らせず、メンテナが「許可ラベル」を付けてから動く pull_request_target + ラベルガード付きワークフローで対応します。
QReusable Workflow と Composite Action の違いは?
AReusable Workflow は「job / matrix / environment 込みの workflow 断片」、Composite Action は「steps の束」です。並列ジョブ・environment 承認・matrix が必要なら Reusable単純に共通セットアップをまとめたいなら Composite。2026 年は Reusable が 10 段ネスト・50 呼び出しまで拡張されたため、大規模モノレポの DRY 化に威力を発揮します。モノレポ設計全般は Claude Code × モノレポ完全ガイド を参照してください。
Qキャッシュが効かないときはどう調査しますか?
A① ワークフローログで Cache restored from key / Cache saved with key を確認、② actions/cachecache-hit output を if: steps.cache.outputs.cache-hit != 'true' でログ出力、③ キャッシュサイズが 10GB を超えていないか(リポジトリ上限)、④ restore-keys が設定されているか確認、の順で切り分けます。Bun や Deno のようにパッケージインストール自体が速い場合、lock ファイルが変わる頻度が高ければフル再インストールの方が速いこともあります(Bun 完全ガイドDeno 2 完全ガイド)。
Qworkflow_dispatch と repository_dispatch はどう使い分けますか?
Aworkflow_dispatch は「GitHub UI の Run workflow ボタン / REST API から手動で起動」、repository_dispatch は「外部システム(Slack / Jira / 自社 Web アプリ)から POST /repos/OWNER/REPO/dispatches で起動」。前者はメンテ作業や手動リリース、後者は自動化パイプラインの外部トリガーに向きます。どちらも inputs(dispatch のみ)や client_payload(repository_dispatch のみ)で引数を渡せます。
QNext.js / Nuxt / Astro / Svelte を CI に載せるベストプラクティスは?
Aどのフレームワークも基本構成は同じです: ①setup-node(または setup-bun / setup-deno)で cache: true、②npm ci / bun install --frozen-lockfile、③npm run lintBiome 推奨)、④npm test、⑤npm run build、⑥artifacts upload(.next / dist)。Next.jsNuxt 4AstroSvelte 5React 19 の各記事でビルド高速化の具体例を解説しています。
QClaude Code を GitHub Actions から呼びたいのですが可能ですか?
A可能です。Claude Code は headless モード(-p フラグ)で CI から実行でき、PR コメントに回答を返す・ Issue を自動トリアージ・コードレビューを生成するなど、多様な自動化が組めます。専用の公式 action も整備されています。詳細は Claude Code GitHub Actions 完全ガイド、headless モードは Claude Code headless モード完全ガイド、スプリント自動化は GitHub Actions × Claude Code Skills を参照してください。

まとめ

  • 基本構造: on(トリガー)・jobs(並列 / 依存関係)・steps(順次)の 3 階層
  • Matrix Strategyで Node×OS×DB などの組合せを数行で表現。include / exclude / fail-fast で細かく制御
  • Secrets は env / with で渡し、echo 禁止。Variables は機密でない設定値に使う
  • OIDCで AWS / GCP / Azure に長期 secret 不要の認証。2026-04 から custom properties による ABAC が GA
  • Environmentsで必須レビュアー・wait-timer・ブランチ制限を UI 側でガード
  • Concurrencyで古い PR ビルドをキャンセル → 月次料金 30〜50% 削減
  • Permissions は read-only をデフォルト、必要な job だけ write 付与
  • Cacheで setup-* の cache: true を使い、任意ディレクトリは actions/cache@v5
  • Artifacts v4は同名上書き禁止。Matrix で一意化
  • Reusable Workflows(10 段ネスト・50 呼び出し)+ Composite Actionsで DRY 化
  • Custom Runner Images(2026-04 GA)で依存焼き込みの高速ランナー
  • セキュリティ 5 原則: SHA pin / read-only / secret echo 禁止 / OIDC / fork PR 制限

Claude Code との連携は Claude Code GitHub Actions 完全ガイドClaude Code headless モードSkills でスプリント進捗自動分析、モノレポ構成は Claude Code × モノレポ完全ガイド、CI でよく使うツールは BiomeBunDeno 2、バッチや自動化での認証は Oracle Wallet(SEPS)完全ガイド、デプロイ先のフレームワークは Next.jsNuxt 4AstroSvelte 5React 19 もあわせてご覧ください。