🤖

Dependabot 全体像とバージョンアップ戦略

2022/12/04に公開

なんとなくで使っていたDependabotについて、一からGitHubの公式ドキュメントを読み込み、検証しました。
この記事では、Dependabotの全体像を解説した後、おすすめのバージョンアップ戦略を紹介します。

記事の流れ

    1. Dependabotの全体像
    1. 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について、さらに概要を深堀りします。

    1. バージョンアップ戦略
    • デフォルトでは、あらゆるレベルの依存パッケージのバージョンアップに追従するPRを作成する
      • 1.0.0→2.0.0といったメジャーバージョンアップもPRを作成する
    • semverを活用して、動作をカスタマイズすることが可能
      • semverについては後述します。
      • おすすめのカスタマイズは後続の章で解説します。
    1. PRの作成単位
    • パッケージ管理ディレクトリ × パッケージ単位となる
      • 例えばモノレポで3フォルダにpackage.jsonがあり、それぞれ3つずつ最新でないパッケージがある場合、合計9個のPRが出る
    1. パッケージ管理ディレクトリの指定
    • 明示的に全てのディレクトリを指定する
      • 自動でフォルダを探索してくれるわけではないため注意。
      • 例えばモノレポで3フォルダにpackage.jsonがある場合、3つ分指定
    1. タイミング
    • 日次、週次、月次などを選ぶことが可能
      • 即時ではない
    • 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で、対象ディレクトリごとに以下のように設定します。

.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の記事が参考になったためご参照ください。
記事内にサンプルコードもありました。
https://dev.classmethod.jp/articles/github-dependabot-auto-merge/

一応、筆者が動作確認したものを載せておきますので、もし上記記事のサンプルが動かない等あれば試してみてください。

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点補足します。

  • onstagingdevといったブランチがある場合、それらも対象に含めてください。
  • permissionsgh pr mergecontents: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点よく使うコマンドを紹介します。

    1. @dependabot rebase
    • Dependabot version updatesは自動的にコンフリクトを検知してリベースしてくれますが、PRを連続でマージするときなどは間に合わないときもあります。このようなときは、このコマンド1つでリベースが可能です。
    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