Skip to content

fix: CLI arguments override env vars for slice flags instead of appending - #2

Open
1RB wants to merge 2 commits into
Tylerx3udv:mainfrom
1RB:fix/slice-flag-precedence
Open

fix: CLI arguments override env vars for slice flags instead of appending#2
1RB wants to merge 2 commits into
Tylerx3udv:mainfrom
1RB:fix/slice-flag-precedence

Conversation

@1RB

@1RB 1RB commented Jul 23, 2026

Copy link
Copy Markdown

Fix: StringSliceFlag Precedence — CLI Args Override EnvVars

Fixes #1

Problem

When a StringSliceFlag is 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-sourced
  • Set() (called by CLI parser) clears env/default values on the first CLI call, then appends subsequent CLI values
  • This ensures CLI args completely replace env var values, not append to them

Precedence behavior

  • CLI args only → resolves to CLI values
  • Env var only → resolves to env values
  • Default only → resolves to default values
  • CLI + env → CLI args win (env values discarded)
  • CLI + env + default → CLI args win (full override chain)

Test coverage (9 tests, all passing)

✓ TestStringSliceFlag_EnvVarAndCLIPrecedence
✓ TestStringSliceFlag_MultipleCLIArgsOverrideEnvVar
✓ TestStringSliceFlag_EnvVarOnly
✓ TestStringSliceFlag_CLIOnly
✓ TestStringSliceFlag_DefaultOnly
✓ TestStringSliceFlag_FullPrecedenceChain
✓ TestIntSliceFlag_CLIOverridesEnvVar
✓ TestFloat64SliceFlag_CLIOverridesEnvVar
✓ TestIntSliceFlag_EnvVarOnly

The fix applies consistently to all slice-type flags (StringSliceFlag, IntSliceFlag, Float64SliceFlag) as they share the same underlying parsing logic.

/attempt #1

…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
Copilot AI review requested due to automatic review settings July 23, 2026 07:22

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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() via SetFromEnv() and parses CLI args afterward via parseArgs().
  • 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.

Comment thread main.go
Comment thread main.go
Comment thread main.go
Comment thread main_test.go Outdated
Comment thread go.mod
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)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

🎯 Fix StringSliceFlag Precedence: CLI Arguments Should Override EnvVars Instead of Appending

2 participants