Skip to content
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 PersistentPreRun to disable required flag for help and completion command #1992

Open
wants to merge 13 commits into
base: main
Choose a base branch
from

Conversation

JunNishimura
Copy link
Contributor

@JunNishimura JunNishimura commented Jul 9, 2023

Overview

Fixes #1918.

The auto-implemented subcommands (help and completion) did't work when MarkPersistentRequiredFlag() called on root command. So I set DisableFlagParsing true for HelpCommand and CompletionCommand (bash, zsh, fish, powershell) to avoid required flags validation.

I also added unit test to see if the code works as I expected.

Related Issue

@CLAassistant
Copy link

CLAassistant commented Jul 9, 2023

CLA assistant check
All committers have signed the CLA.

@marckhouzam
Copy link
Collaborator

marckhouzam commented Jul 9, 2023

Thanks @JunNishimura.

However this change causes a couple of regressions (that are apparently not tested).

  1. ./prog completion bash --no-descriptions no longer works, and the same for the other three shells
  2. ./prog completion bash -h no longer works, and the same for the other three shells
  3. ./prog help -h no longer works (it used to show a help for the help itself)

I don't think we can disable flag parsing on those commands. We have to find another approach.

You may be able to add a PersistentPreRun function to those two commands which would disable the annotation that marks a flag as required. Something like:

			PersistentPreRun: func(cmd *Command, args []string) {
				cmd.Flags().VisitAll(func(pflag *flag.Flag) {
					requiredAnnotation, found := pflag.Annotations[BashCompOneRequiredFlag]
					if found && requiredAnnotation[0] == "true" {
                                                  // Disable any persistent required flags for the help command
						pflag.Annotations[BashCompOneRequiredFlag] = []string{"false"}
					}
				})
			},

Copy link
Collaborator

@marckhouzam marckhouzam left a comment

Choose a reason for hiding this comment

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

See above comment

Disable any persistent required flags for the help command
disable any persistent required flags for the completion command
@JunNishimura
Copy link
Contributor Author

Thanks, @marckhouzam

Your point was right.
I didn't notice that my previous code caused some regressions.

And, I appreciate the alternative suggestions.
I implemented your suggestions in the code.

I would appreciate it if you check the commits again.

@JunNishimura JunNishimura changed the title Disable mark persistent required flag for help and completion command add PersistentPreRun to disable required flag for help and completion command Jul 10, 2023
@marckhouzam
Copy link
Collaborator

@JunNishimura This looks pretty good.
There is a subtle backwards-compatibility impact that we should probably protect against.
If you look at where the PersistentPreRun functions are called you will notice that if a command has a PersistentPreRun, the PersistentPreRun of its parent is not called:

cobra/command.go

Lines 913 to 923 in dcb405a

for p := c; p != nil; p = p.Parent() {
if p.PersistentPreRunE != nil {
if err := p.PersistentPreRunE(c, argWoFlags); err != nil {
return err
}
break
} else if p.PersistentPreRun != nil {
p.PersistentPreRun(c, argWoFlags)
break
}
}
)

So here is the scenario:

  1. a CLI tool using Cobra has defined a PersistentPreRun function on its root command which does something that should be done for every command (e.g., collect some statistics about which command is being called)
  2. this PR adds a PersistentPreRun on the sub-commands completion and help

Because of the new PersistentPreRun on completion and help, the root.PersistentPreRun will no longer be called for those two sub-commands. This is a change in behaviour and could affect projects.

I suggest that at the end of the two new PersistentPreRun functions, we actually call root.PersistentPreRun to get the original behaviour back.

Does that make sense?

@JunNishimura
Copy link
Contributor Author

JunNishimura commented Jul 13, 2023

Thanks, @marckhouzam

I understand the situation.
I'm so glad to know the algorithm of cobra thanks to your points.

I implemented to call root's PersistentPreRun in sub-command's (help and completion) PersistentPreRun.
I also added unit tests to the above implementation just in case.

I would appreciate it if you check the commits again.

@marckhouzam
Copy link
Collaborator

@JunNishimura The backwards-compatibility fix is a little more complicated. For example the root.PersistentPreRun could be nil, so we cannot blindly call it. Also, the root command may not use PersistentPreRun but instead PersistentPreRunE (notice the final E on the second one). So we should mimic what cobra does already to make this work properly. I'm thinking of something like this:

  if cmd.Root().PersistentPreRunE != nil {
      return cmd.Root().PersistentPreRunE(cmd, args)
  } else if cmd.Root().PersistentPreRun != nil {
      cmd.Root().PersistentPreRun(cmd, args)
  }
  return nil

To be able to propagate any error returned by cmd.Root().PersistentPreRunE you will probably have to use PersistentPreRunE for the help and completion commands.

Let me know if you need any clarifications, and thanks again for your efforts!

@JunNishimura
Copy link
Contributor Author

Thanks, @marckhouzam

Your point is right.
My implementation did not take into account the possibility that root.PersistentPreRun is nil.

I modified to use PersitentPreRunE to be able to propagate any error returned by root.PersistentPreRunE instaed of PersistentPreRun.
I also added a check to see if the function is not nil.

Sorry for repeating myself, but I'd appreciate it if you'd check commits again.

Copy link
Collaborator

@marckhouzam marckhouzam left a comment

Choose a reason for hiding this comment

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

This LGTM. Thanks @JunNishimura !
I will mark it as approved but I'll wait a little while to allow @jpmcb to have a look if he wants.

@marckhouzam
Copy link
Collaborator

@JunNishimura The linter is failing 😢 . It is just that this PR introduce a third string "true" which the linter wants us to define a constant for. Could you please do that and use it in the three instance of "true"

Thanks

@marckhouzam marckhouzam added kind/bug A bug in cobra; unintended behavior area/cobra-command Core `cobra.Command` implementations area/shell-completion All shell completions area/flags-args Changes to functionality around command line flags and args lgtm Denotes "looks good to me" from maintainers and signals other collaboratores that a PR is ready labels Jul 14, 2023
@marckhouzam marckhouzam added this to the 1.8.0 milestone Jul 14, 2023
@github-actions github-actions bot removed area/cobra-command Core `cobra.Command` implementations area/shell-completion All shell completions labels Jul 14, 2023
@JunNishimura
Copy link
Contributor Author

Thanks, @marckhouzam

I define a constant for "true" named trueString.
The name trueString might be too direct, so if you have a better name, please let me know and I will change it.

@marckhouzam
Copy link
Collaborator

Thanks for the quick turnaround with the linter @JunNishimura .
This looks good now.

As this change had backwards-compatibility implications

I'll wait a little while to allow @jpmcb to have a look if he wants.

@jpmcb jpmcb self-requested a review July 15, 2023 02:23
@jpmcb
Copy link
Collaborator

jpmcb commented Jul 15, 2023

Planning to take a look this weekend. Thanks @marckhouzam for the heads up!

@JunNishimura
Copy link
Contributor Author

@jpmcb
Hi! How about this PR?

If you haven't seen it because you are busy or for some reasons, that's perfectly fine, as I do not want to rush you. I would appreciate it if you could take a look when you have time.

I reminded you because I thought it was possible that you simply forgot.

@marckhouzam
Copy link
Collaborator

This needs a rebase

@marckhouzam marckhouzam modified the milestones: 1.8.0, 1.9.0 Nov 15, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area/flags-args Changes to functionality around command line flags and args kind/bug A bug in cobra; unintended behavior lgtm Denotes "looks good to me" from maintainers and signals other collaboratores that a PR is ready
Projects
None yet
Development

Successfully merging this pull request may close these issues.

"help" subcommand does not work when MarkPersistentRequiredFlag is used.
4 participants