🔄

cimg/node のバージョンアップデートを Renovate で管理する

2023/11/28に公開

これはなに

CircleCI が提供する Docker イメージ cimg/node のバージョンアップデートを Renovate で適切に管理するための設定手順をまとめたものです。

Renovate による Node.js のアップデート管理

Renovate は以下のファイルに記載されている Node.js のバージョンのうち LTS バージョンのみを自動で検知し、アップデート Pull Request を作成します。

https://docs.renovatebot.com/node/

cimg/node について

cimg/node は Node.js がインストールされた Docker イメージであり、CircleCI で Node.js を使用する際によく使われています。このイメージのバージョン表記はインストールされている Node.js のバージョンを表しており、 例えばcimg/node:18.13.0 は Node.js のバージョン 18.13.0 がインストールされた Docker イメージです。

問題なのは cimg/node が先述した Node.js の管理対象外であることです。単純な SemVer に準拠したバージョンアップデートなら管理してくれますが、全てのアップデートを検知してしまうため、このままでは LTS 以外の不要な Pull Request も作成されてしまいます。つまり package.json.nvmrc などに記載されているバージョンと一致しなくなるリスクがあるため、どうにかして cimg/node も LTS バージョンのみを対象とする必要があります。

ゴール

  • cimg/node のバージョンアップデートは package.json.nvmrc に記載されている Node.js のバージョンと足並みを揃える。
  • Node.js のバージョンアップデートは LTS バージョンのみを対象とする。

サンプルプロジェクト

https://github.com/wakamsha/learn-renovate

設定手順

1. Renovate の設定ファイルを作成する

リポジトリのルート直下に renovate.json を作成します。内容は Renovate を有効化した際に自動生成されるものと同じもので大丈夫です。

renovate.json
{
  "$schema": "https://docs.renovatebot.com/renovate-schema.json",
  "extends": ["config:recommended"]
}

2. cimg/node のバージョニングルールを Node.js に揃える

matchPackageNames フィールドに cimg/node を追加した Package Rule を作成し、さらに versioning フィールドに node を指定します。

renovate.json
{
  "packageRules": [
    {
      "groupName": "nodeJs",
      "matchPackageNames": ["cimg/node"],
      "versioning": "node"
    }
  ]
}

versioning は、対象をどのようなバージョニングルールで管理するかを指定するフィールドです(デフォルトは SemVer)。node と指定することで、Node.js の LTS バージョンのみを対象としたルールが適用されます。

https://docs.renovatebot.com/modules/versioning/#nodejs-versioning

ここまでの設定内容

renovate.json
{
  "$schema": "https://docs.renovatebot.com/renovate-schema.json",
  "extends": ["config:recommended"],
  "timezone": "Asia/Tokyo",
  "separateMultipleMajor": true,
  "separateMinorPatch": true,
  "packageRules": [
    {
      "groupName": "nodeJs",
      "matchPackageNames": ["cimg/node"],
      "versioning": "node"
    }
    //...
  ]
}

これで cimg/nodepackage.json + .nvmrc ( + .node-version ) のアップデートにおける足並みが揃うようになりました。

cimg/node cimg/node
package.json
+
.nvmrc
+
.node-version
node

課題: 1つの Pull Request にまとめたい

バージョニングのルールは揃ったものの、Pull Request が別々に作成されてしまうのは問題です。Renovate は様々な設定を公式プリセットとして提供しており、その中に group:nodeJs というものがあります。これを extends フィールドから指定することで利用・拡張することで cimg/nodepackage.json.nvmrc と同じ扱いにできないか試みたのですが、残念ながらうまくいきませんでした。

renovate.json
{
  "packageRules": [
    {
      "groupName": "nodeJs",
+     "extends": ["group:nodeJs"],
      "matchPackageNames": ["cimg/node"],
      "versioning": "node"
    }
  ]
}

https://docs.renovatebot.com/presets-group/#groupnodejs

結果は変わらず、cimg/nodeの Pull Request は package.json とは別々に作られてしまいます。公式ドキュメントや Issue にもそれらしい情報は見当たらなかったので現状は諦めていますが、もしどなたか知見をお持ちでしたらご教示いただけると幸いです。

追記: extends せず必要なフィールドのみ指定することで解決

group:nodeJs を extend するのではなく、その中から必要なフィールドを抜き出して指定することで期待通りの挙動となります[1]。以下は group:nodeJs のソースコードです。

https://github.com/renovatebot/renovate/blob/68e871e86f1617a6a3830f906bd4a9e6915fbae3/lib/config/presets/internal/group.ts#L298-L310

上記のうち matchDepNames, matchPackagePatterns を流用します。

renovate.json
{
  "packageRules": [
    {
      "groupName": "nodeJs",
-     "extends": ["group:nodeJs"],
-     "matchPackageNames": ["cimg/node"],
+     "matchDepNames": ["node"],
+     "matchPackagePatterns": ["/node$"],
      "versioning": "node"
    }
  ]
}

"matchPackagePatterns": ['/node$']cimg/node にもマッチするため matchPackageNames フィールドは不要となります。

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

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

これでようやく期待通りの挙動となりました。Pull Request が 1 つにまとまり、かつ cimg/node のバージョンアップデートは package.json と同じ扱いになっています。

to-be

versioning フィールドも問題なく機能しており、LTS バージョンを対象とした Pull Request のみが作成されています。

pr-list

なぜ group:nodeJs の extend ではうまくいかないのか

公式ドキュメントには記載されていないのですが、そもそも group preset の extend は非推奨とのことです(実行ログに警告が出力される)。

https://github.com/renovatebot/renovate/blob/main/lib/config/validation.ts#L277-L288

また、詳細は不明ですが matchDatasources: ['docker'] があると期待通りの挙動とならないようです。

https://github.com/renovatebot/renovate/discussions/23441#discussioncomment-6488108

それならば group:nodeJs を extend したうえで matchDatasources を上書きすればよいのではと考えたものの、このフィールドは mergeable: true 扱いのため上書きができないようです。

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

参考文献

https://blog.recruit.co.jp/rmp/front-end/post-21350/

脚注
  1. 弊社の有識者よりご指摘いただきました。 ↩︎

Discussion