GitHubにDependabotを導入した

広告事業本部に所属しているデータエンジニアの木本です。

今回はチームで使用しているGitHubにDependabotを導入してRailsのGemのアップデートの自動化を行なったことについて記事を書こうと思います。

背景

私たちのチームはRailsを使用したアプリケーションを開発しており、最近リモートリポジトリの管理先をGitLabからGitHubに移行しました。

この移行に伴ってプロジェクトのCI/CD環境を整える必要があり、何度かチームで話し合いを行なっていました。

その中で依存関係の管理を自動で行いたいという議題が挙がり、定期的なGemのアップデートの手法としてDependabotを導入することになりました。

Dependabotの概要と機能を調べてみる

Dependabotとはリポジトリ内の依存関係(Gem等のモジュール)をチェックし、必要に応じて更新の候補を列挙するPull Request(以降PRと呼びます)やセキュリティアラートを作成するGitHubがホストしているツールです。

参考URL:https://docs.GitHub.com/ja/code-security/dependabot

Dependabotには主に下記の3種類の機能があります。

機能名 概要
Dependabotアラート 脆弱性のある依存関係を使用しているリポジトリを検出すると通知する
Dependabotセキュリティアップデート 使っている依存関係のうち、既知のセキュリティ脆弱性があるものを更新するためのPRを自動的に生成する
Dependabotバージョンアップデート リポジトリが保有するパッケージやアプリケーションの最新リリースを自動的に把握し、その対策を通知する

今回の要件はGemの定期的なアップデートの実現なので、上記の3種類の機能のうちのDependabotバージョンアップデートを採用しました。

Dependabotバージョンアップデートの導入方法

Dependabotバージョンアップデートの導入方法を説明します。

今回説明するに当たって、サンプルとして新しく作成したRailsアプリを管理するリポジトリを作成しました。

まず導入したいリポジトリ内の、Insights > Dependencygraph > Enable Dependabotの順に移動し、「Enable Dependabot」ボタンを押すことでDependabotを有効にします。

そうすると下記のような画面になるので、「create config file」ボタンを押します。

ボタンを押すと下記のように./github/dependabot.ymlが作成される画面に移動します。

ここで設定ファイルを書き込み、Commitボタンを押すことによってDependabotバージョンアップデートが利用できるようになります。

設定ファイルの作成

Dependabotバージョンアップデートの設定ファイルをリポジトリに置くことができました。

次はこの設定ファイルを書き込んでいこうと思います。

最終的な設定ファイルは下記のようになりました。

version: 2
registries:
  GitHub-resque: # 読み込みにトークンが必要なGitHubのリポジトリを指定
    type: git
    url: https://GitHub.com
    username: x-access-token
    password: ${{secrets.RESQUE_TOKEN}} # アクセストークンを指定(GitHubのDependabot secretsの中にある)
updates:
  - package-ecosystem: "bundler" # パッケージマネージャーの名前
    directory: "/" # パッケージマネージャーがあるフォルダ階層
    insecure-external-code-execution: "allow" # 外部コードの実行を許可
    registries:
      - GitHub-resque
    schedule:
      interval: "weekly" # 更新の頻度(週ごと)
      day: "tuesday" # 更新する曜日
      time: "12:50" # 更新する時間
      timezone: "Asia/Tokyo"
    open-pull-requests-limit: 5 # 最大のPR作成数
    ignore: # 自動アップデートしない依存関係の指定
      - dependency-name: "更新しないGem1" 
      - dependency-name: "更新しないGem2" 
      - dependency-name: "更新しないGem3" 
      - dependency-name: "*"
        update-types: ["version-update:semver-minor", "version-update:semver-patch"] # 更新しないGemの粒度

この設定ファイルを書くにあたって、以下のような条件を主に意識しました。

新バージョンチェックの頻度の指定

今回は週に1回のペース(毎週火曜日の12:50)でチェックを行うようにします。

schedule配下のintervalの設定項目で、日、週、月のいずれかの間隔でGemの更新をチェックするかを設定できます。

このタイムゾーンはデフォルトだとUTCなので注意が必要です。

自動で作成されるPRの数

一度に大量のPRを作成されてしまっては他のPRが見づらくなってしまうため、今回はデフォルトで設定されている最大5個までPRの作成を許可します。

この5個のPRの欄は、1つマージorクローズするとその枠が空くようになっており、この数はopen-pull-requests-limitオプションで変更できます。

チェックするバージョンの粒度

update-typesオプションでGemに更新があった際に、どの粒度でPRを作成するのかを設定できます。

今回はマイナーアップデートとパッチアップデートは無視するように設定します。

2.0.1 => 3.0.1 などのメジャーな更新があった場合はPR作成して欲しいですが、2.0.1 => 2.0.2 などの細かい更新は運用が大変になってくるためPRは作成して欲しくないためです。

ただしセキュリティをより強固にしていくのであれば、この粒度はより細かいものに設定することをお勧めします。

アップデートしないGemの指定

特定のGemをDependabotバージョンアップデートの管理範囲から除外します。

これはアプリケーションの構造に大きく影響を与えるような重要なGemを誤ってアップデートすることを避けるためです。

ignoreオプションで更新があってもPRを作成しないGemの指定が可能です。

注意点として、このignoreオプションで指定されたGemは「Dependabotの追跡対象外」になるのではなく、あくまでも「PRが作成されなくなるだけ」というものです。

私が過去に詰まってしまった点として、権限の関係で更新ができなかったGemをignoreオプションに指定して「Dependabotの追跡対象外」にしたつもりでしたが、ignoreオプションはあくまでも「PRが作成されなくなるだけ」であるためDependabotはその後もそのGemを更新し続けようとしてしまい、全体のGemの更新が失敗し続けてしまいました。

(Dependabotは仕様上、1つのGemの更新に失敗するとその他のGemの更新も失敗してしまいPRが作成されません)

実際に導入してみる

実際にDependabotバージョンアップデートを導入し、設定した時刻になると下記の画像のようなPRが作成されます。

(このPRは試験的にrubocop-railsのGemを更新したもので、後にCloseしています)

ファイルの変更内容としては、Gemの更新の場合GemfileとGemfile.lock、またはGemfile.lockのみの変更となっています。

PRに書かれる内容

PRには主に「Release notes」、「Changelog」、「Commits」、「Dependabot commands and options」の項目があります。

「Release notes」、「Changelog」、「Commits」はGemの元となるリポジトリのリリースノートやコミットリンクが書いてあり、この更新によってどのような変更が成されたのかがわかるようになっています。

「Dependabot commands and options」の欄にはPRでコメントからDependabotに対して命令できる文の一覧があります。

@dependabot rebaseを例にとると、このPR内でリベースしたい場合などは@dependabot rebaseとコメントするだけで自動でmainブランチにリベースしてくれます。

これを受けて、実際にリベース作業が反映されているときには下記のようなコメントもPR欄に書いてくれます。

導入した感想

自動でGemの更新と、その変更点が書かれたPRを作成してくれるのは運用の手間がかなり軽減されると思います。

ただ、今回Gemの更新の粒度をメジャーアップデートのみにして更新頻度を週1回にしたのですが、メジャーアップデートはそんなに頻繁に発生するものではないため月1回の更新にしても良かったのかなと思いました。

まとめと今後の展望

今回はDependabotを通じてGemの定期アップデートを行う方法について記事を書かせていただきました。

Dependabotバージョンアップデートは設定ファイルにより、PR作成の数や更新日時、また対象となるGemや更新の粒度など柔軟なカスタマイズができることがわかりました。

Dependabot導入後は、Gemの更新粒度や誰がどのようにテストなどを行なってからmergeするのかなどの運用方法をチームで話し合っていきたいと思います。

最後まで読んでくださり、ありがとうございました。