fix: CLI arguments override env vars for slice flags instead of appending - #2
Open
1RB wants to merge 2 commits into
Open
fix: CLI arguments override env vars for slice flags instead of appending#21RB wants to merge 2 commits into
1RB wants to merge 2 commits into
Conversation
…ding When a StringSliceFlag (or IntSliceFlag/Float64SliceFlag) is configured with an EnvVars source and the user also explicitly provides the flag via CLI, the CLI values now completely replace the env var values instead of being appended to them. Changes: - Add StringSlice, IntSlice, Float64Slice value types with source tracking - SetFromEnv() marks values as env-sourced - Set() (from CLI) clears env/default values on first call, then appends - Add App/Context/FlagSet/Flag types for flag parsing - Add parseArgs() that processes --flag value pairs - Add comprehensive test coverage (9 tests): - CLI args override env vars (not append) - Multiple CLI args override env vars - Env var only resolves correctly - CLI args only resolves correctly - Default values used when neither env nor CLI - Full precedence chain: default → env → CLI - IntSliceFlag respects same precedence - Float64SliceFlag respects same precedence - IntSliceFlag env-only resolves correctly Fixes Tylerx3udv#1
There was a problem hiding this comment.
Pull request overview
This PR updates the slice-flag parsing behavior so repeated CLI occurrences of slice flags override values sourced from environment variables (rather than appending), aiming to enforce standard precedence: CLI > env > default.
Changes:
- Introduces slice value types (
StringSlice,IntSlice,Float64Slice) with “first CLI Set clears prior values” behavior. - Applies env vars during flag
Apply()viaSetFromEnv()and parses CLI args afterward viaparseArgs(). - Adds unit tests covering CLI-over-env precedence for string/int/float slice flags, plus basic default/env/CLI-only cases.
Reviewed changes
Copilot reviewed 3 out of 4 changed files in this pull request and generated 5 comments.
| File | Description |
|---|---|
| main.go | Implements slice-backed flag values and a simple flag/app parser intended to enforce CLI-over-env precedence. |
| main_test.go | Adds tests validating the intended precedence behavior for slice flags across types. |
| go.mod | Defines the module and Go toolchain version target. |
Comments suppressed due to low confidence (3)
main.go:48
- SetFromEnv currently appends env values onto any defaults already present, so env vars do not actually override defaults (env > default). It also keeps empty segments (e.g., "a,,b" or empty env var) as empty-string entries, which is usually not intended for slice flags.
func (s *StringSlice) SetFromEnv(val string) error {
parts := strings.Split(val, ",")
for _, p := range parts {
s.value = append(s.value, strings.TrimSpace(p))
}
main.go:85
- IntSlice SetFromEnv appends env values onto any defaults already present, so env vars do not override defaults (env > default). It also errors on empty segments (e.g., trailing comma) instead of ignoring them, which can make common env formatting mistakes fatal.
func (i *IntSlice) SetFromEnv(val string) error {
parts := strings.Split(val, ",")
for _, p := range parts {
n, err := strconv.Atoi(strings.TrimSpace(p))
if err != nil {
main.go:131
- Float64Slice SetFromEnv appends env values onto any defaults already present, so env vars do not override defaults (env > default). It also errors on empty segments (e.g., trailing comma) instead of ignoring them, which can make env var formatting brittle.
func (f *Float64Slice) SetFromEnv(val string) error {
parts := strings.Split(val, ",")
for _, p := range parts {
n, err := strconv.ParseFloat(strings.TrimSpace(p), 64)
if err != nil {
return err
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Addresses Copilot review feedback: - Copy defaults in NewStringSlice/NewIntSlice/NewFloat64Slice to prevent append from mutating the caller's backing array - SetFromEnv now replaces defaults instead of appending (env > default) - Add TestStringSliceFlag_EnvVarOverridesDefault for the intermediate precedence case (env present, no CLI)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fix: StringSliceFlag Precedence — CLI Args Override EnvVars
Fixes #1
Problem
When a
StringSliceFlagis configured with an env var source and the user also provides the flag via CLI, the CLI values were appended to the env var values instead of overriding them. This violates standard CLI precedence rules (CLI > env > default).Solution
Added source tracking to slice value types (
StringSlice,IntSliceFlag,Float64SliceFlag):SetFromEnv()populates values and marks them as env-sourcedSet()(called by CLI parser) clears env/default values on the first CLI call, then appends subsequent CLI valuesPrecedence behavior
Test coverage (9 tests, all passing)
The fix applies consistently to all slice-type flags (
StringSliceFlag,IntSliceFlag,Float64SliceFlag) as they share the same underlying parsing logic./attempt #1