New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add ability to mark flags as required or exclusive as a group #1654
Conversation
This PR exceeds the recommended size of 200 lines. Please make sure you are NOT addressing multiple issues with one PR. Note this PR might be rejected due to its size. |
When doing the review of the backlog this feature came up a few times and I have personally wanted to do this as well in my other projects so I thought I would put something up. I utilize the flag annotations which up to this point had just been used for shell completions. This doesn't interact with the shell completions at all but is just validation logic. I don't know if that is a hard stop for someone, but I thought I'd put this up and see. I'll have to lookup the issues that this would impact (don't have them handy right now) but wanted it put up for 👀 . There is surely some cleanup that could occur as well, feel free to comment. I just wanted to make sure it had functioning logic and tests to make it clear how it looked in its current state. |
This PR exceeds the recommended size of 200 lines. Please make sure you are NOT addressing multiple issues with one PR. Note this PR might be rejected due to its size. |
This PR exceeds the recommended size of 200 lines. Please make sure you are NOT addressing multiple issues with one PR. Note this PR might be rejected due to its size. |
The 200 line "suggested max" is exceeded but it includes tests and a new file (so a new file/license header). Regardless, I also think there is a bit of code I can compact. |
This PR exceeds the recommended size of 200 lines. Please make sure you are NOT addressing multiple issues with one PR. Note this PR might be rejected due to its size. |
Pulling some common code out caused some reduction in LOC but then continuing to extract logic into functions for easier reading caused some increase. Not worrying about the LOC unless others think it is a problem. I think the new arrangement of code is easier to understand. |
flag_groups.go
Outdated
RequiredAsGroup = "cobra_annotation_required_if_others_set" | ||
MutuallyExclusive = "cobra_annotation_mutually_exclusive" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
2 new annotations. No utilization for completion, but only for validation.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I like that. I think it is just fine to use the annotations field of a flag for anything we need (even if there are pflag comments saying Annotations are used for completions...)
However, do we need them public? Based on the proposed solution, I don't expect users to access the annotation directly, right?
flag_groups.go
Outdated
continue | ||
} | ||
sort.Strings(unset) | ||
errs = append(errs, fmt.Errorf("if any flags in the group [%v] are set they must all be set; missing %v", flagList, unset)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Definitely open to verbage changes if someone wants to suggest anything. Pointing out the first [%v]
I manually add the brackets since the flagList is just a string even though it is of the form flagA flagB flagC
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The wording seems ok to me. I'm just a little unsure about the format when multiple errors are concatenated together. For example:
./prog child --automatic yes --destination a --fast-deploy fish --effective a <k8s-lab>
Error: if any flags in the group [automatic best certificate] are set they must all be set; missing [best certificate], if any flags in the group [destination fast-deploy] are set none of the others can be; [destination fast-deploy] were all set
Usage:
prog child [flags]
Flags:
[..]
Should the error messages be separated by a newline character?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A newline would work for me; I also didnt like the format but tried to follow the general Go guidance of not using capital letters or ending punctuation.
So you'd prefer something like :
Error: if any flags in the group [automatic best certificate] are set they must all be set; missing [best certificate]
if any flags in the group [destination fast-deploy] are set none of the others can be; [destination fast-deploy] were all set
Usage:...
I could also try and make it so that it makes it like a bulleted list? They are long errors so it doesnt flow particularly great if you have multiples:
Error:
- if any flags in the group [automatic best certificate] are set they must all be set; missing [best certificate]
- if any flags in the group [destination fast-deploy] are set none of the others can be; [destination fast-deploy] were all set
Usage:...
I think the latter looks the best for and end user on the CLI and is just a tiny bit more verbose to implement. What do you think?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why do you have to return all errors? The normal flag parsing code only returns the first error it encounters. This should simplify the code and make the errors smaller and thus better readable.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why do you have to return all errors? The normal flag parsing code only returns the first error it encounters. This should simplify the code and make the errors smaller and thus better readable.
I guess it was to avoid a user having to fix one error at a time, if there were multiple errors?
I see value in both approaches personally, so I'll defer to what you guys settle on.
That being said, the current code is missing the first newline when there are multiple errors:
Error: - if any flags in the group [automatic best certificate] are set they must all be set; missing [best certificate]
- if any flags in the group [destination fast-deploy] are set none of the others can be; [destination fast-deploy] were all set
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm definitely fine with the simplification. Not sure why I defaulted to that originally, I sometimes use both. Making the simplification avoids that problem all together and since its just at invocation time and feedback is fast I dont think its a problem if they have to tweak it a few times and keep finding 'new' problems.
Nice improvement @johnSchnake! I'm interested in having a more detailed look soon. |
What should we do about persistent flags for this feature? Can they be part of groups for example? |
Thanks for the call on persistent flags. I'll double check how they're handled. I know there were some other existing issues about them not getting merged in certain validations. My assumption should be merged prior to this and valid for use with this feature. I'll make sure tests cover that. |
This PR exceeds the recommended size of 200 lines. Please make sure you are NOT addressing multiple issues with one PR. Note this PR might be rejected due to its size. |
This PR exceeds the recommended size of 200 lines. Please make sure you are NOT addressing multiple issues with one PR. Note this PR might be rejected due to its size. |
1 similar comment
This PR exceeds the recommended size of 200 lines. Please make sure you are NOT addressing multiple issues with one PR. Note this PR might be rejected due to its size. |
Updated docs so that didnt slow things down later if this gets 👍 |
Not a proper review but we should try to add the mutually exclusive logic to the shell completion logic, i. e. |
@Luap99 I have no idea regarding shell completions. Could that potentially go in a as a separate PR from someone who has context on that? That seems reasonable to me since it isn't obvious that devs with 1 piece of context will have the other and shell completion is just a convenience feature and not something necessary for the functionality. I have no problem creating an issue to track it as I've pointed out that shortcoming myself too. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is pretty cool! I think it is a nice improvement for our users. Nice job @johnSchnake .
I've added some suggestions in-line for your consideration.
I'll have a look at the completion logic in the mean time.
flag_groups.go
Outdated
RequiredAsGroup = "cobra_annotation_required_if_others_set" | ||
MutuallyExclusive = "cobra_annotation_mutually_exclusive" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I like that. I think it is just fine to use the annotations field of a flag for anything we need (even if there are pflag comments saying Annotations are used for completions...)
However, do we need them public? Based on the proposed solution, I don't expect users to access the annotation directly, right?
flag_groups.go
Outdated
continue | ||
} | ||
sort.Strings(unset) | ||
errs = append(errs, fmt.Errorf("if any flags in the group [%v] are set they must all be set; missing %v", flagList, unset)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The wording seems ok to me. I'm just a little unsure about the format when multiple errors are concatenated together. For example:
./prog child --automatic yes --destination a --fast-deploy fish --effective a <k8s-lab>
Error: if any flags in the group [automatic best certificate] are set they must all be set; missing [best certificate], if any flags in the group [destination fast-deploy] are set none of the others can be; [destination fast-deploy] were all set
Usage:
prog child [flags]
Flags:
[..]
Should the error messages be separated by a newline character?
This PR exceeds the recommended size of 200 lines. Please make sure you are NOT addressing multiple issues with one PR. Note this PR might be rejected due to its size. |
Creating an issue to track this would be great. Maybe I can find some time to work on this. |
I coded something last night but I didn't know how to share it. Sorry @Luap99 . |
This PR exceeds the recommended size of 200 lines. Please make sure you are NOT addressing multiple issues with one PR. Note this PR might be rejected due to its size. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is good for me once the linter and format errors are fixed.
This PR exceeds the recommended size of 200 lines. Please make sure you are NOT addressing multiple issues with one PR. Note this PR might be rejected due to its size. |
All green; going to squash down to 1 commit |
This PR exceeds the recommended size of 200 lines. Please make sure you are NOT addressing multiple issues with one PR. Note this PR might be rejected due to its size. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I was all ready to approve but I did one last testing pass and I hit something I hadn't noticed before.
Say I have a root command with a persistent --debug
flag, and a child command with a --details
flag. Then the child marks both flags as required together. I noticed that I can no longer call the root command with the --debug
flag as it requires the --details
flag, but that flag does not exist on the root.
Here's a test program:
package main
import (
"fmt"
"github.com/spf13/cobra"
)
var (
debug bool
details bool
)
var rootCmd = &cobra.Command{
Use: "prog",
Run: func(cmd *cobra.Command, args []string) {
fmt.Println("rootCmd called")
},
}
var logCmd = &cobra.Command{
Use: "log",
Run: func(cmd *cobra.Command, args []string) {
fmt.Println("child called")
},
}
func main() {
rootCmd.AddCommand(logCmd)
rootCmd.PersistentFlags().BoolVar(&debug, "debug", false, "debug")
logCmd.Flags().BoolVarP(&details, "details", "d", false, "details")
logCmd.MarkFlagsRequiredTogether("details", "debug")
rootCmd.Execute()
}
then I run this:
$ go build -o prog groupFlag.go
$ ./prog --debug
Error: if any flags in the group [details debug] are set they must all be set; missing [details]
[...]
# The root command wants the flag group although it was the child command that created it
$ ./prog --debug --details
Error: unknown flag: --details
[...]
It's hard for me to judge if this is a valid scenario, but it seems like it is plausible, no?
I haven't looked into the logic causing this.
That last test I ran made me think of a situation that is not covered by the PR. Maybe it's not important and we simply won't support it, I just wanted to mention it to get your opinion. Let's use an example to describe the use case. Say I have a Any thoughts on this @johnSchnake ? |
@marckhouzam that is an interesting use case. I do think thats a more narrow use-case so I don't mind leaving that off (users can still manually implement it as they would today); the only alternative would be to do one of two things it seems:
|
Sounds like a good approach to me. |
Is this still good to go or did I miss a separate concern? |
I think we have an inconsistency when dealing with persistent flags. I tried to describe it in the comment above: #1654 (review) Maybe we made thing overly complex by supporting persistent flags? If the feature does not really need to support them, I'd be ok with documenting that persistent flags should not be part of groups. It depends on how you imagine the feature being use @johnSchnake. |
My thoughts on this:
I lean towards modifying the code so that the entire flag group is ignored if not every flag is found. That seems to be the easiest mental model to understand, is easily written into the documentation, and still facilitates the the use case you showed. Documentation will just be updated to reflect something like:
|
This PR exceeds the recommended size of 200 lines. Please make sure you are NOT addressing multiple issues with one PR. Note this PR might be rejected due to its size. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice!
LGTM
@jpmcb are you ok with this new feature? If we don't hear from @jpmcb by Friday afternoon, and since both @johnSchnake and I approved, I suggest @johnSchnake go ahead and merge.
Just squashing preemptively. No other changes on this next push, just FYI |
This change adds two features for dealing with flags: - requiring flags be provided as a group (or not at all) - requiring flags be mutually exclusive of each other By utilizing the flag annotations we can mark which flag groups a flag is a part of and during the parsing process we track which ones we have seen or not. A flag may be a part of multiple groups. The list of flags and the type of group (required together or exclusive) make it a unique group. Signed-off-by: John Schnake <jschnake@vmware.com>
This PR exceeds the recommended size of 200 lines. Please make sure you are NOT addressing multiple issues with one PR. Note this PR might be rejected due to its size. |
[](https://renovatebot.com) This PR contains the following updates: | Package | Type | Update | Change | |---|---|---|---| | [github.com/golang-jwt/jwt/v4](https://togithub.com/golang-jwt/jwt) | require | patch | `v4.4.1` -> `v4.4.2` | | [github.com/spf13/cobra](https://togithub.com/spf13/cobra) | require | minor | `v1.4.0` -> `v1.5.0` | | [github.com/stretchr/testify](https://togithub.com/stretchr/testify) | require | patch | `v1.7.2` -> `v1.7.5` | --- ### Release Notes <details> <summary>golang-jwt/jwt</summary> ### [`v4.4.2`](https://togithub.com/golang-jwt/jwt/releases/tag/v4.4.2) [Compare Source](https://togithub.com/golang-jwt/jwt/compare/v4.4.1...v4.4.2) #### What's Changed - Added MicahParks/keyfunc to extensions by [@​oxisto](https://togithub.com/oxisto) in [golang-jwt/jwt#194 - Update link to v4 on pkg.go.dev page by [@​polRk](https://togithub.com/polRk) in [golang-jwt/jwt#195 - add installation guidelines to the README file by [@​morelmiles](https://togithub.com/morelmiles) in [golang-jwt/jwt#204 - chore: replace ioutil with io and os by [@​estensen](https://togithub.com/estensen) in [golang-jwt/jwt#198 - CI check for Go code formatting by [@​mfridman](https://togithub.com/mfridman) in [golang-jwt/jwt#206 - Create SECURITY.md by [@​mfridman](https://togithub.com/mfridman) in [golang-jwt/jwt#171 - Update SECURITY.md by [@​oxisto](https://togithub.com/oxisto) in [golang-jwt/jwt#207 - Fixed integer overflow in NumericDate.MarshalJSON by [@​qqiao](https://togithub.com/qqiao) in [golang-jwt/jwt#200 - Claims in rsa_test.go Table Driven Test are Unused by [@​gkech](https://togithub.com/gkech) in [golang-jwt/jwt#212 #### New Contributors - [@​polRk](https://togithub.com/polRk) made their first contribution in [golang-jwt/jwt#195 - [@​morelmiles](https://togithub.com/morelmiles) made their first contribution in [golang-jwt/jwt#204 - [@​estensen](https://togithub.com/estensen) made their first contribution in [golang-jwt/jwt#198 - [@​qqiao](https://togithub.com/qqiao) made their first contribution in [golang-jwt/jwt#200 - [@​gkech](https://togithub.com/gkech) made their first contribution in [golang-jwt/jwt#212 **Full Changelog**: golang-jwt/jwt@v4.4.1...v4.4.2 </details> <details> <summary>spf13/cobra</summary> ### [`v1.5.0`](https://togithub.com/spf13/cobra/releases/tag/v1.5.0) [Compare Source](https://togithub.com/spf13/cobra/compare/v1.4.0...v1.5.0) #### Spring 2022 Release 🌥️ Hello everyone! Welcome to another release of cobra. Completions continue to get better and better. This release adds a few really cool new features. We also continue to patch versions of our dependencies as they become available via dependabot. Happy coding! #### Active help 👐🏼 Shout out to [@​marckhouzam](https://togithub.com/marckhouzam) for a big value add: Active Help [spf13/cobra#1482. With active help, a program can provide some inline warnings or hints for users as they hit tab. Now, your CLIs can be even more intuitive to use! Currently active help is only supported for bash V2 and zsh. Marc wrote a whole guide on how to do this, so make sure to give it a good read to learn how you can add this to your cobra code! https://github.com/spf13/cobra/blob/master/active_help.md #### Group flags 🧑🏼🤝🧑🏼 Cobra now has the ability to mark flags as required or exclusive as a ***group***. Shout out to our newest maintainer [@​johnSchnake](https://togithub.com/johnSchnake) for this! [spf13/cobra#1654 Let's say you have a `username` flag that ***MUST*** be partnered with a `password` flag. Well, now, you can enforce those as being required together: ```go rootCmd.Flags().StringVarP(&u, "username", "u", "", "Username (required if password is set)") rootCmd.Flags().StringVarP(&pw, "password", "p", "", "Password (required if username is set)") rootCmd.MarkFlagsRequiredTogether("username", "password") ``` Flags may also be marked as "mutally exclusive" with the `MarkFlagsMutuallyExclusive(string, string ... )` command API. Refer to our [user guide documentation](https://togithub.com/spf13/cobra/blob/master/user_guide.md) for further info! #### Completions 👀 - Add backwards-compatibility tests for legacyArgs() by [@​marckhouzam](https://togithub.com/marckhouzam) in [spf13/cobra#1547 - feat: Add how to load completions in your current zsh session by [@​ondrejsika](https://togithub.com/ondrejsika) in [spf13/cobra#1608 - Introduce FixedCompletions by [@​emersion](https://togithub.com/emersion) in [spf13/cobra#1574 - Add shell completion to flag groups by [@​marckhouzam](https://togithub.com/marckhouzam) in [spf13/cobra#1659 - Modify brew prefix path in macOS system by [@​imxw](https://togithub.com/imxw) in [spf13/cobra#1719 - perf(bash-v2): use backslash escape string expansion for tab by [@​scop](https://togithub.com/scop) in [spf13/cobra#1682 - style(bash-v2): out is not an array variable, do not refer to it as such by [@​scop](https://togithub.com/scop) in [spf13/cobra#1681 - perf(bash-v2): standard completion optimizations by [@​scop](https://togithub.com/scop) in [spf13/cobra#1683 - style(bash): out is not an array variable, do not refer to it as such by [@​scop](https://togithub.com/scop) in [spf13/cobra#1684 - perf(bash-v2): short-circuit descriptionless candidate lists by [@​scop](https://togithub.com/scop) in [spf13/cobra#1686 - perf(bash-v2): speed up filtering entries with descriptions by [@​scop](https://togithub.com/scop) in [spf13/cobra#1689 - perf(bash-v2): speed up filtering menu-complete descriptions by [@​scop](https://togithub.com/scop) in [spf13/cobra#1692 - fix(bash-v2): skip empty completions when filtering descriptions by [@​scop](https://togithub.com/scop) in [spf13/cobra#1691 - perf(bash-v2): read directly to COMPREPLY on descriptionless short circuit by [@​scop](https://togithub.com/scop) in [spf13/cobra#1700 - fix: Don't complete \_command on zsh by [@​twpayne](https://togithub.com/twpayne) in [spf13/cobra#1690 - Improve fish_completions code quality by [@​t29kida](https://togithub.com/t29kida) in [spf13/cobra#1515 - Fix handling of descriptions for bash v3 by [@​marckhouzam](https://togithub.com/marckhouzam) in [spf13/cobra#1735 - undefined or nil Args default to ArbitraryArgs by [@​umarcor](https://togithub.com/umarcor) in [spf13/cobra#1612 - Add Command.SetContext by [@​joshcarp](https://togithub.com/joshcarp) in [spf13/cobra#1551 - Wrap printf tab with quotes by [@​PapaCharlie](https://togithub.com/PapaCharlie) in [spf13/cobra#1665 #### Documentation 📝 - Fixed typos in completions docs - [@​cuishuang](https://togithub.com/cuishuang) [spf13/cobra#1625 - Removed `CHANGELOG.md` as it isn't updated - [@​johnSchnake](https://togithub.com/johnSchnake) [spf13/cobra#1634 - Minor typo fix in `shell_completion.md` - [@​danieldn](https://togithub.com/danieldn) [spf13/cobra#1678 - Changed branch name in the cobra generator link to 'main' - [@​skywalker2909](https://togithub.com/skywalker2909) [spf13/cobra#1645 - Fix Command.Context comment by [@​katexochen](https://togithub.com/katexochen) in [spf13/cobra#1639 - Change appropriate links from http:// to https:// where applicable - [@​deining](https://togithub.com/deining) [spf13/cobra#1695 #### Testing & CI ⚙️ - Test on Golang 1.18 - [@​umarcor](https://togithub.com/umarcor) [spf13/cobra#1635 - Use `RICHGO_FORCE_COLOR` - [@​umarcor](https://togithub.com/umarcor) [spf13/cobra#1647 - Adds size labeler GitHub action by [@​jpmcb](https://togithub.com/jpmcb) in [spf13/cobra#1610 - Update `stale-bot` settings - [@​jpmcb](https://togithub.com/jpmcb) [spf13/cobra#1609 #### Beep boop, bot commits 🤖 - Bumped golangci/golangci-lint-action from 3.1.0 to 3.2.0 - [@​dependabot](https://togithub.com/dependabot) [spf13/cobra#1697 - Bump codelytv/pr-size-labeler from 1.8.0 to 1.8.1 - [@​dependabot](https://togithub.com/dependabot) [spf13/cobra#1661 - Bump actions/stale from 1 to 5 by [@​dependabot](https://togithub.com/dependabot) in [spf13/cobra#1618 - Bump actions/cache from 2 to 3 by [@​dependabot](https://togithub.com/dependabot) in [spf13/cobra#1640 - Bump actions/labeler from 3 to 4 by [@​dependabot](https://togithub.com/dependabot) in [spf13/cobra#1620 - Bump golangci/golangci-lint-action from 2 to 3.1.0 by [@​dependabot](https://togithub.com/dependabot) in [spf13/cobra#1615 - Bump actions/checkout from 2 to 3 by [@​dependabot](https://togithub.com/dependabot) in [spf13/cobra#1619 - Bump github.com/cpuguy83/go-md2man/v2 from 2.0.1 to 2.0.2 by [@​dependabot](https://togithub.com/dependabot) in [spf13/cobra#1688 - Bump actions/setup-go from 2 to 3 by [@​dependabot](https://togithub.com/dependabot) in [spf13/cobra#1660 #### Misc 💭 - Use `errors.Is()` to check for errors - [@​Luap99](https://togithub.com/Luap99) [spf13/cobra#1730 - Prefer ReplaceAll instead of Replace(..., -1) by [@​WhyNotHugo](https://togithub.com/WhyNotHugo) in [spf13/cobra#1530 - Add Kubescape to projects - [@​avinashupadhya99](https://togithub.com/avinashupadhya99) [spf13/cobra#1642 - Add Pulumi as a project using cobra by [@​iwahbe](https://togithub.com/iwahbe) in [spf13/cobra#1720 - Add Polygon Edge as a project using Cobra by [@​zivkovicmilos](https://togithub.com/zivkovicmilos) in [spf13/cobra#1672 Shoutout to *ALL* our contributors (and all the new first time contributors!!) - great work everyone!! Cobra and it's huge impact wouldn't be possible without you 👏🏼 🚀 🐍 **Full Changelog**: spf13/cobra@v1.4.0...v1.5.0 </details> <details> <summary>stretchr/testify</summary> ### [`v1.7.5`](https://togithub.com/stretchr/testify/compare/v1.7.4...v1.7.5) [Compare Source](https://togithub.com/stretchr/testify/compare/v1.7.4...v1.7.5) ### [`v1.7.4`](https://togithub.com/stretchr/testify/compare/v1.7.3...v1.7.4) [Compare Source](https://togithub.com/stretchr/testify/compare/v1.7.3...v1.7.4) ### [`v1.7.3`](https://togithub.com/stretchr/testify/compare/v1.7.2...v1.7.3) [Compare Source](https://togithub.com/stretchr/testify/compare/v1.7.2...v1.7.3) </details> --- ### Configuration 📅 **Schedule**: Branch creation - "before 5am on Thursday" in timezone America/New_York, Automerge - At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 👻 **Immortal**: This PR will be recreated if closed unmerged. Get [config help](https://togithub.com/renovatebot/renovate/discussions) if that's undesired. --- - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, click this checkbox.
[](https://renovatebot.com) This PR contains the following updates: | Package | Type | Update | Change | |---|---|---|---| | [github.com/spf13/cobra](https://togithub.com/spf13/cobra) | require | minor | `v1.4.0` -> `v1.5.0` | --- ### Release Notes <details> <summary>spf13/cobra</summary> ### [`v1.5.0`](https://togithub.com/spf13/cobra/releases/tag/v1.5.0) [Compare Source](https://togithub.com/spf13/cobra/compare/v1.4.0...v1.5.0) #### Spring 2022 Release 🌥️ Hello everyone! Welcome to another release of cobra. Completions continue to get better and better. This release adds a few really cool new features. We also continue to patch versions of our dependencies as they become available via dependabot. Happy coding! #### Active help 👐🏼 Shout out to [@​marckhouzam](https://togithub.com/marckhouzam) for a big value add: Active Help [spf13/cobra#1482. With active help, a program can provide some inline warnings or hints for users as they hit tab. Now, your CLIs can be even more intuitive to use! Currently active help is only supported for bash V2 and zsh. Marc wrote a whole guide on how to do this, so make sure to give it a good read to learn how you can add this to your cobra code! https://github.com/spf13/cobra/blob/master/active_help.md #### Group flags 🧑🏼🤝🧑🏼 Cobra now has the ability to mark flags as required or exclusive as a ***group***. Shout out to our newest maintainer [@​johnSchnake](https://togithub.com/johnSchnake) for this! [spf13/cobra#1654 Let's say you have a `username` flag that ***MUST*** be partnered with a `password` flag. Well, now, you can enforce those as being required together: ```go rootCmd.Flags().StringVarP(&u, "username", "u", "", "Username (required if password is set)") rootCmd.Flags().StringVarP(&pw, "password", "p", "", "Password (required if username is set)") rootCmd.MarkFlagsRequiredTogether("username", "password") ``` Flags may also be marked as "mutally exclusive" with the `MarkFlagsMutuallyExclusive(string, string ... )` command API. Refer to our [user guide documentation](https://togithub.com/spf13/cobra/blob/master/user_guide.md) for further info! #### Completions 👀 - Add backwards-compatibility tests for legacyArgs() by [@​marckhouzam](https://togithub.com/marckhouzam) in [spf13/cobra#1547 - feat: Add how to load completions in your current zsh session by [@​ondrejsika](https://togithub.com/ondrejsika) in [spf13/cobra#1608 - Introduce FixedCompletions by [@​emersion](https://togithub.com/emersion) in [spf13/cobra#1574 - Add shell completion to flag groups by [@​marckhouzam](https://togithub.com/marckhouzam) in [spf13/cobra#1659 - Modify brew prefix path in macOS system by [@​imxw](https://togithub.com/imxw) in [spf13/cobra#1719 - perf(bash-v2): use backslash escape string expansion for tab by [@​scop](https://togithub.com/scop) in [spf13/cobra#1682 - style(bash-v2): out is not an array variable, do not refer to it as such by [@​scop](https://togithub.com/scop) in [spf13/cobra#1681 - perf(bash-v2): standard completion optimizations by [@​scop](https://togithub.com/scop) in [spf13/cobra#1683 - style(bash): out is not an array variable, do not refer to it as such by [@​scop](https://togithub.com/scop) in [spf13/cobra#1684 - perf(bash-v2): short-circuit descriptionless candidate lists by [@​scop](https://togithub.com/scop) in [spf13/cobra#1686 - perf(bash-v2): speed up filtering entries with descriptions by [@​scop](https://togithub.com/scop) in [spf13/cobra#1689 - perf(bash-v2): speed up filtering menu-complete descriptions by [@​scop](https://togithub.com/scop) in [spf13/cobra#1692 - fix(bash-v2): skip empty completions when filtering descriptions by [@​scop](https://togithub.com/scop) in [spf13/cobra#1691 - perf(bash-v2): read directly to COMPREPLY on descriptionless short circuit by [@​scop](https://togithub.com/scop) in [spf13/cobra#1700 - fix: Don't complete \_command on zsh by [@​twpayne](https://togithub.com/twpayne) in [spf13/cobra#1690 - Improve fish_completions code quality by [@​t29kida](https://togithub.com/t29kida) in [spf13/cobra#1515 - Fix handling of descriptions for bash v3 by [@​marckhouzam](https://togithub.com/marckhouzam) in [spf13/cobra#1735 - undefined or nil Args default to ArbitraryArgs by [@​umarcor](https://togithub.com/umarcor) in [spf13/cobra#1612 - Add Command.SetContext by [@​joshcarp](https://togithub.com/joshcarp) in [spf13/cobra#1551 - Wrap printf tab with quotes by [@​PapaCharlie](https://togithub.com/PapaCharlie) in [spf13/cobra#1665 #### Documentation 📝 - Fixed typos in completions docs - [@​cuishuang](https://togithub.com/cuishuang) [spf13/cobra#1625 - Removed `CHANGELOG.md` as it isn't updated - [@​johnSchnake](https://togithub.com/johnSchnake) [spf13/cobra#1634 - Minor typo fix in `shell_completion.md` - [@​danieldn](https://togithub.com/danieldn) [spf13/cobra#1678 - Changed branch name in the cobra generator link to 'main' - [@​skywalker2909](https://togithub.com/skywalker2909) [spf13/cobra#1645 - Fix Command.Context comment by [@​katexochen](https://togithub.com/katexochen) in [spf13/cobra#1639 - Change appropriate links from http:// to https:// where applicable - [@​deining](https://togithub.com/deining) [spf13/cobra#1695 #### Testing & CI ⚙️ - Test on Golang 1.18 - [@​umarcor](https://togithub.com/umarcor) [spf13/cobra#1635 - Use `RICHGO_FORCE_COLOR` - [@​umarcor](https://togithub.com/umarcor) [spf13/cobra#1647 - Adds size labeler GitHub action by [@​jpmcb](https://togithub.com/jpmcb) in [spf13/cobra#1610 - Update `stale-bot` settings - [@​jpmcb](https://togithub.com/jpmcb) [spf13/cobra#1609 #### Beep boop, bot commits 🤖 - Bumped golangci/golangci-lint-action from 3.1.0 to 3.2.0 - [@​dependabot](https://togithub.com/dependabot) [spf13/cobra#1697 - Bump codelytv/pr-size-labeler from 1.8.0 to 1.8.1 - [@​dependabot](https://togithub.com/dependabot) [spf13/cobra#1661 - Bump actions/stale from 1 to 5 by [@​dependabot](https://togithub.com/dependabot) in [spf13/cobra#1618 - Bump actions/cache from 2 to 3 by [@​dependabot](https://togithub.com/dependabot) in [spf13/cobra#1640 - Bump actions/labeler from 3 to 4 by [@​dependabot](https://togithub.com/dependabot) in [spf13/cobra#1620 - Bump golangci/golangci-lint-action from 2 to 3.1.0 by [@​dependabot](https://togithub.com/dependabot) in [spf13/cobra#1615 - Bump actions/checkout from 2 to 3 by [@​dependabot](https://togithub.com/dependabot) in [spf13/cobra#1619 - Bump github.com/cpuguy83/go-md2man/v2 from 2.0.1 to 2.0.2 by [@​dependabot](https://togithub.com/dependabot) in [spf13/cobra#1688 - Bump actions/setup-go from 2 to 3 by [@​dependabot](https://togithub.com/dependabot) in [spf13/cobra#1660 #### Misc 💭 - Use `errors.Is()` to check for errors - [@​Luap99](https://togithub.com/Luap99) [spf13/cobra#1730 - Prefer ReplaceAll instead of Replace(..., -1) by [@​WhyNotHugo](https://togithub.com/WhyNotHugo) in [spf13/cobra#1530 - Add Kubescape to projects - [@​avinashupadhya99](https://togithub.com/avinashupadhya99) [spf13/cobra#1642 - Add Pulumi as a project using cobra by [@​iwahbe](https://togithub.com/iwahbe) in [spf13/cobra#1720 - Add Polygon Edge as a project using Cobra by [@​zivkovicmilos](https://togithub.com/zivkovicmilos) in [spf13/cobra#1672 Shoutout to *ALL* our contributors (and all the new first time contributors!!) - great work everyone!! Cobra and it's huge impact wouldn't be possible without you 👏🏼 🚀 🐍 **Full Changelog**: spf13/cobra@v1.4.0...v1.5.0 </details> --- ### Configuration 📅 **Schedule**: Branch creation - At any time (no schedule defined), Automerge - At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR is behind base branch, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, click this checkbox. --- This PR has been generated by [Mend Renovate](https://www.mend.io/free-developer-tools/renovate/). View repository job log [here](https://app.renovatebot.com/dashboard#github/googleapis/gapic-showcase).
Also fixes #1385 |
This change adds two features for dealing with flags:
By utilizing the flag annotations we can mark which flag groups
a flag is a part of and during the parsing process we track which
ones we have seen or not.
A flag may be a part of multiple groups. The list of flags and the
type of group (required together or exclusive) make it a unique group.
Fixes #1654
Fixes #1595
Fixes #1238
Signed-off-by: John Schnake jschnake@vmware.com