diff --git a/cmd/cmd.go b/cmd/cmd.go index 2e6797c11a7..42c13d20d5c 100644 --- a/cmd/cmd.go +++ b/cmd/cmd.go @@ -55,6 +55,7 @@ func Run() { c, err := cli.New( cli.WithCommandName("kubebuilder"), cli.WithVersion(versionString()), + cli.WithCliVersion(GetKubebuilderVersion()), cli.WithPlugins( golangv4.Plugin{}, gov4Bundle, diff --git a/cmd/version.go b/cmd/version.go index 77520ede984..a533df50c9a 100644 --- a/cmd/version.go +++ b/cmd/version.go @@ -45,7 +45,7 @@ type version struct { GoArch string `json:"goArch"` } -// versionString returns the CLI version +// versionString returns the Full CLI version func versionString() string { if kubeBuilderVersion == unknown { if info, ok := debug.ReadBuildInfo(); ok && info.Main.Version != "" { @@ -62,3 +62,13 @@ func versionString() string { goarch, }) } + +// GetKubebuilderVersion returns only the CLI version string +func GetKubebuilderVersion() string { + if kubeBuilderVersion == unknown { + if info, ok := debug.ReadBuildInfo(); ok && info.Main.Version != "" { + kubeBuilderVersion = info.Main.Version + } + } + return kubeBuilderVersion +} diff --git a/docs/book/src/cronjob-tutorial/testdata/project/PROJECT b/docs/book/src/cronjob-tutorial/testdata/project/PROJECT index 656f6c4372f..9de48f17971 100644 --- a/docs/book/src/cronjob-tutorial/testdata/project/PROJECT +++ b/docs/book/src/cronjob-tutorial/testdata/project/PROJECT @@ -2,6 +2,7 @@ # This file is used to track the info used to scaffold your project # and allow the plugins properly work. # More info: https://book.kubebuilder.io/reference/project-config.html +cliVersion: (devel) domain: tutorial.kubebuilder.io layout: - go.kubebuilder.io/v4 diff --git a/docs/book/src/getting-started/testdata/project/PROJECT b/docs/book/src/getting-started/testdata/project/PROJECT index c38719bc1df..3193d16ab07 100644 --- a/docs/book/src/getting-started/testdata/project/PROJECT +++ b/docs/book/src/getting-started/testdata/project/PROJECT @@ -2,6 +2,7 @@ # This file is used to track the info used to scaffold your project # and allow the plugins properly work. # More info: https://book.kubebuilder.io/reference/project-config.html +cliVersion: (devel) domain: example.com layout: - go.kubebuilder.io/v4 diff --git a/docs/book/src/multiversion-tutorial/testdata/project/PROJECT b/docs/book/src/multiversion-tutorial/testdata/project/PROJECT index d49104d82a5..6071b21b6a7 100644 --- a/docs/book/src/multiversion-tutorial/testdata/project/PROJECT +++ b/docs/book/src/multiversion-tutorial/testdata/project/PROJECT @@ -2,6 +2,7 @@ # This file is used to track the info used to scaffold your project # and allow the plugins properly work. # More info: https://book.kubebuilder.io/reference/project-config.html +cliVersion: (devel) domain: tutorial.kubebuilder.io layout: - go.kubebuilder.io/v4 diff --git a/docs/book/src/reference/project-config.md b/docs/book/src/reference/project-config.md index 5c4f5b57223..d04ec87c479 100644 --- a/docs/book/src/reference/project-config.md +++ b/docs/book/src/reference/project-config.md @@ -14,6 +14,7 @@ Following is an example of a PROJECT config file which is the result of a projec # and allow the plugins properly work. # More info: https://book.kubebuilder.io/reference/project-config.html domain: testproject.org +cliVersion: v4.6.0 layout: - go.kubebuilder.io/v4 plugins: @@ -81,6 +82,7 @@ The `PROJECT` version `3` layout looks like: ```yaml domain: testproject.org +cliVersion: v4.6.0 layout: - go.kubebuilder.io/v4 plugins: @@ -132,6 +134,7 @@ Now let's check its layout fields definition: | Field | Description | |-------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| `cliVersion` | Used to record the specific CLI version used during project scaffolding with `init`. Helps identifying the version of the tooling employed, aiding in troubleshooting and ensuring compatibility with updates. | | `layout` | Defines the global plugins, e.g. a project `init` with `--plugins="go/v4,deploy-image/v1-alpha"` means that any sub-command used will always call its implementation for both plugins in a chain. | | `domain` | Store the domain of the project. This information can be provided by the user when the project is generate with the `init` sub-command and the `domain` flag. | | `plugins` | Defines the plugins used to do custom scaffolding, e.g. to use the optional `deploy-image/v1-alpha` plugin to do scaffolding for just a specific api via the command `kubebuider create api [options] --plugins=deploy-image/v1-alpha`. | diff --git a/pkg/cli/cli.go b/pkg/cli/cli.go index 5ae77febcc6..f6df95a60c3 100644 --- a/pkg/cli/cli.go +++ b/pkg/cli/cli.go @@ -47,8 +47,10 @@ type CLI struct { //nolint:maligned // Root command name. It is injected downstream to provide correct help, usage, examples and errors. commandName string - // CLI version string. + // Full CLI version string. version string + // CLI version string (just the CLI version number, no extra information). + cliVersion string // CLI root's command description. description string // Plugins registered in the CLI. diff --git a/pkg/cli/cmd_helpers.go b/pkg/cli/cmd_helpers.go index 144683accc1..fb20ac99510 100644 --- a/pkg/cli/cmd_helpers.go +++ b/pkg/cli/cmd_helpers.go @@ -128,6 +128,7 @@ func (c *CLI) applySubcommandHooks( errorMessage: errorMessage, projectVersion: c.projectVersion, pluginChain: pluginChain, + cliVersion: c.cliVersion, } cmd.PreRunE = factory.preRunEFunc(options, createConfig) cmd.RunE = factory.runEFunc() @@ -189,6 +190,8 @@ type executionHooksFactory struct { projectVersion config.Version // pluginChain is the plugin chain configured for this project. pluginChain []string + // cliVersion is the version of the CLI. + cliVersion string } func (factory *executionHooksFactory) forEach(cb func(subcommand plugin.Subcommand) error, errorMessage string) error { @@ -244,6 +247,11 @@ func (factory *executionHooksFactory) preRunEFunc( } cfg := factory.store.Config() + // Set the CLI version if creating a new project configuration. + if createConfig { + _ = cfg.SetCliVersion(factory.cliVersion) + } + // Set the pluginChain field. if len(factory.pluginChain) != 0 { _ = cfg.SetPluginChain(factory.pluginChain) diff --git a/pkg/cli/options.go b/pkg/cli/options.go index 208b1c748da..b76ce5ee3fd 100644 --- a/pkg/cli/options.go +++ b/pkg/cli/options.go @@ -57,6 +57,14 @@ func WithVersion(version string) Option { } } +// WithCliVersion is an Option that defines only the version string of the CLI (no extra info). +func WithCliVersion(version string) Option { + return func(c *CLI) error { + c.cliVersion = version + return nil + } +} + // WithDescription is an Option that sets the CLI's root description. func WithDescription(description string) Option { return func(c *CLI) error { diff --git a/pkg/config/interface.go b/pkg/config/interface.go index 1eb9ac949a9..b97a52417a4 100644 --- a/pkg/config/interface.go +++ b/pkg/config/interface.go @@ -27,6 +27,12 @@ type Config interface { // GetVersion returns the current project version. GetVersion() Version + // GetCliVersion returns the CLI binary version that was used to scaffold or initialize the project. + GetCliVersion() string + + // SetCliVersion sets the binary version used to initialize the project. + SetCliVersion(version string) error + /* String fields */ // GetDomain returns the project domain. diff --git a/pkg/config/v3/config.go b/pkg/config/v3/config.go index c6b03f5a0e3..5a55fc829de 100644 --- a/pkg/config/v3/config.go +++ b/pkg/config/v3/config.go @@ -61,6 +61,7 @@ type Cfg struct { Domain string `json:"domain,omitempty"` Repository string `json:"repo,omitempty"` Name string `json:"projectName,omitempty"` + CliVersion string `json:"cliVersion,omitempty"` PluginChain stringSlice `json:"layout,omitempty"` // Boolean fields @@ -93,6 +94,17 @@ func (c Cfg) GetVersion() config.Version { return c.Version } +// GetCliVersion implements config.Config +func (c Cfg) GetCliVersion() string { + return c.CliVersion +} + +// SetCliVersion implements config.Config +func (c *Cfg) SetCliVersion(version string) error { + c.CliVersion = version + return nil +} + // GetDomain implements config.Config func (c Cfg) GetDomain() string { return c.Domain diff --git a/testdata/project-v4-multigroup/PROJECT b/testdata/project-v4-multigroup/PROJECT index 1ad41336592..5823f59befb 100644 --- a/testdata/project-v4-multigroup/PROJECT +++ b/testdata/project-v4-multigroup/PROJECT @@ -2,6 +2,7 @@ # This file is used to track the info used to scaffold your project # and allow the plugins properly work. # More info: https://book.kubebuilder.io/reference/project-config.html +cliVersion: (devel) domain: testproject.org layout: - go.kubebuilder.io/v4 diff --git a/testdata/project-v4-with-plugins/PROJECT b/testdata/project-v4-with-plugins/PROJECT index 48f67097c0a..dc0cdc93ce6 100644 --- a/testdata/project-v4-with-plugins/PROJECT +++ b/testdata/project-v4-with-plugins/PROJECT @@ -2,6 +2,7 @@ # This file is used to track the info used to scaffold your project # and allow the plugins properly work. # More info: https://book.kubebuilder.io/reference/project-config.html +cliVersion: (devel) domain: testproject.org layout: - go.kubebuilder.io/v4 diff --git a/testdata/project-v4/PROJECT b/testdata/project-v4/PROJECT index dee611b980b..608fd538064 100644 --- a/testdata/project-v4/PROJECT +++ b/testdata/project-v4/PROJECT @@ -2,6 +2,7 @@ # This file is used to track the info used to scaffold your project # and allow the plugins properly work. # More info: https://book.kubebuilder.io/reference/project-config.html +cliVersion: (devel) domain: testproject.org layout: - go.kubebuilder.io/v4