diff --git a/Makefile b/Makefile index 8ec93097..d80382e7 100644 --- a/Makefile +++ b/Makefile @@ -5,6 +5,21 @@ BUILD_DIR := $(WORKSPACE)/build export GOBIN=$(BUILD_DIR) +VERSION = $(shell git describe --tags --always --dirty) +BRANCH = $(shell git rev-parse --abbrev-ref HEAD) +REVISION = $(shell git rev-parse HEAD) +REVSHORT = $(shell git rev-parse --short HEAD) +USER = $(shell whoami) +NOW = $(shell date -u +"%Y-%m-%dT%H:%M:%SZ") + +BUILD_VERSION = "\ + -X micromdm.io/v2/pkg/version.appName=${APP_NAME} \ + -X micromdm.io/v2/pkg/version.version=${VERSION} \ + -X micromdm.io/v2/pkg/version.branch=${BRANCH} \ + -X micromdm.io/v2/pkg/version.buildUser=${USER} \ + -X micromdm.io/v2/pkg/version.buildDate=${NOW} \ + -X micromdm.io/v2/pkg/version.revision=${REVISION}" + download: @echo "Download dependencies" @go mod download @@ -14,4 +29,5 @@ install-tools: download @cat cmd/tools/tools.go | grep _ | awk -F'"' '{print $$2}' | xargs -tI % go install % micromdm: - go install -race ./cmd/micromdm + $(eval APP_NAME = micromdm) + go install -race -ldflags ${BUILD_VERSION} ./cmd/micromdm diff --git a/cmd/micromdm/micromdm.go b/cmd/micromdm/micromdm.go index 07affaae..e9d51eb3 100644 --- a/cmd/micromdm/micromdm.go +++ b/cmd/micromdm/micromdm.go @@ -17,6 +17,7 @@ import ( "github.com/peterbourgon/ff/v3/ffcli" "micromdm.io/v2/pkg/log" + "micromdm.io/v2/pkg/version" ) // write a pid so that the server can be restarted with SIGHUP @@ -42,7 +43,7 @@ func micromdm(args []string, stdin io.Reader, stdout, stderr io.Writer) int { ShortUsage: "version [ ...]", ShortHelp: "Print version information.", Exec: func(_ context.Context, args []string) error { - fmt.Println("v2dev") + version.PrintFull() return nil }, } diff --git a/go.mod b/go.mod index b0a5a42f..cb61e8e6 100644 --- a/go.mod +++ b/go.mod @@ -9,4 +9,5 @@ require ( github.com/oklog/ulid v1.3.1 // indirect github.com/oklog/ulid/v2 v2.0.2 github.com/peterbourgon/ff/v3 v3.0.0 + rsc.io/goversion v1.2.0 ) diff --git a/go.sum b/go.sum index 355ff08e..188dcb42 100644 --- a/go.sum +++ b/go.sum @@ -360,5 +360,7 @@ honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWh honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= +rsc.io/goversion v1.2.0 h1:SPn+NLTiAG7w30IRK/DKp1BjvpWabYgxlLp/+kx5J8w= +rsc.io/goversion v1.2.0/go.mod h1:Eih9y/uIBS3ulggl7KNJ09xGSLcuNaLgmvvqa07sgfo= sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o= sourcegraph.com/sourcegraph/appdash v0.0.0-20190731080439-ebfcffb1b5c0/go.mod h1:hI742Nqp5OhwiqlzhgfbWU4mW4yO10fP+LoT9WOswdU= diff --git a/pkg/version/version.go b/pkg/version/version.go new file mode 100644 index 00000000..a2bcb682 --- /dev/null +++ b/pkg/version/version.go @@ -0,0 +1,94 @@ +/* + Package version provides utilities for displaying version information about a Go application. + To use this package, a program would set the package variables at build time, using the + -ldflags go build flag. + Example: + go build -ldflags "-X micromdm.io/v2/pkg/version.version=1.0.0" + Available values and defaults to use with ldflags: + version = "unknown" + branch = "unknown" + revision = "unknown" + buildDate = "unknown" + buildUser = "unknown" + appName = "unknown" +*/ +package version + +import ( + "encoding/json" + "fmt" + "net/http" + "os" + + goversion "rsc.io/goversion/version" +) + +var ( + version = "unknown" + branch = "unknown" + revision = "unknown" + buildDate = "unknown" + buildUser = "unknown" + appName = "micromdm" +) + +// Info holds version and build info about the program. +type Info struct { + Version string `json:"version"` + Branch string `json:"branch"` + Revision string `json:"revision"` + BuildDate string `json:"build_date"` + BuildUser string `json:"build_user"` +} + +// Version returns a struct with the current version information. +func Version() Info { + return Info{ + Version: version, + Branch: branch, + Revision: revision, + BuildDate: buildDate, + BuildUser: buildUser, + } +} + +// Print outputs the app name and version string. +func Print() { + v := Version() + fmt.Printf("%s version %s\n", appName, v.Version) +} + +// PrintFull outputs the app name and detailed version information. +func PrintFull() error { + v := Version() + fmt.Printf("%s - version %s\n", appName, v.Version) + fmt.Printf("branch: \t%s\n", v.Branch) + fmt.Printf("revision: \t%s\n", v.Revision) + fmt.Printf("build date: \t%s\n", v.BuildDate) + fmt.Printf("build user: \t%s\n", v.BuildUser) + + binary, err := os.Executable() + if err != nil { + return err + } + + binVersion, err := goversion.ReadExe(binary) + if err != nil { + return err + } + fmt.Printf("go release: \t%s\n", binVersion.Release) + fmt.Println() + fmt.Println(binVersion.ModuleInfo) + return nil +} + +// Handler provides an HTTP Handler which returns JSON formatted version info. +func Handler() http.Handler { + v := Version() + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + w.Header().Set("Content-Type", "application/json; charset=utf-8") + enc := json.NewEncoder(w) + enc.SetIndent("", " ") + enc.Encode(v) + }) +}