はじめに
こんにちは、エンジニアのケイタMAXです。
今回はDependabotの設定をして、ライブラリのアップデートを検知して自動でPRを作ってもらおうと思います
デフォルト設定だと 1 ライブラリにつき 1 PR が作られるため、例えば Storybook だけで 10 個以上の PR が並ぶこともあります。
この記事では Laravel + Inertia + React プロジェクトを例に、類似ライブラリを 1 つの PR にまとめる groups 機能 を活用した設定をします。
対象プロジェクトの構成
今回設定するプロジェクトは以下のような構成です。
Docker・Laravel・React(Inertia)で作ってるリポジトリで行います。
.
├── .github/
│ └── workflows/
├── docker/
│ ├── app/Dockerfile
│ ├── db/Dockerfile
│ ├── nginx/Dockerfile
│ └── swagger/Dockerfile
├── package.json # ルート (husky)
└── src/
├── package.json # Laravel フロント (React/Vite/Storybook)
└── composer.json # Laravel バック
Dependabot で以下の 7 箇所を監視したいと思います。
| エコシステム | ディレクトリ | 内容 |
|---|---|---|
| npm | / |
husky |
| npm | /src |
React / Vite / Storybook / ESLint など |
| composer | /src |
Laravel / PHPStan / PHPUnit など |
| docker | /docker/app |
PHP |
| docker | /docker/db |
MySQL |
| docker | /docker/nginx |
Nginx |
| docker | /docker/swagger |
Swagger UI |
| github-actions | / |
ワークフロー |
Dependabot の groups 機能とは
Dependabot v2 の groups を使うと、条件にマッチした複数の依存関係を 1 つの PR にまとめる ことができます。
groups:
storybook:
patterns:
- "@storybook/*"
- "storybook"
例えば上記のように設定すると、Storybook 関連のアップデートが 1 つの PR にまとめられ、レビューも CI も 1 回で済みます。
また、update-types を使うと minor / patch のみグループ化し、major は個別 PR にするといった設定も可能です。major は破壊的変更を含むことが多いので、個別にしたい場合に有効です。
groups:
other-minor-patch:
update-types:
- "minor"
- "patch"
完成した dependabot.yml
全体像はこちらです。
version: 2
updates:
# ルート package.json (husky)
- package-ecosystem: "npm"
directory: "/"
schedule:
interval: "weekly"
day: "monday"
time: "09:00"
timezone: "Asia/Tokyo"
open-pull-requests-limit: 5
labels:
- "dependencies"
- "npm"
commit-message:
prefix: "chore(deps)"
prefix-development: "chore(deps-dev)"
include: "scope"
groups:
root-npm-minor-patch:
update-types:
- "minor"
- "patch"
# src/package.json (Laravel フロントエンド)
- package-ecosystem: "npm"
directory: "/src"
schedule:
interval: "weekly"
day: "monday"
time: "09:00"
timezone: "Asia/Tokyo"
open-pull-requests-limit: 10
labels:
- "dependencies"
- "npm"
commit-message:
prefix: "chore(deps)"
prefix-development: "chore(deps-dev)"
include: "scope"
groups:
storybook:
patterns:
- "@storybook/*"
- "storybook"
- "@chromatic-com/storybook"
- "msw-storybook-addon"
eslint:
patterns:
- "eslint"
- "eslint-*"
- "@eslint/*"
- "typescript-eslint"
- "globals"
react:
patterns:
- "react"
- "react-dom"
- "react-slick"
- "slick-carousel"
- "@headlessui/react"
types:
patterns:
- "@types/*"
tailwind:
patterns:
- "tailwindcss"
- "@tailwindcss/*"
- "autoprefixer"
- "postcss"
- "eslint-plugin-tailwindcss"
vite:
patterns:
- "vite"
- "@vitejs/*"
- "laravel-vite-plugin"
inertia:
patterns:
- "@inertiajs/*"
- "ziggy-js"
msw:
patterns:
- "msw"
typescript:
patterns:
- "typescript"
other-minor-patch:
update-types:
- "minor"
- "patch"
# src/composer.json (Laravel バックエンド)
- package-ecosystem: "composer"
directory: "/src"
schedule:
interval: "weekly"
day: "monday"
time: "09:00"
timezone: "Asia/Tokyo"
open-pull-requests-limit: 10
labels:
- "dependencies"
- "composer"
commit-message:
prefix: "chore(deps)"
prefix-development: "chore(deps-dev)"
include: "scope"
groups:
laravel:
patterns:
- "laravel/*"
- "laravel-lang/*"
- "tightenco/ziggy"
- "inertiajs/*"
phpstan:
patterns:
- "larastan/*"
- "phpstan/*"
phpcs:
patterns:
- "squizlabs/php_codesniffer"
- "slevomat/coding-standard"
- "sirbrillig/phpcs-variable-analysis"
- "dealerdirect/phpcodesniffer-composer-installer"
testing:
patterns:
- "phpunit/*"
- "mockery/*"
- "fakerphp/*"
spatie:
patterns:
- "spatie/*"
swagger:
patterns:
- "zircote/*"
other-minor-patch:
update-types:
- "minor"
- "patch"
# Docker (app / db / nginx / swagger)
- package-ecosystem: "docker"
directory: "/docker/app"
schedule:
interval: "weekly"
day: "monday"
time: "09:00"
timezone: "Asia/Tokyo"
labels:
- "dependencies"
- "docker"
commit-message:
prefix: "chore(docker)"
include: "scope"
- package-ecosystem: "docker"
directory: "/docker/db"
schedule:
interval: "weekly"
day: "monday"
time: "09:00"
timezone: "Asia/Tokyo"
labels:
- "dependencies"
- "docker"
commit-message:
prefix: "chore(docker)"
include: "scope"
- package-ecosystem: "docker"
directory: "/docker/nginx"
schedule:
interval: "weekly"
day: "monday"
time: "09:00"
timezone: "Asia/Tokyo"
labels:
- "dependencies"
- "docker"
commit-message:
prefix: "chore(docker)"
include: "scope"
- package-ecosystem: "docker"
directory: "/docker/swagger"
schedule:
interval: "weekly"
day: "monday"
time: "09:00"
timezone: "Asia/Tokyo"
labels:
- "dependencies"
- "docker"
commit-message:
prefix: "chore(docker)"
include: "scope"
# GitHub Actions
- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: "weekly"
day: "monday"
time: "09:00"
timezone: "Asia/Tokyo"
labels:
- "dependencies"
- "github-actions"
commit-message:
prefix: "chore(ci)"
include: "scope"
groups:
github-actions:
patterns:
- "*"
設定のポイント解説(AI解説)
量が多かったのでAIに一つづつ解説させました。
以下はAIが書いた記事が含まれています。
1. npm (/src) — フロントエンドのグループ化
このプロジェクトで一番依存関係が多いのが Laravel フロントの /src/package.json です。
機能ごとに以下のようにグループ化しました。
| グループ名 | 対象 |
|---|---|
storybook |
@storybook/*, storybook, @chromatic-com/storybook, msw-storybook-addon
|
eslint |
eslint, eslint-*, @eslint/*, typescript-eslint, globals
|
react |
react, react-dom, react-slick, slick-carousel, @headlessui/react
|
types |
@types/* |
tailwind |
tailwindcss, @tailwindcss/*, postcss, autoprefixer, eslint-plugin-tailwindcss
|
vite |
vite, @vitejs/*, laravel-vite-plugin
|
inertia |
@inertiajs/*, ziggy-js
|
msw / typescript
|
単体だが明示 |
other-minor-patch |
上記以外の minor / patch |
ポイントは「一緒にバージョンを合わせた方が良いもの」を 1 グループにすることです。
例えば Storybook のアドオンはコア本体とバージョンが揃っていないと動かないことがあるので、必ず一緒に上げるようにしています。
2. composer (/src) — Laravel バックエンドのグループ化
Composer も同様に、関連パッケージをまとめています。
| グループ名 | 対象 |
|---|---|
laravel |
laravel/*, laravel-lang/*, tightenco/ziggy, inertiajs/*
|
phpstan |
larastan/*, phpstan/*
|
phpcs |
squizlabs/php_codesniffer, slevomat/*, sirbrillig/*, dealerdirect/*
|
testing |
phpunit/*, mockery/*, fakerphp/*
|
| その他 |
spatie, swagger など |
Laravel のエコシステム (laravel/framework, laravel/sanctum, laravel/tinker など) はまとめて上げた方が互換性で事故りにくいので、1 つの PR にまとめるのがおすすめです。
3. update-types で major を除外
other-minor-patch:
update-types:
- "minor"
- "patch"
この設定により、major はグループに含まれず個別 PR として作られます。
破壊的変更が入るのは大体 major なので、レビュー単位を分けておくと安心です。
4. スケジュールとタイムゾーン
schedule:
interval: "weekly"
day: "monday"
time: "09:00"
timezone: "Asia/Tokyo"
毎週月曜 9:00 (JST) に更新をチェックするようにしています。
週の始まりに一気にレビューする運用で、「金曜にマージして週末壊れる」事故を防げます。
5. コミットメッセージのプレフィックス
commit-message:
prefix: "chore(deps)"
prefix-development: "chore(deps-dev)"
include: "scope"
Conventional Commits に準拠したメッセージになります。
- 本番依存:
chore(deps): ... - dev 依存:
chore(deps-dev): ... - Docker:
chore(docker): ... - GitHub Actions:
chore(ci): ...
リリースノート自動生成ツール(release-please, semantic-release)との相性も良いです。
6. open-pull-requests-limit
open-pull-requests-limit: 10
同時に開かれる PR の上限です。グループ化で PR 数は減りますが、それでも major 更新が重なると増えるので、私は 10 に設定しています。
導入後の流れ
-
.github/dependabot.ymlをコミットして push - GitHub の Insights → Dependency graph → Dependabot でステータスを確認
- 次の月曜 9:00 (JST) に初回の PR が作成される
- CI が通ったものからマージしていく
初回はまとめて大量の PR が作られるので、時間のある日にまとめて処理するのがおすすめです。
おわりに
この記事での質問や、間違っている、もっといい方法があるといったご意見などありましたらご指摘していただけると幸いです。
最後まで読んでいただきありがとうございました!