Skip to content

[FEAT] plumber config diff: Show differences between current config and defaults #62

@Joseph94m

Description

@Joseph94m

⚠️ This is one of the most difficult good-first-issues we have

Feel free to propose other implementation details.

Is your feature request related to a problem? Please describe.

After customizing .plumber.yaml, users have no easy way to see what they changed from the defaults. This also means they can't spot new controls or configuration keys added in a newer version of Plumber. They won't know they're missing new options unless they manually compare files. When onboarding new team members or auditing config across projects, this becomes a real pain point.

Describe the solution you'd like

Add a plumber config diff subcommand that:

  • Loads the user's .plumber.yaml. The user can optionally specify their conf file with --config (using configuration.LoadPlumberConfig())
  • Loads the embedded default config from internal/defaultconfig (using defaultconfig.Get() and unmarshalling it with the same types)
  • Compares the two and prints a human-readable diff showing only fields that differ
  • Highlights new keys present in the default but absent from the user config (i.e., keys added in newer Plumber versions)
  • Reports keys present in the user config but not in the default (potential typos or deprecated keys)

Example output (This is the difficult part, showing something useful and actionnable to the user):

The following output is a basic view, it has to cover more advanced cases and be tested extensively.

Controls changed from defaults:
containerImageMustNotUseForbiddenTags.enabled: true → false
containerImageMustNotUseForbiddenTags.forbiddenTags: [latest, dev] → [latest]
branchMustBeProtected.enabled: false → true

New keys in default (missing from your config):
containerImageMustPinDigest.enabled (default: false)

Unknown keys in your config (not in defaults):
containerImageMustNotUseForbiddenTag ← possible typo?

Implementation Hints

These are just ideas. Feel free to change the implementation.

  • Add configDiffCmd in cmd/config.go following the existing configViewCmd / configGenerateCmd pattern
  • To get the default config in memory: use defaultconfig.Get() from internal/defaultconfig this returns the embedded YAML as []byte. Unmarshal it into a configuration.PlumberConfig struct using the same YAML unmarshalling as configuration.LoadPlumberConfig()
  • To get the user config: use configuration.LoadPlumberConfig(configFile) as usual
  • For comparison: marshal both structs back to map[string]interface{} (or use yaml.Marshalyaml.Unmarshal into maps) and recursively compare keys and values
  • Alternatively, compare the two PlumberConfig structs field by field using reflect.DeepEqual per field, and print differences with field names
  • Colorize output for quick scanning: green for matching defaults, yellow for changed values, red for missing/unknown keys

Files Touched

  • cmd/config.go (new configDiffCmd subcommand + diff logic)

Why It's Valuable

Helps users discover new controls or configuration options after upgrading Plumber. Also serves as a quick audit tool to understand what was customized and catch accidental misconfigurations. Complements the existing config view, config generate commands (and config validate when it's ready #56)

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions