1. この記事を書こうと思った背景

パッケージのバージョン管理をするとなったときに真っ先に思い浮かぶツールは Renovate だが、なんと .tool-versions のマネージャーが提供されていなかった。

Managers - Renovate Docs で挙げられている dockerfile などはマネージャーが提供されており、たとえば、Dockerfile の場合、デフォルトで以下の書式の Dockerfile に書かれたコンテナイメージのバージョン管理が major を除いてできる。1

(^|/|.)Dockerfile$

(^|/)Dockerfile[^/]*$

さて、マネージャーが提供されていない .tool-versions に書かれた言語やツールのバージョン管理をどうすればよいだろうか?

結論から言うと、Regex Manager.tool-versions から更新管理したいものを指定(キャプチャ)すればよかった。

この記事では、具体的にどうやったか?その設定をするためにどう調べたか?書いていきたい。

2. 前提

2-1. 2022/08/01 時点でのワークアラウンドな方法であること

以下の issue で議論されているように、以前から .tool-versions をサポートしてほしいという声はあがっている。そのため、この記事で書かれていることは、あくまでも 2022/08/01 時点でのワークアラウンドな方法であることとしたい。

Upgrade versions in .tool-versions #4051

2-2. .tool-versions で管理しているもの

  • .tool-versions で管理しているものは、TerraformNode.js
$ cat .tool-versions
terraform 1.0.0
nodejs 16.15.0

3. 環境情報

  • Renovate の実行環境は GitHub App

4. renovate.json5 の設定内容抜粋

regexManagers.tool-versions に書かれた TerraformNode.js の現バージョンをキャプチャする。

$ cat renovate.json5
{
//抜粋
  regexManagers: [
    {
      // Terraform
      fileMatch: ["^.tool-versions$"],
      matchStrings: ["terraform (?<currentValue>\\d+\\.\\d+\\.\\d+)"],
      datasourceTemplate: "github-releases",
      depNameTemplate: "hashicorp/terraform",
      extractVersionTemplate: "^v(?<version>.*)$"
    },
    {
      // Node.js
      fileMatch: ["^.tool-versions$"],
      matchStrings: ["nodejs (?<currentValue>\\d+\\.\\d+\\.\\d+)"],
      datasourceTemplate: "github-tags",
      depNameTemplate: "nodejs/node",
      extractVersionTemplate: "^v(?<version>\\d+\\.\\d+\\.\\d+)$"
    }
  ]
}

4-1. regexManagers の設定項目の解説

必須項目は [必須] 、そうではないものは [任意] としている。

4-2.datasourceTemplate の値の選定方法

datasourceTemplate の値を決めるのに試行錯誤したので、調べたことを書いていく。

  • 基本的な考え方
    • 更新対象のパッケージのマネージャーを Renovate が提供していないか、以下の Renovate のマネージャーのページの Supported Managers から探す。
    • 提供している場合、更新対象のパッケージを取り扱うのマネージャーはどの Datasource をサポートしているか?調べる。
    • 提供されていない場合、 Renovate のドキュメントの Datasource のページの Supported Datasources から、更新したいものがないか?探す。

例1. .tool-versions に書かれた TerraformdatasourceTemplate の場合

例2. .tool-versions に書かれた Node.jsdatasourceTemplate の場合

例3. .tool-versions に書かれた GolangdatasourceTemplate の場合

5. 小ネタを一問一答形式で書く

5-1. .tool-versions に書かれた Terraform のバージョンと tf ファイルの required_version のバージョンの更新 PR をひとつにまとめたい

そもそもどうして別々の PR になっているか?というと、.tool-versions に書かれた Terraform のバージョンと tf ファイルの required_version のバージョンはそれぞれ異なる packageRules で設定しているためである。

このように、複数の packageRules で設定している更新をひとつにまとめたい場合、groupName で同じ値を指定することでまとめられる。

  regexManagers: [
//略
  ],
  packageRules: [
    {
      // .tool-versions
      groupName: "terraform",
      matchManagers: ["regex"],
    },
    {
      // tf ファイルの required_version
      groupName: "terraform",
      matchManagers: ["terraform"],
      matchDepTypes: ["required_version"]
    }
  ]

以下は .tool-versions に書かれた Terraform のバージョンと tf ファイルの required_version の更新PRの CHANGELOG だが、無事、 .tool-versions に書かれた Terraform のバージョンと tf ファイルの required_version のバージョンの更新 PR をひとつにまとめることができた。

Image from Gyazo

5-2. .tool-versions に書かれた Node.js のバージョンと Dockerfile に書かれた Node.js のコンテナイメージのバージョン更新 PR にまとめたい

Node.js の場合も同様に、groupName を使うことでまとめられる。

  regexManagers: [
//略
  ],
  packageRules: [
    {
      // .tool-versions
      groupName: "nodejs",
      matchManagers: ["regex"],
      matchPackageNames: ["nodejs/node"]
    },
    {
      groupName: "nodejs",
      matchDatasources: ["docker"],
      matchPackageNames: ["node"]
    }
  ]

参考: group:nodeJs | Group Presets - Renovate Docs

以下は .tool-versions に書かれた Node.js のバージョンと Dockerfile に書かれた Node.js のコンテナイメージのバージョン更新 PR の CHANGELOG だが、こちらも同様にひとつにグルーピングすることができた。

Image from Gyazo

5-3. terraform-version マネージャーを使ってもいい?

ところで、Renovate には、terraform-version というマネージャーがある。わざわざ、Regex Manager を使わなくても terraform-version マネージャーを使えばいいのではないか?

、、と思って調べてみたが、実は terraform-version マネージャーでは、.tool-versions に書かれた Terraform のバージョン管理はできない。

terraform-version マネージャーは、あくまでも .terraform-version に書かれた Terraform のバージョンの更新管理をするためのマネージャー であり、Terraform のバージョン管理をするためのマネージャーではなかった。

もし、Terraform のバージョン管理役を .tool-versions ではなく、.terraform-version が担っているのであれば、Renovate の設定せずとも .terraform-version に書かれた Terraform のバージョン管理ができる。

By default, Renovate will check any files matching the following regular expression: (^|/).terraform-version$.

参考: Automated Dependency Updates for Terraform Version - Renovate Docs

nodeenv マネージャーも同様で、nodeenv マネージャーで .tool-versions に書かれた Node.js のバージョン管理はできない。nodeenv マネージャーは、あくまでも .node-version に書かれた Node.js のバージョンを更新管理をするためのマネージャーである。

参考: Automated Dependency Updates for nodenv - Renovate Docs

5-4. depName と packageName の違いや使い分けは?

  • packageName が未指定である場合、depName の値が適用される。
  • 両方値が指定されている場合、depName は ログやコミットメッセージ、 PR で使われ、packageName はパッケージレジストリから更新対象をルックアップするのに使われる。

参考: Difference between depName and packageName? · Discussion #14885 · renovatebot/renovate

6. 参考資料


  1. major を除いて、Dockerfile に書かれたコンテナイメージの更新の検知が出来るようになっている理由は、Default Presetdocker ルールが有効になっている一方で、Docker Presetdocker:enableMajor のデフォルト値が disabled であるためである。 ↩︎