From 3f7ffcdab4538371077b2ca26320fa3b45938b1d Mon Sep 17 00:00:00 2001 From: Vitor Floriano <107767584+vitorfloriano@users.noreply.github.com> Date: Tue, 18 Nov 2025 00:12:40 -0300 Subject: [PATCH 1/2] WIP: version pretty output --- cmd/cmd.go | 2 +- cmd/version.go | 22 ++++++++++++---------- pkg/cli/cli.go | 4 ++-- pkg/cli/cli_test.go | 23 +++++++++++++++++++++-- pkg/cli/options.go | 2 +- pkg/cli/options_test.go | 9 ++++++++- pkg/cli/version.go | 14 +++++++++++++- 7 files changed, 58 insertions(+), 18 deletions(-) diff --git a/cmd/cmd.go b/cmd/cmd.go index c4a26fefa16..c01ab0a7292 100644 --- a/cmd/cmd.go +++ b/cmd/cmd.go @@ -64,7 +64,7 @@ func Run() { c, err := cli.New( cli.WithCommandName("kubebuilder"), - cli.WithVersion(versionString()), + cli.WithVersion(versionMap()), cli.WithCliVersion(getKubebuilderVersion()), cli.WithPlugins( golangv4.Plugin{}, diff --git a/cmd/version.go b/cmd/version.go index 0f26a98c3b5..3b3ce940f73 100644 --- a/cmd/version.go +++ b/cmd/version.go @@ -59,17 +59,19 @@ type version struct { } // versionString returns the Full CLI version -func versionString() string { +func versionMap() map[string]string { kubeBuilderVersion = getKubebuilderVersion() - - return fmt.Sprintf("Version: %#v", version{ - kubeBuilderVersion, - kubernetesVendorVersion, - gitCommit, - buildDate, - goos, - goarch, - }) + + version := map[string]string{ + "kubebuilder": kubeBuilderVersion, + "kubernetes": kubernetesVendorVersion, + "buildDate": buildDate, + "gitCommit": gitCommit, + "os": goos, + "arch": goarch, + } + + return version } // getKubebuilderVersion returns only the CLI version string diff --git a/pkg/cli/cli.go b/pkg/cli/cli.go index 28645781524..43ca3f802f2 100644 --- a/pkg/cli/cli.go +++ b/pkg/cli/cli.go @@ -49,7 +49,7 @@ type CLI struct { // Root command name. It is injected downstream to provide correct help, usage, examples and errors. commandName string // Full CLI version string. - version string + version map[string]string // CLI version string (just the CLI version number, no extra information). cliVersion string // CLI root's command description. @@ -527,7 +527,7 @@ func (c *CLI) addSubcommands() { // kubebuilder version // Only add version if a version string was provided - if c.version != "" { + if c.version != nil { c.cmd.AddCommand(c.newVersionCmd()) } } diff --git a/pkg/cli/cli_test.go b/pkg/cli/cli_test.go index 486b99c4624..6380a4ed231 100644 --- a/pkg/cli/cli_test.go +++ b/pkg/cli/cli_test.go @@ -623,7 +623,14 @@ plugins: When("providing a version string", func() { It("should create a valid CLI", func() { - const version = "version string" + version := map[string]string{ + "kubebuilder": "123", + "kubernetes": "123", + "buildDate": "2025/12/3", + "gitCommit": "0123fasdf0123", + "os": "os123", + "arch": "arch123", + } c, err = New( WithPlugins(&golangv4.Plugin{}), WithDefaultPlugins(projectVersion, &golangv4.Plugin{}), @@ -648,7 +655,19 @@ plugins: Expect(err).NotTo(HaveOccurred()) printed, _ := io.ReadAll(r) Expect(string(printed)).To(Equal( - fmt.Sprintf("%s\n", version))) + fmt.Sprintf(`Kubebuilder: %v +Kubernetes: %v +Git Commit: %v +Build date: %v +OS/Arch: %v/%v +`, + version["kubebuilder"], + version["kubernetes"], + version["gitCommit"], + version["buildDate"], + version["os"], + version["arch"], + ))) }) }) diff --git a/pkg/cli/options.go b/pkg/cli/options.go index 2f0c2fc56ef..4fd40784cad 100644 --- a/pkg/cli/options.go +++ b/pkg/cli/options.go @@ -50,7 +50,7 @@ func WithCommandName(name string) Option { } // WithVersion is an Option that defines the version string of the CLI. -func WithVersion(version string) Option { +func WithVersion(version map[string]string) Option { return func(c *CLI) error { c.version = version return nil diff --git a/pkg/cli/options_test.go b/pkg/cli/options_test.go index 55d7bc3015f..9d0a46a4939 100644 --- a/pkg/cli/options_test.go +++ b/pkg/cli/options_test.go @@ -540,7 +540,14 @@ var _ = Describe("CLI options", func() { Context("WithVersion", func() { It("should use the provided version string", func() { - version := "Version: 0.0.0" + version := map[string]string{ + "kubebuilder": "123", + "kubernetes": "123", + "buildDate": "2025/12/3", + "gitCommit": "0123fasdf0123", + "os": "os123", + "arch": "arch123", + } c, err = newCLI(WithVersion(version)) Expect(err).NotTo(HaveOccurred()) Expect(c).NotTo(BeNil()) diff --git a/pkg/cli/version.go b/pkg/cli/version.go index f721c41ff0f..3cc4e2232fd 100644 --- a/pkg/cli/version.go +++ b/pkg/cli/version.go @@ -29,7 +29,19 @@ func (c CLI) newVersionCmd() *cobra.Command { Long: fmt.Sprintf("Print the %s version", c.commandName), Example: fmt.Sprintf("%s version", c.commandName), RunE: func(_ *cobra.Command, _ []string) error { - fmt.Println(c.version) + fmt.Printf(`Kubebuilder: %v +Kubernetes: %v +Git Commit: %v +Build date: %v +OS/Arch: %v/%v +`, + c.version["kubebuilder"], + c.version["kubernetes"], + c.version["gitCommit"], + c.version["buildDate"], + c.version["os"], + c.version["arch"], + ) return nil }, } From ae97bbf8fd9a84ff840586c67c2c121393e8e905 Mon Sep 17 00:00:00 2001 From: Vitor <107767584+vitorfloriano@users.noreply.github.com> Date: Wed, 19 Nov 2025 16:07:18 -0300 Subject: [PATCH 2/2] change approach --- cmd/cmd.go | 2 +- cmd/version.go | 33 ++++++++++++--------------------- pkg/cli/cli.go | 6 +++--- pkg/cli/cli_test.go | 34 +++++++++++++--------------------- pkg/cli/options.go | 2 +- pkg/cli/options_test.go | 20 ++++++++++---------- pkg/cli/version.go | 40 +++++++++++++++++++++++++++------------- 7 files changed, 67 insertions(+), 70 deletions(-) diff --git a/cmd/cmd.go b/cmd/cmd.go index c01ab0a7292..a911ea8afce 100644 --- a/cmd/cmd.go +++ b/cmd/cmd.go @@ -64,7 +64,7 @@ func Run() { c, err := cli.New( cli.WithCommandName("kubebuilder"), - cli.WithVersion(versionMap()), + cli.WithVersion(versionStruct()), cli.WithCliVersion(getKubebuilderVersion()), cli.WithPlugins( golangv4.Plugin{}, diff --git a/cmd/version.go b/cmd/version.go index 3b3ce940f73..f0f7b7ba050 100644 --- a/cmd/version.go +++ b/cmd/version.go @@ -28,6 +28,7 @@ import ( "time" "golang.org/x/mod/semver" + "sigs.k8s.io/kubebuilder/v4/pkg/cli" ) const ( @@ -48,30 +49,20 @@ var ( buildDate = "1970-01-01T00:00:00Z" // build date in ISO8601 format, output of $(date -u +'%Y-%m-%dT%H:%M:%SZ') ) -// version contains all the information related to the CLI version -type version struct { - KubeBuilderVersion string `json:"kubeBuilderVersion"` - KubernetesVendor string `json:"kubernetesVendor"` - GitCommit string `json:"gitCommit"` - BuildDate string `json:"buildDate"` - GoOs string `json:"goOs"` - GoArch string `json:"goArch"` -} - // versionString returns the Full CLI version -func versionMap() map[string]string { +func versionStruct() *cli.Version { kubeBuilderVersion = getKubebuilderVersion() - - version := map[string]string{ - "kubebuilder": kubeBuilderVersion, - "kubernetes": kubernetesVendorVersion, - "buildDate": buildDate, - "gitCommit": gitCommit, - "os": goos, - "arch": goarch, + + version := cli.Version{ + KubeBuilderVersion: kubeBuilderVersion, + KubernetesVendor: kubernetesVendorVersion, + GitCommit: gitCommit, + BuildDate: buildDate, + GoOs: goos, + GoArch: goarch, } - - return version + + return &version } // getKubebuilderVersion returns only the CLI version string diff --git a/pkg/cli/cli.go b/pkg/cli/cli.go index 43ca3f802f2..b59712f1f66 100644 --- a/pkg/cli/cli.go +++ b/pkg/cli/cli.go @@ -48,8 +48,8 @@ type CLI struct { // Root command name. It is injected downstream to provide correct help, usage, examples and errors. commandName string - // Full CLI version string. - version map[string]string + // Full CLI version struct. + version *Version // CLI version string (just the CLI version number, no extra information). cliVersion string // CLI root's command description. @@ -526,7 +526,7 @@ func (c *CLI) addSubcommands() { c.cmd.AddCommand(c.newInitCmd()) // kubebuilder version - // Only add version if a version string was provided + // Only add version if a version struct was provided if c.version != nil { c.cmd.AddCommand(c.newVersionCmd()) } diff --git a/pkg/cli/cli_test.go b/pkg/cli/cli_test.go index 6380a4ed231..ed4b14b6c01 100644 --- a/pkg/cli/cli_test.go +++ b/pkg/cli/cli_test.go @@ -623,18 +623,18 @@ plugins: When("providing a version string", func() { It("should create a valid CLI", func() { - version := map[string]string{ - "kubebuilder": "123", - "kubernetes": "123", - "buildDate": "2025/12/3", - "gitCommit": "0123fasdf0123", - "os": "os123", - "arch": "arch123", + version := Version{ + KubeBuilderVersion: "123", + KubernetesVendor: "123", + GitCommit: "0123fasdf0123", + BuildDate: "2025-12-3", + GoOs: "os123", + GoArch: "arch123", } c, err = New( WithPlugins(&golangv4.Plugin{}), WithDefaultPlugins(projectVersion, &golangv4.Plugin{}), - WithVersion(version), + WithVersion(&version), ) Expect(err).NotTo(HaveOccurred()) Expect(hasSubCommand(c.cmd, "version")).To(BeTrue()) @@ -655,19 +655,11 @@ plugins: Expect(err).NotTo(HaveOccurred()) printed, _ := io.ReadAll(r) Expect(string(printed)).To(Equal( - fmt.Sprintf(`Kubebuilder: %v -Kubernetes: %v -Git Commit: %v -Build date: %v -OS/Arch: %v/%v -`, - version["kubebuilder"], - version["kubernetes"], - version["gitCommit"], - version["buildDate"], - version["os"], - version["arch"], - ))) + fmt.Sprintf("Kubebuilder:\t123\n" + + "Kubernetes:\t123\n" + + "Git Commit:\t0123fasdf0123\n" + + "Build Date:\t2025-12-3\n" + + "OS/Arch:\tos123/arch123\n"))) }) }) diff --git a/pkg/cli/options.go b/pkg/cli/options.go index 4fd40784cad..934dffcb48d 100644 --- a/pkg/cli/options.go +++ b/pkg/cli/options.go @@ -50,7 +50,7 @@ func WithCommandName(name string) Option { } // WithVersion is an Option that defines the version string of the CLI. -func WithVersion(version map[string]string) Option { +func WithVersion(version *Version) Option { return func(c *CLI) error { c.version = version return nil diff --git a/pkg/cli/options_test.go b/pkg/cli/options_test.go index 9d0a46a4939..ed61be15eca 100644 --- a/pkg/cli/options_test.go +++ b/pkg/cli/options_test.go @@ -539,19 +539,19 @@ var _ = Describe("CLI options", func() { }) Context("WithVersion", func() { - It("should use the provided version string", func() { - version := map[string]string{ - "kubebuilder": "123", - "kubernetes": "123", - "buildDate": "2025/12/3", - "gitCommit": "0123fasdf0123", - "os": "os123", - "arch": "arch123", + It("should use the provided version struct", func() { + version := Version{ + KubeBuilderVersion: "123", + KubernetesVendor: "123", + GitCommit: "asdf1324", + BuildDate: "2025-11-19", + GoOs: "os123", + GoArch: "arch123", } - c, err = newCLI(WithVersion(version)) + c, err = newCLI(WithVersion(&version)) Expect(err).NotTo(HaveOccurred()) Expect(c).NotTo(BeNil()) - Expect(c.version).To(Equal(version)) + Expect(c.version).To(Equal(&version)) }) }) diff --git a/pkg/cli/version.go b/pkg/cli/version.go index 3cc4e2232fd..dcd15228f72 100644 --- a/pkg/cli/version.go +++ b/pkg/cli/version.go @@ -22,6 +22,32 @@ import ( "github.com/spf13/cobra" ) +// Version contains all the information related to the CLI version +type Version struct { + KubeBuilderVersion string `json:"kubeBuilderVersion"` + KubernetesVendor string `json:"kubernetesVendor"` + GitCommit string `json:"gitCommit"` + BuildDate string `json:"buildDate"` + GoOs string `json:"goOs"` + GoArch string `json:"goArch"` +} + +// String implements Stringer for Version so we can format the output as needed +func (v Version) String() string { + return fmt.Sprintf( + "Kubebuilder:\t%v\n"+ + "Kubernetes:\t%v\n"+ + "Git Commit:\t%v\n"+ + "Build Date:\t%v\n"+ + "OS/Arch:\t%v/%v", + v.KubeBuilderVersion, + v.KubernetesVendor, + v.GitCommit, + v.BuildDate, + v.GoOs, + v.GoArch) +} + func (c CLI) newVersionCmd() *cobra.Command { cmd := &cobra.Command{ Use: "version", @@ -29,19 +55,7 @@ func (c CLI) newVersionCmd() *cobra.Command { Long: fmt.Sprintf("Print the %s version", c.commandName), Example: fmt.Sprintf("%s version", c.commandName), RunE: func(_ *cobra.Command, _ []string) error { - fmt.Printf(`Kubebuilder: %v -Kubernetes: %v -Git Commit: %v -Build date: %v -OS/Arch: %v/%v -`, - c.version["kubebuilder"], - c.version["kubernetes"], - c.version["gitCommit"], - c.version["buildDate"], - c.version["os"], - c.version["arch"], - ) + fmt.Println(c.version) return nil }, }