diff --git a/framework/flamingo/flamingo.go b/framework/flamingo/flamingo.go index 3f5878d6b..83a3f245a 100644 --- a/framework/flamingo/flamingo.go +++ b/framework/flamingo/flamingo.go @@ -1,9 +1,65 @@ package flamingo +import ( + "fmt" + "io" + "runtime" + "runtime/debug" +) + var appVersion = "develop" +const ( + vcsRevisionSettingKey = "vcs.revision" +) + +type ( + AppInfo struct { + AppVersion string + VCSRevision string + RuntimeVersion string + MainPackagePath string + FlamingoVersion string + } +) + // AppVersion returns the application version // set this during build with `go build -ldflags "-X flamingo.me/flamingo/v3/framework/flamingo.appVersion=1.2.3"`. func AppVersion() string { return appVersion } + +// GetAppInfo provides basic application information like runtime version, flamingo version etc. +func GetAppInfo() AppInfo { + appInfo := AppInfo{ + AppVersion: AppVersion(), + RuntimeVersion: runtime.Version(), + } + + if info, ok := debug.ReadBuildInfo(); ok { + appInfo.MainPackagePath = info.Main.Path + + for _, module := range info.Deps { + if module.Path == "flamingo.me/flamingo/v3" { + appInfo.FlamingoVersion = module.Version + } + } + + for _, setting := range info.Settings { + if setting.Key == vcsRevisionSettingKey { + appInfo.VCSRevision = setting.Value + } + } + } + + return appInfo +} + +// PrintAppInfo prints application info to the writer +func PrintAppInfo(writer io.Writer, appInfo AppInfo) { + _, _ = fmt.Fprintf(writer, "%20s\t%s\n", "App version:", appInfo.AppVersion) + _, _ = fmt.Fprintf(writer, "%20s\t%s\n", "Go runtime version:", appInfo.RuntimeVersion) + _, _ = fmt.Fprintf(writer, "%20s\t%s\n", "VCS revision:", appInfo.VCSRevision) + _, _ = fmt.Fprintf(writer, "%20s\t%s\n", "Path:", appInfo.MainPackagePath) + _, _ = fmt.Fprintf(writer, "%20s\t%s\n", "Flamingo version:", appInfo.FlamingoVersion) +} diff --git a/framework/flamingo/flamingo_test.go b/framework/flamingo/flamingo_test.go new file mode 100644 index 000000000..1bc6b3cc1 --- /dev/null +++ b/framework/flamingo/flamingo_test.go @@ -0,0 +1,48 @@ +package flamingo_test + +import ( + "bytes" + "testing" + + "github.com/stretchr/testify/assert" + + "flamingo.me/flamingo/v3/framework/flamingo" +) + +func TestPrintAppInfo(t *testing.T) { + t.Parallel() + + type args struct { + appInfo flamingo.AppInfo + } + + tests := []struct { + name string + args args + wantWriter string + }{ + { + name: "", + args: args{ + appInfo: flamingo.AppInfo{ + AppVersion: "v1.2.3", + VCSRevision: "c9ce01204a18ff2f3e9ed999fbf7f3eb8e70b614", + RuntimeVersion: "go1.23.3", + MainPackagePath: "go.aoe.com/whitelabel-airline/flamingo", + FlamingoVersion: "v3.11.0", + }, + }, + wantWriter: " App version:\tv1.2.3\n Go runtime version:\tgo1.23.3\n VCS revision:\tc9ce01204a18ff2f3e9ed999fbf7f3eb8e70b614\n Path:\tgo.aoe.com/whitelabel-airline/flamingo\n Flamingo version:\tv3.11.0\n", + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + t.Parallel() + + writer := &bytes.Buffer{} + flamingo.PrintAppInfo(writer, tt.args.appInfo) + assert.Equalf(t, tt.wantWriter, writer.String(), "PrintAppInfo(%v, %v)", writer, tt.args.appInfo) + }) + } +} diff --git a/framework/flamingo/versioncmd.go b/framework/flamingo/versioncmd.go new file mode 100644 index 000000000..2a650e3d2 --- /dev/null +++ b/framework/flamingo/versioncmd.go @@ -0,0 +1,22 @@ +package flamingo + +import ( + "bytes" + + "github.com/spf13/cobra" +) + +func VersionCmd() *cobra.Command { + return &cobra.Command{ + Use: "version", + Short: "Application version", + Run: func(cmd *cobra.Command, args []string) { + var buffer bytes.Buffer + + appInfo := GetAppInfo() + PrintAppInfo(&buffer, appInfo) + + cmd.Println(buffer.String()) + }, + } +} diff --git a/framework/module.go b/framework/module.go index 7a28191e4..4b17cda90 100644 --- a/framework/module.go +++ b/framework/module.go @@ -43,6 +43,7 @@ func (*InitModule) Configure(injector *dingo.Injector) { injector.BindMulti(new(cobra.Command)).ToProvider(web.HandlerCmd) injector.BindMulti(new(cobra.Command)).ToProvider(config.ModulesCmd) injector.BindMulti(new(cobra.Command)).ToProvider(config.Cmd) + injector.BindMulti(new(cobra.Command)).ToProvider(flamingo.VersionCmd) web.BindRoutes(injector, new(routes)) diff --git a/framework/module_test.go b/framework/module_test.go index 96ddc0c4d..688ae5bab 100644 --- a/framework/module_test.go +++ b/framework/module_test.go @@ -4,6 +4,7 @@ import ( "testing" "flamingo.me/dingo" + "flamingo.me/flamingo/v3/framework" ) diff --git a/framework/systemendpoint/application/server.go b/framework/systemendpoint/application/server.go index 08b139666..bfeb20b0b 100644 --- a/framework/systemendpoint/application/server.go +++ b/framework/systemendpoint/application/server.go @@ -3,11 +3,8 @@ package application import ( "context" "errors" - "fmt" "net" "net/http" - "runtime" - "runtime/debug" "sync" "flamingo.me/flamingo/v3/framework/flamingo" @@ -61,16 +58,8 @@ func (s *SystemServer) Start() { } serveMux.HandleFunc("/version", func(writer http.ResponseWriter, _ *http.Request) { - _, _ = fmt.Fprintf(writer, "version: %s\n", flamingo.AppVersion()) - _, _ = fmt.Fprintf(writer, "go: %s\n", runtime.Version()) - if info, ok := debug.ReadBuildInfo(); ok { - _, _ = fmt.Fprintf(writer, "path: %s\n", info.Path) - for _, module := range info.Deps { - if module.Path == "flamingo.me/flamingo/v3" { - _, _ = fmt.Fprintf(writer, "flamingo: %s\n", module.Version) - } - } - } + appInfo := flamingo.GetAppInfo() + flamingo.PrintAppInfo(writer, appInfo) }) listener, err := net.Listen("tcp", s.serviceAddress)