Dependabot 全体像とバージョンアップ戦略
なんとなくで使っていたDependabotについて、一からGitHubの公式ドキュメントを読み込み、検証しました。
この記事では、Dependabotの全体像を解説した後、おすすめのバージョンアップ戦略を紹介します。
記事の流れ
-
- Dependabotの全体像
-
- Dependabot version updates
- 2-1. 概要
- 2-2. おすすめバージョンアップ戦略
- 2-3. Tips
の流れで説明します。
1. Dependabotの全体像
Dependabotといえば、「パッケージのバージョンを自動的にアップデートしてくれるやつ」というイメージではないでしょうか。(筆者はそうでした)
実際には、Dependabotにはいくつかのサービスが含まれており、その一部がバージョンのアップデートです。
この章では、Dependabotの全体像を説明します。
背景
一般に、私たちはビジネスロジックに集中するために、OSSパッケージを広く活用しています。
パッケージを使う際、アプリケーションが各OSSパッケージのどのバージョンに依存しているか、コードベース内で指定します。
これにより、OSSパッケージ側のアップデートによって、気づかないうちに私たちのアプリケーション壊れてしまうことを防いでいます。
一方で、このような一般的なパッケージ管理の方法では、OSSパッケージのアップデートへの追従が疎かになりがちです。
OSSパッケージのアップデートをアプリケーションに取り込むためには、アップデートに気づいたうえで、明示的にパッケージ管理ファイルを修正する必要があるからです。
こうした状況では、次の2点の課題があります。
- 脆弱性対応が遅れる・できない
- より新しい機能が使える機会を失う
- 開発生産性や(パフォーマンス等の)アーキテクチャ特性の改善機会を失う
- 開発チームがパッケージの新しい機能にキャッチアップする機会を失う
Dependabotの3つのサービス
Dependabotは、こうした課題を解決するサービスで、GitHubリポジトリ内の「パッケージへの依存」を管理します。
パブリックリポジトリ/プライベートリポジトリ問わず、全てのサービスを無料で使うことができます。
npmやmavenなど、多くの一般的なパッケージマネージャをサポートしています。
Dependabotは、ざっくり3つのサービスを提供しています。
- Dependabot alerts
- GitHubリポジトリが依存しているパッケージバージョンに脆弱性が含まれている場合、メールなどにアラート通知を行う
- Dependabot security updates
- GitHubリポジトリが依存しているパッケージバージョンに脆弱性が含まれている場合、脆弱性に対応したパッケージバージョンに修正するPRを作成する
- Dependabot version updates
- GitHubリポジトリが依存しているパッケージバージョンが最新でない場合、最新のパッケージバージョンに修正するPRを作成する
2. Dependabot version updates
Dependabotサービスの中で、最もメジャーなサービスはDependabot version updatesかと思います。一般に「Dependabot」というと、このサービスを指すと思われます。
2-1. 概要
前章のマトリクスにあるとおり、Dependabot version updatesは、最新でないパッケージバージョンへの依存を検知した時、バージョンを更新するPRを作成します。デフォルトでは無効であり、.github/dependabot.yml
を作成することで有効化・カスタマイズができます。
この章では、Dependabot version updatesについて、さらに概要を深堀りします。
-
- バージョンアップ戦略
- デフォルトでは、あらゆるレベルの依存パッケージのバージョンアップに追従するPRを作成する
- 1.0.0→2.0.0といったメジャーバージョンアップもPRを作成する
- semverを活用して、動作をカスタマイズすることが可能
- semverについては後述します。
- おすすめのカスタマイズは後続の章で解説します。
-
- PRの作成単位
- パッケージ管理ディレクトリ × パッケージ単位となる
- 例えばモノレポで3フォルダにpackage.jsonがあり、それぞれ3つずつ最新でないパッケージがある場合、合計9個のPRが出る
-
- パッケージ管理ディレクトリの指定
- 明示的に全てのディレクトリを指定する
- 自動でフォルダを探索してくれるわけではないため注意。
- 例えばモノレポで3フォルダにpackage.jsonがある場合、3つ分指定
-
- タイミング
- 日次、週次、月次などを選ぶことが可能
- 即時ではない
- PRはデフォルトで同時に最大5個まで作成されるが、設定が可能
Dependabot version updatesは、全て.github/dependabot.ymlで設定します。
上記ファイルが存在すれば有効となり、またカスタマイズもこのファイルで行います。
以下、設定イメージです。
始め方や設定の詳細はこちらをご覧ください。
補足:semver
semverとは、バージョンの付け方のルールです。
例えば、バージョン1.2.3のパッケージを更新するとき、以下のようなルールになります。
- 後方互換性がない場合、2.0.0にあげる
- 後方互換性がある機能追加の場合、1.3.0に上げる
- 後方互換性があるバグFIXの場合、1.2.4に上げる
多くのパッケージ管理の仕組みでは、semverが採用されています。
これにより、私たちパッケージの利用者は、アプリケーションをパッケージのバージョンアップに追従させる上で、「1.2.3.から2.0.0には気軽に上げられない」「1.2.3から1.2.4にはいつでも更新していい」といったチームのルールを作ったり、自動化することが可能です。
詳細はこちらを参照ください。
2-2. おすすめバージョンアップ戦略
Dependabot version updatesではタイミングなどいくつかのカスタマイズができますが、最も本質的なカスタマイズはバージョンアップの戦略ではないでしょうか。
筆者がおすすめしたい戦略は、以下のとおりです。
- major:Dependabot version updatesの対象外とする
- majorのアップデートは情報として流れてきて気づくことも多い
- 本番運用している場合は、気軽にメジャーを上げられないことも多く、クローズが手間
- minor:デフォルトの動作とする(Dependabot version updatesがPRを作成し、自分でマージする)
- 新しい機能が追加されたのであれば、自動マージするのではなく、どのような機能なのか確認した上でマージしたい
- patch:自動的にマージする
- バグFIXであれば、中身を1つ1つ知る重要度が低い
- 脆弱性に対するパッチであれば、速度を優先できる
この戦略をDependabot version updatesで実現する方法をシェアします。
minorについては、デフォルトの動作のため、majorとpatchについて解説します。
2-2-1. majorをDependabot version updatesの対象外にする
.github/dependabot.yml
で、対象ディレクトリごとに以下のように設定します。
version: 2
updates:
- package-ecosystem: "npm"
...
ignore:
- dependency-name: "*"
update-types: [ "version-update:semver-major" ]
ポイントはignore
で、Dependabot version updatesの対象外とするパターンを指定することができます。
update-types: [ "version-update:semver-major" ]
により、majorのアップデートがignoreとなるよう指定しています。
dependency-name: "*"
は、特定のパッケージではなく全てのパッケージに対してこのルールを適用するための指定です。
2-2-2. patchを自動マージする
こちらはDevelopersIOの記事が参考になったためご参照ください。
記事内にサンプルコードもありました。
一応、筆者が動作確認したものを載せておきますので、もし上記記事のサンプルが動かない等あれば試してみてください。
name: dependabot-patch-automerge
on:
pull_request:
branches: [ "main" ]
permissions:
contents: write
jobs:
merge:
runs-on: ubuntu-latest
if: ${{ github.actor == 'dependabot[bot]' }}
steps:
- name: prepare
id: prepare
uses: dependabot/fetch-metadata@v1.1.1
with:
github-token: '${{ secrets.GITHUB_TOKEN }}'
- name: do
if: ${{ steps.prepare.outputs.update-type == 'version-update:semver-patch' }}
run: gh pr merge --auto --merge ${{github.event.pull_request.html_url}}
env:
GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN}}
2点補足します。
-
on
:staging
やdev
といったブランチがある場合、それらも対象に含めてください。 -
permissions
:gh pr merge
がcontents:write
を必要とするため付与しています。
2-3. Tips
ここまででDependabot version updatesを設定し、開始することができるかと思います。
最後に、運用時のTipsを2点紹介します。
2-3-1. PRの見方
Dependabotが出すPRは以下のような見た目になっています。
ポイントだけ解説します。
- Release notes
- パッケージが有効なリリースノートを持っている場合、バージョン間の差分からリリース内容をまとめてくれます。
- 量が多くなると途中で省略されてしまいますが、minor1つ分のバージョンアップやpatchいくつか分の差分くらいなら、GitHub上でサクっと確認できます。
- Compatibility score
- 当該バージョンアップについて、他のパブリックGitHubリポジトリで、どのくらいCIが成功しているかを示しています。
- 理論上はminorやpatchであれば100%になるべきですが、実態としてはCIを落とすケースもあり、実際どうなのか参考にすることができます。
PRの判断方法は、例えば以下のような目安が考えられます。(もちろん、組織やプロダクトによってルールは違います)
- minorとpatchは、リリースノートをざっと見た上で、compatibilityがよっぽど低くなければ、個人の判断でマージして良しとする
- majorは後方互換性がないため、しっかりとリリースノートを確認し、チーム内で合意を取ってからマージする
2-3-2.PRコメントによる操作
PRにコメントをすることで、Dependabotの出したPRを操作することが出来ます。
全てのコマンドはこちらを参照ください。
以下はイメージです。
例として、2点よく使うコマンドを紹介します。
-
@dependabot rebase
- Dependabot version updatesは自動的にコンフリクトを検知してリベースしてくれますが、PRを連続でマージするときなどは間に合わないときもあります。このようなときは、このコマンド1つでリベースが可能です。
-
@dependabot merge
- CIが通った後に自動的にマージできます。特に、
@dependabot rebase
の後でCIが走りなおしているときに使うと、CIが終わった後に自動でマージすることができます。
また、Dependabotを検証していた際、コマンドを使わず自分でPRを修正したところ、GitHub Actionsが上手く動かなかったこともありました。
※actorがdependabotではないと判定されてしまい、CIがスキップされたのではないかと思います。
コマンドは手間を削減する上、予期しない動作を防ぐためにも役に立ちそうです。
まとめ
Dependabotは大きく3つのサービスから構成されています。
- Dependabot alerts
- Dependabot security updates
- Dependabot version updates
界隈で「Dependabot」というと、Dependabot version updatesを指している場合が多いかと思います。
Dependabot version updatesはsemverに従っています。
設定ファイルやGitHub Actionsとの連携により、majorはPRしない、patchは自動マージするといったバージョンアップ戦略のカスタマイズが可能です。
Dependabot version updatesが出すPRを判断するうえで、PR内でリリースノートやCompatibility Scoreを参考にできます。
また、PRの操作にはPRコメントによる操作が便利です。
この記事を読んで、Dependabotの全体像を押さえつつ、Dependabot version updatesを開始していただけると幸いです。
追伸
よければTwitterもフォローお願いします!
@sumiren_t
もし記載に誤り等ありましたら、いつでもご指摘をお願いいたします。
Discussion