Skip to content

Distinguish an explicitly passed flag from its default value - #419

Open
dpage wants to merge 2 commits into
mainfrom
fix/issue-389-explicit-flag-detection
Open

Distinguish an explicitly passed flag from its default value#419
dpage wants to merge 2 commits into
mainfrom
fix/issue-389-explicit-flag-detection

Conversation

@dpage

@dpage dpage commented Aug 12, 2026

Copy link
Copy Markdown
Member

Summary

The collector and the alerter both document configuration
precedence as built-in defaults, then the configuration file, then
command-line flags, but neither could tell a flag the operator
actually passed from one sitting at its registered default: both
decided the question by comparing the flag's value against its own
hardcoded default. The collector did this for -pg-port and
-pg-sslmode, whose defaults are real values (5432 and
"prefer"), and the alerter did it throughout applyFlagOverrides,
where zero-value defaults mostly masked the problem.

The consequence cuts both ways: a configuration file value that
happens to equal a flag's default was overwritten even though
nothing was passed, and a flag passed explicitly with its default
value was ignored, so a file setting datastore.port: 6000 survived
-pg-port 5432.

This adds pkg/flagutil, a small shared helper that records the
flags a flag.FlagSet actually saw via flag.Visit, and switches
both binaries onto it. The collector threads the set through
loadConfiguration into (*Config).ApplyFlags; the alerter carries
it in the flagOverrides bundle that startup and the SIGHUP reload
path already share, so command-line overrides still survive a
reload. Flag names became constants in both binaries so registration
and lookup cannot drift apart. The documented precedence order is
unchanged; it simply now holds in every case.

One behavioural nicety worth calling out: an explicitly empty
-db-password-file in the alerter is treated as "no password file"
rather than as a path to read, which would otherwise fail on the
empty path.

Test plan

  • New pkg/flagutil tests cover Passed with no flags, with a
    subset, with a flag carrying its own default value, and with a nil
    FlagSet, plus Has on a nil Set: 100% coverage of the package.
  • New collector tests cover the two cases that distinguish the old
    behaviour from the new: a configuration value coinciding with a
    flag default survives when the flag is absent, and an explicitly
    passed default value still wins. A further test drives the whole
    loadConfiguration path with -pg-port 5432 against a file
    setting port: 6000.
  • Equivalent tests for the alerter's applyFlagOverrides, including
    the explicitly empty password-file case.
  • Coverage of the changed units: ApplyFlags 100%,
    applyFlagOverrides 100%, pkg/flagutil 100%, and
    loadConfiguration lifted from 86.4% to 90.9%.
  • cd collector && make test-all and cd alerter && make test-all
    both pass, linting included; go test ./... passes for pkg.
  • Documentation updated: both configuration pages now spell out that
    only a flag you actually pass overrides the file, and
    docs/changelog.md records the fix.

Closes #389

🤖 Generated with Claude Code

https://claude.ai/code/session_01N44XgdgR2msyNydAao5vXY

Summary by CodeRabbit

  • Bug Fixes

    • Corrected command-line configuration precedence for the collector and alerter.
    • Explicitly supplied flags now override configuration files, including built-in default or empty values.
    • Omitted flags no longer overwrite settings loaded from configuration files.
    • Improved password-file handling for explicitly provided values.
  • Documentation

    • Clarified configuration precedence and flag behavior in setup guides and the changelog.

Both services documented the precedence of built-in defaults, then
the configuration file, then command-line flags, but neither could
tell an explicitly passed flag from one left at its registered
default: each decided the question by comparing the flag's current
value against its own hardcoded default. The collector did this for
`-pg-port` and `-pg-sslmode`, whose defaults are real values rather
than zero values, and the alerter did the same for its whole
`applyFlagOverrides` set, where the zero-value defaults mostly
masked the problem.

That comparison conflates two genuinely different situations, and it
gets both of them wrong. A configuration file value that happens to
equal a flag's default was overwritten even though nothing was
passed on the command line, and a flag passed explicitly with its
default value was ignored: a file setting `datastore.port: 6000`
survived `-pg-port 5432`, which is precisely the case an operator
would reach for to force the standard port back.

The new `pkg/flagutil` helper records the flags a `flag.FlagSet`
actually saw, via `flag.Visit`, and both binaries now consult that
set instead of comparing values. The collector threads the set
through `loadConfiguration` into `ApplyFlags`, whilst the alerter
carries it in the `flagOverrides` bundle that both startup and the
SIGHUP reload path already share, so overrides survive a reload
exactly as before. Flag names became constants in both binaries so
registration and lookup cannot drift apart.

Closes #389
@coderabbitai

coderabbitai Bot commented Aug 12, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 18b12aab-414a-4942-a055-2283cc820f55

📥 Commits

Reviewing files that changed from the base of the PR and between b3d516b and 2ff60c0.

📒 Files selected for processing (2)
  • alerter/src/cmd/ai-dba-alerter/flagoverrides_test.go
  • alerter/src/cmd/ai-dba-alerter/main.go
🚧 Files skipped from review as they are similar to previous changes (1)
  • alerter/src/cmd/ai-dba-alerter/main.go

Walkthrough

The change adds explicit command-line flag tracking. Collector and alerter configuration now preserve file values for omitted flags and apply explicitly supplied flags, including values equal to built-in defaults.

Changes

Explicit Flag Precedence

Layer / File(s) Summary
Flag presence tracking contract
pkg/flagutil/*, .claude/golang-expert/testing-strategy.md
Adds flagutil.Set, Passed, and Has for tracking supplied flags. Tests cover omitted, default-valued, subset, and nil inputs.
Collector configuration precedence
collector/src/config.go, collector/src/main.go, collector/src/*_test.go, docs/getting-started/configuration/collector.md
Passes explicit flag state through configuration loading. Config.ApplyFlags overrides file values only for supplied flags. Tests and documentation cover precedence and default-valued flags.
Alerter startup and reload precedence
alerter/src/cmd/ai-dba-alerter/main.go, alerter/src/cmd/ai-dba-alerter/*_test.go, docs/getting-started/configuration/alerter.md, docs/changelog.md
Uses shared flag state during startup and SIGHUP reloads. Explicit default values override configuration, while empty password-file values do not trigger file reads. Tests cover these paths.

Estimated code review effort: 3 (Moderate) | ~25 minutes

Sequence Diagram(s)

sequenceDiagram
  participant CLI as Command-line flags
  participant Collector as Collector
  participant Config as Configuration loader
  participant Alerter as Alerter
  CLI->>Collector: Parse flags and call flagutil.Passed
  Collector->>Config: Pass flagutil.Set to loadConfiguration
  Config->>Config: Apply only explicitly passed flags
  CLI->>Alerter: Parse flags and capture flagOverrides
  Alerter->>Config: Apply flagOverrides at startup or SIGHUP reload
  Config->>Config: Read password file only for non-empty passed paths
Loading
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 48.15% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly describes the main change: distinguishing explicitly passed flags from their default values.
Linked Issues check ✅ Passed The changes satisfy issue #389 by tracking passed flags and applying correct precedence in the collector and alerter.
Out of Scope Changes check ✅ Passed The implementation, tests, documentation, and changelog changes directly support the linked issue objectives.
✨ Finishing Touches 💡 1
📝 Generate docstrings 💡
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/issue-389-explicit-flag-detection

Comment @coderabbitai help to get the list of available commands.

@codacy-production

codacy-production Bot commented Aug 12, 2026

Copy link
Copy Markdown

Up to standards ✅

🟢 Issues 0 issues

Results:
0 new issues

View in Codacy

🟢 Metrics 44 complexity · 0 duplication

Metric Results
Complexity 44
Duplication 0

View in Codacy

NEW Get contextual insights on your PRs based on Codacy's metrics, along with PR and Jira context, without leaving GitHub. Enable AI reviewer
TIP This summary will be updated as you push new changes.

@coderabbitai coderabbitai Bot 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.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@alerter/src/cmd/ai-dba-alerter/main.go`:
- Around line 349-358: Update the configuration handling around
flagDBPasswordFile so cfg.Datastore.PasswordFile is always assigned
o.DBPasswordFile whenever the flag is explicitly passed, including an empty
value, before the conditional file read. Preserve the non-empty path read and
error handling, and add a regression test covering a configured password_file
overridden by an explicit empty flag.

In `@collector/src/main.go`:
- Line 97: Run gofmt across all six unformatted files under pkg/, then fix
QF1001 and ST1005 in pkg/fileutil/fileutil.go:147-148 while preserving behavior
and idiomatic error text. No direct changes are required at
collector/src/main.go:97, collector/src/config.go:101-129,
collector/src/config_test.go:473-736, or collector/src/main_test.go:25-315;
verify the repository-wide Go checks afterward.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 7570ec31-0bcf-450f-8523-223b26f64510

📥 Commits

Reviewing files that changed from the base of the PR and between 19c645d and b3d516b.

📒 Files selected for processing (13)
  • .claude/golang-expert/testing-strategy.md
  • alerter/src/cmd/ai-dba-alerter/flagoverrides_test.go
  • alerter/src/cmd/ai-dba-alerter/main.go
  • alerter/src/cmd/ai-dba-alerter/main_test.go
  • collector/src/config.go
  • collector/src/config_test.go
  • collector/src/main.go
  • collector/src/main_test.go
  • docs/changelog.md
  • docs/getting-started/configuration/alerter.md
  • docs/getting-started/configuration/collector.md
  • pkg/flagutil/flagutil.go
  • pkg/flagutil/flagutil_test.go

Comment thread alerter/src/cmd/ai-dba-alerter/main.go Outdated
Comment thread collector/src/main.go
… flag

An explicitly empty -db-password-file skipped the immediate read but
left the path the configuration file named in place, so the later
cfg.LoadPassword during startup and on every SIGHUP reload still read
that file. The flag now always replaces the configured path,
including with an empty value, whilst only a non-empty path is read.
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.

Collector and alerter can't distinguish an explicit flag from its default value

1 participant