Renovate を使ってほぼ完全自動で依存パッケージをアップデートする
Renovate を使って、人の手を介さずに利用している依存パッケージをアップデートしてみます。
環境
Renovate とは
-
package.json
やpom.xml
、composer.json
といった依存パッケージを定義しているファイルを読み取り - それらのパッケージに新しいバージョンがないかどうかを確認し
- 新しいバージョンがあれば依存パッケージ定義ファイルを更新し、Pull Request を作成する
という依存パッケージのアップデート手順を自動化する GitHub App / サービスです。
GitHub には Dependabot という同じようなものがあるのですが、Dependabot には以下の問題があったので使わなくなりました。
- この記事の表題である、自動マージをするのがたいへん。
- ちょっとブランチプロテクトをかけていると、パーソナルアクセストークンから
@dependabot merge
してもマージしてくれなかったり、ガン無視されたりする…
- ちょっとブランチプロテクトをかけていると、パーソナルアクセストークンから
-
.github/dependabot.yml
を定義して設定した場合、Fork 先リポジトリでも Dependabot が動作する dependabot/dependabot-core#2804- Issue を見ると、いつまで経っても修正されないからこの仕様で作成されたプルリクからメンション爆撃しますみたいなこともやっていてもうひどいことに
- 2022/11/07 に Dependabot pull requests off by default for forks の対応がなされ、この問題は解決しました。
- ベースブランチが更新された際の自動リベースタイミングがめちゃくちゃ遅い
- 複数の Dependabot によるプルリクが作成されたとき、1 つをマージすると
yarn.lock
などがコンフリクトするが、この時にすぐベースブランチをもとに再作成してくれない…
- 複数の Dependabot によるプルリクが作成されたとき、1 つをマージすると
設定
CI ワークフローの作成
Renovate を使うにあたり、CI ワークフローを作りましょう。
依存パッケージに破壊的な変更(e.g., 利用しているメソッドが削除される、期待する結果と変わる)が加わった時にその Pull Request をマージしないようにしなければなりません。
具体的なワークフローは省きますがユニットテストや e2e テストなどをある程度網羅したワークフローを作ることをお勧めします。
JetBrains がやっと GitHub Actions で動くコード品質チェックツールを出したので、このへんも参考にしてください: 雪猫さんによる解説記事
Renovate をインストールする
GitHub Marketplace の Renovate ページ から、インストールする対象のアカウントを選択し Install it for free
をクリックしてインストール画面に進みます。
$0 / month
でフリープランが選択されていることを確認し(そもそも現時点で Renovate にはフリープランしかないのですが)、Complete order and begin installation
をクリックします。
アカウント選択時にオーガニゼーションを選択した場合、インストールページに進むと、オーガニゼーションすべてのリポジトリにインストールするか一部の選択したリポジトリにインストールするかを訊かれます。
-
All repositories
を選択すれば現在あるリポジトリすべてにインストールされます。- この場合、初期セットアップの Pull Request がすべてのリポジトリに作成されます。
- 既存のリポジトリが少ないのであればこれでもかまいません。
-
Only select repositories
を選択すると、指定したリポジトリだけに Renovate をインストールできます。- 個人的にはこちらをお勧めします。
- リポジトリ作成時にインストールする GitHub App を選べますし、Renovate を動作させたくないリポジトリがある場合に上記の
All repositories
では除外設定ができません。- ただし、Renovate が作成する
Configure Renovate
Pull Request をクローズすることで機能しなくはなります。
- ただし、Renovate が作成する
インストールしたい種別を選べたら、Renovate が要求する権限[1]が正しいことを確認し Install
をクリックします。
これで、あなたのオーガニゼーション or アカウントに Renovate をインストールできたはずです。
Renovate をセットアップする
インストールが終わって少し経つと、インストール対象にしたリポジトリに Configure Renovate
というタイトルで Pull Request が作成されます。
デフォルトでは config:base
を読み込むだけとなっているのですが、これだと「ほぼ自動化」はできないので以下のように変えます。
{
"extends": ["config:base"],
"ignorePresets": [":prHourlyLimit2"],
"timezone": "Asia/Tokyo",
"dependencyDashboard": false,
"automerge": true,
"branchConcurrentLimit": 0
}
変える手順についてですが、GitHub Desktop で Pull Request をクローンして編集してコミットしてもよいですし、Web GUI 上で Files changed
タブ → renovate.json
ファイルの「・・・」→ Edit file
から編集してもかまいません。当然、Pull Request を無視して renovate.json を作成しコミットしてもかまいません。
マージした後に編集すると Dependency Dashboard が作成されてしまうのでマージ前に編集することをお勧めします。
上記の設定は以下のようになっています。
- 1 時間あたりに 2 Pull Request までに抑える処理を無効化
- タイムゾーンを
Asia/Tokyo
に指定 - Dependency Dashboard (こういうやつ) を無効化
- オートマージを有効化
- ブランチに対して作成する Pull Request 数の制限を無効化
編集後、マージすれば Renovate が動き出します 👏
ブランチプロテクトの設定
リポジトリ Settings
タブ → 左側 Branches
→ Add rule
でブランチに対する制限(プロテクト)の設定ができます。
最低限、Require status checks to pass before merging
およびその中の Require branches to be up to date before merging
にチェックが入っていれば大丈夫だと思われます。もちろん、必須とするワークフローは指定してください。
Require a pull request before merging
の Require approvals
を設定する場合は、renovate-approval という GitHub App を入れると Renovate が作成した Pull Request に対してのみ自動で Approve するようになり、手動でのレビューが不要になります。
しかし、Require review from Code Owners
をオンにしてしまうと CODEOWNERS
には GitHub App を設定できない ので自動でのマージができなくなります。
Dependabot を無効化する
Renovate を設定し運用し始めたら、基本的には Dependabot は不要なので無効化してしまいましょう。
リポジトリ個々で無効化する場合は、リポジトリ Settings
タブ → 左側 Code security and analysis
→ Dependabot security updates
を Disable
で無効化できます。
オーガニゼーション全体で無効化する場合は、オーガニゼーション Settings
タブ → 左側 Code security and analysis
→ Dependabot security updates
を Disable all
で無効化できます。
一部のパッケージ管理ツール[2]は Renovate が管理しないようで Dependabot は通知するけど Renovate は通知しない…というケースがあることはあるので、両方有効にするのも 1 つの手だと思います。
-
ここでは、Dependabot alerts ・管理設定・オーガニゼーションのメタデータへのアクセス、
Pull Request の Workflow チェック状態(?)・リポジトリのコード・コミットの状態・ Issue ・ Pull Request・GitHub ワークフローへのアクセスと書き込み権限、ユーザーのメールアドレスへのアクセス権限を付与します。 ↩︎ -
具体的には、
yarn.lock
のみに定義されている依存パッケージ(依存パッケージが依存するパッケージ)を Renovate は追跡しません。
例としてdiscord.js
が依存するnode-fetch
の< 2.6.7
には 脆弱性がありました が、Dependabot しかこれを通知しませんでした。 ↩︎
Discussion