go installで指定しているバージョンをRenovate管理する
はじめに
Go 1.16から go install
コマンドでバージョン指定ができるようになって久しいですが、このバージョンがRenovateに管理されずに困っているという方は少なくないのではと思っています。
例えば golang.org/x/tools/cmd/stringer
のインストールは
go install golang.org/x/tools/cmd/stringer@v0.7.0
というコマンドで特定のバージョンを指定してインストールを行います。ここでこの@v0.7.0
のバージョンをRenovateに管理してほしいところですが、実際にはこれではRenovateの管理下には置かれません。
それもそのはず、RenovateはGo Modulesに対しては go.mod
のみ管理対象にするため、リポジトリに含まれる go.mod
は管理してくれますが、それ以外のファイルに記述されたpackageに関しては無視されてしまいます。
しかし以下のようにDockerfileやMakefile等にツール系packageのインストールを記述することはあると思います。
FROM golang:1.20.1
RUN go install golang.org/x/tools/cmd/stringer@v0.7.0
RUN go install github.com/99designs/gqlgen@v0.17.23
...
ではどうするのか?
Renovate管理したい
Renovateには "regex manager" という「正規表現でRenovate管理するpackage情報を指定する」という仕組みがあり、これを上手く使います。
ref. https://docs.renovatebot.com/modules/manager/regex/
例えば上記のようにDockerfile内でいくつかのpackageをgo install
でインストールするようにしている場合、
RUN go install golang.org/x/tools/cmd/stringer@v0.7.0
RUN go install github.com/99designs/gqlgen@v0.17.23
次のような設定をrenovate.json
等のRenovate設定ファイルに設定しておくと、Renovateが更新プルリクエストを出してくれるようになります。
{
"$schema": "https://docs.renovatebot.com/renovate-schema.json",
"extends": ["config:base"],
// 以下の"regexManagers"が必要な設定
"regexManagers": [
{
"fileMatch": ["^Dockerfile$"],
"matchStrings": ["go install (?<depName>[^@]+?)@(?<currentValue>.+)\n"],
"datasourceTemplate": "go"
}
]
}
またもう一つの例として、Goのlinterとしてよく使用されている golangci-lint の場合は、以下のようにするとOKです。(※今回はDockerfileに対して記述した例ばかりですが、Makefileやシェルスクリプトにも応用することができます)
ENV GOLANGCI_LINT_VERSION v1.51.1
RUN curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s -- -b $(go env GOPATH)/bin $GOLANGCI_LINT_VERSION
{
"$schema": "https://docs.renovatebot.com/renovate-schema.json",
"extends": ["config:base"],
"regexManagers": [
{
"fileMatch": ["^Dockerfile$"],
"matchStrings": ["ENV GOLANGCI_LINT_VERSION (?<currentValue>.*?)\n"],
"depNameTemplate": "github.com/golangci/golangci-lint",
"datasourceTemplate": "go"
}
]
}
このように fileMatch
、matchStrings
, depNameTemplate
あたりをパラメータとして(go install
に限らず)Renovate管理するpackage情報を設定することができるので、今回挙げた例以外のpackageにも調整次第で対応することができます。
サンプルリポジトリ
サンプルというよりも動作確認のために作成したリポジトリもあるのでご参考ください。(実際Renovateがプルリクエストを出してくれてる様子が見て取れます)
余談
go install
によるバージョン指定可能になる以前はbuild tagを利用してツール系packageを管理する方法がGo公式のwikiで紹介されているので、これを利用してgo.mod
を作成し、それをRenovate管理させるという方法もあります。
tools/tools.go
(tools.go
が例としてよく挙げられますが、実際は任意のファイル名・パッケージ名です)を用意して、以下のように build tag + blank import を利用して「通常のビルド対象からは外れる(不要なコードをビルドしない)がgo.mod
を作ることができる」という状況にすることができます。
// go:build tools
package tools
import _ golang.org/x/tools/cmd/stringer
$ cd tools/
$ go mod init github.com/shirakiya/go-tool-modules/tools
$ go mod tidy
module github.com/shirakiya/go-tool-modules/tools
go 1.19
require golang.org/x/tools v0.6.0
require (
golang.org/x/mod v0.8.0 // indirect
golang.org/x/sys v0.5.0 // indirect
)
しかし、当然このようにgo.mod
を作るだけだと実行可能バイナリがビルドされるわけではないので、go.mod
に記載された package + バージョン でgo install
する必要があります。
- stringerの場合のようにビルドインストールしたいものはサブパッケージ(
golang.org/x/tools/cmd/stringer
)で、go.mod
に記載されるpackage管理対象のパッケージ(golang.org/x/tools
)と異なるケースがある -
go install
の対象となるパッケージをtools/tools.go
やgo.mod
から抽出する必要がある
等の問題があり、私はあまりこちらの方法は取りたくない選択肢だと考えています。
Discussion