renovate.json を書く上でのヒント集

[Renovate](https://docs.renovatebot.com/) の設定ファイルである renovate.json を書くうえで、私が悩んだポイントをまとめました。
この記事が誰かの参考になれば幸いです。
（もっと良いやり方をご存知の方がいれば、コメントにてお教えください。）

# `extends` には何を指定すべき？

JavaScript もとい TypeScript を用いた Web アプリケーション開発であるならば、大抵は `config:js-app` を指定すれば良いでしょう。

```json:renovate.json
{
  "extends": ["config:js-app"]
}
```

> Default configuration for webapps.

https://docs.renovatebot.com/presets-config/#configjs-app

これを指定することによる効果は以下の通りです。

- `config:recommended`
    - `:dependencyDashboard`
        - issue に "Dependency Dashboard" を作成する
    - `:semanticPrefixFixDepsChoreOthers`
        - セマンティックコミットが使われている場合は、コミットに `fix:` や `chore:` 接頭辞を付与する
    - `:ignoreModulesAndTests`
        - `node_modules/` や `__tests__/` などのディレクトリを無視する
    - `group:monorepos`
        - 既知のモノレポパッケージをグループ化する
        - 例えば https://github.com/facebook/react から提供されるパッケージの更新は 1 つのプルリクエストにまとめてくれる
    - `group:recommended`
        - 推奨される非モノレポパッケージがグループ化される
        - 例えば [@types/react](https://www.npmjs.com/package/@types/react) と [@types/react-dom](https://www.npmjs.com/package/@types/react-dom) の更新は 1 つのプルリクエストにまとめてくれる
    - `replacements:all`
        - 既知の改名済みパッケージに追従してくれる
        - 例えばアプリの依存関係に `@material-ui/icons` が存在する場合は、適当なタイミングで [@mui/icons-material](https://www.npmjs.com/package/@mui/icons-material) に書き換えてくれる
    - `workarounds:all`
        - 一部パッケージの既知の問題を回避する
- `:pinAllExceptPeerDependencies`
    - `peerDependencies` を除く全てのパッケージのバージョンを固定する
    - package.json から `^`や `~` がなくなる

# タイムゾーンを指定したい

Reonvate はデフォルトだと UTC 基準で動作するので、違うタイムゾーンで動かしたい場合は `timezone` に適当な [IANA タイムゾーン](https://en.wikipedia.org/wiki/List_of_tz_database_time_zones)を指定しましょう。

```json:renovate.json
{
  "timezone": "Asia/Tokyo"
}
```

> By default, Renovate schedules use the UTC timezone. If you want Renovate to use your local time, use the `timezone` configuration option. The timezone must be a valid IANA time zone.

https://docs.renovatebot.com/key-concepts/scheduling/#setting-your-timezone

# 同時に存在するプルリクエストの数を制限したい

`branchConcurrentLimit` を指定しましょう。

```json:renovate.json
{
  "branchConcurrentLimit": 3
}
```

> Limit to a maximum of x concurrent branches. 0 means no limit, `null` (default) inherits value from `prConcurrentLimit`.

https://docs.renovatebot.com/configuration-options/#branchconcurrentlimit

# プルリクエストにラベルを付与したい

`labels` を指定しましょう。

```json:renovate.json
{
  "labels": ["renovate"]
}
```

> By default, Renovate won't add any labels to PRs. If you want Renovate to add labels to PRs it creates then define a `labels` array of one or more label strings. If you want the same label(s) for every PR then you can configure it at the top level of config. However you can also fully override them on a per-package basis.

https://docs.renovatebot.com/configuration-options/#labels

# 一部のパッケージを Renovate の監視対象から除外したい

破壊的変更が多いパッケージなど、Renovate に依存せず手動でアップデートした方が良いものも存在します。
そういったケースでは、 `ignoreDeps` を指定しましょう。
例えば [React Native](https://reactnative.dev/) とそれに関連するパッケージを除外したい場合は、以下のルールで実現できます。

```json:renovate.json
{
  "ignoreDeps": [
    "gradle",
    "com.android.tools.build:gradle",
    "react-native",
    "@types/react-native",
    "metro-react-native-babel-preset",
    "com.facebook.react:react-native",
    "com.facebook.flipper:flipper-fresco-plugin",
    "com.facebook.flipper:flipper-network-plugin",
    "com.facebook.flipper:flipper",
    "org.webkit:android-jsc",
    "jest",
    "babel-jest",
    "@types/jest",
    "org.jetbrains.kotlin:kotlin-gradle-plugin"
  ]
}
```

> The `ignoreDeps` configuration field allows you to define a list of dependency names to be ignored by Renovate. Currently it supports only "exact match" dependency names and not any patterns.

https://docs.renovatebot.com/configuration-options/#ignoredeps

# 特定の条件を満たしたパッケージを Renovate の監視対象から除外したい

「メジャーバージョンだけ手動でアップデートしたい」というケースも存在します。
例えば [Storybook](https://storybook.js.org/) のメジャーバージョンだけ除外したい場合は、以下のルールで実現できます。

```json:renovate.json
{
  "packageRules": [
    {
      "matchSourceUrls": ["https://github.com/storybookjs/storybook"],
      "matchUpdateTypes": ["major"],
      "enabled": false
    }
  ]
}
```

# 特定の条件を満たすパッケージを自動でマージしたい

例えば `devDependencies` だけオートマージを有効化したい場合は、以下のルールで実現できます。

```json:renovate.json
{
  "packageRules": [
    {
      "matchDepTypes": ["devDependencies"],
      "automerge": true
    }
  ]
}
```

ちなみに、デフォルトだとオートマージが実行される時間に制限はありません。
そこを制限したい場合は `automergeSchedule` を指定しましょう。

> Use the `automergeSchedule` option to define times of week or month during which Renovate may automerge its PRs. The default value for `automergeSchedule` is "at any time", which functions the same as setting a `null` schedule. 

https://docs.renovatebot.com/configuration-options/#automergeschedule

# 一部の依存関係の管理を特定の人に任せたい

例えば `backend/` ディレクトリ配下の依存関係をアプデするプルリクエストに `"taro"` さんをレビュアーとしてアサインしたい場合は、以下のルールで実現できます。

```json:renovate.json
{
  "packageRules": [
    {
      "matchFileNames": ["backend/**"],
      "reviewers": ["taro"]
    }
  ]
}
```

`reviewers` には、ユーザー名などを指定します。
GitHub の場合はユーザー名（GitHub の Reviewers 一覧上に表示される方のやつ）やチーム名が指定可能です。

> Requested reviewers for Pull Requests (either username or email address depending on the platform).

> If you're assigning a team to review on GitHub, you must use the prefix `team:` and add the last part of the team name.

https://docs.renovatebot.com/configuration-options/#reviewers

# `group:monorepos` に含まれていないモノレポをグループ化したい

例えば [React Native Firebase](https://rnfirebase.io/) のパッケージをグループ化したい場合は、以下のルールで実現できます。

```json:renovate.json
{
  "packageRules": [
    {
      "matchSourceUrls": ["https://github.com/invertase/react-native-firebase"],
      "groupName": "react-native-firebase monorepo",
      "matchUpdateTypes": ["digest", "patch", "minor", "major"]
    }
  ]
}
```

# モノレポじゃないパッケージ同士をグループ化したい

例えばプロダクトで使用している Node.js のバージョン（package.json の `engines.node` フィールドや、.node-version ファイルなど）と [cmig/node](https://circleci.com/developer/ja/images/image/cimg/node) をグループ化したい場合は、以下のルールで実現できます。

```json:renovate.json
{
  "packageRules": [
    {
      "matchPackageNames": ["node", "cimg/node"],
      "groupName": "node",
      "matchUpdateTypes": ["digest", "patch", "minor", "major"]
    }
  ]
}
```

# 任意のコマンドを実行したい

`postUpgradeTasks` を指定することで、コミット前に任意のコマンドを実行させることができます。これにより、例えばリントを走らせたり、React Native を使ったプロダクトであれば `pod install` を走らせたりすることができます。
ただしこの機能は **self-hosted な Renovate インスタンスでしか使えません**。ご注意ください。
逆に言えば、この機能が欲しい場合は self-hosted 方式を検討しましょう。

> Post-upgrade tasks that are executed before a commit is made by Renovate.

> Post-upgrade tasks can only be used on self-hosted Renovate instances.

https://docs.renovatebot.com/configuration-options/#postupgradetasks

# GitHub の設定はどうしたら良い？

## プルリクエストのレビュー

プルリクエストのレビューが必須となっている場合は、GitHub の "[Allow specified actors to bypass required pull requests](https://github.blog/changelog/2021-11-19-allow-bypassing-required-pull-requests/)" オプションを使うか、[renovate-approve](https://github.com/apps/renovate-approve) を使いましょう。

> If you're on `github.com` or GitHub Enterprise Server (`>=3.4`) you can let Renovate bypass the mandatory Pull Request reviews using the "Allow specified actors to bypass required pull requests" option in your branch protection rules.
> 
> Alternatively, if you use the Mend Renovate App, you can also install the helper apps renovate-approve and renovate-approve-2 and they will mark all automerging Pull Requests by Renovate as approved. These approval helper apps are only available for GitHub.

https://docs.renovatebot.com/key-concepts/automerge/#required-pull-request-reviews

## GitHub のオートマージ機能の利用

`platformAutomerge` を `true` に、`automergeType` を `pr` にすることで、プラットフォームのオートマージ機能が使えるようになります。これにより、オートマージが高速化されます。
（なお、これらのオプションはデフォルトでそうなっています。）

> If you have enabled `automerge` and set `automergeType=pr` in the Renovate config, then leaving `platformAutomerge` as `true` speeds up merging via the platform's native automerge functionality.

https://docs.renovatebot.com/configuration-options/#platformautomerge

https://docs.renovatebot.com/configuration-options/#automergetype

GitHub 側では、リポジトリの "[Allow auto-merge](https://docs.github.com/ja/repositories/configuring-branches-and-merges-in-your-repository/configuring-pull-request-merges/managing-auto-merge-for-pull-requests-in-your-repository)" オプションを ON にし、ブランチ保護ルールを作成しましょう。

> ただし、 GitHub の Automerge には注意が必要であり、気をつけないと CI が失敗しているのに Pull Request がマージされてしまいます。
> 
> - リポジトリの設定で Allow auto-merge を有効化する必要がある
> - base branch に Branch Protection Rule を設定する必要がある
>   - `Status checks that are required.` で status checks を選択する。一つも選択しないと、 Automerge を有効化できない
> 
> `Status checks that are required.` でチェックしたもの以外が失敗していても Pull Request はマージされてしまうことに気をつけてください。 GitHub Actions の job が if で skip されて実行されてない場合もマージされるようです。

https://blog.studysapuri.jp/entry/2022/02/18/080000

## GitHub マージキューの利用

筆者は使ったことがありませんが、GitHub には[マージキュー](https://docs.github.com/ja/repositories/configuring-branches-and-merges-in-your-repository/configuring-pull-request-merges/managing-a-merge-queue)なる機能があるそうです。
Renovate でも使えるようなので、興味のある人は調べてみてください。

> Renovate supports GitHub's Merge Queue.

https://docs.renovatebot.com/key-concepts/automerge/#github-merge-queue