cobra icon indicating copy to clipboard operation
cobra copied to clipboard

Context only propagates to child commands the first time

Open KernelDeimos opened this issue 3 years ago • 4 comments

I have an application that can be called in two ways:

  1. manually invoke from the CLI
  2. process directives in specially-formatted lines of a text file, which contain CLI arguments in the same format

For the second use case, I'm creating a Context that I'm passing to ExecuteContext for each of my directives. I noticed that the first time, sub-commands get my new context. However, for subsequent inputs the context is only updated on the root command.

Is this behaviour intentional? I can imagine this being overlooked as Cobra commands are typically executed only once for an instance of a program. I realize fixing this would cause a regression, so I'd like to propose something like this as an opt-in for the behaviour I was expecting:

func init() {
    cobra.OverwriteChildContexts = true
}

KernelDeimos avatar Aug 09 '21 20:08 KernelDeimos

Probably related to #908.

umarcor avatar Aug 26 '21 06:08 umarcor

This issue is being marked as stale due to a long period of inactivity

github-actions[bot] avatar Oct 26 '21 00:10 github-actions[bot]

Very similar to #1109

marckhouzam avatar Mar 18 '22 10:03 marckhouzam

I've got the same trouble as well. I've bypassed it by traversing back to the root command and using its context instead of using the current cmd.Context()

Hacky, but it's working.

// ExtractContext traverse backwards to the root command and extracts the context
// of it.
// More info: https://github.com/spf13/cobra/issues/1469
func ExtractContext(cmd *cobra.Command) context.Context {
	if cmd == nil {
		return nil
	}

	var (
		ctx = cmd.Context()
		p   = cmd.Parent()
	)
	if cmd.Parent() == nil {
		return ctx
	}
	for {
		ctx = p.Context()
		p = p.Parent()
		if p == nil {
			break
		}
	}
	return ctx
}

tarvitz avatar Sep 15 '22 12:09 tarvitz