cli
cli copied to clipboard
Flag Action not invoked when the value is supplied from ENV Sources
My urfave/cli version is
3.3.3
Checklist
- [x] Are you running the latest v3 release? The list of releases is here.
- [x] Did you check the manual for your release? The v3 manual is here
- [x] Did you perform a search about this problem? Here's the GitHub guide about searching.
Dependency Management
- My project is using go modules.
Describe the bug
The program cli-flag-action invokes the Flag Action function when an option is given, but not when the option comes from an EnvVars source.
➜ cli-flag-action --config=flag.yml
Flag Action: flag.yml
Config: flag.yml
➜ CONFIG=env.yml cli-flag-action
Config: env.yml
The program:
package main
import (
"context"
"fmt"
"github.com/urfave/cli/v3"
"os"
)
func main() {
cmd := &cli.Command{
Action: func(ctx context.Context, command *cli.Command) error {
fmt.Println("Config:", command.String("config"))
return nil
},
Flags: []cli.Flag{
&cli.StringFlag{
Name: "config",
Usage: "Configuration file",
Required: false,
Sources: cli.EnvVars("CONFIG"),
Action: func(ctx context.Context, command *cli.Command, s string) error {
fmt.Println("Flag Action:", s)
return nil
},
},
},
}
cmd.Run(context.Background(), os.Args)
}
To reproduce
See above.
Observed behavior
Flag action not called for environment sources.
Expected behavior
Flag Action invoked regardless of value source.
Additional context
n/a
Want to fix this yourself?
Perhaps, if my expectations are confirmed.
Run go version and paste its output here
go version go1.23.1 linux/amd64
Run go env and paste its output here
# paste `go env` output in here
Seems like this issue is a duplicate of #2041
Seems like this issue is a duplicate of #2041
Perhaps similar, though the value of Local has not effect on the behavior, so it is not a viable workaround.
The question is when exactly should the flag action be executed ? When a flag is set on cmd line it triggers the flag action. Without that we have no way to figure out when to trigger the action. For a "Local" flag we could say that after the parsing of current command/subcommand is complete we could trigger the action. For a non local/persistent flag it is non-trivial to implement.
I'd be fine with Local: true for my use-case.
This is also true if you want to fetch a flag by using directly the *Command where command.IsSet("flag-set-with-default-value") and command.IsSet("flag-set-with-sources") returns false. This was not the case in v2.
Also having a default Value does not trigger action functions, which might be useful whenever there is some json parsing for the given flag.
I also just encountered this issue. Worked fine in v2 and now won't trigger when the arg is supplied via env. I can't switch to v3 until this is addressed.
I'd say if the flag has a value after all the sources gathering, call the action (it should also be called when there's a default Value as the previous commenter said).
I'm also open to suggestions, like perhaps a validator? Is that triggered? Seems yes, so maybe I can switch to that instead. Perhaps I missed some page that explains when actions are supposed to be used (and when we can expect them to be triggered) as opposed to a validator?