🤖

Renovateの導入と半年間の運用の振り返り

2022/05/20に公開

TERASSのsunadoiです。

みなさん、ライブラリのアップデートは定期的にしていますか。
今回はライブラリを定期的にアップデートするという目標を掲げてプロジェクトにRenovateを導入してから半年程経ったのでその振り返りを残しておこうと思います。
実際に半年ほど運用してみて知見が溜まってきたので、どんな感じの設定をしているかを導入当時の背景とともに紹介しつつ振り返っていきます。

導入したプロジェクトの構成はReact, TypeScript, Cloud Functions for Firebaseのモノレポです。

Renovateとは

プロジェクトの依存関係の更新を自動化してくれるツールです。
npmライブラリだけでなく、GitHub Actionsで使うコマンドやDockerイメージのバージョンなんかも監視してくれて、バージョンアップのためのPR作成まで自動で行なってくれます。

https://www.whitesourcesoftware.com/free-developer-tools/renovate/

似たようなツールとしてDependabotがありますが、いくつかの観点から今回はDependabotではなくRenovateを採用しました。
その辺の選定の話は最後の方に。

Renovate導入前の課題

Renovateを導入する前はライブラリの定期的なアップデートは行われておらず、以下のような課題がありました。

これらを解決するためにRenovateを導入しました。
ちなみに、導入前にそれまでアップデートされていなかったライブラリは全てアップデートしました。
中にはバージョンがわりと古いものもあって破壊的変更の確認に骨が折れるものもあり、この時点で既にこまめなアップデートの重要さを身に染みて実感。。

Renovateの導入

GitHub Appが用意されているので導入はかなり簡単です。
導入すると設定用のPRが作成され、renovate.jsonという設定用ファイルが作成されます。

この設定項目が非常に多いんですよね。
なので運用方法によって非常に柔軟な設定が可能になります。
https://docs.renovatebot.com/configuration-options/

運用ルールを決める

導入にあたってまず運用ルールを決めて、それができそうな設定をするという順番で進めました。
設定項目は多岐にわたりますが、チームでの運用を考えたときに考慮したのは主に以下の3つです。

  • PRの自動マージ
  • PR発行の頻度
  • PRの集約単位

Renovateは定期的にバージョンアップデートのPRを自動で作成はしてくれますが、アップデートでCIが落ちた時の対応や破壊的変更の影響確認はエンジニアが行う必要があります。
当時導入したプロジェクトに関わっているエンジニアは3名程度だったので、上記の対応を3人のエンジニアが持ち回り制で行う運用方法としました。
運用の手間ができるだけかからない方法を模索すべく、先に挙げた3つの項目をどう設定するか話し合いました。

PRの自動マージ

RenovateではCIが通ったときに自動でPRをマージしてくれる機能があります。
まず大きな方針としてこの自動マージは設定しないことにしました。
プロジェクトの規模がそこまで大きくないというのもあり、ある程度人がレビューした方が安心できるからというのが主な理由です。
その代わり後述するPR発行の頻度やPRの集約単位を調整することでレビューの負担を減らす運用としました。

ちなみに他社の大規模プロジェクトとかだと毎日数百のPRをRenovateで自動マージしていたりする例もあるそうです。すごい()

PR発行の頻度

PRの発行頻度は毎日、1週間ごと、2週間ごと、1ヶ月ごとなど柔軟に設定できます。
先述した通り、各PRのレビューはエンジニアが行うことにしたのでできるだけ負担が少ないようにとりあえず月1回のアップデート頻度としました。
つまりエンジニア3人の場合、3ヶ月に1回Renovateのレビュー担当が回ってくるということになります。

PRの集約単位

そのままの設定だと各ライブラリごとにPRが発行されます。
今回はマイナーバージョンとパッチバージョンのアップデートはまとめて1つのPRとして集約することにしました。
npmライブラリではSemanticVersioningが採用されていてマイナーバージョンとパッチバージョンのアップデートでは後方互換性ありとされているので、CIが通っていればそれらを同時にアップデートしても問題ないであろうという判断からです。

また、各ライブラリごとにPRを発行するとPRの数が非常に多くなるのでプロジェクトの機能に関係ないPRが溢れることになります。検索できるとはいえ見通しが悪くなるのは嫌ですね。

まとめると、以下のような運用方針になりました

  • 1ヶ月ごとにバージョンアップデートのPRを作成
  • マイナーバージョンとパッチバージョンのアップデートは1つのPRにまとめる
  • PRは自動マージせず、エンジニアが持ち回り制でレビューする

設定ファイル

これらを設定ファイルに反映させると大体下記のようになりました。

renovate.json
{
  "extends": ["config:base"],
  "schedule": "before 9am on the first day of the month",
  "timezone": "Asia/Tokyo",
  "prHourlyLimit": 0,
  "rangeStrategy": "bump",
  "packageRules": [
    {
      "matchUpdateTypes": ["patch", "minor"],
      "excludePackageNames": ["typescript"],
      "groupName": "all minor and patch dependencies"
    },
  ],
  "enabledManagers": ["github-actions", "npm"]
}

config:baseである程度デフォルトの設定を引き継ぎつつ、各種設定をしています。
運用に関わるところだけピックアップして記載します。

schedule

毎月1日にまとめてPRを発行するように設定しました。
before 9amとすることで朝9時にPR発行と思いきや、どうやら発行するタイミングとは無関係のようです。
これは範囲設定になるらしく(?)、9時前に全てのPRをマージしたとしても、そこから9時までの間にアップデートがあればPRを作成し続けてくれるようです。

packageRules

PR作成の細かな設定を記述する場所。
matchUpdateTypesでマイナーとパッチバージョンをまとめる設定にしつつ、typescriptはこれらのまとめから排除しています。
これは運用後、typescriptのバージョンアップデートによって型チェックのCIが落ちることがたびたびあったからで、他のライブラリのアップデートを阻害しないようにtypescriptだけはマイナーバージョンアップデートだとしても単体でやるという方針にしました。
その他、諸事情によりまとめから排除したいライブラリは適宜excludePackageNamesに追加しています。

Dependabotとの違い

似たようなツールとして有名なものにDependabotがあるかと思います。
当初はDependabotを利用しようとも思ってたのですが、最終的にRenovateに落ち着きました。

理由はいくつかあるのですが、いくつかのアップデートをまとめて1つのPRに集約できること、設定項目がかなり多くユースケースに沿ったカスタマイズができることなどが主な要因です。
もしかしたらDependabotでもできたのかもしれませんが、設定が見当たらなかったのとRenovateの方がカスタマイズしやすそうだったのでRenovateに落ち着きました。

実際の運用方法

基本的にはRenovateが発行したPRにはRelease Noteが貼られているのでどんな変更があったのか確認しています。
ここで取り入れても影響がないかを判断しつつ、CIが落ちたものや修正が必要なものは随時対応の上マージするという運用です。

中にはすぐには取り入れられずライブラリ側の対応が必要なものだったり、修正が困難なものもあったりします。
そういったものは協議の上、一時的にPRをCloseしたりマイナーパッチバージョンの集約PRから外してその他の影響ないものだけをマージするなどしています。
集約PRから特定のライブラリを外す作業は、excludePackageNamesに該当のライブラリを含めたPRを別で作成してマージしています。
そうするとRenovateが勝手にrebaseしてくれて、そのライブラリを含めないコミットとして作り直してくれます。

半年程運用してみた振り返り

一言で言うと、導入して本当に良かったなと思います。

元々あった課題が解決されたからというのはもちろんそうなんですが、ライブラリにどういう変更が入ったのかチェックするようになったのは思わぬ副産物でした。
最新の機能自体は使わないことも多々ありますが、変更内容に興味を持つようになったのは非常によかったです。

また、ある時CIが落ちていてそれがアップデートによる意図しない挙動の変更によるもので、こちらはissueを立てて対応してもらいました。
自分でPR作ってというものではないですが、ささやかながらOSS活動っぽいことができて嬉しかったのを覚えています。
これもこの仕組みがなかったらやれてなかっただろうなと思うので、いい機会を与えてもらいました。

設定に関して、導入した当時はどんな感じで運用していくか見えない部分もあったのでとりあえずやってみて修正していこう精神で始めたんですが、結果的にはほぼ当初の設定のままです。

「メジャーバージョンアップデートはそんなに多くない & マイナーバージョンとパッチバージョンはCIほぼ落ちないから運用そんな大変じゃないだろう」という思惑のもとスタートしたんですが、今のところマイナーパッチバージョンのアップデートは半分くらいの確率でCI落ちてます。笑
ただ型定義関連とか修正が軽微なものが多いのでそこまで運用の負担も重くない印象ですね。

無理なく続けられてると思うので、しばらくこの方針で運用していこうかなと思います。

余談

1月1日のこと。
0時過ぎて早々にやたら通知がたくさん来るのでみんなあけおめの連絡くれたんだなと思ったらRenovateのPR発行通知でした。
Renovateあけましておめでとう、これからもよろしく。

採用情報

TERASSではエンジニアを採用中です!
ご興味ある方は以下のリンクを見てみてください!

https://terassinc.notion.site/TERASS-Engineering-Technology-22dcf74f0aed492684003117b6420946

Discussion