go.mod で管理されていないライブラリを Renovate で更新する
これまでに Renovate を使って Go のライブラリ更新や、Go 本体のバージョン更新を行なってきました。
Renovate は go.mod を監視しており、go.mod で管理しているライブラリは Renovate で更新することができます。
しかし逆に、go.mod で管理されていなければ Renovate で更新できないのか?と言われるとそうでもありません。
今回は go.mod で管理されていないライブラリを Renovate で更新するための方法を紹介します。
やり方としては2つあります。
- Go 1.24 で導入された tool directive を使う
- Renovate の Custom Manager を使う
tool directive を使う
Go 1.24 では、go.mod 内の tool directive を使用してライブラリの依存関係を追跡できるようになりました(Go 1.24 Release Notes)。
これまで go.mod で管理されていなかったものも、この仕組みに乗せることで Renovate の更新対象に含めることができます。
次のように Dockerfile 内で go install
を使ってライブラリをインストールしていると仮定し、これを tool directive に乗せ替えてみます。
RUN go install go.uber.org/mock/mockgen@v0.4.0
RUN go install github.com/air-verse/air@v1.60.0
上記2つのライブラリで go get -tool <tool_path>
を実行します。
go get -tool go.uber.org/mock/mockgen@v0.4.0
go get -tool github.com/air-verse/air@v1.60.0
すると、go.mod に次のように記述されます。
require (
~省略~
+ github.com/air-verse/air v1.60.0 // indirect
+ go.uber.org/mock v0.4.0 // indirect
~省略~
)
+ tool (
+ github.com/air-verse/air
+ go.uber.org/mock/mockgen
+ )
続いて、Dockerfile に記述していた go install <tool_path>
を go install tool
に変更します。
- RUN go install go.uber.org/mock/mockgen@v0.4.0
- RUN go install github.com/air-verse/air@v1.60.0
+ RUN go install tool
これにより tool directive に記述された全ライブラリのバイナリを $GOBIN
(デフォルトで $GOPATH/bin
) にインストールします。
RUN go install tool
を実行せずとも、go tool mockgen
のようにして指定のツールを実行することもできます。
しかし、その場合はモックの生成コマンドが mockgen
から go tool mockgen
に変わってしまうためモックを生成しているコードに影響を及ぼしてしまいます。
そのため、ここではバイナリを $GOBIN
にインストールすることでコマンドインターフェースを従来通りに保つようにしています。
上記の変更を main ブランチにマージすると、Renovate によって更新する準備が整いました。
あとは、Go のライブラリ更新で紹介したような renovate.json を構成すると、tool directive に記述されたライブラリのバージョンを最新化するPRが Renovate によって作成されました。
Custom Manager を使う
tool directive を使う方法一本で解決できれば良いですが、それができないケースもあります。
例えば golangci-lint では、 go get
コマンドを使ったインストールの動作保証をしておらず、代わりにバイナリインストールを推奨しています。
このようなケースでは Custom Manager を使うことで、他の組み込みマネージャーでは検出されない依存関係を検出するように Renovate を構成できます。
Custom Manager には regex と jsonata の2種類がありますが、今回は regex を使います。
次のように Dockerfile で golangci-lint のバイナリをインストールしていると仮定し、これを Renovate で自動更新できるようにしていきます。
RUN curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s -- -b $(go env GOPATH)/bin v2.1.1
まず、バージョン値を正規表現で抽出しやすい形に変えるべく環境変数化します。
ENV GOLANGCI_LINT_VERSION=v2.1.1
RUN curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s -- -b $(go env GOPATH)/bin ${GOLANGCI_LINT_VERSION}
次に、renovate.json に customManagers の設定を行います。
{
"customManagers": [
{
"customType": "regex",
"fileMatch": ["^Dockerfile$"],
"matchStrings": [
"ENV GOLANGCI_LINT_VERSION=(?<currentValue>\\S+)"
],
"depNameTemplate": "github.com/golangci/golangci-lint",
"datasourceTemplate": "go",
"versioningTemplate": "semver-coerced"
}
]
}
-
customType:regex custom manager を使用するため
regex
を指定します。 - fileMatch:Renovate がリポジトリ内のどのファイルを解析・抽出するかを判断するための正規表現パターンを記述します。ここでは、golangci-lint のバージョンを記述したファイル名を
Dockerfile
としているので、そのファイル名を検出する正規表現にしています。 -
matchStrings:名前付きキャプチャグループの正規表現パターンを記述します。
GOLANGCI_LINT_VERSION
に渡す値をcurrentValue
として抽出し、Renovate に現在のバージョンを認識させます。ちなみに上記例では、v1.64.5 # comment
のようにコメントが含まれる場合でもバージョン番号だけが抽出されるようにしています。 - depNameTemplate:depName を指定します。具体的にはバージョンを検索するライブラリのパスを指定します。この文字列がPRタイトルやコミットメッセージにも含まれます。類似項目として packageNameTemplate がありますが、こちらは検索用途でのみ使用されます(参考)。
-
datasourceTemplate:datasource を指定します。ここでは Go ライブラリの検索を行うため
go
を指定します。 - versioningTemplate: versioning を指定します。ここでは regex Custom Manager のデフォルト値である semver-coerced を指定します。
最後に、renovate.json で enabledManagers を使用している場合、そこに custom.regex
を追加して Custom Manager を有効化します。
{
"enabledManagers": [
"gomod",
"dockerfile",
// 追加
"custom.regex"
],
}
最終的な renovate.json の設定は次のようになります。今回追記した箇所以外については Go 本体のバージョン更新をご参考ください。
{
"$schema": "https://docs.renovatebot.com/renovate-schema.json",
"extends": [
"config:recommended",
":label(renovate)",
":timezone(Asia/Tokyo)"
],
"schedule": ["* * * * 2"],
"rangeStrategy": "bump",
"prHourlyLimit": 10,
"reviewers": [
"atushi-koga"
],
"enabledManagers": [
"gomod",
"dockerfile",
// 今回追記箇所
"custom"
],
// 今回追記箇所
"customManagers": [
{
"customType": "regex",
"fileMatch": ["^Dockerfile$"],
"matchStrings": [
"ENV GOLANGCI_LINT_VERSION=(?<currentValue>\\S+)"
],
"depNameTemplate": "github.com/golangci/golangci-lint",
"datasourceTemplate": "go"
}
],
"postUpdateOptions": [
"gomodTidy"
],
"packageRules": [
{
"matchManagers": [
"gomod"
],
"matchDatasources": [
"golang-version"
],
"groupName": "golang-version-updates"
},
{
"matchManagers": [
"dockerfile"
],
"groupName": "golang-version-updates"
},
{
"matchManagers": [
"gomod"
],
"matchDatasources": [
"go"
],
"matchUpdateTypes": [
"minor",
"patch"
],
"groupName": "golang-modules-minor-patch-updates"
}
]
}
上記設定を main ブランチに反映すると、Renovate によって golangci-lint を更新するPRが作成されました。
Files changed を見てみると、ENV GOLANGCI_LINT_VERSION
が v2.1.1
から v2.1.2
に変更されています。
これで Custom Manager を使ったバージョン管理ができるようになりました!🎉
Discussion