dev: add Go version to version information (#3625)

This commit is contained in:
Ludovic Fernandez 2023-03-02 00:34:22 +01:00 committed by GitHub
parent 3443b7a93e
commit e5b30649e6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 70 additions and 40 deletions

View File

@ -3,12 +3,15 @@ package main
import ( import (
"fmt" "fmt"
"os" "os"
"runtime/debug"
"github.com/golangci/golangci-lint/pkg/commands" "github.com/golangci/golangci-lint/pkg/commands"
"github.com/golangci/golangci-lint/pkg/exitcodes" "github.com/golangci/golangci-lint/pkg/exitcodes"
) )
var ( var (
goVersion = "unknown"
// Populated by goreleaser during build // Populated by goreleaser during build
version = "master" version = "master"
commit = "?" commit = "?"
@ -16,7 +19,24 @@ var (
) )
func main() { func main() {
e := commands.NewExecutor(version, commit, date) if buildInfo, available := debug.ReadBuildInfo(); available {
goVersion = buildInfo.GoVersion
if date == "" {
version = buildInfo.Main.Version
commit = fmt.Sprintf("(unknown, mod sum: %q)", buildInfo.Main.Sum)
date = "(unknown)"
}
}
info := commands.BuildInfo{
GoVersion: goVersion,
Version: version,
Commit: commit,
Date: date,
}
e := commands.NewExecutor(info)
if err := e.Execute(); err != nil { if err := e.Execute(); err != nil {
fmt.Fprintf(os.Stderr, "failed executing command with error %v\n", err) fmt.Fprintf(os.Stderr, "failed executing command with error %v\n", err)

View File

@ -1,17 +0,0 @@
package main
import (
"fmt"
"runtime/debug"
)
//nolint:gochecknoinits
func init() {
if info, available := debug.ReadBuildInfo(); available {
if date == "" {
version = info.Main.Version
commit = fmt.Sprintf("(unknown, mod sum: %q)", info.Main.Sum)
date = "(unknown)"
}
}
}

View File

@ -30,13 +30,20 @@ import (
"github.com/golangci/golangci-lint/pkg/timeutils" "github.com/golangci/golangci-lint/pkg/timeutils"
) )
type BuildInfo struct {
GoVersion string `json:"goVersion"`
Version string `json:"version"`
Commit string `json:"commit"`
Date string `json:"date"`
}
type Executor struct { type Executor struct {
rootCmd *cobra.Command rootCmd *cobra.Command
runCmd *cobra.Command runCmd *cobra.Command
lintersCmd *cobra.Command lintersCmd *cobra.Command
exitCode int exitCode int
version, commit, date string buildInfo BuildInfo
cfg *config.Config // cfg is the unmarshaled data from the golangci config file. cfg *config.Config // cfg is the unmarshaled data from the golangci config file.
log logutils.Log log logutils.Log
@ -56,13 +63,11 @@ type Executor struct {
} }
// NewExecutor creates and initializes a new command executor. // NewExecutor creates and initializes a new command executor.
func NewExecutor(version, commit, date string) *Executor { func NewExecutor(buildInfo BuildInfo) *Executor {
startedAt := time.Now() startedAt := time.Now()
e := &Executor{ e := &Executor{
cfg: config.NewDefault(), cfg: config.NewDefault(),
version: version, buildInfo: buildInfo,
commit: commit,
date: date,
DBManager: lintersdb.NewManager(nil, nil), DBManager: lintersdb.NewManager(nil, nil),
debugf: logutils.Debug(logutils.DebugKeyExec), debugf: logutils.Debug(logutils.DebugKeyExec),
} }
@ -135,7 +140,7 @@ func NewExecutor(version, commit, date string) *Executor {
e.loadGuard = load.NewGuard() e.loadGuard = load.NewGuard()
e.contextLoader = lint.NewContextLoader(e.cfg, e.log.Child(logutils.DebugKeyLoader), e.goenv, e.contextLoader = lint.NewContextLoader(e.cfg, e.log.Child(logutils.DebugKeyLoader), e.goenv,
e.lineCache, e.fileCache, e.pkgCache, e.loadGuard) e.lineCache, e.fileCache, e.pkgCache, e.loadGuard)
if err = e.initHashSalt(version); err != nil { if err = e.initHashSalt(buildInfo.Version); err != nil {
e.log.Fatalf("Failed to init hash salt: %s", err) e.log.Fatalf("Failed to init hash salt: %s", err)
} }
e.debugf("Initialized executor in %s", time.Since(startedAt)) e.debugf("Initialized executor in %s", time.Since(startedAt))

View File

@ -24,7 +24,7 @@ const (
func (e *Executor) persistentPreRun(_ *cobra.Command, _ []string) error { func (e *Executor) persistentPreRun(_ *cobra.Command, _ []string) error {
if e.cfg.Run.PrintVersion { if e.cfg.Run.PrintVersion {
_, _ = fmt.Fprintf(logutils.StdOut, "golangci-lint has version %s built from %s on %s\n", e.version, e.commit, e.date) _ = printVersion(logutils.StdOut, e.buildInfo)
os.Exit(exitcodes.Success) // a return nil is not enough to stop the process because we are inside the `preRun`. os.Exit(exitcodes.Success) // a return nil is not enough to stop the process because we are inside the `preRun`.
} }
@ -145,7 +145,7 @@ func (e *Executor) initRoot() {
} }
func (e *Executor) needVersionOption() bool { func (e *Executor) needVersionOption() bool {
return e.date != "" return e.buildInfo.Date != ""
} }
func initRootFlagSet(fs *pflag.FlagSet, cfg *config.Config, needVersionOption bool) { func initRootFlagSet(fs *pflag.FlagSet, cfg *config.Config, needVersionOption bool) {

View File

@ -3,7 +3,9 @@ package commands
import ( import (
"encoding/json" "encoding/json"
"fmt" "fmt"
"io"
"os" "os"
"runtime/debug"
"strings" "strings"
"github.com/spf13/cobra" "github.com/spf13/cobra"
@ -12,10 +14,9 @@ import (
"github.com/golangci/golangci-lint/pkg/config" "github.com/golangci/golangci-lint/pkg/config"
) )
type jsonVersion struct { type versionInfo struct {
Version string `json:"version"` Info BuildInfo
Commit string `json:"commit"` BuildInfo *debug.BuildInfo
Date string `json:"date"`
} }
func (e *Executor) initVersionConfiguration(cmd *cobra.Command) { func (e *Executor) initVersionConfiguration(cmd *cobra.Command) {
@ -28,6 +29,7 @@ func initVersionFlagSet(fs *pflag.FlagSet, cfg *config.Config) {
// Version config // Version config
vc := &cfg.Version vc := &cfg.Version
fs.StringVar(&vc.Format, "format", "", wh("The version's format can be: 'short', 'json'")) fs.StringVar(&vc.Format, "format", "", wh("The version's format can be: 'short', 'json'"))
fs.BoolVar(&vc.Debug, "debug", false, wh("Add build information"))
} }
func (e *Executor) initVersion() { func (e *Executor) initVersion() {
@ -37,22 +39,35 @@ func (e *Executor) initVersion() {
Args: cobra.NoArgs, Args: cobra.NoArgs,
ValidArgsFunction: cobra.NoFileCompletions, ValidArgsFunction: cobra.NoFileCompletions,
RunE: func(cmd *cobra.Command, _ []string) error { RunE: func(cmd *cobra.Command, _ []string) error {
if e.cfg.Version.Debug {
info, ok := debug.ReadBuildInfo()
if !ok {
return nil
}
switch strings.ToLower(e.cfg.Version.Format) {
case "json":
return json.NewEncoder(os.Stdout).Encode(versionInfo{
Info: e.buildInfo,
BuildInfo: info,
})
default:
fmt.Println(info.String())
return printVersion(os.Stdout, e.buildInfo)
}
}
switch strings.ToLower(e.cfg.Version.Format) { switch strings.ToLower(e.cfg.Version.Format) {
case "short": case "short":
fmt.Println(e.version) fmt.Println(e.buildInfo.Version)
return nil return nil
case "json": case "json":
ver := jsonVersion{ return json.NewEncoder(os.Stdout).Encode(e.buildInfo)
Version: e.version,
Commit: e.commit,
Date: e.date,
}
return json.NewEncoder(os.Stdout).Encode(&ver)
default: default:
fmt.Printf("golangci-lint has version %s built from %s on %s\n", e.version, e.commit, e.date) return printVersion(os.Stdout, e.buildInfo)
return nil
} }
}, },
} }
@ -60,3 +75,9 @@ func (e *Executor) initVersion() {
e.rootCmd.AddCommand(versionCmd) e.rootCmd.AddCommand(versionCmd)
e.initVersionConfiguration(versionCmd) e.initVersionConfiguration(versionCmd)
} }
func printVersion(w io.Writer, buildInfo BuildInfo) error {
_, err := fmt.Fprintf(w, "golangci-lint has version %s built with %s from %s on %s\n",
buildInfo.Version, buildInfo.GoVersion, buildInfo.Commit, buildInfo.Date)
return err
}

View File

@ -38,6 +38,7 @@ func NewDefault() *Config {
type Version struct { type Version struct {
Format string `mapstructure:"format"` Format string `mapstructure:"format"`
Debug bool `mapstructure:"debug"`
} }
func IsGreaterThanOrEqualGo118(v string) bool { func IsGreaterThanOrEqualGo118(v string) bool {