Revised 2026-08-07. The original issue proposed making the environment uniform across all 19 options via a VisitAll loop. That part was wrong and should not be done — see Why not uniform below. The dependency removal, which is the valuable half, is implemented in the linked PR.
Problem
Viper contributes 35 of the module's 38 non-stdlib packages to configure six flags from the environment. It is used for nothing but AutomaticEnv:
viper.SetEnvPrefix("HTTP_ASSERT")
viper.GetViper().SetEnvKeyReplacer(strings.NewReplacer("-", "_"))
viper.AutomaticEnv()
No config files, no remote providers, no watching — and for that the graph carries fsnotify, afero, mapstructure, pelletier/go-toml, locafero, sourcegraph/conc, gotenv, cast and yaml.
|
Before |
After |
| Non-stdlib packages |
38 |
3 (cobra, pflag, mousetrap) |
| Total packages |
235 |
193 |
| Binary |
9.93 MB |
9.01 MB |
Why not uniform
The original proposal was to apply the environment to every flag via VisitAll. Preserving --maphost's existing semantics requires splitting one variable into several values on whitespace (viper's behaviour, verified). Applied uniformly, that corrupts every option whose values contain spaces:
'X-Foo: bar baz' -> strings.Fields -> ['X-Foo:', 'bar', 'baz']
'Cache-Control: max-age=3600' -> strings.Fields -> ['Cache-Control:', 'max-age=3600']
Header values routinely contain spaces; host mappings never do. Uniformity would trade one inconsistency for a silent value-corrupting footgun across ten flags — strictly worse than the split it was meant to fix.
The inconsistency is instead addressed where it actually hurt: it is now a single named list in the source, and documented in the README, rather than an accident of which flags happened to get a BindPFlag line.
If per-flag environment support for the remaining options is still wanted, it needs a separator that cannot appear in a header value (indexed variables such as HTTP_ASSERT_HEADER_1, or a NUL/newline delimiter) — that is a different design and deserves its own issue.
What shipped
applyEnv, ~25 lines over the flag set, replacing all 13 viper call sites.
- Every option now read from cobra;
envFlags names the six that also consult the environment.
- Behaviour preserved exactly — empty variable means unset, whitespace separates repeated values, command line beats environment.
- Separately: unparseable values are now rejected instead of coerced. Previously
HTTP_ASSERT_MAX_TIME=abc became 0, and a zero http.Client.Timeout means no timeout at all.
Verification
The behaviour-preserving commit touches no test file. All 233 subtests — including 32 added beforehand specifically to cover environment parsing — pass unedited. Coverage went 39% → 100%.
Problem
Viper contributes 35 of the module's 38 non-stdlib packages to configure six flags from the environment. It is used for nothing but
AutomaticEnv:No config files, no remote providers, no watching — and for that the graph carries
fsnotify,afero,mapstructure,pelletier/go-toml,locafero,sourcegraph/conc,gotenv,castandyaml.Why not uniform
The original proposal was to apply the environment to every flag via
VisitAll. Preserving--maphost's existing semantics requires splitting one variable into several values on whitespace (viper's behaviour, verified). Applied uniformly, that corrupts every option whose values contain spaces:Header values routinely contain spaces; host mappings never do. Uniformity would trade one inconsistency for a silent value-corrupting footgun across ten flags — strictly worse than the split it was meant to fix.
The inconsistency is instead addressed where it actually hurt: it is now a single named list in the source, and documented in the README, rather than an accident of which flags happened to get a
BindPFlagline.If per-flag environment support for the remaining options is still wanted, it needs a separator that cannot appear in a header value (indexed variables such as
HTTP_ASSERT_HEADER_1, or a NUL/newline delimiter) — that is a different design and deserves its own issue.What shipped
applyEnv, ~25 lines over the flag set, replacing all 13 viper call sites.envFlagsnames the six that also consult the environment.HTTP_ASSERT_MAX_TIME=abcbecame0, and a zerohttp.Client.Timeoutmeans no timeout at all.Verification
The behaviour-preserving commit touches no test file. All 233 subtests — including 32 added beforehand specifically to cover environment parsing — pass unedited. Coverage went 39% → 100%.