From f0c190436343e51e6b4dc98a368cf7bae0e5f33a Mon Sep 17 00:00:00 2001 From: Ludovic Fernandez Date: Thu, 22 Aug 2024 23:28:56 +0200 Subject: [PATCH] feat: check that Go version use to build is greater or equals to the Go version of the project (#4938) --- pkg/config/config.go | 37 +++++++++++++++++++++++++++ pkg/config/config_test.go | 54 +++++++++++++++++++++++++++++++++++++++ pkg/config/loader.go | 5 ++++ 3 files changed, 96 insertions(+) diff --git a/pkg/config/config.go b/pkg/config/config.go index 1dd064013a22..14c684d41081 100644 --- a/pkg/config/config.go +++ b/pkg/config/config.go @@ -1,8 +1,11 @@ package config import ( + "fmt" + "go/version" "os" "regexp" + "runtime" "strings" hcversion "github.com/hashicorp/go-version" @@ -108,3 +111,37 @@ func trimGoVersion(v string) string { return v } + +func getRuntimeGoVersion() string { + goVersion := runtime.Version() + + parts := strings.Fields(goVersion) + + if len(parts) == 0 { + return goVersion + } + + // When using GOEXPERIMENT, the version returned might look something like "go1.23.0 X:boringcrypto". + return parts[0] +} + +func checkGoVersion(goVersion string) error { + langVersion := version.Lang(getRuntimeGoVersion()) + + runtimeVersion, err := hcversion.NewVersion(strings.TrimPrefix(langVersion, "go")) + if err != nil { + return err + } + + targetedVersion, err := hcversion.NewVersion(trimGoVersion(goVersion)) + if err != nil { + return err + } + + if runtimeVersion.LessThan(targetedVersion) { + return fmt.Errorf("the Go language version (%s) used to build golangci-lint is lower than the targeted Go version (%s)", + langVersion, goVersion) + } + + return nil +} diff --git a/pkg/config/config_test.go b/pkg/config/config_test.go index e56e6f775d91..6819a2a4bf50 100644 --- a/pkg/config/config_test.go +++ b/pkg/config/config_test.go @@ -4,6 +4,7 @@ import ( "testing" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) func TestIsGoGreaterThanOrEqual(t *testing.T) { @@ -131,3 +132,56 @@ func Test_trimGoVersion(t *testing.T) { }) } } + +func Test_checkGoVersion(t *testing.T) { + testCases := []struct { + desc string + version string + require require.ErrorAssertionFunc + }{ + { + desc: "version greater than runtime version (patch)", + version: "1.30.1", + require: require.Error, + }, + { + desc: "version greater than runtime version (family)", + version: "1.30", + require: require.Error, + }, + { + desc: "version greater than runtime version (RC)", + version: "1.30.0-rc1", + require: require.Error, + }, + { + desc: "version equals to runtime version", + version: getRuntimeGoVersion(), + require: require.NoError, + }, + { + desc: "version lower than runtime version (patch)", + version: "1.19.1", + require: require.NoError, + }, + { + desc: "version lower than runtime version (family)", + version: "1.19", + require: require.NoError, + }, + { + desc: "version lower than runtime version (RC)", + version: "1.19.0-rc1", + require: require.NoError, + }, + } + + for _, test := range testCases { + t.Run(test.desc, func(t *testing.T) { + t.Parallel() + + err := checkGoVersion(test.version) + test.require(t, err) + }) + } +} diff --git a/pkg/config/loader.go b/pkg/config/loader.go index 91984930d84d..05f324330ce5 100644 --- a/pkg/config/loader.go +++ b/pkg/config/loader.go @@ -74,6 +74,11 @@ func (l *Loader) Load(opts LoadOptions) error { l.handleGoVersion() + err = checkGoVersion(l.cfg.Run.Go) + if err != nil { + return err + } + err = l.handleEnableOnlyOption() if err != nil { return err