Back

GitHub Actions 2026:モノレポCI/CDからSelf-hosted Runnerまで完全ガイド

GitHub Actionsのワークフローが45分かかる。チームはイライラ。プッシュするたびにモノレポ全体がリビルドされる。毎月の無料分がすぐ底をつく。

聞き覚えありますか?一人じゃないですよ。コードベースが大きくなってモノレポが当たり前になると、単一パッケージでうまく動いてたCI/CDが急にボトルネックになる。でもGitHub Actionsもかなり進化してるんです。ほとんどの開発者がまだフル活用できてないだけ。

この記事では2026年のGitHub Actionsのほぼすべてをカバーします。モノレポワークフローの最適化からセルフホステッドランナーのセットアップ、高度なキャッシング戦略からコスト管理まで。CI/CDをボトルネックから競争力に変えましょう。

モノレポの落とし穴:なぜビルドが遅いのか

今どきモノレポ使ってないところないですよね。Turborepo、Nx、Lerna、Rush—ツールは成熟しました。でもCI/CDはほとんどのチームでまだ昔のまま。

問題の状況

# ダメなやり方:毎回全部ビルド name: CI on: [push, pull_request] jobs: build: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - run: npm ci - run: npm run build - run: npm test

このワークフローの致命的な問題3つ:

  1. 変更検知なしpackages/utilsだけ直したのに全パッケージビルド
  2. 並列化なし:テストが順番に回る
  3. キャッシングなし:毎回ゼロから

3つとも直しましょう。

変更検知:変わったものだけビルド

キーインサイト:モノレポでほとんどのコミットは一部のパッケージしか触らない。本当に変わったものだけビルドしてテストすればいい。

paths-filterを使う

name: CI on: push: branches: [main] pull_request: jobs: changes: runs-on: ubuntu-latest outputs: frontend: ${{ steps.filter.outputs.frontend }} backend: ${{ steps.filter.outputs.backend }} shared: ${{ steps.filter.outputs.shared }} steps: - uses: actions/checkout@v4 - uses: dorny/paths-filter@v3 id: filter with: filters: | frontend: - 'packages/frontend/**' - 'packages/shared/**' backend: - 'packages/backend/**' - 'packages/shared/**' shared: - 'packages/shared/**' frontend: needs: changes if: ${{ needs.changes.outputs.frontend == 'true' }} runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - run: npm ci - run: npm run build --workspace=packages/frontend - run: npm test --workspace=packages/frontend backend: needs: changes if: ${{ needs.changes.outputs.backend == 'true' }} runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - run: npm ci - run: npm run build --workspace=packages/backend - run: npm test --workspace=packages/backend

結果packages/frontend/src/Button.tsxだけ変えたらfrontendジョブだけ回る。backendは完全スキップ。

Turborepo内蔵の検知機能

Turborepo使ってれば変更検知が内蔵されてます:

jobs: build: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 with: fetch-depth: 0 # 変更検知に必要 - uses: pnpm/action-setup@v3 - uses: actions/setup-node@v4 with: node-version: 22 cache: 'pnpm' - run: pnpm install - run: pnpm turbo build --filter='...[origin/main]' - run: pnpm turbo test --filter='...[origin/main]'

--filter='...[origin/main]'がorigin/main以降に変わったパッケージだけ実行って意味。

高度なキャッシング

キャッシングでほとんどのチームがパフォーマンスを逃してます。actions/cacheの先へ。

レイヤー1:パッケージマネージャーキャッシュ

これは基本:

- uses: actions/setup-node@v4 with: node-version: 22 cache: 'pnpm' # または 'npm', 'yarn'

lockfileのハッシュに基づいてnode_modulesをキャッシュ。

レイヤー2:Turborepoビルドキャッシュ

Turborepoのリモートキャッシングがゲームチェンジャー:

- run: pnpm turbo build --filter='...[origin/main]' env: TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }} TURBO_TEAM: ${{ vars.TURBO_TEAM }}

リモートキャッシュ有効なら、チームメイトが同じ入力でpackages/utilsをビルド済みならCIマシンでもキャッシュヒット。

レイヤー3:重い依存関係の別キャッシュ

インストールに時間かかるものは別でキャッシュ:

- name: Playwrightブラウザキャッシュ uses: actions/cache@v4 with: path: ~/.cache/ms-playwright key: playwright-${{ runner.os }}-${{ hashFiles('**/package-lock.json') }} - name: Playwrightインストール run: npx playwright install --with-deps if: steps.cache-playwright.outputs.cache-hit != 'true'

レイヤー4:Dockerレイヤーキャッシング

Dockerイメージビルドなら:

- uses: docker/build-push-action@v5 with: context: . push: true tags: myapp:latest cache-from: type=gha cache-to: type=gha,mode=max

type=ghaがGitHub ActionsキャッシュをDockerレイヤーに使う。ビルド時間80%以上短縮可能。

マトリックスビルド:全部並列で

マトリックスビルドで同じジョブを違う設定で並列実行できます。

基本マトリックス

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

これで9個の並列ジョブ(Nodeバージョン3つ × OS 3つ)。

モノレポ用動的マトリックス

変わったパッケージを基にマトリックスを動的生成:

jobs: detect: runs-on: ubuntu-latest outputs: packages: ${{ steps.detect.outputs.packages }} steps: - uses: actions/checkout@v4 - id: detect run: | packages=$(ls -d packages/*/ | jq -R -s -c 'split("\n")[:-1]') echo "packages=$packages" >> $GITHUB_OUTPUT test: needs: detect runs-on: ubuntu-latest strategy: matrix: package: ${{ fromJson(needs.detect.outputs.packages) }} steps: - uses: actions/checkout@v4 - run: npm ci - run: npm test --workspace=${{ matrix.package }}

これで各パッケージが自分の並列ジョブでテストされます。

Fail-Fast vs 全完了

デフォルトだとマトリックスジョブが1つ失敗したら残り全部キャンセル。でも全部最後まで回したい時もありますよね:

strategy: fail-fast: false # 1つ失敗しても残り続行 matrix: node: [18, 20, 22]

Self-Hosted Runners:いつ、どうやって

GitHubホステッドランナーは便利だけど限界あり:

  • 7GB RAM、2 CPU(スタンダード)
  • 永続ストレージなし
  • 分課金が積み重なる
  • GPUなし

セルフホステッドランナーが全部解決。

セルフホステッド使うとき

使うべき場合:

  • リソースもっと必要(RAM、CPU、GPU)
  • 長時間ジョブがホステッドで高い
  • オンプレミスリソースへのアクセス必要
  • MLワークロードでGPU必要

使わない方がいい場合:

  • 小さいチーム、シンプルビルド
  • インフラ管理できない
  • セキュリティ分離が最優先

セルフホステッドランナーセットアップ

  1. GitHubでランナー作成:Settings → Actions → Runners → New self-hosted runner

  2. サーバーで

# ランナーダウンロード mkdir actions-runner && cd actions-runner curl -o actions-runner-linux-x64.tar.gz -L https://github.com/actions/runner/releases/download/v2.320.0/actions-runner-linux-x64.tar.gz tar xzf actions-runner-linux-x64.tar.gz # 設定 ./config.sh --url https://github.com/your-org/your-repo \ --token YOUR_TOKEN \ --labels gpu,linux,x64 # サービスとして実行 sudo ./svc.sh install sudo ./svc.sh start
  1. ワークフローで使用
jobs: ml-training: runs-on: [self-hosted, gpu, linux] steps: - uses: actions/checkout@v4 - run: python train.py

Actions Runner Controller (ARC) でスケーリング

Kubernetes環境なら、ARCが需要に応じてランナーを自動スケール:

# ARC用 values.yaml controllerServiceAccount: namespace: arc-systems name: arc-controller githubConfigUrl: "https://github.com/your-org" githubConfigSecret: github-config-secret maxRunners: 10 minRunners: 1 template: spec: containers: - name: runner image: ghcr.io/actions/actions-runner:latest resources: requests: cpu: 2 memory: 4Gi

ジョブがキューに入るとランナーがスピンアップ、アイドルならスピンダウン。

コスト最適化戦略

GitHub Actionsの請求は予想外になりがち。コントロールする方法:

1. macOS/WindowsよりUbuntu

ランナー分単価
ubuntu-latest$0.008
windows-latest$0.016(2倍)
macos-latest$0.08(10倍)

macOSはiOSビルドかmacOS特有のテストだけに。

2. 重複実行をキャンセル

素早く複数コミットプッシュする時、古い実行をキャンセル:

concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true

3. 大きいランナーを戦略的に

GitHubに大きいランナーあります(4倍、8倍、16倍)。逆説的に安くなることも:

jobs: build: runs-on: ubuntu-latest-8-cores # 2コアの代わりに8コア

ビルドが2コアで20分、8コアで6分なら、分単価高くてもコスト節約。

4. ジョブにタイムアウト

暴走ジョブを防止:

jobs: build: runs-on: ubuntu-latest timeout-minutes: 30 # 30分でキル

5. 急がないジョブをスケジュール

重いジョブを空いてる時間に:

on: schedule: - cron: '0 2 * * *' # 毎日UTC午前2時

高度なパターン

再利用可能ワークフロー

リポ間で繰り返し防止:

# .github/workflows/reusable-test.yml name: Reusable Test Workflow on: workflow_call: inputs: node-version: required: true type: string 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-reusable: uses: ./.github/workflows/reusable-test.yml with: node-version: '22'

Composite Actions

複数ステップを再利用可能なアクションにまとめる:

# .github/actions/setup-project/action.yml name: 'Setup Project' description: 'Setup Node.js, install deps, and cache' runs: using: 'composite' steps: - uses: pnpm/action-setup@v3 with: version: 9 - uses: actions/setup-node@v4 with: node-version: 22 cache: 'pnpm' - run: pnpm install --frozen-lockfile shell: bash

使用:

steps: - uses: actions/checkout@v4 - uses: ./.github/actions/setup-project - run: pnpm build

環境保護ルール

本番デプロイに承認を要求:

jobs: deploy-prod: runs-on: ubuntu-latest environment: name: production url: https://myapp.com steps: - run: ./deploy.sh

リポ設定でproduction環境にレビュー必須を設定。

OIDCでクラウド認証

長期クラウド認証情報の保存やめよう。OIDCを:

jobs: deploy: runs-on: ubuntu-latest permissions: id-token: write contents: read steps: - uses: aws-actions/configure-aws-credentials@v4 with: role-to-assume: arn:aws:iam::123456789:role/GitHubActionsRole aws-region: us-east-1 - run: aws s3 sync ./dist s3://my-bucket

シークレット保存なし—GitHubがOIDCで一時認証情報を生成。

トラブルシューティング:よくある問題

"Resource not accessible by integration"

ワークフローに権限がない:

permissions: contents: read pull-requests: write issues: write

キャッシュが復元されない

キャッシュキーを確認。よくある問題:

  • lockfileがハッシュに入ってない
  • 保存時と復元時のランナーOSが違う
  • キャッシュ上限超過(リポあたり10GB)
- uses: actions/cache@v4 with: path: ~/.npm key: npm-${{ runner.os }}-${{ hashFiles('**/package-lock.json') }} restore-keys: | npm-${{ runner.os }}-

マトリックスジョブがタイムアウト

ジョブがハングしたら明示的タイムアウトとデバッグを追加:

jobs: test: timeout-minutes: 30 steps: - run: npm test timeout-minutes: 20 env: DEBUG: '*'

セルフホステッドランナーがオフライン

よくある原因:

  1. マシン再起動でサービスが起動しなかった
  2. トークン期限切れ(30日ごとに更新)
  3. ビルドアーティファクトでディスク満杯

モニタリング設定:

# ランナーステータス確認 sudo ./svc.sh status # ログを見る sudo journalctl -u actions.runner.*

完全なモノレポワークフロー

全部まとめたプロダクションレディワークフロー:

name: CI/CD on: push: branches: [main] pull_request: concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true jobs: changes: runs-on: ubuntu-latest outputs: packages: ${{ steps.filter.outputs.changes }} steps: - uses: actions/checkout@v4 - uses: dorny/paths-filter@v3 id: filter with: filters: | frontend: - 'packages/frontend/**' backend: - 'packages/backend/**' shared: - 'packages/shared/**' build-and-test: needs: changes if: ${{ needs.changes.outputs.packages != '[]' }} runs-on: ubuntu-latest strategy: fail-fast: false matrix: package: ${{ fromJson(needs.changes.outputs.packages) }} steps: - uses: actions/checkout@v4 - uses: ./.github/actions/setup-project - name: Build run: pnpm turbo build --filter=${{ matrix.package }} env: TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }} TURBO_TEAM: ${{ vars.TURBO_TEAM }} - name: Test run: pnpm turbo test --filter=${{ matrix.package }} - name: Upload coverage uses: codecov/codecov-action@v4 with: flags: ${{ matrix.package }} deploy: needs: build-and-test if: github.ref == 'refs/heads/main' runs-on: ubuntu-latest environment: production permissions: id-token: write contents: read steps: - uses: actions/checkout@v4 - uses: ./.github/actions/setup-project - uses: aws-actions/configure-aws-credentials@v4 with: role-to-assume: ${{ secrets.AWS_ROLE_ARN }} aws-region: us-east-1 - run: pnpm deploy

まとめ:45分から5分へ

これらのテクニックで:

  1. ビルド時間80%+短縮 - 変更検知、キャッシング、並列化
  2. コスト50%+削減 - 賢いランナー選択、並行制御
  3. 自信を持ってスケール - セルフホステッドランナー、ARC
  4. 安全なデプロイ - OIDC、環境保護

GitHub Actionsが単純CIツールから強力な自動化プラットフォームに成長しました。これをマスターしたチームはデプロイ速度と開発者体験で大きなアドバンテージを持てます。

一つの最適化から始めましょう—変更検知やリモートキャッシングとか。改善を測定して。繰り返して。未来の自分(とチーム)が感謝するはず。

さあ、パイプラインを速くしに行きましょう 🚀

GitHub ActionsCI/CDDevOpsMonorepoAutomationSelf-Hosted Runners

関連ツールを見る

Pockitの無料開発者ツールを試してみましょう