【GitHub】Actions完全ガイド|4階層モデル・OIDCパスワードレスデプロイ・最小権限・モノレポ最適化・セキュリティhardening

【GitHub】ActionsでCI/CDを自動化する方法 Git

GitHub ActionsはGitHubに統合されたCI/CDプラットフォームで、.github/workflows/*.ymlにYAMLを書くだけでビルド・テスト・デプロイ・運用自動化まで完結できます。Jenkins/CircleCI/Travis CIからの移行先としても定番で、publicリポジトリなら実質無料、2026年時点でGitHub上のOSS/企業プロジェクトのデフォルトCI/CDといえる地位を確立しています。

しかし多くの入門記事は「Hello World的なテスト実行」までで止まっており、OIDCによるAWS/GCP/Azureへのパスワードレスデプロイreusable workflow vs composite actionの使い分け、環境変数/Secrets/Variablesの3層管理GITHUB_TOKENの最小権限設計サードパーティActionのSHAピン留めなど、実務で差がつくトピックがまとまっていません。

この記事では、GitHub Actionsの基礎から運用レベルまで、クイックスタート→トリガー全種→環境変数3層→最小権限設計→マトリクス・キャッシュ・Artifacts→reusable/composite→OIDCパスワードレスデプロイ(AWS/GCP/Azure実例)→Environment protection(承認フロー)→セキュリティhardening→モノレポ最適化(paths/concurrency/merge queue)→コスト最適化(larger/ARM/self-hosted)→デバッグのコツまで、2026年の現場ですぐ使える完全ガイドとしてまとめます。

この記事で学べること

  • GitHub Actions の4階層モデル(Workflow/Job/Step/Event)
  • トリガー全種:pushpull_requestscheduleworkflow_dispatchworkflow_runissue_commentなど
  • 環境変数3層管理:ハードコード/Variables/Secretsの使い分け
  • GITHUB_TOKENpermissionsによる最小権限設計
  • マトリクス戦略(includeexcludefail-fast
  • キャッシュ vs Artifacts の使い分けと設定完全版
  • ジョブ間の依存(needs)とoutputsで値を受け渡し
  • reusable workflow vs composite actionの比較と選び方
  • OIDCによるAWS/GCP/Azureパスワードレスデプロイ(実YAML)
  • Environment protection rules(環境別承認フロー)
  • セキュリティhardening:SHAピン留め/最小権限/secrets scanning
  • モノレポ最適化(pathsフィルタ/concurrency/merge queue)
  • コスト最適化(larger runners/ARM64/self-hosted runners)
  • デバッグ手法(ACT/tmate/ログレベル制御)
スポンサーリンク

30秒クイックスタート:最小のCI

まずは動くものから。.github/workflows/ci.ymlに以下を置けば、pushとPRで自動テストが走ります。

最小CI(Node.js)
# .github/workflows/ci.yml
name: CI

on:
  push:
    branches: [main]
  pull_request:

jobs:
  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 test

commit&pushした瞬間にActionsが起動し、GitHubの Actions タブで進捗が見えます。5分でCIが成立する驚異的な手軽さがGitHub Actions最大の魅力。

GitHub Actionsの4階層モデル

用語が多いですが構造はシンプル。Event → Workflow → Job → Stepの4階層を理解すれば、どんな複雑なパイプラインも書き起こせます。

階層 役割 YAMLキー
Event ワークフローを起動するトリガー(push、PR、cron等) on:
Workflow 1つのYAMLファイル=1つのWorkflow ファイル全体
Job 独立VMで実行される単位(デフォルト並列) jobs.<name>:
Step Job内の逐次実行タスク(コマンド or Action) steps: - run: / uses:

runs-onとrunner(実行環境)

  • ubuntu-latest:Ubuntu 24.04(2026年現在の推奨)
  • windows-latest:Windows Server 2022
  • macos-latest:macOS 14 (Apple Silicon)
  • ubuntu-24.04-arm:ARM64 linux(料金20%オフ)
  • ubuntu-latest-8core:Larger runner(高速だが有料)
  • [self-hosted, linux, gpu]:セルフホスト(GPU/社内ネット)

トリガーイベント全種:使いこなしカタログ

よく使うトリガー一覧
# プッシュ
on:
  push:
    branches: [main, "release/**"]
    tags: ["v*.*.*"]
    paths: ["src/**", "package.json"]
    paths-ignore: ["docs/**"]

# Pull Request
on:
  pull_request:
    branches: [main]
    types: [opened, synchronize, reopened]
    paths: ["src/**"]

# スケジュール(UTC時間)
on:
  schedule:
    - cron: '0 3 * * *'   # 毎日12:00 JST(UTC+9)
    - cron: '0 0 * * 1'   # 毎週月曜 09:00 JST

# 手動実行(パラメータ付き)
on:
  workflow_dispatch:
    inputs:
      environment:
        description: Deploy target
        required: true
        type: choice
        options: [staging, production]
      force:
        description: Force deploy
        type: boolean
        default: false

# 他ワークフロー完了で起動
on:
  workflow_run:
    workflows: ["CI"]
    types: [completed]
    branches: [main]

# Issue/PRコメント
on:
  issue_comment:
    types: [created]

# ラベル付与
on:
  pull_request:
    types: [labeled]

# 複数イベント混在
on:
  push:
    branches: [main]
  pull_request:
  schedule: [{cron: '0 * * * *'}]
  workflow_dispatch:

cronのタイムゾーンはUTC固定(タイムゾーン指定は不可)。JST 09:00に動かしたければcron: '0 0 * * *'(UTC 00:00)と指定。混乱を避けるためコメントでJSTを明記するのがおすすめ。またscheduleはGitHub側の負荷分散で数分遅れることがあり、厳密な時刻保証は期待できません。

環境変数3層管理:ハードコード/Variables/Secrets

設定値はどこに置くかでセキュリティと保守性が大きく変わります。

保管先 用途 ログ露出 参照構文
YAML直書き 固定パス、非機密設定 ✓ 公開される env:
Variables 非機密の環境別設定(URL/region等) ✓ 公開される ${{ vars.NAME }}
Secrets 機密情報(APIキー/証明書/パスワード) ✗ 自動マスク(*** ${{ secrets.NAME }}
実例:環境変数の階層使い分け
env:
  # ワークフロー全体で共通の非機密(全体公開される)
  NODE_OPTIONS: "--max-old-space-size=4096"

jobs:
  deploy:
    runs-on: ubuntu-latest
    environment: production   # Environmentを指定
    env:
      # Variables:Settings → Secrets and variables → Variables
      AWS_REGION: ${{ vars.AWS_REGION }}
      APP_URL: ${{ vars.APP_URL }}
    steps:
      - run: echo "Region is $AWS_REGION"   # 非機密なので表示OK
      - run: ./deploy.sh
        env:
          # Secrets:自動マスクされる
          DEPLOY_TOKEN: ${{ secrets.DEPLOY_TOKEN }}
          DB_PASSWORD: ${{ secrets.DB_PASSWORD }}

Variables vs Secretsの決め方

“漏れても実害がない”ものはVariables、”漏れたら事故”はSecrets。AWS region名/APIバージョン/ステージング用URL等はVariables、パスワード/APIキー/署名鍵はSecrets。Secretsは保存後に読み戻せない(書き換えのみ)仕組みで、ログ出力しても***にマスクされます。

GITHUB_TOKENとpermissions:最小権限設計

各Jobには自動発行されるGITHUB_TOKENがあり、permissionsキーで最小権限を明示するのが2026年のベストプラクティス。「デフォルト権限でいいや」はセキュリティインシデントの温床です。

permissions指定の完全例
# ワークフロー全体のデフォルトを最小化
permissions:
  contents: read       # リポジトリ読み取りのみ

jobs:
  test:
    runs-on: ubuntu-latest
    # testジョブは追加権限不要
    steps:
      - uses: actions/checkout@v4

  release:
    runs-on: ubuntu-latest
    # このジョブだけ権限拡張
    permissions:
      contents: write  # リリース作成
      id-token: write  # OIDC用
      packages: write  # GHCRプッシュ
    steps:
      - uses: actions/checkout@v4
      - run: gh release create ...

主要な権限スコープ

スコープ 主な用途
contents コード取得(read)/リリース作成・push(write)
pull-requests PR作成・コメント・ラベル操作
issues Issue作成・コメント
id-token OIDCでクラウドプロバイダに認証
packages GHCRへのイメージpush
pages GitHub Pagesデプロイ
security-events SARIFアップロード(CodeQL等)

Settings → Actions → Workflow permissionsRead and write permissions(デフォルト)のままにするのは危険。サプライチェーン攻撃でサードパーティActionが悪意あるコードをpushする経路になります。“Read repository contents and packages permissions”に変更し、各workflowで必要な権限だけ明示的に付与するのが最小権限設計。

マトリクス戦略:include/exclude/fail-fast

OS・ランタイムバージョンの組み合わせで並列テストするのがマトリクス。シンプルな直積からincludeexcludeによる微調整まで使いこなすと便利です。

基本のマトリクス
jobs:
  test:
    runs-on: ${{ matrix.os }}
    strategy:
      fail-fast: false          # 1つ失敗しても他は続行
      max-parallel: 4           # 同時実行上限
      matrix:
        os: [ubuntu-latest, windows-latest, macos-latest]
        node: ['18', '20', '22']
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: ${{ matrix.node }}
      - run: npm ci && npm test

# → 3 × 3 = 9 パターン並列
include/excludeで微調整
strategy:
  matrix:
    os: [ubuntu-latest, windows-latest]
    node: ['18', '20']
    include:
      # Ubuntu + Node 22 だけ追加(特殊テスト含む)
      - os: ubuntu-latest
        node: '22'
        experimental: true
    exclude:
      # Windows + Node 18 は不要
      - os: windows-latest
        node: '18'

# experimentalフラグで条件分岐
steps:
  - if: matrix.experimental == true
    run: npm test -- --experimental-features

fail-fast: false実務のデフォルト。デフォルト(true)だと1つ失敗で残りがキャンセルされ、「WindowsとmacOSで同時に直すべき問題」の全体像が見えません。

キャッシュ vs Artifacts:使い分け

似ているようで役割が異なる2つ。理解して使い分けるとCIが大幅に高速化します。

項目 Cache Artifact
目的 ビルド高速化(依存・中間成果物) ワークフロー間/ユーザーへの成果物共有
保持期間 7日アクセスなしで自動削除 デフォルト90日(設定可)
サイズ上限 10GB(リポジトリ合計) ジョブあたり2GB/合計なし
ダウンロード workflow内のみ UIからダウンロード可
典型用途 node_modules、pip、Docker layer ビルドバイナリ、テストレポート
actions/cache完全例
# npm系はsetup-nodeのcacheオプションで十分
- uses: actions/setup-node@v4
  with:
    node-version: '20'
    cache: npm

# 複雑なキャッシュ(Docker buildkit/gradle等)
- uses: actions/cache@v4
  with:
    path: |
      ~/.gradle/caches
      ~/.gradle/wrapper
    key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*') }}
    restore-keys: |
      ${{ runner.os }}-gradle-
Artifactsでジョブ間共有
# ビルドジョブで生成物アップロード
build:
  runs-on: ubuntu-latest
  steps:
    - uses: actions/checkout@v4
    - run: npm ci && npm run build
    - uses: actions/upload-artifact@v4
      with:
        name: web-dist
        path: dist/
        retention-days: 7

# デプロイジョブでダウンロード
deploy:
  needs: build
  runs-on: ubuntu-latest
  steps:
    - uses: actions/download-artifact@v4
      with:
        name: web-dist
        path: dist/
    - run: ./deploy.sh

ジョブ間の依存(needs)とoutputsで値を受け渡し

needs+outputs
jobs:
  prepare:
    runs-on: ubuntu-latest
    outputs:
      version: ${{ steps.ver.outputs.version }}
      should_deploy: ${{ steps.check.outputs.should_deploy }}
    steps:
      - uses: actions/checkout@v4
      - id: ver
        run: echo "version=$(git describe --tags)" >> $GITHUB_OUTPUT
      - id: check
        run: |
          if [[ "${{ github.ref }}" == "refs/heads/main" ]]; then
            echo "should_deploy=true" >> $GITHUB_OUTPUT
          else
            echo "should_deploy=false" >> $GITHUB_OUTPUT
          fi

  deploy:
    needs: prepare
    if: needs.prepare.outputs.should_deploy == 'true'
    runs-on: ubuntu-latest
    steps:
      - run: echo "Deploying version ${{ needs.prepare.outputs.version }}"

outputsの上限

outputは1MB以下に制限されます。大きいファイルを受け渡したい場合はactions/upload-artifactを使ってください。環境変数経由($GITHUB_ENV)もありますが、これは同一ジョブ内のみ有効でジョブ間共有はできません。

reusable workflow vs composite action:使い分け

共通処理を切り出す2つの方法。それぞれ階層が違うため用途も異なります。

観点 Reusable Workflow Composite Action
粒度 Job単位(複数step) Step単位(複数run)
ファイル位置 .github/workflows/ .github/actions/<name>/action.yml
呼び出し uses: org/repo/.github/workflows/x.yml@ref uses: ./.github/actions/x
VM 独立(別VM) 呼び出し元と同じVM
用途 複数リポで共通の品質ゲート・リリース手順 繰り返し使うstepの塊(例:Setup+cache)
Reusable Workflowの例
# .github/workflows/reusable-test.yml
name: Reusable Test
on:
  workflow_call:
    inputs:
      node-version:
        required: true
        type: string
    secrets:
      NPM_TOKEN:
        required: false

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

# 呼び出し側
# .github/workflows/ci.yml
jobs:
  test:
    uses: ./.github/workflows/reusable-test.yml
    with:
      node-version: '20'
    secrets:
      NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
Composite Actionの例
# .github/actions/setup-node-env/action.yml
name: 'Setup Node env'
description: 'Setup Node.js with cache + install deps'
inputs:
  node-version:
    required: true
    default: '20'
runs:
  using: 'composite'
  steps:
    - uses: actions/setup-node@v4
      with:
        node-version: ${{ inputs.node-version }}
        cache: npm
    - shell: bash
      run: npm ci

# 呼び出し側
jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: ./.github/actions/setup-node-env
        with:
          node-version: '20'
      - run: npm test

OIDC:AWS/GCP/Azureへのパスワードレスデプロイ

クラウドにデプロイする際、アクセスキーを長期Secretsに保存するのはアンチパターンOpenID Connect(OIDC)を使えば、GitHubがその都度短命のトークンを発行し、クラウド側が検証してロール引き受けを許可します。2026年時点の必須技術です。

AWSへのOIDC認証

aws-actions/configure-aws-credentials
# 事前準備(AWS IAM側)
# 1. IAM → Identity providers → "Add provider"
#    - Provider type: OpenID Connect
#    - URL: https://token.actions.githubusercontent.com
#    - Audience: sts.amazonaws.com
# 2. IAMロールを作成し、Trust policyで対象リポジトリを許可
#    Condition:
#      token.actions.githubusercontent.com:sub: repo:ORG/REPO:ref:refs/heads/main

# ワークフロー
name: Deploy to AWS
on:
  push:
    branches: [main]

permissions:
  id-token: write    # ← OIDC必須
  contents: read

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: aws-actions/configure-aws-credentials@v4
        with:
          role-to-assume: arn:aws:iam::123456789012:role/github-actions-deploy
          aws-region: ap-northeast-1
      # 以降、AWS CLIコマンドが動く
      - run: aws s3 sync ./dist s3://my-bucket/

Google CloudへのOIDC認証

google-github-actions/auth
# GCP事前準備
# 1. Workload Identity Poolを作成
# 2. Providerで GitHub を許可(audience: sts.googleapis.com)
# 3. Service Accountに iam.workloadIdentityUser を付与

permissions:
  id-token: write
  contents: read

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - id: auth
        uses: google-github-actions/auth@v2
        with:
          workload_identity_provider: projects/123/locations/global/workloadIdentityPools/gh-pool/providers/gh-prov
          service_account: ci-deploy@project.iam.gserviceaccount.com
      - uses: google-github-actions/setup-gcloud@v2
      - run: gcloud run deploy myapp --source .

AzureへのOIDC認証

azure/login
permissions:
  id-token: write
  contents: read

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: azure/login@v2
        with:
          client-id: ${{ vars.AZURE_CLIENT_ID }}
          tenant-id: ${{ vars.AZURE_TENANT_ID }}
          subscription-id: ${{ vars.AZURE_SUBSCRIPTION_ID }}
      - run: az webapp deploy --name myapp --resource-group rg --src-path dist.zip

OIDCのメリット:①アクセスキーが漏洩しても長期被害が出ない(トークン寿命は短い)、②鍵のローテーション不要、③Secretsが減って管理が楽、④Trust Policyでリポジトリ・ブランチを厳密に制限できる。2026年の新規プロジェクトはOIDC一択で設計すべきです。

Environment protection rules:承認フローを組み込む

本番デプロイはレビュアー承認・待機時間・ブランチ制限で暴走を防ぐのが定石。GitHubのEnvironment機能がこれを標準提供します。

Environment活用例
jobs:
  deploy:
    needs: test
    runs-on: ubuntu-latest
    environment:
      name: production        # ← Environment指定
      url: https://myapp.com  # デプロイ先URL(UI表示)
    steps:
      - run: ./deploy.sh

Environment側の設定

Settings → Environments → New environment

  • Required reviewers:最大6名、承認されるまで待機
  • Wait timer:デプロイを指定分数遅延(0〜43200分)
  • Deployment branchesmainrelease/**のみ許可
  • Environment secrets:production専用のSecrets
  • Environment variables:production専用の設定値

推奨構成:staging環境は自動デプロイ(承認不要)、production環境は2名レビュアー承認+10分wait timer+mainブランチ限定。「急いでデプロイしてロールバック」のミスを構造的に防げます。

セキュリティhardening:4つの必須対策

① Actionの参照をSHAピン留め

サードパーティActionは「タグ」がマルウェアに書き換えられる攻撃が過去に発生しています。コミットSHA固定が2026年のベストプラクティス。

SHAピン留めの書き方
# ❌ 弱い:タグ参照(書き換えられるリスク)
- uses: actions/checkout@v4

# ⭕ 強い:SHA + バージョンコメント
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683  # v4.2.2

# Dependabotで自動更新(.github/dependabot.yml)
# version: 2
# updates:
#   - package-ecosystem: "github-actions"
#     directory: "/"
#     schedule:
#       interval: "weekly"

② permissions最小化

既に上のセクションで解説。contents: readをデフォルトにし、必要なjobだけ拡張。

③ Secrets漏洩を防ぐ設定

Secrets取り扱いの注意
# Secretsを直接echoしない(自動マスクはされるが念のため)
# ❌
run: echo "$TOKEN"

# ⭕ 必要な箇所だけ使う
run: ./deploy.sh
env:
  TOKEN: ${{ secrets.TOKEN }}

# PR由来のworkflowではsecrets露出に注意
# pull_request_target はリポオーナー向けの特権トリガー
# → 信頼済みPRのみで使用

④ OIDCでアクセスキーを廃止

既出。クラウドデプロイは全てOIDCへ移行するのが望ましい。

pull_request_targetトリガーの罠:通常のpull_requestはforkからのPRではSecretsが空になりますが、pull_request_targettargetリポジトリの権限で実行され、Secretsも有効になります。forkのPRで任意コード実行を許すとアクセスキー全漏洩の大事故。このトリガーを使う際は絶対にPR由来コードを実行しないこと。

モノレポ最適化:paths/concurrency/merge queue

大規模モノレポではCIが関係ないパッケージでも走ると時間とコストが無駄に。3つのテクニックで大幅に改善できます。

① pathsフィルタで関係パッケージのみ実行

package単位で条件分岐
on:
  pull_request:
    paths:
      - 'packages/web/**'
      - '.github/workflows/web-ci.yml'

jobs:
  web-test:
    runs-on: ubuntu-latest
    defaults:
      run:
        working-directory: packages/web
    steps:
      - uses: actions/checkout@v4
      - run: npm ci && npm test

② concurrencyで古い実行をキャンセル

同一PRの古いCIをキャンセル
# ブランチ単位で古い実行をキャンセル
concurrency:
  group: ${{ github.workflow }}-${{ github.ref }}
  cancel-in-progress: true

# 本番デプロイはキャンセルさせない(安全優先)
concurrency:
  group: production-deploy
  cancel-in-progress: false

③ Merge Queueで統合テストを最小化

Merge queue(2023年GA)

mainへの並列mergeをシリアルに並べ、「直前のマージ済みコード」との組み合わせでCIを1回だけ流してから統合する仕組み。複数PRが同時にmergeされた時の「mainが壊れる」問題を防ぎつつ、個別PRで毎回重たいCIを走らせなくて済みます。Settings → Rules → Require merge queueから有効化。

Merge queue対応workflow
on:
  pull_request:
  merge_group:          # ← merge queue対応

jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - run: npm ci && npm test

コスト最適化:larger runners/ARM64/self-hosted

GitHub Actionsはパブリックリポは無料ですが、プライベートだと課金対象。無料分(月2,000分程度/プランによる)を超えたら最適化が必要です。

手段 特徴 向いているケース
ARM64 runner
(ubuntu-24.04-arm)
料金20〜37%オフ/性能同等以上 ARM対応プロジェクト
Larger runner
(ubuntu-latest-8core等)
多コア/高RAM/SSD ビルドが律速のプロジェクト
Self-hosted ランタイム分課金ゼロ/GPU可 重いGPU/社内リソース/常時稼働
cache徹底 依存・Dockerレイヤーのキャッシュ 全プロジェクト共通の基本対策
ARM64 runner指定
jobs:
  test:
    runs-on: ubuntu-24.04-arm   # ARM64、料金20%オフ
    steps:
      - uses: actions/checkout@v4
      - run: npm test

コスト削減の順序:①不要なjobs削減+paths filter、②キャッシュ徹底、③ARM64移行、④重いビルドだけlarger runner、⑤稼働の多いGPU/長時間テストはself-hosted。①〜③だけで実分の50%以上削減できるケースが多いです。

デバッグ:ログ/tmate/ACTローカル実行

① デバッグログレベルを上げる

実行時ログ詳細化
# SettingsのSecretsに以下を追加
ACTIONS_RUNNER_DEBUG: true       # runner側の詳細
ACTIONS_STEP_DEBUG: true         # step側の詳細

# これだけで普段見えない内部ログが表示される
# デバッグ後は削除(ログが重くなる)

② tmate でSSH直接デバッグ

失敗したrunnerにSSH
- name: Setup tmate
  if: ${{ failure() }}        # 失敗した時だけ
  uses: mxschmitt/action-tmate@v3
  timeout-minutes: 15

# ログに表示されるSSH接続情報でログイン → 直接調査

③ ACTでローカル実行

ACT(nektos/act)
# インストール(macOS/Linux)
brew install act

# ローカルで実行
act push
act pull_request
act -j test                    # 特定ジョブだけ
act -s GITHUB_TOKEN=xxx        # Secrets指定

# Dockerイメージサイズで選択
act -P ubuntu-latest=ghcr.io/catthehacker/ubuntu:act-latest

失敗時の確認ポイント

  • 起動しないon条件・paths・ブランチ名ミスマッチ
  • 403権限エラーpermissions設定不足
  • Secretsが空:fork由来PRはsecrets無効(意図的)
  • cacheヒットしない:キー計算に使うhashFilesが変わった
  • マトリクスの一部が失敗fail-fast: falseで全体像把握

よくある質問

QGitHub ActionsとCircleCI/Jenkinsの違いは?
AGitHub ActionsはGitHub本体と統合され、初期設定なし/無料枠あり/YAMLでOK/Marketplaceに豊富なAction、という手軽さが最大の強み。CircleCIは並列度と高速性でやや優位、Jenkinsはオンプレ+プラグインで最大の自由度。新規のGitHub上のプロジェクトはActions一択、大規模オンプレ要件ならJenkins併用も検討価値があります。
Qパブリックリポジトリは完全無料?
Aパブリックリポは標準runner(2〜4コア)の使用は無制限で無料です。プライベートリポはプラン別の月間無料分を超えると分単位課金。larger runnerとself-hosted、Artifacts/Cache容量は別途課金対象。詳細はBilling設定ページでリアルタイムに確認可能。
Qfork由来PRでSecretsが使えないのはなぜ?
A悪意あるfork PRが任意コードでsecrets.PROD_TOKENを盗んで外部送信するのを防ぐため、GitHubは意図的にpull_requestトリガーでforkPRにはSecretsを渡しません。信頼済みPRのみ実行したい場合はpull_request_targetを使いますが、forkコードを実行してはいけないという制約があります。
Q実行時間が長い。短縮のコツは?
A①依存キャッシュ(setup-nodeのcache, actions/cache)、②関係ないjobをpathsで除外、③concurrencyで古い実行キャンセル、④マトリクスを必要最小限に、⑤Dockerビルドはcache-fromcache-toでGHA cache活用、⑥larger runner or ARM64 runnerに乗り換え。最も効果が大きいのは①と②です。
QActionsのバージョン更新はどう管理する?
A.github/dependabot.ymlpackage-ecosystem: "github-actions"を設定すれば毎週自動PRが来ます。SHA固定+Dependabotの組み合わせが2026年の標準運用。タグ参照(@v4)のままだと書き換え攻撃リスクが残るので推奨できません。
Qworkflow_dispatchで入力値を使う方法は?
Aworkflow_dispatch.inputsで型指定(string/boolean/choice/environment)の入力パラメータを定義し、${{ inputs.NAME }}または${{ github.event.inputs.NAME }}で参照できます。手動デプロイのtier選択(staging/production)やdebugモード切替に最適です。
QActionsでタグに紐づくリリースを作りたい
Aon: push: tags: ["v*.*.*"]で起動し、gh release create ${GITHUB_REF_NAME} --generate-notes dist/*.tar.gzで作成。詳しい連携フローは【Git】タグ完全ガイドでGitHub Actionsとsemantic-release連携まで解説しています。
Qreusable workflowとcomposite actionどっちを使う?
A独立した品質ゲート(テスト一式・リリース手順)を複数リポで共有したいならReusable Workflow(Job単位、別VM)。“Setup + cache + install”のような繰り返されるstep塊を共通化したいならComposite Action(Step単位、同一VM)。「外から呼ぶ独立ワークフロー」がreusable、「workflow内で埋め込む部品」がcomposite、という使い分け。
QOIDCとPATやアクセスキー、どれを使うべき?
AクラウドデプロイならOIDC一択。アクセスキーを長期Secretsに置く旧来方式はローテーション負担・漏洩時の被害が大きく、2026年時点ではアンチパターン扱い。GitHub内部操作(PR作成等)はPATよりGITHUB_TOKENpermissions、組織横断の自動化はGitHub App経由が推奨です。

関連記事

まとめ

  • GitHub ActionsはEvent→Workflow→Job→Stepの4階層モデル
  • 環境変数はYAML/Variables/Secretsの3層を適切に使い分け
  • permissions最小権限設計contents: readをデフォルトに)
  • マトリクスはfail-fast: falseincludeexcludeで柔軟に
  • Cache(ビルド高速化・7日)とArtifact(成果物共有・90日)を目的別に使い分け
  • ジョブ間はneedsoutputsで値を受け渡し(1MB制限)
  • Reusable Workflow(Job単位)とComposite Action(Step単位)で階層を選ぶ
  • OIDCでAWS/GCP/Azureにパスワードレスデプロイ(2026年標準)
  • Environment protection rulesで承認+wait timer+branch制限
  • セキュリティ4点:SHAピン留め/permissions最小/Secrets取扱/OIDC
  • モノレポ最適化:pathsconcurrencymerge queue
  • コスト削減の王道:cache徹底→paths除外→ARM64→larger/self-hosted検討
  • デバッグ:ACTIONS_STEP_DEBUGtmateACTローカル実行

GitHub Actionsは「YAML書くだけ」の手軽さで始められますが、実務レベルでは最小権限設計・OIDC・reusable workflow・セキュリティhardening・コスト最適化のどれを押さえるかで運用品質が大きく変わります。本記事のガイドに沿ってゼロから成熟運用へ段階的に進化させれば、Jenkins/CircleCIから移行したチームでも1〜2週間で完成度の高いCI/CDパイプラインが手に入ります。タグ自動リリースは【Git】タグ完全ガイド、submodule認証は【Git】submodule完全ガイドと組み合わせてご活用ください。