モノレポに Dependabot を素朴に入れると、月曜の朝に数十本のPRが並ぶ——そして誰も見なくなります。原因は明確で、モノレポでは更新対象が「パッケージ数 × 依存数」に膨らむからです。けれどこれは設計で解けます。directories で集約し、groups で束ね、cooldown で寝かせ、auto-merge で patch/minor を流す——この4点で、巨大モノレポでも依存更新は静かに自動化されます。
この記事はDependabot 本番運用ガイドの各論として、モノレポ特有の設計にフォーカスします。Turborepo / pnpm workspaces を主な題材にしますが、npm/yarn workspaces・Nx でも考え方は同じです。
この記事のルール:設定キー・挙動は GitHub 公式ドキュメント(2026年6月時点) に基づきます。
directories(グロブ)・group-byは比較的新しい機能です。本番前に必ず公式の設定リファレンスで最新を確認してください。
0. なぜモノレポで破綻するのか
通常リポジトリ: 1 つの package.json → 依存 N 個 → 最大 N 本のPR
モノレポ(素朴): M 個の package.json → 依存 N 個ずつ → 最大 M×N 本のPR
apps/ に5つ、packages/ に10、それぞれが数十の依存を持てば、容易に3桁のPRになります。これを「頻度を下げる」で誤魔化すと、今度は脆弱性対応が遅れます。正しい解は集約と束ねです。順に組み立てます。
1. directories のグロブで1エントリに集約
かつてはディレクトリの数だけ updates エントリを書いていました。いまは directories(複数形)+グロブで1エントリにまとめられます。
version: 2
updates:
- package-ecosystem: "npm"
directories:
- "/" # ルート(ワークスペース定義・共有devDeps)
- "/apps/*" # 各アプリ
- "/packages/**" # 共有パッケージ(再帰)
schedule:
interval: "weekly"
* は1階層、** は再帰。これで新しいアプリ/パッケージを足しても設定変更が不要になります(ETC:変更が一箇所に閉じる)。
2. ワークスペースとロックファイルの関係(ここが肝)
モノレポの依存解決はロックファイルの位置で決まります。
- pnpm workspaces:
pnpm-lock.yamlはリポジトリ・ルートに1つ。全ワークスペースの依存がここに解決されます。 - npm / yarn workspaces:同様にルートに単一のロックファイル(
package-lock.json/yarn.lock)。
つまり多くのモノレポでは、まずルート(/)の1エントリだけで、全ワークスペースの外部依存を更新できます。各 apps/* の package.json は「どの外部依存を使うか」を宣言しますが、解決の真実源はルートのロックファイルです。
# pnpm/npm/yarn workspaces:まずはルート1エントリで十分なことが多い
updates:
- package-ecosystem: "npm"
directory: "/"
schedule:
interval: "weekly"
個別アプリで異なる更新ポリシー(頻度・グループ・ignore)を分けたいときに初めて
directoriesで展開します。YAGNI:最初からアプリ単位に割らず、必要になってから割るのが運用を軽く保つコツです。
3. groups でPRを束ねる
集約しても、束ねなければPRは依存数だけ出ます。groups で意味のある単位にまとめます。
updates:
- package-ecosystem: "npm"
directory: "/"
schedule:
interval: "weekly"
groups:
types:
patterns: ["@types/*"]
testing:
patterns: ["vitest", "@testing-library/*", "playwright", "msw"]
linting:
patterns: ["eslint*", "prettier", "@typescript-eslint/*"]
# 上記以外の minor/patch を1本に(major は個別PRのまま)
minor-and-patch:
update-types: ["minor", "patch"]
exclude-patterns: ["@types/*", "vitest", "eslint*"]
これで「型」「テスト」「lint」「その他 minor/patch」の4〜5本に集約され、レビュー対象が劇的に減ります。groups の全オプションは設定完全ガイドへ。
4. group-by: dependency-name でディレクトリ横断に統合
アプリ単位で directories を割っている場合、「全アプリの react 更新がバラバラにPR化」されると本末転倒です。group-by: dependency-name でディレクトリをまたいで同一依存をまとめます。
- package-ecosystem: "npm"
directories: ["/apps/*"]
schedule:
interval: "weekly"
groups:
react-across-apps:
patterns: ["react", "react-dom", "next"]
group-by: "dependency-name" # 全 app の react/next 更新を1PRに
フレームワークのバージョンをモノレポ全体で揃える運用(バージョンスキューの防止)と相性が良い設定です。
5. 内部パッケージは更新対象外(だから楽)
モノレポでは内部パッケージを "@acme/ui": "workspace:*" のように参照します。この workspace:* 参照は Dependabot の更新対象になりません——内部パッケージのバージョンはモノレポ自身が管理するものだからです。
つまり Dependabot は外部依存の追従だけに集中します。「内部依存を ignore しなきゃ」と心配する必要はありません。内部パッケージ間の整合は、Turborepo/Nx のビルドグラフや changesets など別のツールの仕事です(SRP:責務を混ぜない)。
6. パッケージ別ポリシー(リスクに比例した更新)
すべてを同じ強度で更新する必要はありません。本番に近いほど慎重に割り当てます。
updates:
# アプリ:積極的に追従(minor/patch は groups でまとめ auto-merge 前提)
- package-ecosystem: "npm"
directories: ["/apps/*"]
schedule:
interval: "weekly"
groups:
app-minor-patch:
update-types: ["minor", "patch"]
ignore:
- dependency-name: "*"
update-types: ["version-update:semver-major"] # major は人間が棚卸し
# 共有ライブラリ:保守的(月次・cooldown 長め)
- package-ecosystem: "npm"
directories: ["/packages/**"]
schedule:
interval: "monthly"
cooldown:
default-days: 14
共有ライブラリの破壊的変更は全アプリに波及します。だから libs は頻度を落とし cooldown を長めに。アプリは速く小さく追従。この使い分けが、安定性と鮮度のトレードオフを地に足のついた形で解きます。
7. CI と auto-merge:影響範囲だけ回す
モノレポで全パッケージをフルテストすると、Dependabot PR のたびに CI 時間(=Actions 課金)を浪費します。影響パッケージだけテストします。
# .github/workflows/ci.yml(抜粋)— Turborepo の filter で影響範囲のみ
- run: pnpm install --frozen-lockfile
- run: pnpm turbo run lint test build --filter="...[origin/main]"
--filter="...[origin/main]" は「変更の影響を受けるパッケージとその依存元だけ」を回す指定。Dependabot PR の差分に応じて必要最小限のテストになり、速く・安く・確実になります。
その上でauto-mergeを組み合わせ、グループ化された patch/minor を CI 条件付きで自動マージします。
- name: Auto-merge grouped patch/minor
if: |
steps.meta.outputs.dependency-group != '' &&
steps.meta.outputs.update-type != 'version-update:semver-major'
run: gh pr merge --auto --squash "$PR_URL"
env:
PR_URL: ${{ github.event.pull_request.html_url }}
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
8. モノレポ運用チェックリスト
- ルート1エントリから始める(ワークスペースのロックファイルはルート単一)
- アプリ別ポリシーが要るときだけ
directoriesで展開(YAGNI) -
groupsで型/テスト/lint/その他 minor-patch を束ねる - アプリ横断のバージョン統一は
group-by: dependency-name - 共有ライブラリは月次+長め cooldown、アプリは週次+積極追従
- CI は影響範囲のみ(Turborepo/Nx の filter)で時間とコストを最小化
- グループ化 patch/minor は auto-merge、major は人間レビュー
9. FAQ
Q. apps と packages で全部 package.json があります。エントリも分けるべき?
A. まずはルート1エントリで十分なことが多いです(ワークスペースのロックファイルはルート単一)。頻度やグループを個別に変えたくなってから directories で割ってください。
Q. 全アプリの react がバラバラにPR化されます。
A. directories を割っているなら group-by: dependency-name で同一依存をディレクトリ横断にまとめてください。バージョンスキューも防げます。
Q. 内部パッケージ(workspace:*)も更新されますか? A. されません。Dependabot は外部依存だけを見ます。内部整合は changesets や Turborepo/Nx の仕事です。
Q. PRごとに全パッケージのCIが回って遅い・高いです。 A. Turborepo/Nx の filter で影響範囲だけテストしてください。Dependabot は標準ランナーで無料ですが、CI 自体は通常通り Actions 分を消費します。
Q. pnpm の pnpm-lock.yaml は正しく更新されますか?
A. はい。Dependabot はルートのロックファイルを解決して更新します。ロックファイルは必ずコミットしてください。