1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

はじめに

こんにちは、エンジニアのケイタ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 に設定しています。

導入後の流れ

  1. .github/dependabot.yml をコミットして push
  2. GitHub の Insights → Dependency graph → Dependabot でステータスを確認
  3. 次の月曜 9:00 (JST) に初回の PR が作成される
  4. CI が通ったものからマージしていく

初回はまとめて大量の PR が作られるので、時間のある日にまとめて処理するのがおすすめです。

おわりに

この記事での質問や、間違っている、もっといい方法があるといったご意見などありましたらご指摘していただけると幸いです。

最後まで読んでいただきありがとうございました!

参考リンク

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?