cli icon indicating copy to clipboard operation
cli copied to clipboard

Flag Action not invoked when the value is supplied from ENV Sources

Open nicfit opened this issue 6 months ago • 4 comments

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

nicfit avatar May 14 '25 23:05 nicfit

Seems like this issue is a duplicate of #2041

Shackelford-Arden avatar May 16 '25 15:05 Shackelford-Arden

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.

nicfit avatar May 17 '25 16:05 nicfit

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.

dearchap avatar May 18 '25 22:05 dearchap

I'd be fine with Local: true for my use-case.

nicfit avatar May 29 '25 00:05 nicfit

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.

cenk1cenk2 avatar Jul 12 '25 21:07 cenk1cenk2

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?

jvilhuber avatar Aug 25 '25 16:08 jvilhuber