Skip to content

✨ feat(CLI): Add completion for the plugins flag#5596

Open
vitorfloriano wants to merge 1 commit intokubernetes-sigs:masterfrom
vitorfloriano:dynamic-completion-for-plugins-flag
Open

✨ feat(CLI): Add completion for the plugins flag#5596
vitorfloriano wants to merge 1 commit intokubernetes-sigs:masterfrom
vitorfloriano:dynamic-completion-for-plugins-flag

Conversation

@vitorfloriano
Copy link
Copy Markdown
Contributor

@vitorfloriano vitorfloriano commented Apr 9, 2026

This PR adds dynamic flag completion for the --plugins flag.

The --plugins flag now shows completion for all the available plugins (external ones too, including out-of-tree! 🎉), while hiding deprecated ones.

$ kubebuilder init --plugins 
autoupdate.kubebuilder.io/v1-alpha       (Proposes Kubebuilder scaffold updates via GitHub Actions)
base.go.kubebuilder.io/v4                (Default scaffold (go/v4 + kustomize/v2))
deploy-image.go.kubebuilder.io/v1-alpha  (Scaffolds a CRD+controller to deploy an image-based Operand)
foo.acme.io/v2                           (External or custom plugin)
go.kubebuilder.io/v4                     (Default scaffold (go/v4 + kustomize/v2))
grafana.kubebuilder.io/v1-alpha          (Generates Grafana Dashboards for metrics)
helm.kubebuilder.io/v2-alpha             (Generates a Helm chart for project distribution)
kustomize.common.kubebuilder.io/v2       (Scaffolds base Kustomize configuration)

This will improve plugin discoverability and usage, especially for the autoupdate plugin.

Relates to #5446 and #5291

Note

Completion does not work for comma-chained values, so users will either use another instance of --plugins to get completion or type everything (or copy-paste) the keys after a comma:

Works (multiple instances of the flag):

$ kubebuilder init --plugins=foo.acme.io/v2 --plugins autoupdate.kubebuilder.io/v1-alpha --plugins base.go.kubebuilder.io/v4 --plugins helm.kubebuilder.io/v2-alpha --plugins 
deploy-image.go.kubebuilder.io/v1-alpha  (Scaffolds a CRD+controller to deploy an image-based Operand)
go.kubebuilder.io/v4                     (Default scaffold (go/v4 + kustomize/v2))
grafana.kubebuilder.io/v1-alpha          (Generates Grafana Dashboards for metrics)
kustomize.common.kubebuilder.io/v2       (Scaffolds base Kustomize configuration)

Does not work (trailing comma):

$ kubebuilder init --plugins foo.acme.io/v2,<TAB><TAB><TAB furiously>
(nothing happens)
$ kubebuilder init --plugins=foo.acme.io/v2,<TAB><TAB><TAB furiously>
(nothing happens)

This is a known limitation in Cobra. There are workarounds but they look a bit of a kludge.

@k8s-ci-robot k8s-ci-robot added the cncf-cla: yes Indicates the PR's author has signed the CNCF CLA. label Apr 9, 2026
@k8s-ci-robot
Copy link
Copy Markdown
Contributor

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by: vitorfloriano
Once this PR has been reviewed and has the lgtm label, please assign varshaprasad96 for approval. For more information see the Code Review Process.

The full list of commands accepted by this bot can be found here.

Details Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@k8s-ci-robot k8s-ci-robot added the size/M Denotes a PR that changes 30-99 lines, ignoring generated files. label Apr 9, 2026
@vitorfloriano vitorfloriano changed the title feat(cli): add completion for the plugins flag ✨ feat(CLI): Add completion for the plugins flag Apr 9, 2026
@vitorfloriano vitorfloriano force-pushed the dynamic-completion-for-plugins-flag branch 3 times, most recently from c6c1805 to d9b9d71 Compare April 9, 2026 18:00
Comment thread docs/book/src/plugins/plugins.md Outdated
> [!TIP]
> To take advantage of tab completion, pass one plugin key at a time to multiple instances of the plugins flag:
> ```
> kubebuilder init --plugins pluginA --plugins pluginB --plugins pluginC
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The completion should work as it works the plugins
So, it should work well with --plugins=pluginA,pluginB,pluginB

Could we ensure that?
Also, do we really need this note here?
If yes, could we add the default style note instead [!TIP]?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could we ensure that?

I couldn't. 😅

I even opened a ticket with the Cobra folx to see if I could get some help, but their guidance was not enough (at least for me) to get this to work. See: spf13/cobra#2385

Other related issues: spf13/cobra#1963 and spf13/cobra#1981

Also, the solution the maintainer provided has been tried by other well-maintained CLIs, like gh (GitHub's CLI) and they also couldn't achieve the flag completion for comma-separated values. See: cli/cli#3628

So I believe it is indeed a shell/Cobra limitation.

If you find any Cobra-based CLIs that support completion after comma, please let me know and I'll take a look at their completion function.

Also, do we really need this note here?
If yes, could we add the default style note instead [!TIP]?

Yeah, I don't think that's really necessary. I'll remove that.

The --plugins flag now shows completion for
shows all the available plugins (external ones too!).
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds dynamic shell completion for the --plugins flag in the Kubebuilder CLI to improve plugin discoverability (including external/out-of-tree plugins) while omitting deprecated plugins.

Changes:

  • Registers a Cobra flag-completion function for the root --plugins persistent flag.
  • Implements completionPluginsFlag to suggest plugin keys with descriptions, filtering already-entered and deprecated plugins.
  • Adds a unit test covering suggested plugins and filtering behavior.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 3 comments.

File Description
pkg/cli/root.go Registers and implements --plugins dynamic completion logic.
pkg/cli/cli_test.go Adds a test for completionPluginsFlag behavior.

Comment thread pkg/cli/root.go
// in case the user chains the --plugins flag multiple times,
alreadyEntered, err := cmd.Flags().GetStringSlice(pluginsFlag)
if err != nil {
cobra.CheckErr(err)
Copy link

Copilot AI Apr 11, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In a completion callback, calling cobra.CheckErr on GetStringSlice error can terminate the completion run (os.Exit), which can break shell completion unexpectedly. Prefer returning (nil, cobra.ShellCompDirectiveError) or treating the error as “no already-entered values” instead of exiting.

Suggested change
cobra.CheckErr(err)
return nil, cobra.ShellCompDirectiveError

Copilot uses AI. Check for mistakes.
Comment thread pkg/cli/root.go
Comment on lines +274 to +275

for pluginKey, p := range c.plugins {
Copy link

Copilot AI Apr 11, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The completion list is built by ranging over a map, so the suggestion order will be non-deterministic between runs. For a stable UX (and deterministic tests if added later), collect keys and sort them before appending to comps.

Suggested change
for pluginKey, p := range c.plugins {
pluginKeys := make([]string, 0, len(c.plugins))
for pluginKey := range c.plugins {
pluginKeys = append(pluginKeys, pluginKey)
}
slices.Sort(pluginKeys)
for _, pluginKey := range pluginKeys {
p := c.plugins[pluginKey]

Copilot uses AI. Check for mistakes.
Comment thread pkg/cli/cli_test.go
k2 := plugin.KeyFor(p2)

c.cmd = c.newRootCmd()
c.cmd.Flags().StringSlice(pluginsFlag, []string{}, "test usage")
Copy link

Copilot AI Apr 11, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

newRootCmd() already defines --plugins as a PersistentFlag; re-declaring the same flag via c.cmd.Flags().StringSlice risks a duplicate-flag panic and also means the test may not be exercising the real persistent-flag behavior. Remove the extra StringSlice() call and just Set() the existing flag (or set it on PersistentFlags()).

Suggested change
c.cmd.Flags().StringSlice(pluginsFlag, []string{}, "test usage")

Copilot uses AI. Check for mistakes.
@k8s-ci-robot k8s-ci-robot added the needs-rebase Indicates a PR cannot be merged because it has merge conflicts with HEAD. label Apr 19, 2026
@k8s-ci-robot
Copy link
Copy Markdown
Contributor

PR needs rebase.

Details

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes-sigs/prow repository.

@k8s-ci-robot
Copy link
Copy Markdown
Contributor

@vitorfloriano: The following test failed, say /retest to rerun all failed tests or /retest-required to rerun all mandatory failed tests:

Test name Commit Details Required Rerun command
pull-kubebuilder-e2e-k8s-1-36-0 9eaff61 link true /test pull-kubebuilder-e2e-k8s-1-36-0

Full PR test history. Your PR dashboard. Please help us cut down on flakes by linking to an open issue when you hit one in your PR.

Details

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes-sigs/prow repository. I understand the commands that are listed here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

cncf-cla: yes Indicates the PR's author has signed the CNCF CLA. needs-rebase Indicates a PR cannot be merged because it has merge conflicts with HEAD. size/M Denotes a PR that changes 30-99 lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants