Renovate の PR を 89% 自動マージして楽している話
はじめに
この記事は食べログアドベントカレンダー2021の 18 日目の記事です。
食べログ FE チームの @hagevvashi です。
食べログでは 2021年7月から Renovate を運用しています。
Renovate は月に 50 件近い PR を出してきますが、半年近く溜めずに運用を続けられています。
もちろんこの量の PR を一つ一つ動作確認してから手でマージしているわけではありません。自動マージを活用して楽に運用しています。
この記事ではどのように自動マージを設計し、運用しているか紹介します。
自動マージ導入による効果
まずは、Renovate の自動マージを導入することによってどのような効果がもたらされたのか紹介します。
2021/7/21 に導入を開始してから合計 235 件の PR が Renovate によって作られました。
その内 89% を占める 210 件もの PR が自動でマージされています。
1 割程度の手運用なら Renovate の運用が回ると思いませんか?
Renovate の導入に悩んでらっしゃる方は是非この記事を読んで Renovate の運用の方法を考えてみてください。
自動マージ機能の設計
自動マージ機能は便利ですが、見境なくすべての PR を自動でマージするわけにもいきません。
ライブラリアップデートによるプロダクト影響の有無を確認せず自動マージすると、バグの市場流出のリスクがあります。
食べログでは webpack を使用しているため、webpack のビルド結果に差分がない場合はプロダクションへの影響がないと言えます。
CI Pipeline にビルド結果の差分を比較する Job を組み込むことで、安心安全な自動マージを実現しています。
自動マージができる PR、できない PR、Renovate ではない開発者の PR で Pipeline を分けています。
パターン1. Renovate の PR
Renovate の PR の中には husky などの開発生産性を上げるためのライブラリもたくさんあります。
それらはプロダクションのビルド結果に差分は出ないのに、破壊的な変更を伴っていることがあります。
いつの間にか壊れてしまって開発生産性が下がらないように自動マージは OFF にしています。
下記のような設定で husky という名前を含むライブラリに関しては自動マージされなくなります。
パターン2. 開発者の PR
自動マージは Renovate のための Pipeline なので、機能開発の PR については除外しておく必要があります。
Renovate は設定でブランチ名のパターンを指定できるので、CI の branch filtering 機能を用いて Job の制御を行っています。
この設計にしたことのメリット
この設計にすることで次のようなメリットがあり、チーム内でも好評でした。
・Renovate の運用コストを大幅に下げることができた
・Pipeline をシンプルに保てている
・自動マージしても問題ないことの根拠が説明できた
・機能開発の Pipeline には一切影響が出ていない
・開発生産性を下げてしまう PR は自動マージから除外されており、安心
ビルド結果の差分比較 Job の設計
どのようにしてビルド結果の差分比較をしているのか紹介します。
食べログでは github と CircleCI を使って PR のブランチから比較対象のバージョンを特定して差分比較を行っています。
前準備として、毎回の push 毎の Pipeline で CircleCI の Artifacts にビルド結果を差分比較用としてアップロードしておきます。
① Renovate がライブラリバージョンアップの PR を作成する
② Renovate が push してきたブランチと差分比較をするための branch 名を github pulls api を用いて取得する。(現状の運用だと柔軟性をもたせるためにわざわざ取得しておりますが、実際にはほぼ master です)
③ ②で取得した branch 名を引数に git の cli command を用いて、Renovate のブランチが別れた地点の commit hash(sha) を取得する
④ ③で取得した commit hash(sha) を引数として、github status api を用いて CircleCI の Build ID(Job ID) を取得する
⑤ ④で取得した Build ID(Job ID) を引数として、CircleCI の API を用いて Artifacts の URL を取得する
⑥ Artifacts の URL から比較対象のビルド結果をダウンロードする
⑦ Renovate によるライブラリバージョンアップブランチのビルド結果と Artifacts の URL からダウンロードしたビルド結果の差分を比較する
下記の図中の黄色い付箋は上記リストの番号と対応しています。
①から⑦のプロセスの内、いくつか注意すべきポイントがあるので紹介します。
①: Artifacts にアップロードしたファイルは 1 ファイル毎に URL が発行されますのでダウンロードする時の手間を考えるとアップロード時点で tar に固めておくとよいでしょう。
②、③: Pull Request があることが前提の Pipeline になっているので、push してすぐに Pipeline が実行されると Pull Request の ID が分からない状態になります。CircleCI の設定の「Only build pull requests」を有効にしておくと失敗しなくなります。
④: commit hash(sha) が分かっている状態から github status api への一度のリクエストで Job の ID を取得したいため、CircleCI の設定の「GitHub Status Updates」を有効にしておくと楽になります。
④、⑤: shell script で実装するにしては複雑な内容になるため、食べログでは TypeScript で実装しています。他の部分は CircleCI の機能や shell script で 1-2 行程度で実装できます。
React の github リポジトリの実装を参考にしました。
④: https://github.com/facebook/react/blob/2c1cf5618a24238136e3bd6139fb7f359dffe0f9/scripts/release/shared-commands/get-build-id-for-commit.js
⑤: https://github.com/facebook/react/blob/2c1cf5618a24238136e3bd6139fb7f359dffe0f9/scripts/release/shared-commands/download-build-artifacts.js
CircleCI の設定項目の調整やビルド結果を tar に固めることで実装の考慮事項を減らし、複雑になりそうなところは TypeScript を用いることでメンテナビリティの高い実装ができました。
こういった実装については、修正頻度は多くありませんが日々の業務を支える根幹となるプロセスの自動化にあたるため、今回は慎重に設計実装を行いました。
手運用が発生する PR について
自動マージしなかった PR の運用について紹介します。
CI が通っている PR (図のパターン1-b の Green)に関しては、動作確認を行い、開発生産性に問題がないことを確認します。
CI が落ちてしまう PR(図のパターン1-a の Red、パターン1-b の Red)に関しては、まずは CI が落ちている原因を確認し、それぞれ対応していきます。
CI が落ちる原因は様々ですが、食べログで多いのは下記の 2 つです。
1. ビルド結果に差分が発生して CI が落ちる
2. フォーマッターやリンター、型チェックで CI が落ちる
順番に頻度と対処法を確認していきましょう。
1. ビルド結果に差分が発生して CI が落ちる
こちらは dependencies に追加してある依存ライブラリのアップデートや、core-js や babel のアップデートによって生じます。
ですので、そこそこの頻度で発生します。
対処法としては、実際に UI を操作する低カバレッジのスモークテストでデグレが無いかを確認してから、別に PR を切って手動でマージすることになります。
2. フォーマッターやリンター、型チェックで CI が落ちる
Prettier や ESLint、TypeScript のバージョンアップ、ライブラリの型のアップデート発生します。
このケースで CI が落ちていることがほとんどです。
基本的な対処法は、Pretteir であれば --fix オプションを付与して自動解決を目論みます。
ESLint や TypeScript、ライブラリの型アップデートは人の手による修正が必須ですが、こちらが曲者で、案外はまることが多いです。
思わず影響範囲が大きい修正になってしまったり、コアコードの修正によりビルド結果に差分が出てしまったりします。
ちなみに、この手の PR は得られる経験値が多いため我々は「はぐ○メタル」と呼んだりしています。
手運用のコスト感
ある程度の手運用が発生することはやむを得ませんが、手運用が発生する割合が 11% 程度だとすると全体としては非常に低コストな運用ができていると感じています。
とはいえまだ効率化の余地はありまして、今後は以下の対応を行っていきたいと考えています。
・husky などの意図的に自動マージを off にしているライブラリアップデートの PR に関しては、自動で検証できる仕組みを導入して自動マージできるようにしていく
・低カバレッジのスモークテストを自動化する
まとめ
食べログでは Renovate を導入しており、半年近く運用してきました。
90% 近くの PR が自動マージされています。
運用コストを減らすために自動マージを有効活用しており、ビルド結果の差分比較により安心安全な自動マージを実現しています。
github と CircleCI を使って PR のブランチから比較対象のバージョンを特定して差分比較を行っています。
手運用の部分もあるものの、運用できる範囲になっております。
今後は、自動マージを意図的に OFF にしているライブラリに対して自動テストの仕組みを導入したり、スモークテストの自動化をすることで自動マージできる PR を増やし、運用のコストを減らしていくことを考えています。
最後に
現在、食べログではフロントエンドに関わるポジションとして以下の2つを募集しています。
気になった方は是非チェックしてみてください!
・フロントエンド統括チームに所属するフロントエンドエンジニア
・フロントエンドをメインにサービス開発を担当していくWEBエンジニア
・難しい課題にチーム一丸となって取り組みたい
・React/TypeScriptでバリバリ開発したい
・レガシーなシステムのリファクタリングがしたい
・アーキテクチャについて探求したい
・食べログというプロダクトに貢献したい
・大規模なシステムの開発に携わりたい
・柔軟に働ける環境で自分のスキルを活かしたい
どれかに当てはまった方は以下のリンクも是非御覧ください!
明日は食べログアドベントカレンダー2021の19日目の記事が公開される予定です!ご期待ください!
この記事が気に入ったらサポートをしてみませんか?