diff --git a/Makefile b/Makefile index 6dac85287a..753675ec33 100644 --- a/Makefile +++ b/Makefile @@ -7,6 +7,13 @@ .PHONY : docker-apps docker-bin docker-volume .PHONY : docker-run docker-stop +VERSION := $(shell git describe) + +RFC_3339 := "+%Y-%m-%dT%H:%M:%SZ" +DATE := $(shell date -u $(RFC_3339)) +COMMIT := $(shell git rev-list -1 HEAD) + +PROJECT_BASE := github.com/SkycoinProject/skywire-mainnet OPTS?=GO111MODULE=on DOCKER_IMAGE?=skywire-runner # docker image to use for running skywire-visor.`golang`, `buildpack-deps:stretch-scm` is OK too DOCKER_NETWORK?=SKYNET @@ -14,7 +21,16 @@ DOCKER_NODE?=SKY01 DOCKER_OPTS?=GO111MODULE=on GOOS=linux # go options for compiling for docker container TEST_OPTS?=-race -tags no_ci -cover -timeout=5m TEST_OPTS_NOCI?=-race -cover -timeout=5m -v -BUILD_OPTS?= + +BUILDINFO_PATH := $(PROJECT_BASE)/pkg/util/buildinfo + +BUILDINFO_VERSION := -X $(BUILDINFO_PATH).version=$(VERSION) +BUILDINFO_DATE := -X $(BUILDINFO_PATH).date=$(DATE) +BUILDINFO_COMMIT := -X $(BUILDINFO_PATH).commit=$(COMMIT) + +BUILDINFO?=-ldflags="$(BUILDINFO_VERSION) $(BUILDINFO_DATE) $(BUILDINFO_COMMIT)" + +BUILD_OPTS?=$(BUILDINFO) check: lint test ## Run linters and tests @@ -75,9 +91,9 @@ install-linters: ## Install linters ${OPTS} go get -u golang.org/x/tools/cmd/goimports format: ## Formats the code. Must have goimports installed (use make install-linters). - ${OPTS} goimports -w -local github.com/SkycoinProject/skywire ./pkg - ${OPTS} goimports -w -local github.com/SkycoinProject/skywire ./cmd - ${OPTS} goimports -w -local github.com/SkycoinProject/skywire ./internal + ${OPTS} goimports -w -local ${PROJECT_BASE} ./pkg + ${OPTS} goimports -w -local ${PROJECT_BASE} ./cmd + ${OPTS} goimports -w -local ${PROJECT_BASE} ./internal dep: ## Sorts dependencies ${OPTS} go mod vendor -v @@ -158,7 +174,6 @@ run-syslog: ## Run syslog-ng in docker. Logs are mounted under /tmp/syslog -docker container rm syslog-ng -f docker run -d -p 514:514/udp -v /tmp/syslog:/var/log --name syslog-ng balabit/syslog-ng:latest - integration-startup: ## Starts up the required transports between `skywire-visor`s of interactive testing environment ./integration/startup.sh diff --git a/cmd/dmsgpty/commands/root.go b/cmd/dmsgpty/commands/root.go index 6f13031c3d..91039ebde1 100644 --- a/cmd/dmsgpty/commands/root.go +++ b/cmd/dmsgpty/commands/root.go @@ -11,6 +11,7 @@ import ( "github.com/SkycoinProject/skywire-mainnet/internal/skyenv" "github.com/SkycoinProject/skywire-mainnet/pkg/dmsgpty" + "github.com/SkycoinProject/skywire-mainnet/pkg/util/buildinfo" ) var ptyCLI dmsgpty.CLI @@ -32,6 +33,10 @@ var rootCmd = &cobra.Command{ Use: "dmsgpty", Short: "Run commands over dmsg", PreRunE: func(*cobra.Command, []string) error { + if _, err := buildinfo.Get().WriteTo(log.Writer()); err != nil { + log.Printf("Failed to output build info: %v", err) + } + return readDstAddr() }, RunE: func(*cobra.Command, []string) error { diff --git a/cmd/dmsgpty/dmsgpty.go b/cmd/dmsgpty/dmsgpty.go index 92ce4bb87e..83233da6c0 100644 --- a/cmd/dmsgpty/dmsgpty.go +++ b/cmd/dmsgpty/dmsgpty.go @@ -1,6 +1,8 @@ package main -import "github.com/SkycoinProject/skywire-mainnet/cmd/dmsgpty/commands" +import ( + "github.com/SkycoinProject/skywire-mainnet/cmd/dmsgpty/commands" +) func main() { commands.Execute() diff --git a/cmd/hypervisor/commands/gen-config.go b/cmd/hypervisor/commands/gen-config.go index e6e223ca29..0461a6e0fb 100644 --- a/cmd/hypervisor/commands/gen-config.go +++ b/cmd/hypervisor/commands/gen-config.go @@ -15,7 +15,7 @@ var ( output string replace bool configLocType = pathutil.WorkingDirLoc - testenv bool + testEnv bool ) // nolint:gochecknoinits @@ -23,13 +23,13 @@ func init() { outputUsage := "path of output config file. Uses default of 'type' flag if unspecified." replaceUsage := "whether to allow rewrite of a file that already exists." configLocTypeUsage := fmt.Sprintf("config generation mode. Valid values: %v", pathutil.AllConfigLocationTypes()) - testEnv := "whether to use production or test deployment service." + testEnvUsage := "whether to use production or test deployment service." rootCmd.AddCommand(genConfigCmd) genConfigCmd.Flags().StringVarP(&output, "output", "o", "", outputUsage) genConfigCmd.Flags().BoolVarP(&replace, "replace", "r", false, replaceUsage) genConfigCmd.Flags().VarP(&configLocType, "type", "m", configLocTypeUsage) - genConfigCmd.Flags().BoolVarP(&testenv, "testing-environment", "t", false, testEnv) + genConfigCmd.Flags().BoolVarP(&testEnv, "testing-environment", "t", false, testEnvUsage) } // nolint:gochecknoglobals @@ -50,11 +50,11 @@ var genConfigCmd = &cobra.Command{ var conf hypervisor.Config switch configLocType { case pathutil.WorkingDirLoc: - conf = hypervisor.GenerateWorkDirConfig(testenv) + conf = hypervisor.GenerateWorkDirConfig(testEnv) case pathutil.HomeLoc: - conf = hypervisor.GenerateHomeConfig(testenv) + conf = hypervisor.GenerateHomeConfig(testEnv) case pathutil.LocalLoc: - conf = hypervisor.GenerateLocalConfig(testenv) + conf = hypervisor.GenerateLocalConfig(testEnv) default: log.Fatalln("invalid config type:", configLocType) } diff --git a/cmd/hypervisor/commands/root.go b/cmd/hypervisor/commands/root.go index b80ebae8ce..295eb4f4b1 100644 --- a/cmd/hypervisor/commands/root.go +++ b/cmd/hypervisor/commands/root.go @@ -3,6 +3,7 @@ package commands import ( "fmt" "net/http" + "os" "github.com/SkycoinProject/dmsg" "github.com/SkycoinProject/dmsg/disc" @@ -11,6 +12,7 @@ import ( "github.com/spf13/cobra" "github.com/SkycoinProject/skywire-mainnet/pkg/hypervisor" + "github.com/SkycoinProject/skywire-mainnet/pkg/util/buildinfo" "github.com/SkycoinProject/skywire-mainnet/pkg/util/pathutil" ) @@ -43,6 +45,10 @@ var rootCmd = &cobra.Command{ Use: "hypervisor", Short: "Manages Skywire App Nodes", Run: func(_ *cobra.Command, args []string) { + if _, err := buildinfo.Get().WriteTo(os.Stdout); err != nil { + log.Printf("Failed to output build info: %v", err) + } + if configPath == "" { configPath = pathutil.FindConfigPath(args, -1, configEnv, pathutil.HypervisorDefaults()) } diff --git a/cmd/hypervisor/hypervisor.go b/cmd/hypervisor/hypervisor.go index cde4e7977a..d049201954 100644 --- a/cmd/hypervisor/hypervisor.go +++ b/cmd/hypervisor/hypervisor.go @@ -3,7 +3,9 @@ skywire hypervisor */ package main -import "github.com/SkycoinProject/skywire-mainnet/cmd/hypervisor/commands" +import ( + "github.com/SkycoinProject/skywire-mainnet/cmd/hypervisor/commands" +) func main() { commands.Execute() diff --git a/cmd/setup-node/commands/root.go b/cmd/setup-node/commands/root.go index e9e32cba23..5466d441b5 100644 --- a/cmd/setup-node/commands/root.go +++ b/cmd/setup-node/commands/root.go @@ -16,6 +16,7 @@ import ( "github.com/SkycoinProject/skywire-mainnet/pkg/metrics" "github.com/SkycoinProject/skywire-mainnet/pkg/setup" + "github.com/SkycoinProject/skywire-mainnet/pkg/util/buildinfo" ) var ( @@ -29,6 +30,9 @@ var rootCmd = &cobra.Command{ Use: "setup-node [config.json]", Short: "Route Setup Node for skywire", Run: func(_ *cobra.Command, args []string) { + if _, err := buildinfo.Get().WriteTo(log.Writer()); err != nil { + log.Printf("Failed to output build info: %v", err) + } logger := logging.MustGetLogger(tag) if syslogAddr != "" { diff --git a/cmd/setup-node/setup-node.go b/cmd/setup-node/setup-node.go index e882d663e2..fbf1c7e2d7 100644 --- a/cmd/setup-node/setup-node.go +++ b/cmd/setup-node/setup-node.go @@ -1,6 +1,8 @@ package main -import "github.com/SkycoinProject/skywire-mainnet/cmd/setup-node/commands" +import ( + "github.com/SkycoinProject/skywire-mainnet/cmd/setup-node/commands" +) func main() { commands.Execute() diff --git a/cmd/skywire-cli/commands/node/version.go b/cmd/skywire-cli/commands/node/version.go new file mode 100644 index 0000000000..859eff2dd6 --- /dev/null +++ b/cmd/skywire-cli/commands/node/version.go @@ -0,0 +1,27 @@ +package node + +import ( + "os" + + "github.com/spf13/cobra" +) + +func init() { + RootCmd.AddCommand(buildInfoCmd) +} + +var buildInfoCmd = &cobra.Command{ + Use: "version", + Short: "Obtains version and build info of the node", + Run: func(_ *cobra.Command, _ []string) { + client := rpcClient() + summary, err := client.Summary() + if err != nil { + log.Fatal("Failed to connect:", err) + } + + if _, err := summary.BuildInfo.WriteTo(os.Stdout); err != nil { + log.Fatal("Failed to output build info:", err) + } + }, +} diff --git a/cmd/skywire-visor/commands/root.go b/cmd/skywire-visor/commands/root.go index 7c916a93d9..41f1faf9c0 100644 --- a/cmd/skywire-visor/commands/root.go +++ b/cmd/skywire-visor/commands/root.go @@ -24,6 +24,7 @@ import ( "github.com/SkycoinProject/skywire-mainnet/internal/utclient" "github.com/SkycoinProject/skywire-mainnet/pkg/restart" + "github.com/SkycoinProject/skywire-mainnet/pkg/util/buildinfo" "github.com/SkycoinProject/skywire-mainnet/pkg/util/pathutil" "github.com/SkycoinProject/skywire-mainnet/pkg/visor" ) @@ -58,6 +59,10 @@ var rootCmd = &cobra.Command{ Use: "skywire-visor [config-path]", Short: "Visor for skywire", Run: func(_ *cobra.Command, args []string) { + if _, err := buildinfo.Get().WriteTo(log.Writer()); err != nil { + log.Printf("Failed to output build info: %v", err) + } + cfg.args = args cfg.startProfiler(). @@ -67,7 +72,7 @@ var rootCmd = &cobra.Command{ waitOsSignals(). stopNode() }, - Version: visor.Version, + Version: buildinfo.Get().Version, } func init() { diff --git a/pkg/hypervisor/hypervisor.go b/pkg/hypervisor/hypervisor.go index a5b05afce0..71901f80e3 100644 --- a/pkg/hypervisor/hypervisor.go +++ b/pkg/hypervisor/hypervisor.go @@ -148,9 +148,9 @@ func (m *Node) ServeHTTP(w http.ResponseWriter, req *http.Request) { r.Get("/user", m.users.UserInfo()) r.Post("/change-password", m.users.ChangePassword()) r.Get("/nodes", m.getNodes()) + r.Get("/nodes/{pk}", m.getNode()) r.Get("/nodes/{pk}/health", m.getHealth()) r.Get("/nodes/{pk}/uptime", m.getUptime()) - r.Get("/nodes/{pk}", m.getNode()) r.Get("/nodes/{pk}/apps", m.getApps()) r.Get("/nodes/{pk}/apps/{app}", m.getApp()) r.Put("/nodes/{pk}/apps/{app}", m.putApp()) diff --git a/pkg/util/buildinfo/buildinfo.go b/pkg/util/buildinfo/buildinfo.go new file mode 100644 index 0000000000..f460f64aca --- /dev/null +++ b/pkg/util/buildinfo/buildinfo.go @@ -0,0 +1,52 @@ +package buildinfo + +import ( + "fmt" + "io" +) + +const unknown = "unknown" + +var ( + version = unknown + commit = unknown + date = unknown +) + +// Version returns version from git describe. +func Version() string { + return version +} + +// Commit returns commit hash. +func Commit() string { + return commit +} + +// Date returns date of build in RFC3339 format. +func Date() string { + return date +} + +// Get returns build info summary. +func Get() *Info { + return &Info{ + Version: Version(), + Commit: Commit(), + Date: Date(), + } +} + +// Info is build info summary. +type Info struct { + Version string `json:"version"` + Commit string `json:"commit"` + Date string `json:"date"` +} + +// WriteTo writes build info summary to io.Writer. +func (info *Info) WriteTo(w io.Writer) (int64, error) { + msg := fmt.Sprintf("Version %q built on %q agaist commit %q\n", info.Version, info.Date, info.Commit) + n, err := w.Write([]byte(msg)) + return int64(n), err +} diff --git a/pkg/visor/rpc.go b/pkg/visor/rpc.go index 0f36478829..58154f647c 100644 --- a/pkg/visor/rpc.go +++ b/pkg/visor/rpc.go @@ -14,6 +14,7 @@ import ( "github.com/SkycoinProject/skywire-mainnet/pkg/app" "github.com/SkycoinProject/skywire-mainnet/pkg/routing" "github.com/SkycoinProject/skywire-mainnet/pkg/transport" + "github.com/SkycoinProject/skywire-mainnet/pkg/util/buildinfo" ) const ( @@ -144,7 +145,7 @@ func newTransportSummary(tm *transport.Manager, tp *transport.ManagedTransport, // Summary provides a summary of a Skywire Visor. type Summary struct { PubKey cipher.PubKey `json:"local_pk"` - NodeVersion string `json:"node_version"` + BuildInfo *buildinfo.Info `json:"build_info"` AppProtoVersion string `json:"app_protocol_version"` Apps []*AppState `json:"apps"` Transports []*TransportSummary `json:"transports"` @@ -161,7 +162,7 @@ func (r *RPC) Summary(_ *struct{}, out *Summary) error { }) *out = Summary{ PubKey: r.node.conf.Node.StaticPubKey, - NodeVersion: Version, + BuildInfo: buildinfo.Get(), AppProtoVersion: supportedProtocolVersion, Apps: r.node.Apps(), Transports: summaries, diff --git a/pkg/visor/rpc_client.go b/pkg/visor/rpc_client.go index 58bdf73e4c..f5c17d4fba 100644 --- a/pkg/visor/rpc_client.go +++ b/pkg/visor/rpc_client.go @@ -22,6 +22,7 @@ import ( "github.com/SkycoinProject/skywire-mainnet/pkg/snet" "github.com/SkycoinProject/skywire-mainnet/pkg/snet/snettest" "github.com/SkycoinProject/skywire-mainnet/pkg/transport" + "github.com/SkycoinProject/skywire-mainnet/pkg/util/buildinfo" ) var ( @@ -424,7 +425,7 @@ func NewMockRPCClient(r *rand.Rand, maxTps int, maxRules int) (cipher.PubKey, RP client := &mockRPCClient{ s: &Summary{ PubKey: localPK, - NodeVersion: Version, + BuildInfo: buildinfo.Get(), AppProtoVersion: supportedProtocolVersion, Apps: []*AppState{ {Name: "foo.v1.0", AutoStart: false, Port: 10}, diff --git a/pkg/visor/visor.go b/pkg/visor/visor.go index fb1051e2f1..6385e82df6 100644 --- a/pkg/visor/visor.go +++ b/pkg/visor/visor.go @@ -56,9 +56,6 @@ var ( ErrNoConfigPath = errors.New("no config path") ) -// Version is the node version. -const Version = "0.0.1" - const supportedProtocolVersion = "0.0.1" var reservedPorts = map[routing.Port]string{0: "router", 1: "skychat", 3: "skysocks"}