👮

go installで指定しているバージョンをRenovate管理する

2023/03/08に公開

はじめに

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"
    }
  ]
}

このように fileMatchmatchStrings, depNameTemplate あたりをパラメータとして(go installに限らず)Renovate管理するpackage情報を設定することができるので、今回挙げた例以外のpackageにも調整次第で対応することができます。

サンプルリポジトリ

サンプルというよりも動作確認のために作成したリポジトリもあるのでご参考ください。(実際Renovateがプルリクエストを出してくれてる様子が見て取れます)

https://github.com/shirakiya/go-renovate-test

余談

go installによるバージョン指定可能になる以前はbuild tagを利用してツール系packageを管理する方法がGo公式のwikiで紹介されているので、これを利用してgo.modを作成し、それをRenovate管理させるという方法もあります。

tools/tools.gotools.goが例としてよく挙げられますが、実際は任意のファイル名・パッケージ名です)を用意して、以下のように build tag + blank import を利用して「通常のビルド対象からは外れる(不要なコードをビルドしない)がgo.modを作ることができる」という状況にすることができます。

tools/tools.go
// 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
go.mod
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する必要があります。

  1. stringerの場合のようにビルドインストールしたいものはサブパッケージ(golang.org/x/tools/cmd/stringer)で、go.modに記載されるpackage管理対象のパッケージ(golang.org/x/tools)と異なるケースがある
  2. go installの対象となるパッケージをtools/tools.gogo.modから抽出する必要がある

等の問題があり、私はあまりこちらの方法は取りたくない選択肢だと考えています。

Discussion