Renovateで人類には早すぎたライブラリの更新を自動化してみた(in gitlab-ci

永井です、このブログには1年5ヶ月ぶりの登場です。お久しぶりです。

皆様年末年始はいかがお過ごしだったでしょうか、大晦日にふるさと納税を納めた方、3が日は実家から一歩も出なかった方、朝方に寝て昼過ぎに起きる生活を送っていた方……。ちなみに全て僕の事です。 毎年こんなもんですが今回は本を1冊読めました、誰か褒めて。

さて本題に入りまして、今回はRenovateをgitlab-ci上で定期実行し、ライブラリのバージョンを自動で追跡するようにした話をします。似た状況で導入を考えてる方や、バージョンのアップデートについていけないとお悩みの方の助けになれば幸いです。

Renovateとは

renovatebot.com

主にgithubやgitlab上で動作するbotで、package.jsonなどを読み取り、依存性を解決した上でバージョンアップを行ったマージリクエスト(プルリク)を行ってくれるというものです。

これを人間の手で行うにはあまりに手間で、「バージョンアップは人類には早すぎた」と感じていたので存在を知ってすぐに導入を決意しました。

導入にあたって

本来は https://github.co.jp/https://gitlab.com/ 内で管理されたプロジェクトにbotとして導入することで自動的にマジリク(プルリク)を作ってくれますが、現在バージョン管理は自社サーバで運用をしているgitlab上で行っているため、セキュリティやネットワークの問題があり手軽に導入できる環境では無いという問題がありました。

しかし調査を進めていくと、Renovateはオープンソースであり、しかもDockerのimageを公式に配ってくれていることが分かりました。このimageで好きなところでコンテナを立ち上げればRenovateの実行が容易にできます。

hub.docker.com

「えっ、じゃあこれgitlab-ciで回せばよくない?」と思い構築をしたので、その手順を共有します。

やりたいこと

  1. 対象はフロントエンド周り(TypeScript + React + Redux ...etc)
  2. 毎日午前4時にRenovateを実行し、ライブラリのバージョンアップを確認する。バージョンが上がるものがあればマージリクエストが提出される
  3. Renovateが提出したマージリクエストを検知してビルドの可否とテストコードの実行を行う

これを実現することで、エンジニアはマージリクエストを確認し、ビルドとテストが通っていればmergeボタンをポチッと押すだけでバージョンアップができます。

逆に通っていなければ、マジリク元のブランチをローカルで編集、pushすることでスムーズに修正を行うことができます。

導入手順

以下の手順で行いました。

  1. gitlabのtokenの発行
  2. (とりあえずローカルで動かしてみる)
  3. Renovateの設定ファイルの作成
  4. gitlab-ci.ymlの設定
  5. schedulerに登録

順を追って説明します

gitlabのtokenの発行

gitlabにRenovateのコンテナがアクセスするためのtokenを発行します。

UserSettings > Access Tokensから発行ができるので、権限はAPIにチェックを入れ発行して下さい。名前と期限は任意で良いです。

f:id:AdwaysEngineerBlog:20190111142041p:plain

発行されたらWDjG3cXmgTthH2w4soUtの様な文字列が表示されるのでメモっておきます。

とりあえずローカルで動かしてみる

dockerが入った環境で以下のコマンドを叩けば動かすことができます。

docker run --rm renovate/renovate --platform gitlab --token {発行したtoken} --endpoint https://{gitlabのhost}/api/v4 {リポジトリ名}

手で打つだけならこれでOKです。

Renovateの設定ファイルの作成

先程のコマンドにあったオプションを始めとするセルフホスティングにおける設定は以下にまとまっており、設定ファイルに書くことでコマンド実行時のオプションを省略することができます。

renovatebot.com

今回は config.jsというファイルにしてアプリケーションのルートディレクトリに置きます。

module.exports = {
  logLevel: "info",
  platform: "gitlab",
  token: "{発行したtoken}",
  endpoint: "https://{使っているgitlabのhost}/api/v4",
}

また、Renovateの挙動に関しても設定ファイルを作ることで操作ができます。設定項目は以下にまとまってあります。

renovatebot.com

例えばautomergeの項目をtrueにしておくと、マージも自動でしてくれて大変ロックになります。

今回はrenovate.jsonという名前で以下を記述しました。

{
  "includePaths": ["frontend/package.json"],
  "extends": [
    "group:reactMonorepo",
    "group:storybookMonorepo",
    "group:emotionMonorepo",
    "group:jestMonorepo",
    "group:muiMonorepo"
  ]
}

includePathパッケージ管理ファイルのpathを書くことでRenovateを実行する範囲を指定することができます。今のプロジェクトではサーバサイドとフロントエンドのソースを同じリポジトリで管理しており、フロントエンド周りのみ実行範囲としたかったため指定しています。検証当初は指定しなかったため、開発環境用のDockerfileを見て片っ端からアップデート(もちろん動かない)しようとして大変なことになりました。

extendsは上記のように書くと複数のライブラリをある程度まとめてアップデートしてくれるため便利です。今回はReactやJestなどをまとめる設定をしています。

まとめ方は自分で設定もできますが、すでに基本セットを公式に用意してくれています。

renovatebot.com

gitlab-ci.ymlの設定

さてRenovateの設定が完了したので、これをgitlab-ciに組み込みます。

.gitlab-ci.ymlに以下を追加します。

renovate:
  stage: check_version
  image:
    name: renovate/renovate
    entrypoint: [""]
  script: node /usr/src/app/lib/renovate.js {リポジトリ名}
  only:
    variables:
      - $renovate
    refs:
      - master

renovateという変数付きのmasterブランチのイベントに対してRenovateを走らせるようにしています。この変数がポイントで、これが無いとmasterブランチがpushされる度にRenovateが走ります。そのため次に設定するschedulerでのみ走るように設定しておきます。

スケジューラーに登録

あとは定期的に走らせるためにgitlab内のスケジューラーに登録をします。CD/CIのScheduler→New Scheduleで登録画面に遷移して、以下のように入力します。

f:id:AdwaysEngineerBlog:20190111143115p:plain

「毎日午前4時にmasterブランチに対してrenovateという変数付きでイベントを走らせてね」という設定内容です。これによって.gitlab-ci.ymlで設定したスクリプトが走ります。

ちなみに実行ボタンもあるので、任意のタイミングで走らせることもできます。

f:id:AdwaysEngineerBlog:20190111142101p:plain

実行結果

以下のようにマージリクエストがずらーっと出てきます。

f:id:AdwaysEngineerBlog:20190111142143p:plain

中身はこんな感じ、バージョンの変化や参照先のリンクもあって、至れり尽くせりです。

f:id:AdwaysEngineerBlog:20190111142157p:plain

設定方法は割愛しますが、ブランチはrenovate/hogehogeという名前で自動で作られるので、renovate/~~に反応してテストを走らせるようにしておきます。

f:id:AdwaysEngineerBlog:20190111142207p:plain

これで一通り構築が完了しました。あとは日々提出されるマージリクエストを見てマージしたり修正したりしていきます。

注意点

バージョンアップを長い間行っていないプロダクトにいきなり入れるのは危険です。古いライブラリを全てを最新にするべくマジリクが大量に出されてビルドが総コケしてテストもロクに走らず空は堕ち大地は割れ海は涸れます(すいません盛りました)

Renovateはバージョンを一つずつ上げるというよりは最新にするために動くため、新規の環境に導入するとコスパが良いと思います。自分達のプロダクトではjQuery→Reactに移る際に完全にディレクトリを分け1から作り直しているため導入することができました。サーバサイドでの導入は要検討中です。

まとめ

gitlab-ciでRenovateを定期実行することによって放置されがちだったライブラリのアップデートがグッと楽になり、テストを書くメリットも増やすことができました。

特にフロントエンド周りは本当に意味のわからないペースでアップデートが進んでいるので、今のうちに導入ができて良かったです。導入後、元旦にアップデートのマジリクの通知が来ていた時は「元旦くらい休もうよ」と突っ込んだのを覚えています。

今回はnodeのバージョンの管理を行いましたが、PHPやPythonも管理ができるようなので(なぜかRubyは対象外)、なにか新しくプロダクトを立ち上げる際には導入を検討してみてはいかがでしょうか。