Issue 16 empty envvars#18
Conversation
| // If the flags are already set, values are overwritten | ||
| // by the values in the config file. Defaults are not set | ||
| // if the flag is not in the file. | ||
| func (g *GlobalConf) ParseSet(flagSetName string, set *flag.FlagSet) { |
There was a problem hiding this comment.
Does ParseSet need to exist at all? It is not tested and It looks like Parse will do the work as long as the flagset is registered.
There was a problem hiding this comment.
Parse works on the default flag set, ParseSet works on a particular one. I don't know why Parse doesn't use ParseSet though.
I will try to rewrite a bunch of things after this PR. Thanks for pointing them out.
There was a problem hiding this comment.
I stared at TestParse_GlobalAndCustom for a while to figure out how parse, which calls ParseAll was processing the custom FlagSet. Register adds the set to the flags map , which already has the default flag.CommandLine in it, and then ParseAll iterates over all the sets and parses them.
There was a problem hiding this comment.
Globally registering a flagset is not always what users can do. We should leave the decision to the user. We should maybe remove registration and ParseAll rather than removing the fundamental flagset-scoped ParseSet.
There was a problem hiding this comment.
I don't feel safe breaking the API without existing releases with semantic versioning in place, especially since I have code using globalconf in production. I think ParseSet is fine to keep, I was just a little uneasy about making a change to it without existing tests, so was looking to save the work of adding tests. Would you prefer I add tests proving it does what it says in the comment block? Now that I read that, It has a different behavior than what happens in Parse. It will overwrite already set flags.
There was a problem hiding this comment.
Would you prefer I add tests proving it does what it says in the comment block?
Yes, please. I don't think this PR is where we should discuss ParseSet. It is beyond the scope. Could you please file another issue if you have more questions?
|
I take, from the failing ci, it that |
| set.VisitAll(func(f *flag.Flag) { | ||
| val := getEnv(g.EnvPrefix, flagSetName, f.Name) | ||
| if val != "" { | ||
| val, exists := getEnv(g.EnvPrefix, flagSetName, f.Name) |
There was a problem hiding this comment.
The second bool argument is usually called ok.
if val, ok := getEnv(...); ok {
set.Set(f.Name, val)
return
}
|
|
||
| val := getEnv(g.EnvPrefix, name, f.Name) | ||
| if val != "" { | ||
| val, exists := getEnv(g.EnvPrefix, name, f.Name) |
| } | ||
|
|
||
| func TestParse_GlobalWithEmptyValue(t *testing.T) { | ||
| t.Log("Given the need to test overwriting a flag with an environmental variable set to an empty string") |
There was a problem hiding this comment.
Don't log this.
Use a comment block to explain.
There was a problem hiding this comment.
I picked up this test explaining style from Go In Action. I saw a number of benefits to it such as when you go test -v the output looks like:
=== RUN TestParse_GlobalWithEmptyValue
--- PASS: TestParse_GlobalWithEmptyValue (0.00s)
globalconf_test.go:100: Given the need to test overwriting a flag with an environmental variable set to an empty string
globalconf_test.go:101: Reset the flags and clear the env
globalconf_test.go:106: Set the env var for the c flag to an empty string
globalconf_test.go:108: Define the c flag and parse the INI file
globalconf_test.go:113: Expect flagC to an empty string and not be the value Hello World from the INI file
This helped me see where failures were happening more quickly along with educating me on what the test was doing.
| resetForTesting("") | ||
| } | ||
|
|
||
| t.Log("\tSet the env var for the c flag to an empty string") |
| flagC := flag.String("c", "", "") | ||
|
|
||
| parse(t, "./testdata/global.ini", envTestPrefix) | ||
| t.Log("\t\tExpect flagC to an empty string and not be the value Hello World from the INI file") |
| parse(t, "./testdata/global.ini", envTestPrefix) | ||
| t.Log("\t\tExpect flagC to an empty string and not be the value Hello World from the INI file") | ||
| if *flagC != "" { | ||
| t.Errorf("\t\tflagC found %v, expected an empty string", *flagC) |
There was a problem hiding this comment.
don't add \t\t. Test log is formatted nicely by the tool already.
| parse(t, "./testdata/global.ini", envTestPrefix) | ||
| t.Log("\t\tExpect flagC to an empty string and not be the value Hello World from the INI file") | ||
| if *flagC != "" { | ||
| t.Errorf("\t\tflagC found %v, expected an empty string", *flagC) |
There was a problem hiding this comment.
Let's use the defacto go test formatting here.
if got, want := *flagC, ""; got != want {
t.Errorf("got flag = %q, want empty string", got)
}
There was a problem hiding this comment.
This is nice. By the time I joined the Go projects I'm working on, the testify package was already adopted and I'm used to seeing require.Equal(t, expected, got)
Use defacto go test formatting Move test explaination to comment block
|
It is weird that github does not mark your comments as addressed anymore. |
|
@johnlockwood-wf, is this your first time contributing to a Google project? If so, could you review the Google CLA underneath https://cla.developers.google.com/clas and sign? Thanks! |
|
I did the individual CLA for now and am looking into if we have one of those google groups registered that I can add myself to. |
|
Thanks! Looking at #19 shortly. |
Previously, If you set an environmental variable that matches an
ENVPREFIX_FLAG_NAMEto an empty string, it would not overwrite the flag_name in the INI file. This usesos.LookupEnvto overwrite the flag if it is set at all.Addresses #16