• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

kubernetes-sigs / kubebuilder / 21778493952

07 Feb 2026 10:13AM UTC coverage: 73.863% (-0.09%) from 73.954%
21778493952

Pull #5448

github

camilamacedo86
fix(CLI/API) prevent --help from being validated as plugin name

- Add PersistentPreRunE hook to detect help flags in plugin values
- Filter help flags before plugin validation
- Show plugin descriptions instead of project versions
- Use short plugin keys (go/v4 vs go.kubebuilder.io/v4)
- Filter plugins by subcommand (init/edit/create)
- Hide deprecated plugins from help output
- Add documentation links for each plugin
- Improve root help wording for better getting-started experience

Generate-by: Cursour/Claude
Pull Request #5448: 🐛 fix(CLI/API) prevent --help from being validated as plugin name

174 of 227 new or added lines in 15 files covered. (76.65%)

1 existing line in 1 file now uncovered.

6887 of 9324 relevant lines covered (73.86%)

43.55 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

88.89
/pkg/plugin/bundle.go
1
/*
2
Copyright 2022 The Kubernetes Authors.
3

4
Licensed under the Apache License, Version 2.0 (the "License");
5
you may not use this file except in compliance with the License.
6
You may obtain a copy of the License at
7

8
    http://www.apache.org/licenses/LICENSE-2.0
9

10
Unless required by applicable law or agreed to in writing, software
11
distributed under the License is distributed on an "AS IS" BASIS,
12
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
See the License for the specific language governing permissions and
14
limitations under the License.
15
*/
16

17
package plugin
18

19
import (
20
        "fmt"
21

22
        "sigs.k8s.io/kubebuilder/v4/pkg/config"
23
)
24

25
type bundle struct {
26
        name        string
27
        version     Version
28
        plugins     []Plugin
29
        description string
30

31
        supportedProjectVersions []config.Version
32
        deprecateWarning         string
33
}
34

35
// BundleOption define the options to create the bundle
36
type BundleOption func(*bundle)
37

38
// WithName allow set the name of the Bundle Plugin
39
func WithName(name string) BundleOption {
30✔
40
        return func(opts *bundle) {
60✔
41
                opts.name = name
30✔
42
        }
30✔
43
}
44

45
// WithVersion allow set the version of the Bundle Plugin
46
func WithVersion(version Version) BundleOption {
30✔
47
        return func(opts *bundle) {
60✔
48
                opts.version = version
30✔
49
        }
30✔
50
}
51

52
// WithPlugins allow set the plugins which will be used in the composition for the Bundle Plugin
53
func WithPlugins(plugins ...Plugin) BundleOption {
30✔
54
        return func(opts *bundle) {
60✔
55
                opts.plugins = plugins
30✔
56
        }
30✔
57
}
58

59
// WithDeprecationMessage allow set a deprecate message when needed
60
func WithDeprecationMessage(msg string) BundleOption {
14✔
61
        return func(opts *bundle) {
28✔
62
                opts.deprecateWarning = msg
14✔
63
        }
14✔
64
}
65

66
// WithDescription allows setting a description for the bundle
NEW
67
func WithDescription(desc string) BundleOption {
×
NEW
68
        return func(opts *bundle) {
×
NEW
69
                opts.description = desc
×
NEW
70
        }
×
71
}
72

73
// NewBundleWithOptions creates a new Bundle with the provided BundleOptions.
74
// The list of supported project versions is computed from the provided plugins in options.
75
func NewBundleWithOptions(opts ...BundleOption) (Bundle, error) {
30✔
76
        bundleOpts := bundle{}
30✔
77

30✔
78
        for _, opts := range opts {
134✔
79
                opts(&bundleOpts)
104✔
80
        }
104✔
81

82
        supportedProjectVersions := CommonSupportedProjectVersions(bundleOpts.plugins...)
30✔
83
        if len(supportedProjectVersions) == 0 {
38✔
84
                return nil, fmt.Errorf("in order to bundle plugins, they must all support at least one common project version")
8✔
85
        }
8✔
86

87
        // Plugins may be bundles themselves, so unbundle here
88
        // NOTE(Adirio): unbundling here ensures that Bundle.Plugin always returns a flat list of Plugins instead of also
89
        //               including Bundles, and therefore we don't have to use a recursive algorithm when resolving.
90
        allPlugins := make([]Plugin, 0, len(bundleOpts.plugins))
22✔
91
        for _, plugin := range bundleOpts.plugins {
66✔
92
                if pluginBundle, isBundle := plugin.(Bundle); isBundle {
46✔
93
                        allPlugins = append(allPlugins, pluginBundle.Plugins()...)
2✔
94
                } else {
44✔
95
                        allPlugins = append(allPlugins, plugin)
42✔
96
                }
42✔
97
        }
98

99
        return bundle{
22✔
100
                name:                     bundleOpts.name,
22✔
101
                version:                  bundleOpts.version,
22✔
102
                plugins:                  allPlugins,
22✔
103
                description:              bundleOpts.description,
22✔
104
                supportedProjectVersions: supportedProjectVersions,
22✔
105
                deprecateWarning:         bundleOpts.deprecateWarning,
22✔
106
        }, nil
22✔
107
}
108

109
// Name implements Plugin
110
func (b bundle) Name() string {
16✔
111
        return b.name
16✔
112
}
16✔
113

114
// Version implements Plugin
115
func (b bundle) Version() Version {
16✔
116
        return b.version
16✔
117
}
16✔
118

119
// SupportedProjectVersions implements Plugin
120
func (b bundle) SupportedProjectVersions() []config.Version {
18✔
121
        return b.supportedProjectVersions
18✔
122
}
18✔
123

124
// Plugins implements Bundle
125
func (b bundle) Plugins() []Plugin {
22✔
126
        return b.plugins
22✔
127
}
22✔
128

129
// Description implements Describable
NEW
130
func (b bundle) Description() string {
×
NEW
131
        return b.description
×
NEW
132
}
×
133

134
// DeprecationWarning return the warning message
135
func (b bundle) DeprecationWarning() string {
2✔
136
        return b.deprecateWarning
2✔
137
}
2✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc