diff --git a/CHANGELOG.md b/CHANGELOG.md index a9fa3484..fff05b09 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -37,6 +37,11 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) ## Unreleased +### Improvements + +* [#104](https://github.com/babylonlabs-io/finality-provider/pull/104) Print fpd binary version + + ## v0.9.0 ### Improvements diff --git a/Makefile b/Makefile index d6afa36a..913f25fc 100644 --- a/Makefile +++ b/Makefile @@ -13,7 +13,9 @@ MOCKGEN_REPO=github.com/golang/mock/mockgen MOCKGEN_VERSION=v1.6.0 MOCKGEN_CMD=go run ${MOCKGEN_REPO}@${MOCKGEN_VERSION} -ldflags := $(LDFLAGS) +VERSION := $(shell echo $(shell git describe --tags) | sed 's/^v//') + +ldflags := $(LDFLAGS) -X github.com/babylonlabs-io/finality-provider/version.version=$(VERSION) build_tags := $(BUILD_TAGS) build_args := $(BUILD_ARGS) diff --git a/finality-provider/cmd/fpd/daemon/daemon_commands.go b/finality-provider/cmd/fpd/daemon/daemon_commands.go index 2238ffee..d439fe77 100644 --- a/finality-provider/cmd/fpd/daemon/daemon_commands.go +++ b/finality-provider/cmd/fpd/daemon/daemon_commands.go @@ -6,7 +6,9 @@ import ( "encoding/json" "fmt" "github.com/babylonlabs-io/finality-provider/finality-provider/proto" + fpversion "github.com/babylonlabs-io/finality-provider/version" "strconv" + "strings" "cosmossdk.io/math" "github.com/babylonlabs-io/babylon/types" @@ -548,3 +550,33 @@ func loadKeyName(homeDir string, cmd *cobra.Command) (string, error) { } return keyName, nil } + +// CommandVersion prints cmd version +func CommandVersion() *cobra.Command { + var cmd = &cobra.Command{ + Use: "version", + Short: "Prints version of this binary.", + Aliases: []string{"v"}, + Example: `fpd version`, + Args: cobra.NoArgs, + Run: func(cmd *cobra.Command, _ []string) { + version := fpversion.Version() + commit, ts := fpversion.CommitInfo() + + if version == "" { + version = "main" + } + + var sb strings.Builder + _, _ = sb.WriteString("Version: " + version) + _, _ = sb.WriteString("\n") + _, _ = sb.WriteString("Git Commit: " + commit) + _, _ = sb.WriteString("\n") + _, _ = sb.WriteString("Git Timestamp: " + ts) + _, _ = sb.WriteString("\n") + + cmd.Printf(sb.String()) //nolint:govet // it's not an issue + }, + } + return cmd +} diff --git a/finality-provider/cmd/fpd/main.go b/finality-provider/cmd/fpd/main.go index 5a0c384a..6c9ca981 100644 --- a/finality-provider/cmd/fpd/main.go +++ b/finality-provider/cmd/fpd/main.go @@ -34,7 +34,7 @@ func main() { daemon.CommandGetDaemonInfo(), daemon.CommandCreateFP(), daemon.CommandLsFP(), daemon.CommandInfoFP(), daemon.CommandRegisterFP(), daemon.CommandAddFinalitySig(), daemon.CommandExportFP(), daemon.CommandTxs(), daemon.CommandUnjailFP(), - daemon.CommandEditFinalityDescription(), + daemon.CommandEditFinalityDescription(), daemon.CommandVersion(), ) if err := cmd.Execute(); err != nil { diff --git a/finality-provider/service/rpcserver.go b/finality-provider/service/rpcserver.go index a377903d..9a0f3f4b 100644 --- a/finality-provider/service/rpcserver.go +++ b/finality-provider/service/rpcserver.go @@ -77,7 +77,7 @@ func (r *rpcServer) RegisterWithGrpcServer(grpcServer *grpc.Server) error { func (r *rpcServer) GetInfo(context.Context, *proto.GetInfoRequest) (*proto.GetInfoResponse, error) { return &proto.GetInfoResponse{ - Version: version.Version(), + Version: version.VersionRpc(), }, nil } diff --git a/version/version.go b/version/version.go index 17f641b9..e4fcfe33 100644 --- a/version/version.go +++ b/version/version.go @@ -5,170 +5,42 @@ package version import ( - "bytes" "fmt" - "math" "runtime/debug" - "strings" ) -var ( - // Commit stores the current commit of this build, which includes the - // most recent tag, the number of commits since that tag (if non-zero), - // the commit hash, and a dirty marker. This should be set using the - // -ldflags during compilation. - Commit string +// version set at build-time +var version = "main" - // CommitHash stores the current commit hash of this build. - CommitHash string +func CommitInfo() (hash string, timestamp string) { + hash, timestamp = "unknown", "unknown" + hashLen := 7 - // RawTags contains the raw set of build tags, separated by commas. - RawTags string - - // GoVersion stores the go version that the executable was compiled - // with. - GoVersion string -) - -// semanticAlphabet is the set of characters that are permitted for use in an -// AppPreRelease. -const semanticAlphabet = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz-." - -// These constants define the application version and follow the semantic -// versioning 2.0.0 spec (http://semver.org/). -const ( - // AppMajor defines the major version of this binary. - AppMajor uint = 0 - - // AppMinor defines the minor version of this binary. - AppMinor uint = 2 - - // AppPatch defines the application patch for this binary. - AppPatch uint = 2 - - // AppPreRelease MUST only contain characters from semanticAlphabet - // per the semantic versioning spec. - AppPreRelease = "alpha" - - // defaultAgentName is the default name of the software that is added as - // the first part of the user agent string. - defaultAgentName = "fpd" -) - -// agentName stores the name of the software that is added as the first part of -// the user agent string. This defaults to the value "fpd" when being run as -// a standalone component but can be overwritten by LiT for example when fpd -// is integrated into the UI. -var agentName = defaultAgentName - -// SetAgentName overwrites the default agent name which can be used to identify -// the software fpd is bundled in (for example LiT). This function panics if -// the agent name contains characters outside of the allowed semantic alphabet. -func SetAgentName(newAgentName string) { - for _, r := range newAgentName { - if !strings.ContainsRune(semanticAlphabet, r) { - panic(fmt.Errorf("rune: %v is not in the semantic "+ - "alphabet", r)) - } + info, ok := debug.ReadBuildInfo() + if !ok { + return hash, timestamp } - agentName = newAgentName -} - -// UserAgent returns the full user agent string that identifies the software -// that is submitting swaps to the loop server. -func UserAgent(initiator string) string { - // We'll only allow "safe" characters in the initiator portion of the - // user agent string and spaces only if surrounded by other characters. - initiatorAlphabet := semanticAlphabet + ". " - cleanInitiator := normalizeVerString( - strings.TrimSpace(initiator), initiatorAlphabet, - ) - if len(cleanInitiator) > 0 { - cleanInitiator = fmt.Sprintf(",initiator=%s", cleanInitiator) - } - - // The whole user agent string is limited to 255 characters server side - // and also consists of the agent name, version and commit. So we only - // want to take up at most 150 characters for the initiator. Anything - // more will just be dropped. - strLen := len(cleanInitiator) - cleanInitiator = cleanInitiator[:int(math.Min(float64(strLen), 150))] - - // Assemble full string, including the commit hash of current build. - return fmt.Sprintf( - "%s/v%s/commit=%s%s", agentName, semanticVersion(), Commit, - cleanInitiator, - ) -} - -func init() { - // Assert that AppPreRelease is valid according to the semantic - // versioning guidelines for pre-release version and build metadata - // strings. In particular it MUST only contain characters in - // semanticAlphabet. - for _, r := range AppPreRelease { - if !strings.ContainsRune(semanticAlphabet, r) { - panic(fmt.Errorf("rune: %v is not in the semantic "+ - "alphabet", r)) - } - } - - // Get build information from the runtime. - if info, ok := debug.ReadBuildInfo(); ok { - GoVersion = info.GoVersion - for _, setting := range info.Settings { - switch setting.Key { - case "vcs.revision": - CommitHash = setting.Value - - case "-tags": - RawTags = setting.Value + for _, s := range info.Settings { + if s.Key == "vcs.revision" { + if len(s.Value) < hashLen { + hashLen = len(s.Value) } + hash = s.Value[:hashLen] + } else if s.Key == "vcs.time" { + timestamp = s.Value } } -} - -// Version returns the application version as a properly formed string per the -// semantic versioning 2.0.0 spec (http://semver.org/). -func Version() string { - return fmt.Sprintf("%s commit=%s", semanticVersion(), Commit) -} - -// Tags returns the list of build tags that were compiled into the executable. -func Tags() []string { - if len(RawTags) == 0 { - return nil - } - return strings.Split(RawTags, ",") + return hash, timestamp } -// normalizeVerString returns the passed string stripped of all characters -// which are not valid according to the given alphabet. -func normalizeVerString(str, alphabet string) string { - var result bytes.Buffer - for _, r := range str { - if strings.ContainsRune(alphabet, r) { - result.WriteRune(r) - } - } - return result.String() +// Version returns the version +func Version() string { + return version } -// semanticVersion returns the SemVer part of the version. -func semanticVersion() string { - // Start with the major, minor, and patch versions. - version := fmt.Sprintf("%d.%d.%d", AppMajor, AppMinor, AppPatch) - - // Append pre-release version if there is one. The hyphen called for - // by the semantic versioning spec is automatically appended and should - // not be contained in the pre-release string. The pre-release version - // is not appended if it contains invalid characters. - preRelease := normalizeVerString(AppPreRelease, semanticAlphabet) - if preRelease != "" { - version = fmt.Sprintf("%s-%s", version, preRelease) - } - - return version +func VersionRpc() string { + commit, ts := CommitInfo() + return fmt.Sprintf("version: %s, commit: %s, timestamp: %s ", version, commit, ts) }