feat: automatic Go version detection (#2669)
Some checks failed
Release a tag / release (push) Has been cancelled
Release a tag / docker-release (map[Dockerfile:build/Dockerfile.alpine]) (push) Has been cancelled
Release a tag / docker-release (map[Dockerfile:build/Dockerfile]) (push) Has been cancelled
Some checks failed
Release a tag / release (push) Has been cancelled
Release a tag / docker-release (map[Dockerfile:build/Dockerfile.alpine]) (push) Has been cancelled
Release a tag / docker-release (map[Dockerfile:build/Dockerfile]) (push) Has been cancelled
* feat: disable unsupported go1.18 govet analyzers * fix: inactivate interfacer with go1.18
This commit is contained in:
parent
da0a6b3b8a
commit
7bbbe77e5e
@ -66,8 +66,8 @@ run:
|
|||||||
|
|
||||||
# Define the Go version limit.
|
# Define the Go version limit.
|
||||||
# Mainly related to generics support in go1.18.
|
# Mainly related to generics support in go1.18.
|
||||||
# Default: 1.17
|
# Default: use Go version from the go.mod file, fallback on the env var `GOVERSION`, fallback on 1.17
|
||||||
go: 1.18
|
go: '1.18'
|
||||||
|
|
||||||
|
|
||||||
# output configuration options
|
# output configuration options
|
||||||
|
@ -130,6 +130,7 @@ issues:
|
|||||||
|
|
||||||
run:
|
run:
|
||||||
timeout: 5m
|
timeout: 5m
|
||||||
|
go: '1.17' # TODO(ldez): we force to use an old version of Go for the CI and the tests.
|
||||||
skip-dirs:
|
skip-dirs:
|
||||||
- test/testdata_etc
|
- test/testdata_etc
|
||||||
- internal/cache
|
- internal/cache
|
||||||
|
@ -110,6 +110,10 @@ func NewExecutor(version, commit, date string) *Executor {
|
|||||||
e.log.Fatalf("Can't read config: %s", err)
|
e.log.Fatalf("Can't read config: %s", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if commandLineCfg.Run.Go == "" && e.cfg.Run.Go == "" {
|
||||||
|
e.cfg.Run.Go = config.DetectGoVersion()
|
||||||
|
}
|
||||||
|
|
||||||
// recreate after getting config
|
// recreate after getting config
|
||||||
e.DBManager = lintersdb.NewManager(e.cfg, e.log).WithCustomLinters()
|
e.DBManager = lintersdb.NewManager(e.cfg, e.log).WithCustomLinters()
|
||||||
|
|
||||||
|
@ -95,7 +95,7 @@ func initFlagSet(fs *pflag.FlagSet, cfg *config.Config, m *lintersdb.Manager, is
|
|||||||
"Modules download mode. If not empty, passed as -mod=<mode> to go tools")
|
"Modules download mode. If not empty, passed as -mod=<mode> to go tools")
|
||||||
fs.IntVar(&rc.ExitCodeIfIssuesFound, "issues-exit-code",
|
fs.IntVar(&rc.ExitCodeIfIssuesFound, "issues-exit-code",
|
||||||
exitcodes.IssuesFound, wh("Exit code when issues were found"))
|
exitcodes.IssuesFound, wh("Exit code when issues were found"))
|
||||||
fs.StringVar(&rc.Go, "go", "1.17", wh("Targeted Go version"))
|
fs.StringVar(&rc.Go, "go", "", wh("Targeted Go version"))
|
||||||
fs.StringSliceVar(&rc.BuildTags, "build-tags", nil, wh("Build tags"))
|
fs.StringSliceVar(&rc.BuildTags, "build-tags", nil, wh("Build tags"))
|
||||||
|
|
||||||
fs.DurationVar(&rc.Timeout, "deadline", defaultTimeout, wh("Deadline for total work"))
|
fs.DurationVar(&rc.Timeout, "deadline", defaultTimeout, wh("Deadline for total work"))
|
||||||
|
@ -1,5 +1,13 @@
|
|||||||
package config
|
package config
|
||||||
|
|
||||||
|
import (
|
||||||
|
"os"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
hcversion "github.com/hashicorp/go-version"
|
||||||
|
"github.com/ldez/gomoddirectives"
|
||||||
|
)
|
||||||
|
|
||||||
// Config encapsulates the config data specified in the golangci yaml config file.
|
// Config encapsulates the config data specified in the golangci yaml config file.
|
||||||
type Config struct {
|
type Config struct {
|
||||||
cfgDir string // The directory containing the golangci config file.
|
cfgDir string // The directory containing the golangci config file.
|
||||||
@ -31,3 +39,32 @@ func NewDefault() *Config {
|
|||||||
type Version struct {
|
type Version struct {
|
||||||
Format string `mapstructure:"format"`
|
Format string `mapstructure:"format"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func IsGreaterThanOrEqualGo118(v string) bool {
|
||||||
|
v1, err := hcversion.NewVersion(strings.TrimPrefix(v, "go"))
|
||||||
|
if err != nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
limit, err := hcversion.NewVersion("1.18")
|
||||||
|
if err != nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
return v1.GreaterThanOrEqual(limit)
|
||||||
|
}
|
||||||
|
|
||||||
|
func DetectGoVersion() string {
|
||||||
|
file, _ := gomoddirectives.GetModuleFile()
|
||||||
|
|
||||||
|
if file != nil && file.Go != nil && file.Go.Version != "" {
|
||||||
|
return file.Go.Version
|
||||||
|
}
|
||||||
|
|
||||||
|
v := os.Getenv("GOVERSION")
|
||||||
|
if v != "" {
|
||||||
|
return v
|
||||||
|
}
|
||||||
|
|
||||||
|
return "1.17"
|
||||||
|
}
|
||||||
|
@ -374,7 +374,8 @@ type GoSecSettings struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type GovetSettings struct {
|
type GovetSettings struct {
|
||||||
CheckShadowing bool `mapstructure:"check-shadowing"`
|
Go string `mapstructure:"-"`
|
||||||
|
CheckShadowing bool `mapstructure:"check-shadowing"`
|
||||||
Settings map[string]map[string]interface{}
|
Settings map[string]map[string]interface{}
|
||||||
|
|
||||||
Enable []string
|
Enable []string
|
||||||
@ -383,7 +384,7 @@ type GovetSettings struct {
|
|||||||
DisableAll bool `mapstructure:"disable-all"`
|
DisableAll bool `mapstructure:"disable-all"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cfg GovetSettings) Validate() error {
|
func (cfg *GovetSettings) Validate() error {
|
||||||
if cfg.EnableAll && cfg.DisableAll {
|
if cfg.EnableAll && cfg.DisableAll {
|
||||||
return errors.New("enable-all and disable-all can't be combined")
|
return errors.New("enable-all and disable-all can't be combined")
|
||||||
}
|
}
|
||||||
|
@ -119,35 +119,18 @@ var (
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
func isAnalyzerEnabled(name string, cfg *config.GovetSettings, defaultAnalyzers []*analysis.Analyzer) bool {
|
func NewGovet(cfg *config.GovetSettings) *goanalysis.Linter {
|
||||||
if cfg.EnableAll {
|
var settings map[string]map[string]interface{}
|
||||||
for _, n := range cfg.Disable {
|
if cfg != nil {
|
||||||
if n == name {
|
settings = cfg.Settings
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true
|
|
||||||
}
|
}
|
||||||
// Raw for loops should be OK on small slice lengths.
|
return goanalysis.NewLinter(
|
||||||
for _, n := range cfg.Enable {
|
"govet",
|
||||||
if n == name {
|
"Vet examines Go source code and reports suspicious constructs, "+
|
||||||
return true
|
"such as Printf calls whose arguments do not align with the format string",
|
||||||
}
|
analyzersFromConfig(cfg),
|
||||||
}
|
settings,
|
||||||
for _, n := range cfg.Disable {
|
).WithLoadMode(goanalysis.LoadModeTypesInfo)
|
||||||
if n == name {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if cfg.DisableAll {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
for _, a := range defaultAnalyzers {
|
|
||||||
if a.Name == name {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func analyzersFromConfig(cfg *config.GovetSettings) []*analysis.Analyzer {
|
func analyzersFromConfig(cfg *config.GovetSettings) []*analysis.Analyzer {
|
||||||
@ -170,16 +153,42 @@ func analyzersFromConfig(cfg *config.GovetSettings) []*analysis.Analyzer {
|
|||||||
return enabledAnalyzers
|
return enabledAnalyzers
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewGovet(cfg *config.GovetSettings) *goanalysis.Linter {
|
func isAnalyzerEnabled(name string, cfg *config.GovetSettings, defaultAnalyzers []*analysis.Analyzer) bool {
|
||||||
var settings map[string]map[string]interface{}
|
if (name == nilness.Analyzer.Name || name == unusedwrite.Analyzer.Name) &&
|
||||||
if cfg != nil {
|
config.IsGreaterThanOrEqualGo118(cfg.Go) {
|
||||||
settings = cfg.Settings
|
return false
|
||||||
}
|
}
|
||||||
return goanalysis.NewLinter(
|
|
||||||
"govet",
|
if cfg.EnableAll {
|
||||||
"Vet examines Go source code and reports suspicious constructs, "+
|
for _, n := range cfg.Disable {
|
||||||
"such as Printf calls whose arguments do not align with the format string",
|
if n == name {
|
||||||
analyzersFromConfig(cfg),
|
return false
|
||||||
settings,
|
}
|
||||||
).WithLoadMode(goanalysis.LoadModeTypesInfo)
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// Raw for loops should be OK on small slice lengths.
|
||||||
|
for _, n := range cfg.Enable {
|
||||||
|
if n == name {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, n := range cfg.Disable {
|
||||||
|
if n == name {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if cfg.DisableAll {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, a := range defaultAnalyzers {
|
||||||
|
if a.Name == name {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
}
|
}
|
||||||
|
@ -1,9 +1,6 @@
|
|||||||
package linter
|
package linter
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"strings"
|
|
||||||
|
|
||||||
hcversion "github.com/hashicorp/go-version"
|
|
||||||
"golang.org/x/tools/go/analysis"
|
"golang.org/x/tools/go/analysis"
|
||||||
"golang.org/x/tools/go/packages"
|
"golang.org/x/tools/go/packages"
|
||||||
|
|
||||||
@ -126,7 +123,7 @@ func (lc *Config) Name() string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (lc *Config) WithNoopFallback(cfg *config.Config) *Config {
|
func (lc *Config) WithNoopFallback(cfg *config.Config) *Config {
|
||||||
if isGreaterThanOrEqualGo118(cfg) {
|
if cfg != nil && config.IsGreaterThanOrEqualGo118(cfg.Run.Go) {
|
||||||
lc.Linter = &Noop{
|
lc.Linter = &Noop{
|
||||||
name: lc.Linter.Name(),
|
name: lc.Linter.Name(),
|
||||||
desc: lc.Linter.Desc(),
|
desc: lc.Linter.Desc(),
|
||||||
@ -134,6 +131,9 @@ func (lc *Config) WithNoopFallback(cfg *config.Config) *Config {
|
|||||||
return nil, nil
|
return nil, nil
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
lc.LoadMode = 0
|
||||||
|
return lc.WithLoadFiles()
|
||||||
}
|
}
|
||||||
|
|
||||||
return lc
|
return lc
|
||||||
@ -145,21 +145,3 @@ func NewConfig(linter Linter) *Config {
|
|||||||
}
|
}
|
||||||
return lc.WithLoadFiles()
|
return lc.WithLoadFiles()
|
||||||
}
|
}
|
||||||
|
|
||||||
func isGreaterThanOrEqualGo118(cfg *config.Config) bool {
|
|
||||||
if cfg == nil {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
v1, err := hcversion.NewVersion(strings.TrimPrefix(cfg.Run.Go, "go"))
|
|
||||||
if err != nil {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
limit, err := hcversion.NewVersion("1.18")
|
|
||||||
if err != nil {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
return v1.GreaterThanOrEqual(limit)
|
|
||||||
}
|
|
||||||
|
@ -22,7 +22,6 @@ type Noop struct {
|
|||||||
|
|
||||||
func (n Noop) Run(_ context.Context, lintCtx *Context) ([]result.Issue, error) {
|
func (n Noop) Run(_ context.Context, lintCtx *Context) ([]result.Issue, error) {
|
||||||
lintCtx.Log.Warnf("%s is disabled because of go1.18."+
|
lintCtx.Log.Warnf("%s is disabled because of go1.18."+
|
||||||
" If you are not using go1.18, you can set `go: go1.17` in the `run` section."+
|
|
||||||
" You can track the evolution of the go1.18 support by following the https://github.com/golangci/golangci-lint/issues/2649.", n.name)
|
" You can track the evolution of the go1.18 support by following the https://github.com/golangci/golangci-lint/issues/2649.", n.name)
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
@ -164,6 +164,10 @@ func (m Manager) GetAllSupportedLinterConfigs() []*linter.Config {
|
|||||||
unusedCfg = &m.cfg.LintersSettings.Unused
|
unusedCfg = &m.cfg.LintersSettings.Unused
|
||||||
varnamelenCfg = &m.cfg.LintersSettings.Varnamelen
|
varnamelenCfg = &m.cfg.LintersSettings.Varnamelen
|
||||||
wrapcheckCfg = &m.cfg.LintersSettings.Wrapcheck
|
wrapcheckCfg = &m.cfg.LintersSettings.Wrapcheck
|
||||||
|
|
||||||
|
if govetCfg != nil {
|
||||||
|
govetCfg.Go = m.cfg.Run.Go
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const megacheckName = "megacheck"
|
const megacheckName = "megacheck"
|
||||||
@ -446,7 +450,8 @@ func (m Manager) GetAllSupportedLinterConfigs() []*linter.Config {
|
|||||||
WithLoadForGoAnalysis().
|
WithLoadForGoAnalysis().
|
||||||
WithPresets(linter.PresetStyle).
|
WithPresets(linter.PresetStyle).
|
||||||
WithURL("https://github.com/mvdan/interfacer").
|
WithURL("https://github.com/mvdan/interfacer").
|
||||||
Deprecated("The repository of the linter has been archived by the owner.", "v1.38.0", ""),
|
Deprecated("The repository of the linter has been archived by the owner.", "v1.38.0", "").
|
||||||
|
WithNoopFallback(m.cfg),
|
||||||
|
|
||||||
linter.NewConfig(golinters.NewIreturn(ireturnCfg)).
|
linter.NewConfig(golinters.NewIreturn(ireturnCfg)).
|
||||||
WithSince("v1.43.0").
|
WithSince("v1.43.0").
|
||||||
|
@ -43,6 +43,7 @@ func TestFix(t *testing.T) {
|
|||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
args := []string{
|
args := []string{
|
||||||
|
"--go=1.17", // TODO(ldez): we force to use an old version of Go for the CI and the tests.
|
||||||
"--disable-all", "--print-issued-lines=false", "--print-linter-name=false", "--out-format=line-number",
|
"--disable-all", "--print-issued-lines=false", "--print-linter-name=false", "--out-format=line-number",
|
||||||
"--allow-parallel-runners", "--fix",
|
"--allow-parallel-runners", "--fix",
|
||||||
input,
|
input,
|
||||||
|
@ -179,6 +179,7 @@ func saveConfig(t *testing.T, cfg map[string]interface{}) (cfgPath string, finis
|
|||||||
func testOneSource(t *testing.T, sourcePath string) {
|
func testOneSource(t *testing.T, sourcePath string) {
|
||||||
args := []string{
|
args := []string{
|
||||||
"run",
|
"run",
|
||||||
|
"--go=1.17", // TODO(ldez): we force to use an old version of Go for the CI and the tests.
|
||||||
"--allow-parallel-runners",
|
"--allow-parallel-runners",
|
||||||
"--disable-all",
|
"--disable-all",
|
||||||
"--print-issued-lines=false",
|
"--print-issued-lines=false",
|
||||||
|
@ -98,7 +98,10 @@ func (r *LintRunner) Run(args ...string) *RunResult {
|
|||||||
func (r *LintRunner) RunCommand(command string, args ...string) *RunResult {
|
func (r *LintRunner) RunCommand(command string, args ...string) *RunResult {
|
||||||
r.Install()
|
r.Install()
|
||||||
|
|
||||||
runArgs := append([]string{command}, "--internal-cmd-test")
|
runArgs := append([]string{command},
|
||||||
|
"--go=1.17", // TODO(ldez): we force to use an old version of Go for the CI and the tests.
|
||||||
|
"--internal-cmd-test",
|
||||||
|
)
|
||||||
runArgs = append(runArgs, args...)
|
runArgs = append(runArgs, args...)
|
||||||
|
|
||||||
defer func(startedAt time.Time) {
|
defer func(startedAt time.Time) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user