Monorepo Turborepo Remote Cache 設計完全ガイド|CI パイプライン・GitHub Actions・2026 実践
- Monorepo CI のボトルネックは 「毎 PR 全パッケージビルド」 だ。
- Turborepo の タスクグラフ + Remote Cache +
--filter=...[origin/main]で影響範囲だけ実行し、CI 時間を 70% 以上削減できる。 - 2026 年の定番構成は pnpm workspace + turbo.json pipeline + Vercel/S3 Remote Cache + GitHub Actions matrix 分割。
- OpenAPI CI バリデーション など横断品質ゲートも turbo タスクとして統合し、Required Check 一本化が保守しやすい。
なぜ Monorepo に Turborepo Remote Cache が必要か
フロントエンド、バックエンド API、共有 UI ライブラリ、OpenAPI 生成クライアント——複数パッケージを 1 リポジトリ にまとめる Monorepo は、コード共有と atomic change の恩恵が大きい。反面、CI 時間はパッケージ数に比例して膨らむ。
従来の「各 package.json で npm run build を順番に実行」では、変更していないパッケージまで毎回ビルド してしまう。GitHub Actions の無料枠 2,000 分/月をすぐ消費し、開発者は PR マージを待つ時間が増える。
Turborepo は次の 3 層でこの問題を解く。
- タスクグラフ(pipeline) —
dependsOn: ["^build"]で依存順序を宣言的に定義 - ローカルキャッシュ — 同一マシン内で inputs ハッシュが一致すれば再実行をスキップ
- Remote Cache — チーム全員と CI runner がキャッシュアーティファクトを S3 / Vercel 経由で共有
Remote Cache が効くと、main ブランチで一度ビルドした packages/ui の dist/ が、別開発者の laptop や PR CI から ネットワーク経由で即座に復元 される。ビルド時間ではなく ダウンロード時間 になる。
| Remote Cache なし | Remote Cache あり |
|---|---|
| PR ごとに全 12 パッケージ build | 変更 2 パッケージ + 依存 1 件のみ build |
| CI 18 分、月 4,000 分消費 | CI 4 分、キャッシュ warm-up で main は 6 分 |
| ローカルと CI で別々に同じ compile | main CI の成果物を feature ブランチが再利用 |
| lint/test も毎回フル実行 | inputs 未変更タスクは 0 秒で skip |
Monorepo ディレクトリ構成(2026 定番)
以下は Next.js アプリ、Express API、共有 UI、OpenAPI クライアント生成を含む典型的構成だ。
monorepo/
├── apps/
│ ├── web/ # Next.js 15 フロント
│ ├── api/ # Node.js API サーバー
│ └── docs/ # Astro / Starlight ドキュメント
├── packages/
│ ├── ui/ # React コンポーネントライブラリ
│ ├── config-eslint/ # 共有 ESLint 設定
│ ├── config-typescript/ # 共有 tsconfig
│ └── api-client/ # OpenAPI から生成された SDK
├── openapi/
│ └── openapi.yaml # API 契約の Single Source of Truth
├── turbo.json
├── pnpm-workspace.yaml
├── package.json
└── .github/
└── workflows/
├── ci.yml
├── ci-main.yml
└── release.yml
OpenAPI 仕様の CI バリデーションは OpenAPI CI バリデーション完全ガイド で解説した validate → lint → diff パイプラインを、turbo.json の validate:openapi タスクとして組み込む。Monorepo では API 契約変更が複数 apps に波及するため、merge 前の spec 検証は必須 だ。
turbo.json 設計:ルート pipeline 定義
Turborepo 2.x の turbo.json は ルート 1 ファイル で全 workspace を統治する。以下は本番運用を想定した 完全なルート turbo.json だ。
{
"$schema": "https://turbo.build/schema.json",
"ui": "tui",
"globalDependencies": [
".env",
"tsconfig.json",
"pnpm-lock.yaml"
],
"globalEnv": [
"NODE_ENV",
"CI",
"VERCEL",
"VERCEL_ENV"
],
"globalPassThroughEnv": [
"npm_lifecycle_event",
"TURBO_TEAM",
"TURBO_TOKEN",
"TURBO_API",
"TURBO_REMOTE_CACHE_SIGNATURE_KEY"
],
"tasks": {
"build": {
"dependsOn": ["^build"],
"inputs": ["$TURBO_DEFAULT$", ".env*"],
"outputs": ["dist/**", ".next/**", "!.next/cache/**", "build/**"],
"env": [
"NEXT_PUBLIC_API_URL",
"NEXT_PUBLIC_APP_ENV"
]
},
"dev": {
"cache": false,
"persistent": true
},
"lint": {
"dependsOn": ["^build"],
"inputs": ["$TURBO_DEFAULT$", "../../packages/config-eslint/**"]
},
"typecheck": {
"dependsOn": ["^build"],
"inputs": ["$TURBO_DEFAULT$", "tsconfig.json", "tsconfig.*.json"]
},
"test": {
"dependsOn": ["^build"],
"inputs": ["$TURBO_DEFAULT$", "**/*.test.ts", "**/*.test.tsx", "**/*.spec.ts"],
"outputs": ["coverage/**"],
"env": ["VITEST_POOL", "TZ"]
},
"test:e2e": {
"dependsOn": ["build"],
"inputs": ["$TURBO_DEFAULT$", "e2e/**", "playwright.config.ts"],
"outputs": ["playwright-report/**", "test-results/**"],
"env": ["PLAYWRIGHT_BROWSERS_PATH", "BASE_URL"],
"cache": true
},
"validate:openapi": {
"dependsOn": [],
"inputs": [
"../../openapi/**",
"../../.spectral.yaml",
"../../scripts/validate-openapi.mjs"
],
"outputs": [],
"cache": true
},
"generate:api-client": {
"dependsOn": ["validate:openapi"],
"inputs": ["../../openapi/openapi.yaml", "orval.config.ts"],
"outputs": ["src/generated/**"]
},
"clean": {
"cache": false
}
}
}
設計上のポイント
| キー | 意図 |
|---|---|
dependsOn: ["^build"] | 依存 workspace の build 完了後に実行(キャレット ^ は upstream) |
inputs | ハッシュ対象ファイル。未変更ならキャッシュヒット |
outputs | Remote Cache にアップロードする成果物パス |
env | 値が変わるとキャッシュミス。公開 env のみ列挙 |
cache: false | dev サーバー等、キャッシュ不要タスク |
env に DATABASE_URL や JWT_SECRET を入れると、値が runner ごとに異なり 常にキャッシュミス になる。シークレットはタスク内で参照するだけにし、inputs/env には含めない。build 成果物に secrets が混入しないよう outputs も慎重に設計する。
apps/web 専用 turbo.json(Package Configurations)
Turborepo 2.x の Package Configurations を使うと、パッケージ単位で pipeline を上書きできる。Next.js アプリ apps/web/turbo.json の完全例:
{
"$schema": "https://turbo.build/schema.json",
"extends": ["//"],
"tasks": {
"build": {
"dependsOn": ["^build", "generate:api-client"],
"inputs": [
"$TURBO_DEFAULT$",
"next.config.ts",
"postcss.config.mjs",
"tailwind.config.ts"
],
"outputs": [".next/**", "!.next/cache/**"],
"env": [
"NEXT_PUBLIC_API_URL",
"NEXT_PUBLIC_ANALYTICS_ID",
"NEXT_PUBLIC_APP_ENV"
]
},
"test:e2e": {
"dependsOn": ["build"],
"inputs": ["e2e/**", "playwright.config.ts"],
"outputs": ["playwright-report/**"],
"env": ["BASE_URL", "E2E_AUTH_TOKEN"],
"passThroughEnv": ["PLAYWRIGHT_BROWSERS_PATH"]
}
}
}
extends: ["//"] はルート turbo.json を継承する記法だ。アプリ固有の next.config.ts を inputs に追加することで、設定変更時だけ build キャッシュが無効化される。
packages/ui 共有ライブラリの turbo.json
UI ライブラリは 最もキャッシュヒット率が高い パッケージになりやすい。変更頻度が低く、複数 apps から dependsOn: ["^build"] で参照されるためだ。
{
"$schema": "https://turbo.build/schema.json",
"extends": ["//"],
"tasks": {
"build": {
"dependsOn": [],
"inputs": ["src/**", "tsconfig.json", "tsup.config.ts"],
"outputs": ["dist/**"],
"env": []
},
"test": {
"dependsOn": [],
"inputs": ["src/**", "**/*.test.tsx", "vitest.config.ts"],
"outputs": ["coverage/**"]
}
}
}
packages/ui/dist/** が Remote Cache に載ると、apps/web と apps/docs の build が compile なしでリンク できる。
Remote Cache アーキテクチャ
Remote Cache のデータフローは次のとおり。
sequenceDiagram
participant Dev as 開発者 laptop
participant CI as GitHub Actions
participant Turbo as Turborepo CLI
participant RC as Remote Cache (Vercel/S3)
Dev->>Turbo: turbo run build
Turbo->>Turbo: inputs ハッシュ計算
Turbo->>RC: GET cache/{hash}
alt キャッシュヒット
RC-->>Turbo: artifacts (dist, .next)
Turbo-->>Dev: 復元完了 (skip build)
else キャッシュミス
Turbo->>Turbo: タスク実行
Turbo->>RC: PUT cache/{hash}
Turbo-->>Dev: ビルド完了
end
CI->>Turbo: turbo run build --filter=...[origin/main]
Turbo->>RC: GET (Dev が upload した hash)
RC-->>Turbo: ヒット → CI 時間短縮
Vercel Remote Cache(最速セットアップ)
Vercel アカウントとリンクしていなくても、Standalone Remote Cache として利用できる。
# ローカル初回セットアップ
pnpm dlx turbo login
pnpm dlx turbo link
# 確認
pnpm turbo run build --summarize
GitHub Secrets に登録する値:
| Secret | 説明 |
|---|---|
TURBO_TOKEN | Vercel ダッシュボード → Settings → Tokens |
TURBO_TEAM | チーム slug(team_xxx 形式) |
セルフホスト S3 Remote Cache
データ residency 要件がある組織向け。Turborepo の Remote Cache API は HTTP ベースで、community プロキシまたは @turbo/gen テンプレートで S3 バックエンドを構築できる。
# 環境変数(GitHub Actions / ローカル共通)
export TURBO_API="https://turbo-cache.internal.example.com"
export TURBO_TOKEN="Bearer eyJhbGciOiJIUzI1NiIs..."
export TURBO_TEAM="acme-corp"
export TURBO_REMOTE_CACHE_SIGNATURE_KEY="base64-encoded-32-bytes-key"
S3 バケットポリシーでは CI OIDC ロールからの PutObject/GetObject のみ 許可し、パブリックアクセスは Block する。
[object Object]
[object Object]
[object Object]
[object Object]
[object Object]
pnpm workspace 設定
ルート pnpm-workspace.yaml:
packages:
- "apps/*"
- "packages/*"
ルート package.json:
{
"name": "acme-monorepo",
"private": true,
"packageManager": "[email protected]",
"scripts": {
"build": "turbo run build",
"dev": "turbo run dev",
"lint": "turbo run lint",
"test": "turbo run test",
"typecheck": "turbo run typecheck",
"validate:openapi": "turbo run validate:openapi",
"ci": "turbo run lint typecheck test build validate:openapi --filter=...[origin/main]"
},
"devDependencies": {
"turbo": "^2.5.0",
"typescript": "^5.8.0"
},
"engines": {
"node": ">=20.0.0",
"pnpm": ">=9.0.0"
}
}
GitHub Actions:PR CI ワークフロー(完全版)
以下は pull_request 時 に影響パッケージだけ lint / test / build する .github/workflows/ci.yml の完全例だ。
name: CI
on:
pull_request:
branches: [main]
paths-ignore:
- "**/*.md"
- "docs/**"
concurrency:
group: ci-${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: true
env:
TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }}
TURBO_TEAM: ${{ secrets.TURBO_TEAM }}
FORCE_COLOR: 3
CI: true
jobs:
changes:
name: Detect affected packages
runs-on: ubuntu-latest
outputs:
has-changes: ${{ steps.filter.outputs.changes }}
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- uses: pnpm/action-setup@v4
with:
version: 9
- uses: actions/setup-node@v4
with:
node-version: 20
cache: pnpm
- name: Install dependencies
run: pnpm install --frozen-lockfile
- name: Check affected
id: filter
run: |
AFFECTED=$(pnpm turbo run build --filter=...[origin/main] --dry-run=json | jq '.tasks | length')
echo "Affected tasks: $AFFECTED"
if [ "$AFFECTED" -gt 0 ]; then
echo "changes=true" >> "$GITHUB_OUTPUT"
else
echo "changes=false" >> "$GITHUB_OUTPUT"
fi
quality:
name: Lint, Test, Build
needs: changes
if: needs.changes.outputs.has-changes == 'true'
runs-on: ubuntu-latest
timeout-minutes: 30
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- uses: pnpm/action-setup@v4
with:
version: 9
- uses: actions/setup-node@v4
with:
node-version: 20
cache: pnpm
- name: Install dependencies
run: pnpm install --frozen-lockfile
- name: Turbo lint + typecheck + test + build
run: |
pnpm turbo run lint typecheck test build validate:openapi \
--filter=...[origin/main] \
--summarize \
--continue
- name: Upload Turbo Run Summary
if: always()
uses: actions/upload-artifact@v4
with:
name: turbo-run-summary
path: .turbo/runs
retention-days: 14
- name: Report cache hit rate
if: always()
run: |
if [ -d .turbo/runs ]; then
CACHED=$(find .turbo/runs -name "*.json" -exec jq -r '.tasks[] | select(.cache.status == "HIT") | .taskId' {} \; 2>/dev/null | wc -l)
TOTAL=$(find .turbo/runs -name "*.json" -exec jq -r '.tasks[] | .taskId' {} \; 2>/dev/null | wc -l)
echo "Cache hits: $CACHED / $TOTAL"
fi
--filter=...[origin/main] の読み方
| フィルタ | 意味 |
|---|---|
--filter=web | web パッケージのみ |
--filter=web... | web とその依存(downstream) |
--filter=...web | web に依存する全パッケージ(upstream) |
--filter=...[origin/main] | main との git diff から影響パッケージを自動算出 |
PR CI では ...[origin/main] が最頻出。OpenAPI 変更 → packages/api-client → apps/web という依存チェーンも Turborepo が自動追跡する。
GitHub Actions:main ブランチ キャッシュ warm-up
main への merge 後に フルビルド して Remote Cache を seed する。feature ブランチ PR が main の最新キャッシュを引き継げる。
name: CI Main (Cache Warm-up)
on:
push:
branches: [main]
paths-ignore:
- "**/*.md"
concurrency:
group: ci-main-${{ github.sha }}
cancel-in-progress: false
env:
TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }}
TURBO_TEAM: ${{ secrets.TURBO_TEAM }}
CI: true
jobs:
warm-cache:
name: Full build and cache upload
runs-on: ubuntu-latest
timeout-minutes: 45
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- uses: pnpm/action-setup@v4
with:
version: 9
- uses: actions/setup-node@v4
with:
node-version: 20
cache: pnpm
- name: Install dependencies
run: pnpm install --frozen-lockfile
- name: Full turbo pipeline
run: |
pnpm turbo run lint typecheck test build validate:openapi generate:api-client \
--summarize
- name: Upload summary artifact
if: always()
uses: actions/upload-artifact@v4
with:
name: turbo-main-summary-${{ github.sha }}
path: .turbo/runs
retention-days: 30
GitHub Actions:matrix 分割で E2E 並列化
E2E は重いので shard 分割 + Remote Cache を組み合わせる。apps/web/turbo.json の test:e2e タスクを利用。
name: E2E
on:
pull_request:
branches: [main]
paths:
- "apps/web/**"
- "packages/ui/**"
env:
TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }}
TURBO_TEAM: ${{ secrets.TURBO_TEAM }}
CI: true
jobs:
e2e:
name: Playwright shard ${{ matrix.shard }}
runs-on: ubuntu-latest
timeout-minutes: 25
strategy:
fail-fast: false
matrix:
shard: [1, 2, 3, 4]
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- uses: pnpm/action-setup@v4
with:
version: 9
- uses: actions/setup-node@v4
with:
node-version: 20
cache: pnpm
- name: Install dependencies
run: pnpm install --frozen-lockfile
- name: Install Playwright browsers
run: pnpm exec playwright install --with-deps chromium
working-directory: apps/web
- name: Build (cached)
run: pnpm turbo run build --filter=web
- name: Run E2E shard
run: |
pnpm turbo run test:e2e --filter=web -- \
--shard=${{ matrix.shard }}/4
env:
BASE_URL: http://127.0.0.1:3000
- name: Upload Playwright report
if: failure()
uses: actions/upload-artifact@v4
with:
name: playwright-report-shard-${{ matrix.shard }}
path: apps/web/playwright-report
retention-days: 7
build ステップが Remote Cache ヒットすれば、4 shard すべてが 同一 cached .next からスタートできる。
GitHub Actions:OpenAPI バリデーション統合
OpenAPI CI バリデーション で構築した validate / lint / diff を Monorepo タスクとして統合する。openapi/ 変更時のみ走らせる dedicated workflow:
name: OpenAPI CI
on:
pull_request:
paths:
- "openapi/**"
- ".spectral.yaml"
- "scripts/validate-openapi.mjs"
- "packages/api-client/**"
env:
TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }}
TURBO_TEAM: ${{ secrets.TURBO_TEAM }}
CI: true
jobs:
openapi:
name: Validate OpenAPI spec
runs-on: ubuntu-latest
timeout-minutes: 10
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- uses: pnpm/action-setup@v4
with:
version: 9
- uses: actions/setup-node@v4
with:
node-version: 20
cache: pnpm
- name: Install dependencies
run: pnpm install --frozen-lockfile
- name: Validate, lint, diff OpenAPI
run: pnpm turbo run validate:openapi --summarize
- name: Regenerate API client (dry check)
run: pnpm turbo run generate:api-client --summarize
- name: Check for uncommitted generated files
run: |
if ! git diff --exit-code packages/api-client/src/generated; then
echo "Generated API client is out of date. Run pnpm turbo run generate:api-client locally."
exit 1
fi
validate:openapi タスクの inputs に openapi/** を指定しているため、spec ファイルが変わらなければ CI スキップ される。
packages/api-client の turbo.json
OpenAPI から SDK を生成するパッケージ。validate タスク完了後のみ実行。
{
"$schema": "https://turbo.build/schema.json",
"extends": ["//"],
"tasks": {
"generate:api-client": {
"dependsOn": ["validate:openapi"],
"inputs": [
"../../openapi/openapi.yaml",
"orval.config.ts",
"package.json"
],
"outputs": ["src/generated/**"],
"cache": true
},
"build": {
"dependsOn": ["generate:api-client"],
"inputs": ["src/**", "tsconfig.json", "tsup.config.ts"],
"outputs": ["dist/**"]
}
}
}
GitHub Actions:リリース workflow
タグ push 時に キャッシュを使いつつ 本番 build + publish する完全例。
name: Release
on:
push:
tags:
- "v*.*.*"
permissions:
contents: read
id-token: write
env:
TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }}
TURBO_TEAM: ${{ secrets.TURBO_TEAM }}
CI: true
jobs:
release:
name: Build and publish packages
runs-on: ubuntu-latest
timeout-minutes: 60
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- uses: pnpm/action-setup@v4
with:
version: 9
- uses: actions/setup-node@v4
with:
node-version: 20
cache: pnpm
registry-url: https://registry.npmjs.org
- name: Install dependencies
run: pnpm install --frozen-lockfile
- name: Build all packages
run: pnpm turbo run build validate:openapi --summarize
- name: Publish packages
run: pnpm turbo run publish-packages
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
- name: Upload build artifacts
uses: actions/upload-artifact@v4
with:
name: release-build-${{ github.ref_name }}
path: |
apps/web/.next
packages/ui/dist
packages/api-client/dist
retention-days: 90
キャッシュヒット率の最適化
Remote Cache の効果は ヒット率 に直結する。2026 年の実務で効く調整をまとめる。
1. inputs を最小限かつ正確に
{
"tasks": {
"build": {
"inputs": ["src/**", "package.json", "tsconfig.json", "vite.config.ts"],
"outputs": ["dist/**"]
}
}
}
README.md や CHANGELOG.md を inputs に含めると、ドキュメント修正だけで build キャッシュが全失効する。
2. globalDependencies の慎重な運用
ルート package.json の devDependencies 更新(turbo バージョンアップ等)は 全タスクキャッシュを無効化 する。Renovate PR では --force 再ビルドを許容し、merge 後に warm-up job で seed し直す。
3. --summarize で可視化
pnpm turbo run build --summarize
# .turbo/runs/<id>.json に HIT/MISS 一覧
週次で .turbo/runs を集計し、MISS 率が高いタスク の env/inputs を監査する。
4. ロックファイルの統一
pnpm の pnpm-lock.yaml は globalDependencies に含める。npm / yarn 混在は hash 不一致の温床。
| キャッシュミス原因 | 対策 |
|---|---|
| env に DATABASE_URL を列挙 | env から削除、runtime のみ参照 |
| outputs に .next/cache を含む | !.next/cache/** で除外 |
| 各 package で Node バージョン不一致 | .node-version + engines 統一 |
| generate タスクが非決定的 | OpenAPI generator の version 固定 |
| PR で fetch-depth: 1 | fetch-depth: 0 で filter 正確化 |
Turborepo と Nx / Lage の比較
| 観点 | Turborepo | Nx | Lage |
|---|---|---|---|
| 学習曲線 | 低(turbo.json のみ) | 中〜高(プラグインエコシステム) | 低 |
| Remote Cache | Vercel / セルフホスト | Nx Cloud | Azure Blob |
| JS/TS 特化 | 強い | 強い(フレームワーク統合) | Microsoft 内部向け |
| CI 連携 | --filter が簡潔 | affected コマンド | pipeline 定義 |
| 2026 トレンド | pnpm + Turbo 定番 | エンタープライズ Java/TS | 限定的 |
新規 JS/TS Monorepo なら Turborepo + pnpm が初期コスト最小。Java/Kotlin 混在なら Nx を検討。
セキュリティチェックリスト
Remote Cache は ビルド成果物を外部ストレージに置く 設計だ。以下を merge 前に確認する。
- TURBO_TOKEN — 最小スコープ、90 日ローテーション、漏洩時は即 revoke
- outputs 監査 —
dist/に.env.productionや source map が含まれないか - 署名キー —
TURBO_REMOTE_CACHE_SIGNATURE_KEYで artifact tampering 検知 - PR fork 対策 — fork PR では Secrets を渡さない(
pull_request_target禁止) - S3 暗号化 — SSE-KMS、バケットポリシーで IP/VPC 制限
fork PR 向け CI では Remote Cache read-only に留め、write は github.ref == 'refs/heads/main' の job のみに限定する。
ローカル開発ワークフロー
# 初回
pnpm install
pnpm dlx turbo login
pnpm dlx turbo link
# 日常開発(web と依存だけ)
pnpm turbo run dev --filter=web
# PR 前チェック(origin/main との差分のみ)
git fetch origin main
pnpm turbo run lint typecheck test build validate:openapi --filter=...[origin/main]
# キャッシュ状態確認
pnpm turbo run build --dry-run
pnpm turbo run build --summarize
main CI が warm-up 済みなら、ローカルの --filter=...[origin/main] は 大半 HIT になり、ラップトップのファンが静かになる。
トラブルシューティング
キャッシュヒットしない
# 詳細ログ
TURBO_LOG_VERBOSITY=2 pnpm turbo run build --force
# ハッシュ差分の原因調査
pnpm turbo run build --dry-run=json | jq '.tasks[] | {task: .taskId, hash: .hash, inputs: .inputs}'
よくある原因:pnpm-lock.yaml 変更、Node バージョン差、globalEnv の VERCEL がローカルのみ設定されている。
Remote Cache 接続エラー
Error: Failed to connect to Remote Cache
TURBO_TOKEN期限切れ → 再発行- 企業プロキシ →
HTTPS_PROXY設定 - セルフホスト
TURBO_APIの TLS 証明書 → runner に CA 追加
--filter=...[origin/main] が空
fetch-depth: 0 未設定で shallow clone だと git diff が不完全。actions/checkout@v4 で fetch-depth: 0 を必ず指定する。
2026 年の Monorepo CI ベストプラクティスまとめ
[object Object]
[object Object]
[object Object]
[object Object]
[object Object]
[object Object]
Monorepo の CI は 「全部走らせない」 が鉄則だ。Turborepo Remote Cache は、その方針を インフラとして強制 する。
- turbo.json — タスク依存と inputs/outputs をコード化
- Remote Cache — チーム + CI で成果物共有
--filter=...[origin/main]— git diff ベースの部分実行- GitHub Actions — concurrency、cancellation、matrix 分割
- OpenAPI 連携 — OpenAPI CI バリデーション と generate タスク統合
API 契約、UI コンポーネント、Web アプリが 1 リポジトリに共存する時代、ビルドパイプラインの設計 が開発速度を決める。Turborepo Remote Cache は 2026 年時点で 最もコスト対効果の高い Monorepo CI 基盤 の一つだ。
関連記事
この記事は インフラ・DNS テーマの一環です。あわせて読むと理解が深まる関連記事をまとめました。
| トピック | 記事 |
|---|---|
| DNSが反映されたか確認する方法 | DNSが反映されたか確認する方法|nslookupとdigコマンドの使い方 |
| HTTPSレコードとSVCBレコードの完全解説 | HTTPSレコードとSVCBレコードの完全解説|ALPN・ECH・HTTP/3のDNS設定 |
| CNAME lookup・DNS check の確認手順とよくある失敗 | CNAME lookup・DNS check の確認手順とよくある失敗 |
| SSL証明書の有効期限を確認する方法 | SSL証明書の有効期限を確認する方法|opensslコマンドと注意点 |
| .htaccessでリダイレクトをかける方法 | .htaccessでリダイレクトをかける方法|301と302の使い分け |
| robots.txtの書き方と役割 | robots.txtの書き方と役割|クローラーを正しく制御する方法 |
| AIクローラー対応 robots.txt・llms.txt 設定ガイド 2026 | AIクローラー対応 robots.txt・llms.txt 設定ガイド 2026|GPTBot・ClaudeBot・Google-Extended・GEO戦略 |
| ブログの SEO と JSON-LD 構造化データ入門 | ブログの SEO と JSON-LD 構造化データ入門 |
| 依存関係脆弱性管理とSBOM CycloneDX完全ガイド | 依存関係脆弱性管理とSBOM CycloneDX完全ガイド|npm audit・OSV・Dependabot・サプライチェーンセキュリティ2026 |
| Redisキャッシュスタンピード防止ガイド | Redisキャッシュスタンピード防止ガイド|Singleflight・Mutex・SET NX・確率的早期失効 |
| Git Worktree 並行開発ワークフロー完全ガイド | Git Worktree 並行開発ワークフロー完全ガイド|複数ブランチ同時作業・IDE設定・CI連携(2026) |
| JSONの「Unexpected token」エラー原因と対処法 | JSONの「Unexpected token」エラー原因と対処法 |