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つ:
- 変更検知なし:
packages/utilsだけ直したのに全パッケージビルド - 並列化なし:テストが順番に回る
- キャッシングなし:毎回ゼロから
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必要
使わない方がいい場合:
- 小さいチーム、シンプルビルド
- インフラ管理できない
- セキュリティ分離が最優先
セルフホステッドランナーセットアップ
-
GitHubでランナー作成:Settings → Actions → Runners → New self-hosted runner
-
サーバーで:
# ランナーダウンロード 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
- ワークフローで使用:
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: '*'
セルフホステッドランナーがオフライン
よくある原因:
- マシン再起動でサービスが起動しなかった
- トークン期限切れ(30日ごとに更新)
- ビルドアーティファクトでディスク満杯
モニタリング設定:
# ランナーステータス確認 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分へ
これらのテクニックで:
- ビルド時間80%+短縮 - 変更検知、キャッシング、並列化
- コスト50%+削減 - 賢いランナー選択、並行制御
- 自信を持ってスケール - セルフホステッドランナー、ARC
- 安全なデプロイ - OIDC、環境保護
GitHub Actionsが単純CIツールから強力な自動化プラットフォームに成長しました。これをマスターしたチームはデプロイ速度と開発者体験で大きなアドバンテージを持てます。
一つの最適化から始めましょう—変更検知やリモートキャッシングとか。改善を測定して。繰り返して。未来の自分(とチーム)が感謝するはず。
さあ、パイプラインを速くしに行きましょう 🚀
関連ツールを見る
Pockitの無料開発者ツールを試してみましょう