Renovate ではじめる依存関係更新の自動化

本記事は、リクルートライフスタイルアドベントカレンダー10日目の記事です。

リクルートテクノロジーズ兼リクルートライフスタイルのASGチームに所属している渡邉です。

最近は新規開発をやっていて、日々プロジェクトの package.json の更新に追われています。本記事ではその更新タスクを大いに助けてくれた Renovate について紹介します。

Renovate とは

Renovate はプロジェクトの依存関係 (Dependency) の更新を自動化するツールです。似たようなツールとしては、DependabotGreenkeeper があります。プロダクションレベルのプロジェクトでは、明示している Dependency だけでも 20~30 程度あるのではないでしょうか。それらの Dependency は日々更新されており、最新版に追従していくだけでも時間と手間がかかります。Renovate はそのような悩みを解消してくれるすばらしいツールです。

Renovate で Dependency の更新をやってみる

github.comgitlab.com であれば、それぞれ GitHub App と GitLab App が用意されているので導入は簡単です。今回は、社内でホスティングしている GitHub Enterprise(GHE)と GitLab のリポジトリで Renovate を運用する必要があったので、公式にあるドキュメントを見ながらセルフホスティングをやってみました。

準備

リポジトリへアクセストークンを用意します。以下に GitHub と GitLab でのアクセストークンの作成方法を説明します。

GitHub

ドキュメントにしたがって、アクセストークンを作成します。トークンのスコープは “repo” を選択しておきます。

GitHub のアクセストークン生成

トークン生成後、生成されたトークンを控えておきます。

GitLab

ログイン後、右上の “Settings” から “User Settings” 画面に遷移し、サイドバーの “Access Tokens” リンクをクリックすると、トークン生成画面に遷移できます。スコープは “api” を選択しておきます。

GitLab のアクセストークン生成

こちらもトークン生成後、生成されたトークンを控えておきます。

Docker で動かす

ローカル PC に Docker がインストールされていれば、以下のコマンドを実行するだけでリポジトリにプルリクエスト(マージリクエスト)を送ることができます。初回はイメージのダウンロードとビルドで時間がかかります。

1
docker run --rm renovate/renovate --platform ${platform} --token ${token} --endpoint ${endpoint} ${repository-name}

オプションは以下です。

  • platform: GHE なら github、GitLab なら gitlab
  • token: 準備のところで作成した、GHE または GitLab の API トークン
  • endpoint: リポジトリの API エンドポイント (ex. https://self-hosted.gitlab/api/v4/)
  • repository-name: リポジトリ名 (ex. owner/repository-name)

リポジトリのルートに renovate.json がなければ、最初の PR で renovate.json を追加する変更が送られてきます。

Configure Renovate

画像では空の JSON になっていますが、以下のように公式で用意されている base の設定を継承することもできます。

1
2
3
{
  "extends": ["config:base"]
}

renovate.json がある状態で、もう一度コマンドを実行すると、Dependency の更新があれば、その変更 PR が送られてきます。当初の Renovate 導入の目的は、npm パッケージの自動更新でしたが、Renovate 自体は package.json 以外のパッケージファイルもサポートしています。たとえば、Gemfile (Ruby)、build.gradle/build.gradle.kts (Java)、Dockerfile などです。

上記のコマンドをローカル PC の cron に設定しておけば、最小の形で Renovate のセルフホスティングができます。ローカル実行なのでセルフホスティングとは言えないかもしれませんが、どこで実行しても同じクオリティの Dependency 更新 PR が作れるので、ローカル実行でも十分に有用だと思います。

Kubernetes で動かす

Kubernetes での動作方法もドキュメントにサンプルが載っています。cronjob.yaml は以下のようになります。サンプルとほとんど同じですが、一部コメントを入れています。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
apiVersion: batch/v1beta1
kind: CronJob
metadata:
  name: renovate
spec:
  schedule: '@hourly'
  concurrencyPolicy: Forbid
  jobTemplate:
    spec:
      template:
        spec:
          containers:
            - name: renovate
              image: renovate/renovate:13.71.0 # 新しいやつ使う
              args:
                - owner/repository-name # ブランチ指定
              env:
                - name: RENOVATE_PLATFORM
                  valueFrom:
                    secretKeyRef:
                      key: renovate-platform
                      name: renovate-env
                - name: RENOVATE_ENDPOINT
                  valueFrom:
                    secretKeyRef:
                      key: renovate-endpoint
                      name: renovate-env
                - name: RENOVATE_TOKEN
                  valueFrom:
                    secretKeyRef:
                      key: renovate-token
                      name: renovate-env
                - name: GITHUB_COM_TOKEN
                  valueFrom:
                    secretKeyRef:
                      key: github-token
                      name: renovate-env
                - name: RENOVATE_AUTODISCOVER
                  valueFrom:
                    secretKeyRef:
                      key: renovate-autodiscover
                      name: renovate-env
          restartPolicy: Never

secret.yaml を以下のようにします。

1
2
3
4
5
6
7
8
9
10
11
apiVersion: v1
kind: Secret
metadata:
  name: renovate-env
type: Opaque
stringData:
  renovate-platform: 'github'
  renovate-endpoint: 'https://github.company.com/api/v3'
  renovate-token: 'your-github-enterprise-renovate-user-token'
  github-token: 'any-personal-user-token-for-github-com-for-fetching-changelogs'
  renovate-autodiscover: 'false' # リポジトリを自動検知するかどうか

renovate-platformrenovate-endpointrenovate-token は Docker のところで説明したものと同じです。github-token は github.com の読み取り権限トークンです。これはパッケージのリポジトリからリリースノートを取得するために使われます。指定しなくても動作はしますが、API 制限にあたらないように指定しておくことが推奨されています。renovate-autodiscover はリポジトリを自動検知するかどうかの設定です。自分は最初 true に設定していて、チーム内のすべてのリポジトリに renovate.json 追加の PR を送りつけました。手元で試すときは注意してください。

kubectl が使えれば、ローカルでも実行できます。ローカルで実行できたら、あとはどこかしらにホスティングするだけです。チームでは GCP を使ってるので、GKE 上でホスティングするようにしました。

Renovate On-Premises

先日、WhiteSource 社が Renovate を買収したというニュースがあり、 github.com や gitlab.com のプライベートリポジトリの無料化、オンプレミス版の無料化が発表されました。無料化ということで、小さく試すときにも選択肢になりそうです。実際には試していないので、ドキュメントだけ貼っておきます。

WhiteSource Renovate On-Premises Overview

renovate/pro の Docker イメージで構築するようです。以下は Renovate の CLI ツールとの違いです。

  • ジョブの優先度付けができる
  • スケジューラーが組み込まれてるので cron の設定が必要ない
  • リポジトリイベントに対する webhook がある

Renovate を運用してみてよかったこと

Renovate に限らないかもしれませんが、運用してみてよかったところを上げてみました。

小さく始めやすい

Renovate はローカルでも簡単に実行できるので、Dependency 更新の PR を送るという目標まですぐに到達できます。チームへの導入にあたって、早い段階で動くものを見せられるのはいい点だと感じています。ホスティングまでたどり着けなかったとしても、ローカルの便利ツールとしては使い続けられます。

パッケージの更新をキャッチアップしやすい

Renovate が休むことなく PR を送ってくるので使っているライブラリへの感度が上がります。npm 等に publish されてからすぐ後に PR が来るので Renovate 起点でライブラリの更新を知ることが多くなりました。リリースノートをちゃんと書いているパッケージであれば、PR をみるだけでだいたいの変更を把握できます。

パッケージ更新の変更点がわかりやすい

Renovate の PR から、パッケージの変更差分が簡単に見られます。はまっていたバグの修正や気になる更新の内容をソースレベルで見ることができます。GitHub の機能でもバージョンごとの差異は見られますが、PR から直接見れるのはかなり助かります。

Renovate Change

画像の “Change” のリンクから、Renovate が用意しているバージョン間の差分ページを見ることができます。

運用 Tips

renovate.json には多くの設定オプションが用意されています。自動マージや PR の頻度、lock ファイルのメンテナンスなどができます。基本は base の設定を使っているのですが、運用上必要だった設定を紹介します。

Monorepo 設定

Renovate には monorepo パッケージをまとめて PR を送ってくれる機能があります。たとえば、react と react-dom のように、同時に更新するべきパッケージを1つの PR にまとめてくれます。個別の PR でそれぞれマージしていくと、コンフリクトが発生してしまい、少々手間が増えてしまいます。

Renovate Monorepo

この機能は base の設定 を継承しておくだけで使えます。このとき Renovate に monorepo として認識されるのは、Renovarte の monorepo 設定 に書かれているパッケージだけです。ここに載っていないパッケージは個別に設定を書くことができます。以下はリクルートテクノロジーズの OSS である AgreedSpecter をそれぞれ monorepo としてグルーピングする設定です。

1
2
3
4
5
6
7
8
9
10
11
12
13
{
  "extends": ["config:base"],
  "packageRules": [
    {
      "groupName": "agreed",
      "packagePatterns": ["^@agreed/"]
    },
    {
      "groupName": "specter",
      "packagePatterns": ["^@specter/"]
    }
  ]
}

ignorePaths

1つのリポジトリにバックエンドとフロントエンドのコードが入っていて、フロントエンドは Renovate 使いたいが、バックエンド (Java) はまだ使わないという話がありました。そのようなときは、ignorePaths の設定を入れて、パス単位で無視させることもできます。

1
2
3
4
{
  "extends": ["config:base"],
  "ignorePaths": ["backend/**"]
}

peerDependencies の警告チェック

Renovate で npm の peerDependencies の警告チェックはできないようでした。更新をマージし、npm i してから peerDependencies の警告が発覚するということです。Renovate だけでは検知できなかったので、現在は PR に対して、CI で警告をチェックするようにしています。

まとめ

Renovate のセルフホスティング方法と実際に運用した所感について説明しました。

リクルートライフスタイルおよびリクルートテクノロジーズでは DX と UX を極めていくフロントエンドエンジニアを募集しています!もちろん他の領域も幅広く募集しています!!

キャリア採用の関連職種ページはこちら

関連職種の採用情報
詳しくはこちら

リクルートの採用TOPページはこちら