🌊

Renovate を dry-run する CI を作る

2022/12/07に公開

この記事では Renovate の設定を変更した際に dry-run する GitHub Actions のワークフローを書いたので紹介します。
これは 天久保 Advent Calendar 2022 の 7 日目の記事です。

背景

Renovate という依存関係の更新を自動化するツールがあります。

https://github.com/renovatebot/renovate
https://docs.renovatebot.com

Renovate を使えば、GitHub App をリポジトリにインストールするだけで依存関係を更新する PR の作成を自動化できます。
Renovate は多くのパッケージマネージャをビルトインサポートしている[1]ので、設定なしで使えるユースケースも多いです。

しかし時には Renovate がサポートしていない形式でリポジトリにコミットされた依存関係を更新したい場合があります。そんなときに活躍するのが Regex Manager です。

https://docs.renovatebot.com/modules/manager/regex

これは Renovate の設定ファイル[2]にファイルパスとファイル内の文字列にそれぞれマッチする正規表現を設定することで、Renovate が依存関係を検出してくれるようになる機能です。
本題から逸れるので Regex Manager の詳しい説明や具体的なユースケースは上記の Regex Manager のドキュメントを参照してください。

このように Renovate がビルトインサポートしていない形式の依存関係にも対応できるのはありがたいことです。しかし、複雑な Regex Manager の設定を書いていると実際に Renovate が意図した通り設定を解釈してくれるのか確認[3][4]したくなります。

renovate.json をテストする仕組みの例として、Renovate の onboarding PR があります。

Renovate onboarding PR

わかりにくいですが、写真最下部の以下のようなリンクを踏むことで、onboarding PR のブランチの renovate.json で Reanovate を実行したログを見ることができます。

View repository job log here.

しかし、この onboarding PR の仕組みは Renovate をリポジトリに導入するときにしか使用できません。
リポジトリに Renovate を導入した後で renovate.json に変更を加えてテストしたい場合は以下のような手順を踏む必要があります。

  1. すでにある onboarding の PR をリネームし
  2. default branch から renovate.json を削除し
  3. もう一度 onbording をやり直す

https://docs.renovatebot.com/getting-started/installing-onboarding/#nuke-config-and-re-onboard

renovate.json のテストのためにこのような手順は踏みたくありません。
そこで、Renovate を dry-run する CI を自前で作っていくことにします。

実装

Renovate の実装は OSS になっており、CLI や GitHub Actions のアクションとして実行できます。
そして Renovate のドキュメントを睨むと、丁度要求を満たしてくれるオプションが見つかります。

これらのオプションを渡して実行してやれば良さそうです。
実際に手元で試してみると、うまく行きました。

npm install -g renovate
RENOVATE_TOKEN='<GitHub Personal Access Token>' LOG_LEVEL=debug RENOVATE_BASE_BRANCHES='<custom-branch>' \
  renovate '<owner>/<repository>' \
  --dry-run=full \
  --use-base-branch-config=merge

これをそのまま GitHub Actions に載せたのが以下のワークフローです。

しかしこれを実行すると以下のメッセージとともに終了してしまいました。こまりましたね。

# 中略
"message": "Response code 403 (Forbidden)",
# 中略
    "url": "https://api.github.com/user",
    "hostType": "github",
    "username": "",
    "password": "",
    "method": "GET",
    "http2": false
# 中略
DEBUG: Error authenticating with GitHub
# 中略

どうやら GitHub API の /user にアクセスしようとして拒否されているようです。
ここで Renovate が使用している GitHub の API token は GitHub Actions の ${{ github.token }} に自動的に注入されるものです。このトークンには /user にアクセスする権限がありません。そのため、Renovate が GitHub API の /user 以下へアクセスした際にエラーが出ています。
GitHub Actions で自動的に注入されるトークンを使用せず、専用の Github App を作成してこの制限を回避するなどの対処は考えられます。しかし Renovate の dry-run のためにわざわざその手間をかけるのは避けたいです。

実装 2

ドキュメントにも手がかりがないので、Renovate の実装を追ってなんとかできないか調べることにしました。

まずは /user を直接呼び出すコードを確認します。
この getUserDetails という関数で GitHub からユーザ情報を fetch しているようです。
同じファイルの getUserEmail も怪しいですが一旦置いておきます。

https://github.com/renovatebot/renovate/blob/190099a6e3ed2604aafedb89e9b67b7c7dbe7df7/lib/modules/platform/github/user.ts#L7-L28

次に getUserDetails を呼び出している箇所を探します。
関連のあるコードパスで getUserDetails を呼び出している箇所は以下の部分だけでした。

https://github.com/renovatebot/renovate/blob/190099a6e3ed2604aafedb89e9b67b7c7dbe7df7/lib/modules/platform/github/index.ts#L145-L153

https://github.com/renovatebot/renovate/blob/190099a6e3ed2604aafedb89e9b67b7c7dbe7df7/lib/modules/platform/github/index.ts#L155-L167

コードから見て、GitHub のユーザ名と Git の commit author の名前を取得するために Users API を叩いており、あらかじめセットしておけば呼び出さなくなるようです。希望が見えてきました。
ついでに getUserEmail も少なくともこのコードパスでは呼び出されなくなりそうです。

再び Renovate のドキュメントに戻ります。
Renovate のドキュメントで GitHub のユーザ名と Git の commit author の名前を渡すことができそうなオプションを探すと、以下の 2 つがありました。
これを指定すればよさそうです。

完成

最後に

以上、Renovate を dry-run する CI の紹介でした。
自分はすでに息切れしていますが、天久保 Advent Calendar 2022 はまだ続くのでよろしくお願いします。

脚注
  1. Renovate Docs | Renovate DocsLanguage Support を参照。 ↩︎

  2. 以降は renovate.json と表記する。実際には renovate.json 以外もある。Installing & Onboarding - Renovate Docs ↩︎

  3. 以降はこの作業を指して「renovate.json のテスト」または単に「テスト」と呼ぶ。 ↩︎

  4. Renovate に同梱されている renovate-config-validator というツールもあるが、あくまでも renovate.json の形式を確認するだけなので今回の要件は満たせない。https://docs.renovatebot.com/getting-started/installing-onboarding/#reconfigure-via-pr ↩︎

Discussion