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
で管理しているものは、Terraform
とNode.js
$ cat .tool-versions
terraform 1.0.0
nodejs 16.15.0
3. 環境情報
Renovate
の実行環境はGitHub App
4. renovate.json5 の設定内容抜粋
regexManagers
で .tool-versions
に書かれた Terraform
や Node.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 の設定項目の解説
必須項目は [必須]
、そうではないものは [任意]
としている。
- [必須]fileMatch
- キャプチャする対象が書かれているファイルを指定する。
- [必須]matchStrings
- キャプチャする対象
(currentValue)
を適宜正規表現も使って指定する。 \
(バックスラッシュ) はそれ自体もエススケープする必要がある。たとえば、\n
を書く場合、\\n
となる。
- キャプチャする対象
- [必須]matchStrings に depName を書くか、depNameTemplate を指定する。
- [必須]matchStrings に datasource を書くか、datasourceTemplate を指定する。
datasourceTemplate
には以下のページで書かれているSupported Datasources
のいずれかを指定する。
- [任意]extractVersionTemplate
datasource
やdatasourceTemplate
で指定した更新バージョンの情報を整形する- 例: 頭についている
v
を取り除いた任意の文字列を取得する場合は、"^v(?<version>.*)$"
4-2.datasourceTemplate の値の選定方法
datasourceTemplate
の値を決めるのに試行錯誤したので、調べたことを書いていく。
- 基本的な考え方
- 更新対象のパッケージのマネージャーを Renovate が提供していないか、以下の Renovate のマネージャーのページの Supported Managers から探す。
- 提供している場合、更新対象のパッケージを取り扱うのマネージャーはどの
Datasource
をサポートしているか?調べる。 - 提供されていない場合、 Renovate のドキュメントの
Datasource
のページの Supported Datasources から、更新したいものがないか?探す。
例1. .tool-versions
に書かれた Terraform
の datasourceTemplate
の場合
datasourceTemplate: "github-releases"
例2. .tool-versions に書かれた Node.js
の datasourceTemplate
の場合
datasourceTemplate: "github-tags"
例3. .tool-versions
に書かれた Golang
の datasourceTemplate
の場合
datasourceTemplate: "golang-version"
- ※ Renovate から
Golang
のマネージャーが提供されていないので、これまでのやりかたと異なり、Renovate のドキュメントの Datasource のページの Supported Datasources からgolang-version
をみつける。 - 参考: golang-version の Datasource のドキュメント
- ※ Renovate から
- cf. Golang の Datasource を
golang-version
とした経緯が書かれた issue - cf. Go Modules のマネージャーは Renovate から提供されている。
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 をひとつにまとめることができた。
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 だが、こちらも同様にひとつにグルーピングすることができた。
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. 参考資料
Regex Manager
について調べるにあたり参考にしたドキュメントdepName
とpackageName
の違いや使い分け
major を除いて、Dockerfile に書かれたコンテナイメージの更新の検知が出来るようになっている理由は、
Default Preset
の docker ルールが有効になっている一方で、Docker Preset
の docker:enableMajor のデフォルト値が disabled であるためである。 ↩︎