internal/version: use gitCommit injection in version handling code (#25851)

This changes the CI build to store the git commit and date into package
internal/version instead of package main. Doing this essentially merges our
two ways of tracking the go-ethereum version into a single place, achieving
two objectives:

- Bad block reports, which use version.Info(), will now have the git commit
  information even when geth is built in an environment such as
  launchpad.net where git access is unavailable.

- For geth builds created by `go build ./cmd/geth` (i.e. not using `go run
  build/ci.go install`), git information stored by the go tool is now used
  in the p2p node name as well as in `geth version` and `geth
  version-check`.
This commit is contained in:
Felix Lange 2022-09-23 14:08:25 +02:00 committed by GitHub
parent e6d4aedb8c
commit 65f3c1b46f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
16 changed files with 100 additions and 105 deletions

View File

@ -254,8 +254,8 @@ func doInstall(cmdline []string) {
func buildFlags(env build.Environment, staticLinking bool, buildTags []string) (flags []string) { func buildFlags(env build.Environment, staticLinking bool, buildTags []string) (flags []string) {
var ld []string var ld []string
if env.Commit != "" { if env.Commit != "" {
ld = append(ld, "-X", "main.gitCommit="+env.Commit) ld = append(ld, "-X", "github.com/ethereum/go-ethereum/internal/version.gitCommit="+env.Commit)
ld = append(ld, "-X", "main.gitDate="+env.Date) ld = append(ld, "-X", "github.com/ethereum/go-ethereum/internal/version.gitDate="+env.Date)
} }
// Strip DWARF on darwin. This used to be required for certain things, // Strip DWARF on darwin. This used to be required for certain things,
// and there is no downside to this, so we just keep doing it. // and there is no downside to this, so we just keep doing it.

View File

@ -33,14 +33,6 @@ import (
"github.com/urfave/cli/v2" "github.com/urfave/cli/v2"
) )
var (
// Git SHA1 commit hash of the release (set via linker flags)
gitCommit = ""
gitDate = ""
app *cli.App
)
var ( var (
// Flags needed by abigen // Flags needed by abigen
abiFlag = &cli.StringFlag{ abiFlag = &cli.StringFlag{
@ -82,8 +74,9 @@ var (
} }
) )
var app = flags.NewApp("Ethereum ABI wrapper code generator")
func init() { func init() {
app = flags.NewApp(gitCommit, gitDate, "ethereum checkpoint helper tool")
app.Name = "abigen" app.Name = "abigen"
app.Flags = []cli.Flag{ app.Flags = []cli.Flag{
abiFlag, abiFlag,

View File

@ -28,16 +28,9 @@ import (
"github.com/urfave/cli/v2" "github.com/urfave/cli/v2"
) )
var ( var app = flags.NewApp("ethereum checkpoint helper tool")
// Git SHA1 commit hash of the release (set via linker flags)
gitCommit = ""
gitDate = ""
app *cli.App
)
func init() { func init() {
app = flags.NewApp(gitCommit, gitDate, "ethereum checkpoint helper tool")
app.Commands = []*cli.Command{ app.Commands = []*cli.Command{
commandStatus, commandStatus,
commandDeploy, commandDeploy,

View File

@ -215,13 +215,7 @@ The gendoc generates example structures of the json-rpc communication types.
`} `}
) )
var ( var app = flags.NewApp("Manage Ethereum account operations")
// Git SHA1 commit hash of the release (set via linker flags)
gitCommit = ""
gitDate = ""
app = flags.NewApp(gitCommit, gitDate, "Manage Ethereum account operations")
)
func init() { func init() {
app.Name = "Clef" app.Name = "Clef"

View File

@ -19,30 +19,17 @@ package main
import ( import (
"fmt" "fmt"
"os" "os"
"path/filepath"
"github.com/ethereum/go-ethereum/internal/debug" "github.com/ethereum/go-ethereum/internal/debug"
"github.com/ethereum/go-ethereum/internal/flags" "github.com/ethereum/go-ethereum/internal/flags"
"github.com/ethereum/go-ethereum/p2p/enode" "github.com/ethereum/go-ethereum/p2p/enode"
"github.com/ethereum/go-ethereum/params"
"github.com/urfave/cli/v2" "github.com/urfave/cli/v2"
) )
var ( var app = flags.NewApp("go-ethereum devp2p tool")
// Git information set by linker when building with ci.go.
gitCommit string
gitDate string
app = &cli.App{
Name: filepath.Base(os.Args[0]),
Usage: "go-ethereum devp2p tool",
Version: params.VersionWithCommit(gitCommit, gitDate),
Writer: os.Stdout,
HideVersion: true,
}
)
func init() { func init() {
// Set up the CLI app. app.HideVersion = true
app.Flags = append(app.Flags, debug.Flags...) app.Flags = append(app.Flags, debug.Flags...)
app.Before = func(ctx *cli.Context) error { app.Before = func(ctx *cli.Context) error {
flags.MigrateGlobalFlags(ctx) flags.MigrateGlobalFlags(ctx)
@ -56,6 +43,7 @@ func init() {
fmt.Fprintf(os.Stderr, "No such command: %s\n", cmd) fmt.Fprintf(os.Stderr, "No such command: %s\n", cmd)
os.Exit(1) os.Exit(1)
} }
// Add subcommands. // Add subcommands.
app.Commands = []*cli.Command{ app.Commands = []*cli.Command{
enrdumpCommand, enrdumpCommand,

View File

@ -28,14 +28,10 @@ const (
defaultKeyfileName = "keyfile.json" defaultKeyfileName = "keyfile.json"
) )
// Git SHA1 commit hash of the release (set via linker flags)
var gitCommit = ""
var gitDate = ""
var app *cli.App var app *cli.App
func init() { func init() {
app = flags.NewApp(gitCommit, gitDate, "an Ethereum key manager") app = flags.NewApp("Ethereum key manager")
app.Commands = []*cli.Command{ app.Commands = []*cli.Command{
commandGenerate, commandGenerate,
commandInspect, commandInspect,

View File

@ -27,13 +27,6 @@ import (
"github.com/urfave/cli/v2" "github.com/urfave/cli/v2"
) )
var (
gitCommit = "" // Git SHA1 commit hash of the release (set via linker flags)
gitDate = ""
app = flags.NewApp(gitCommit, gitDate, "the evm command line interface")
)
var ( var (
DebugFlag = &cli.BoolFlag{ DebugFlag = &cli.BoolFlag{
Name: "debug", Name: "debug",
@ -192,6 +185,8 @@ var blockBuilderCommand = &cli.Command{
}, },
} }
var app = flags.NewApp("the evm command line interface")
func init() { func init() {
app.Flags = []cli.Flag{ app.Flags = []cli.Flag{
BenchFlag, BenchFlag,

View File

@ -49,6 +49,7 @@ import (
"github.com/ethereum/go-ethereum/eth/ethconfig" "github.com/ethereum/go-ethereum/eth/ethconfig"
"github.com/ethereum/go-ethereum/ethclient" "github.com/ethereum/go-ethereum/ethclient"
"github.com/ethereum/go-ethereum/ethstats" "github.com/ethereum/go-ethereum/ethstats"
"github.com/ethereum/go-ethereum/internal/version"
"github.com/ethereum/go-ethereum/les" "github.com/ethereum/go-ethereum/les"
"github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/node" "github.com/ethereum/go-ethereum/node"
@ -93,11 +94,6 @@ var (
ether = new(big.Int).Exp(big.NewInt(10), big.NewInt(18), nil) ether = new(big.Int).Exp(big.NewInt(10), big.NewInt(18), nil)
) )
var (
gitCommit = "" // Git SHA1 commit hash of the release (set via linker flags)
gitDate = "" // Git commit date YYYYMMDD of the release (set via linker flags)
)
//go:embed faucet.html //go:embed faucet.html
var websiteTmpl string var websiteTmpl string
@ -226,9 +222,10 @@ type wsConn struct {
func newFaucet(genesis *core.Genesis, port int, enodes []*enode.Node, network uint64, stats string, ks *keystore.KeyStore, index []byte) (*faucet, error) { func newFaucet(genesis *core.Genesis, port int, enodes []*enode.Node, network uint64, stats string, ks *keystore.KeyStore, index []byte) (*faucet, error) {
// Assemble the raw devp2p protocol stack // Assemble the raw devp2p protocol stack
git, _ := version.VCS()
stack, err := node.New(&node.Config{ stack, err := node.New(&node.Config{
Name: "geth", Name: "geth",
Version: params.VersionWithCommit(gitCommit, gitDate), Version: params.VersionWithCommit(git.Commit, git.Date),
DataDir: filepath.Join(os.Getenv("HOME"), ".faucet"), DataDir: filepath.Join(os.Getenv("HOME"), ".faucet"),
P2P: p2p.Config{ P2P: p2p.Config{
NAT: nat.Any(), NAT: nat.Any(),

View File

@ -35,6 +35,7 @@ import (
"github.com/ethereum/go-ethereum/eth/ethconfig" "github.com/ethereum/go-ethereum/eth/ethconfig"
"github.com/ethereum/go-ethereum/internal/ethapi" "github.com/ethereum/go-ethereum/internal/ethapi"
"github.com/ethereum/go-ethereum/internal/flags" "github.com/ethereum/go-ethereum/internal/flags"
"github.com/ethereum/go-ethereum/internal/version"
"github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/metrics" "github.com/ethereum/go-ethereum/metrics"
"github.com/ethereum/go-ethereum/node" "github.com/ethereum/go-ethereum/node"
@ -108,9 +109,10 @@ func loadConfig(file string, cfg *gethConfig) error {
} }
func defaultNodeConfig() node.Config { func defaultNodeConfig() node.Config {
git, _ := version.VCS()
cfg := node.DefaultConfig cfg := node.DefaultConfig
cfg.Name = clientIdentifier cfg.Name = clientIdentifier
cfg.Version = params.VersionWithCommit(gitCommit, gitDate) cfg.Version = params.VersionWithCommit(git.Commit, git.Date)
cfg.HTTPModules = append(cfg.HTTPModules, "eth") cfg.HTTPModules = append(cfg.HTTPModules, "eth")
cfg.WSModules = append(cfg.WSModules, "eth") cfg.WSModules = append(cfg.WSModules, "eth")
cfg.IPCPath = "geth.ipc" cfg.IPCPath = "geth.ipc"

View File

@ -52,11 +52,6 @@ const (
) )
var ( var (
// Git SHA1 commit hash of the release (set via linker flags)
gitCommit = ""
gitDate = ""
// The app that holds all commands and flags.
app = flags.NewApp(gitCommit, gitDate, "the go-ethereum command line interface")
// flags that configure the node // flags that configure the node
nodeFlags = flags.Merge([]cli.Flag{ nodeFlags = flags.Merge([]cli.Flag{
utils.IdentityFlag, utils.IdentityFlag,
@ -205,6 +200,8 @@ var (
} }
) )
var app = flags.NewApp("the go-ethereum command line interface")
func init() { func init() {
// Initialize the CLI app and start Geth // Initialize the CLI app and start Geth
app.Action = geth app.Action = geth

View File

@ -25,6 +25,7 @@ import (
"github.com/ethereum/go-ethereum/cmd/utils" "github.com/ethereum/go-ethereum/cmd/utils"
"github.com/ethereum/go-ethereum/consensus/ethash" "github.com/ethereum/go-ethereum/consensus/ethash"
"github.com/ethereum/go-ethereum/internal/version"
"github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/params"
"github.com/urfave/cli/v2" "github.com/urfave/cli/v2"
) )
@ -38,9 +39,7 @@ var (
VersionCheckVersionFlag = &cli.StringFlag{ VersionCheckVersionFlag = &cli.StringFlag{
Name: "check.version", Name: "check.version",
Usage: "Version to check", Usage: "Version to check",
Value: fmt.Sprintf("Geth/v%v/%v-%v/%v", Value: version.ClientName(clientIdentifier),
params.VersionWithCommit(gitCommit, gitDate),
runtime.GOOS, runtime.GOARCH, runtime.Version()),
} }
makecacheCommand = &cli.Command{ makecacheCommand = &cli.Command{
Action: makecache, Action: makecache,
@ -67,7 +66,7 @@ Regular users do not need to execute it.
`, `,
} }
versionCommand = &cli.Command{ versionCommand = &cli.Command{
Action: version, Action: printVersion,
Name: "version", Name: "version",
Usage: "Print version numbers", Usage: "Print version numbers",
ArgsUsage: " ", ArgsUsage: " ",
@ -127,14 +126,16 @@ func makedag(ctx *cli.Context) error {
return nil return nil
} }
func version(ctx *cli.Context) error { func printVersion(ctx *cli.Context) error {
git, _ := version.VCS()
fmt.Println(strings.Title(clientIdentifier)) fmt.Println(strings.Title(clientIdentifier))
fmt.Println("Version:", params.VersionWithMeta) fmt.Println("Version:", params.VersionWithMeta)
if gitCommit != "" { if git.Commit != "" {
fmt.Println("Git Commit:", gitCommit) fmt.Println("Git Commit:", git.Commit)
} }
if gitDate != "" { if git.Date != "" {
fmt.Println("Git Commit Date:", gitDate) fmt.Println("Git Commit Date:", git.Date)
} }
fmt.Println("Architecture:", runtime.GOARCH) fmt.Println("Architecture:", runtime.GOARCH)
fmt.Println("Go Version:", runtime.Version()) fmt.Println("Go Version:", runtime.Version())

View File

@ -100,14 +100,8 @@ var (
} }
) )
var (
// Git information set by linker when building with ci.go.
gitCommit string
gitDate string
)
func main() { func main() {
app := flags.NewApp(gitCommit, gitDate, "devp2p simulation command-line client") app := flags.NewApp("devp2p simulation command-line client")
app.Flags = []cli.Flag{ app.Flags = []cli.Flag{
apiFlag, apiFlag,
} }

View File

@ -20,15 +20,17 @@ import (
"fmt" "fmt"
"strings" "strings"
"github.com/ethereum/go-ethereum/internal/version"
"github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/params"
"github.com/urfave/cli/v2" "github.com/urfave/cli/v2"
) )
// NewApp creates an app with sane defaults. // NewApp creates an app with sane defaults.
func NewApp(gitCommit, gitDate, usage string) *cli.App { func NewApp(usage string) *cli.App {
git, _ := version.VCS()
app := cli.NewApp() app := cli.NewApp()
app.EnableBashCompletion = true app.EnableBashCompletion = true
app.Version = params.VersionWithCommit(gitCommit, gitDate) app.Version = params.VersionWithCommit(git.Commit, git.Date)
app.Usage = usage app.Usage = usage
app.Copyright = "Copyright 2013-2022 The go-ethereum Authors" app.Copyright = "Copyright 2013-2022 The go-ethereum Authors"
app.Before = func(ctx *cli.Context) error { app.Before = func(ctx *cli.Context) error {

View File

@ -23,6 +23,6 @@ import "runtime/debug"
// In Go versions before 1.18, VCS information is not available. // In Go versions before 1.18, VCS information is not available.
func vcsInfo(info *debug.BuildInfo) (gitStatus, bool) { func buildInfoVCS(info *debug.BuildInfo) (VCSInfo, bool) {
return gitStatus{}, false return VCSInfo{}, false
} }

View File

@ -19,29 +19,36 @@
package version package version
import "runtime/debug" import (
"runtime/debug"
"time"
)
// In go 1.18 and beyond, the go tool embeds VCS information into the build. // In go 1.18 and beyond, the go tool embeds VCS information into the build.
// vcsInfo returns VCS information of the build. const (
func vcsInfo(info *debug.BuildInfo) (s gitStatus, ok bool) { govcsTimeLayout = "2006-01-02T15:04:05Z"
ourTimeLayout = "20060102"
)
// buildInfoVCS returns VCS information of the build.
func buildInfoVCS(info *debug.BuildInfo) (s VCSInfo, ok bool) {
for _, v := range info.Settings { for _, v := range info.Settings {
switch v.Key { switch v.Key {
case "vcs.revision": case "vcs.revision":
if len(v.Value) < 8 { s.Commit = v.Value
s.revision = v.Value
} else {
s.revision = v.Value[:8]
}
case "vcs.modified": case "vcs.modified":
if v.Value == "true" { if v.Value == "true" {
s.modified = true s.Dirty = true
} }
case "vcs.time": case "vcs.time":
s.time = v.Value t, err := time.Parse(govcsTimeLayout, v.Value)
if err == nil {
s.Date = t.Format(ourTimeLayout)
}
} }
} }
if s.revision != "" && s.time != "" { if s.Commit != "" && s.Date != "" {
ok = true ok = true
} }
return return

View File

@ -19,6 +19,7 @@ package version
import ( import (
"fmt" "fmt"
"runtime"
"runtime/debug" "runtime/debug"
"strings" "strings"
@ -27,6 +28,43 @@ import (
const ourPath = "github.com/ethereum/go-ethereum" // Path to our module const ourPath = "github.com/ethereum/go-ethereum" // Path to our module
// These variables are set at build-time by the linker when the build is
// done by build/ci.go.
var gitCommit, gitDate string
// VCSInfo represents the git repository state.
type VCSInfo struct {
Commit string // head commit hash
Date string // commit time in YYYYMMDD format
Dirty bool
}
// VCS returns version control information of the current executable.
func VCS() (VCSInfo, bool) {
if gitCommit != "" {
// Use information set by the build script if present.
return VCSInfo{Commit: gitCommit, Date: gitDate}, true
}
if buildInfo, ok := debug.ReadBuildInfo(); ok {
if buildInfo.Main.Path == ourPath {
return buildInfoVCS(buildInfo)
}
}
return VCSInfo{}, false
}
// ClientName creates a software name/version identifier according to common
// conventions in the Ethereum p2p network.
func ClientName(clientIdentifier string) string {
git, _ := VCS()
return fmt.Sprintf("%s/v%v/%v-%v/%v",
strings.Title(clientIdentifier),
params.VersionWithCommit(git.Commit, git.Date),
runtime.GOOS, runtime.GOARCH,
runtime.Version(),
)
}
// runtimeInfo returns build and platform information about the current binary. // runtimeInfo returns build and platform information about the current binary.
// //
// If the package that is currently executing is a prefixed by our go-ethereum // If the package that is currently executing is a prefixed by our go-ethereum
@ -40,22 +78,20 @@ func Info() (version, vcs string) {
return version, "" return version, ""
} }
version = versionInfo(buildInfo) version = versionInfo(buildInfo)
if status, ok := vcsInfo(buildInfo); ok { if status, ok := VCS(); ok {
modified := "" modified := ""
if status.modified { if status.Dirty {
modified = " (dirty)" modified = " (dirty)"
} }
vcs = status.revision + "-" + status.time + modified commit := status.Commit
if len(commit) > 8 {
commit = commit[:8]
}
vcs = commit + "-" + status.Date + modified
} }
return version, vcs return version, vcs
} }
type gitStatus struct {
revision string
time string
modified bool
}
// versionInfo returns version information for the currently executing // versionInfo returns version information for the currently executing
// implementation. // implementation.
// //