Skip to content

Expose --config <PATH> and NETSUKE_CONFIG precedence#285

Draft
leynos wants to merge 3 commits intomainfrom
expose-config-path-netsuke-is6m0i
Draft

Expose --config <PATH> and NETSUKE_CONFIG precedence#285
leynos wants to merge 3 commits intomainfrom
expose-config-path-netsuke-is6m0i

Conversation

@leynos
Copy link
Copy Markdown
Owner

@leynos leynos commented Apr 16, 2026

Summary

  • Implement an explicit config-path surface via a CLI flag --config <PATH> and a user-facing environment variable NETSUKE_CONFIG to specify a config file directly, while keeping backwards-compatible NETSUKE_CONFIG_PATH as a silent alias.
  • Integrate this into Netsuke's existing two-pass discovery with a clear precedence: --config > NETSUKE_CONFIG > NETSUKE_CONFIG_PATH > discovery.
  • Update documentation, localization keys, tests, and roadmap artifacts accordingly.

Rationale

  • Allow users to bypass automatic discovery and load a specific configuration file deterministically. Explicit precedence and clear messaging reduce ambiguity for users upgrading to the new surface.

What changed

  • CLI surface
    • Added config: Option<PathBuf> to Cli with #[serde(skip)] and localized help.
    • Introduced local resolution logic that prefers --config, then NETSUKE_CONFIG, then NETSUKE_CONFIG_PATH, else discovery.
    • Ensure the explicit path is respected by discovery/push logic when provided.
  • Discovery & merge wiring
    • Centralized explicit config path resolution and wired it into the merge path, so an explicit path bypasses two-pass discovery and loads the file directly.
    • Updated the diag-JSON collection so early resolution also respects the explicit config path.
    • Adjusted merge entry points to pass the explicit config path through the pipeline.
  • Environment variable precedence
    • Implemented precedence so NETSUKE_CONFIG overrides NETSUKE_CONFIG_PATH when both are set.
  • Localization & build-time anchors
    • Added a new Fluent key for the --config flag help and English/Spanish messages.
    • Mapped the new key in src/cli_l10n.rs.
    • Added build-time symbol anchors where needed.
  • Tests
    • Added integration tests for --config and NETSUKE_CONFIG interactions in tests/cli_tests/config_selection.rs.
    • Extended existing tests to cover explicit config behavior and precedence rules.
    • Expanded BDD coverage in tests/features/configuration_discovery.feature with scenarios for explicit config behavior.
  • Documentation & sample configs
    • Added annotated docs/sample-netsuke.toml demonstrating all keys.
    • Updated user docs (docs/users-guide.md) to document --config, NETSUKE_CONFIG, and precedence.
    • Updated design docs (docs/netsuke-design.md) to reflect the new surface.
    • Updated roadmap (docs/roadmap.md) to mark 3.11.3 as done.
  • Artifacts
    • New execplan document: 3-11-3-expose-config-path-and-netsuke-config.md under docs/execplans.
    • Updated various references to ensure documentation and localization stay in sync with the new behavior.

Precedence and behavior

  • Precedence ladder for selecting a config file:
      1. --config (CLI flag, highest)
      1. NETSUKE_CONFIG (environment variable, new user-facing name)
      1. NETSUKE_CONFIG_PATH (environment variable, legacy alias)
      1. Automatic discovery (project/user scopes)
  • Behavior details
    • The --config path is resolved against the process working directory and is a file selector (loads that file directly).
    • If the explicit path does not exist or cannot parse, an error is surfaced rather than silently falling back to discovery.
    • Relative paths passed to --config are resolved against the current working directory.
    • NETSUKE_CONFIG_PATH remains supported as a silent alias and is overridden by NETSUKE_CONFIG when both are set.
    • The existing two-pass discovery remains the default path when no explicit config is provided.

Documentation & localization impact

  • Localization keys
    • Added CLI_FLAG_CONFIG_HELP and wired it to map to the --config flag help.
    • English and Spanish Fluent messages added for the new flag.
  • Documentation artifacts
    • docs/sample-netsuke.toml provides an annotated, parsable sample config.
    • docs/users-guide.md updated to describe --config, NETSUKE_CONFIG, and the precedence.
    • docs/netsuke-design.md updated to reflect the new override surface and precedence rules.
    • docs/roadmap.md updated to mark 3.11.3 as complete.

Tests & validation

  • Integration tests
    • New tests in tests/cli_tests/config_selection.rs validate:
      • --config loads the specified file and bypasses discovery
      • NETSUKE_CONFIG loads the specified file
      • precedence: NETSUKE_CONFIG > NETSUKE_CONFIG_PATH
      • --config takes precedence over NETSUKE_CONFIG when both are set
    • Extended or added tests cover missing files and error handling for explicit config loads.
  • Behavior-driven tests
    • Extended tests/features/configuration_discovery.feature with explicit-config scenarios demonstrating the behavior to end users.
  • Documentation checks
    • New sample config and documentation updated accordingly; localization checks aligned with new keys.

Validation gates

  • fmt, lint, tests pass in CI environment per the execplan.
  • Help output for netsuke --help includes a localized --config flag description.
  • All acceptance criteria from the plan are satisfied, including explicit config loading, environment override precedence, and silent alias support.

Artifacts and notes

  • Code changes across: src/cli/mod.rs, src/cli/config_merge.rs, src/cli/config_merge_tests.rs, src/cli_l10n.rs, src/localization/keys.rs.
  • Localization files updated: locales/en-US/messages.ftl, locales/es-ES/messages.ftl.
  • Tests updated/added: tests/cli_tests/config_selection.rs, tests/features/configuration_discovery.feature, tests/bdd/steps/configuration_discovery.rs.
  • Documentation: docs/sample-netsuke.toml, docs/users-guide.md, docs/netsuke-design.md, docs/roadmap.md.
  • ExecPlan added: docs/execplans/3-11-3-expose-config-path-and-netsuke-config.md.

If you have any questions or need adjustments to the wording of the new sections, I can tailor them to your preferred PR messaging style.

📎 Task: https://www.devboxer.com/task/05c12be9-87ad-42d7-8ba0-8e576601053d

…nfig file

Introduce a new command-line flag `--config <PATH>` and a new environment variable `NETSUKE_CONFIG` to allow users to explicitly specify a configuration file. This bypasses the automatic config discovery mechanism and loads the specified file directly. The legacy `NETSUKE_CONFIG_PATH` remains supported as a silently deprecated alias, with precedence:

- `--config` flag (highest)
- `NETSUKE_CONFIG` env variable (new documented alias)
- `NETSUKE_CONFIG_PATH` env variable (legacy)
- automatic discovery (lowest)

The `config` field is added to the `Cli` struct with proper annotations (`#[serde(skip)]` and clap arguments) to exclude it from OrthoConfig serialization and merging pipelines, preventing it from leaking as a config preference.

The merge pipeline functions are updated to honor the explicit config path, loading that file directly and skipping discovery when specified. Errors on missing or invalid explicit config files are propagated.

Localization keys for the flag help text are added with English and Spanish translations. The user guide and design documentation are updated to describe the new flag and environment variable and the precedence rules.

Comprehensive integration and behavioral tests verify correct loading precedence, error handling, and backward compatibility.

This completes roadmap item 3.11.3, enhancing config file specification clarity and control for users.

Co-authored-by: devboxerhub[bot] <devboxerhub[bot]@users.noreply.github.com>
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Apr 16, 2026

Important

Review skipped

Draft detected.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: b8025d6d-9da8-4422-8eff-5376a344be54

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch expose-config-path-netsuke-is6m0i

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

@sourcery-ai
Copy link
Copy Markdown
Contributor

sourcery-ai Bot commented Apr 16, 2026

Reviewer's Guide

Adds a detailed ExecPlan document for roadmap item 3.11.3 (exposing a --config flag and NETSUKE_CONFIG env var) and performs minor formatting/line-wrap fixes in the developers guide; no CLI or runtime behavior is changed in this PR.

Sequence diagram for explicit config selection in merge pipeline

sequenceDiagram
  actor User
  participant NetsukeCli as Netsuke_CLI_binary
  participant CliParser as Cli_parser
  participant ConfigMerge as Config_merge
  participant ResolvePath as resolve_config_path
  participant FileLoader as File_loader
  participant Discovery as Config_discovery

  User->>NetsukeCli: invoke netsuke [args, env]
  NetsukeCli->>CliParser: parse CLI into Cli
  CliParser-->>NetsukeCli: Cli { config, directory, ... }

  NetsukeCli->>ConfigMerge: merge_with_config(Cli, matches)
  ConfigMerge->>ResolvePath: resolve_config_path(Cli)
  alt CLI --config provided
    ResolvePath-->>ConfigMerge: Some(Path_from_cli)
  else NETSUKE_CONFIG set
    ResolvePath-->>ConfigMerge: Some(Path_from_NETSUKE_CONFIG)
  else NETSUKE_CONFIG_PATH set
    ResolvePath-->>ConfigMerge: Some(Path_from_NETSUKE_CONFIG_PATH)
  else no explicit path
    ResolvePath-->>ConfigMerge: None
  end

  alt explicit config path resolved
    ConfigMerge->>FileLoader: load_config_file_as_chain(path)
    alt file exists and parses
      FileLoader-->>ConfigMerge: Merge_layers_from_file
      ConfigMerge-->>NetsukeCli: Merged_Cli_with_explicit_file
    else file missing or invalid
      FileLoader-->>ConfigMerge: Error
      ConfigMerge-->>NetsukeCli: Error(no_fallback_to_discovery)
    end
  else no explicit path
    ConfigMerge->>Discovery: config_discovery(directory)
    Discovery-->>ConfigMerge: Merge_layers_from_discovery
    ConfigMerge-->>NetsukeCli: Merged_Cli_from_discovery
  end

  NetsukeCli-->>User: run command with final merged config
Loading

Flow diagram for config path resolution precedence

flowchart TD
  Start([Start netsuke invocation])
  HasCliConfig{CLI flag
  --config set?}
  HasEnvConfig{Env NETSUKE_CONFIG
  set?}
  HasEnvConfigPath{Env NETSUKE_CONFIG_PATH
  set?}
  UseCliConfig[[Use CLI --config path
  as config file]]
  UseEnvConfig[[Use NETSUKE_CONFIG path
  as config file]]
  UseEnvConfigPath[[Use NETSUKE_CONFIG_PATH path
  as config file]]
  RunDiscovery[[Run two-pass
  config discovery]]
  LoadConfig[[Load selected config
  into merge pipeline]]
  ErrorMissing[[Error: explicit config
  file missing or invalid]]

  Start --> HasCliConfig
  HasCliConfig -- Yes --> UseCliConfig
  HasCliConfig -- No --> HasEnvConfig

  HasEnvConfig -- Yes --> UseEnvConfig
  HasEnvConfig -- No --> HasEnvConfigPath

  HasEnvConfigPath -- Yes --> UseEnvConfigPath
  HasEnvConfigPath -- No --> RunDiscovery

  UseCliConfig --> CheckCliFile{File exists
  and parses?}
  CheckCliFile -- Yes --> LoadConfig
  CheckCliFile -- No --> ErrorMissing

  UseEnvConfig --> CheckEnvFile{File exists
  and parses?}
  CheckEnvFile -- Yes --> LoadConfig
  CheckEnvFile -- No --> ErrorMissing

  UseEnvConfigPath --> CheckEnvPathFile{File exists
  and parses?}
  CheckEnvPathFile -- Yes --> LoadConfig
  CheckEnvPathFile -- No --> ErrorMissing

  RunDiscovery --> LoadConfig
  LoadConfig --> End([Proceed with merged config])
  ErrorMissing --> End
Loading

File-Level Changes

Change Details Files
Add an execution plan document describing how to expose --config and NETSUKE_CONFIG and integrate them into config discovery, testing, localization, and documentation.
  • Introduce docs/execplans/3-11-3-expose-config-path-and-netsuke-config.md as a comprehensive design and plan for implementing an explicit config path surface.
  • Document intended CLI, environment variable precedence, discovery behavior, risks, validation steps, and affected files for future implementation.
  • Capture constraints, tolerances, decision log, and staged work plan for roadmap item 3.11.3.
docs/execplans/3-11-3-expose-config-path-and-netsuke-config.md
Tidy up documentation formatting in the developers guide to improve line wrapping without changing meaning.
  • Reflow paragraphs to keep sentences within the preferred line width while preserving wording.
  • Adjust bullet text wrapping in the CLI overrides section for consistent formatting.
docs/developers-guide.md

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

codescene-delta-analysis[bot]

This comment was marked as outdated.

…config file selection

- Introduce a visible `--config <FILE>` CLI flag to specify an explicit config file, bypassing automatic discovery.
- Add `NETSUKE_CONFIG` environment variable as the documented override, keeping `NETSUKE_CONFIG_PATH` as a legacy fallback.
- Centralize explicit config path resolution in `resolve_config_path()` to unify precedence handling across merging and diagnostic JSON resolution.
- Update configuration discovery logic to prioritize explicit selectors (`--config` > `NETSUKE_CONFIG` > `NETSUKE_CONFIG_PATH`) before falling back to automatic discovery.
- Extend integration and behavioral tests to cover CLI/environment precedence, missing file errors, and legacy support.
- Provide a sample annotated config file and update documentation accordingly.

This change improves user ergonomics by exposing explicit config file selection via CLI and environment, clarifies configuration precedence, and unifies implementation logic to prevent inconsistencies.

Co-authored-by: devboxerhub[bot] <devboxerhub[bot]@users.noreply.github.com>
@leynos leynos changed the title Plan: expose --config path and NETSUKE_CONFIG Expose --config path and NETSUKE_CONFIG precedence Apr 20, 2026
codescene-delta-analysis[bot]

This comment was marked as outdated.

@leynos
Copy link
Copy Markdown
Owner Author

leynos commented Apr 21, 2026

@coderabbitai Please suggest a fix for this issue and supply a prompt for an AI coding agent to enable it to apply the fix. Include the file and symbol names indicated in the issue at the head of your response.

tests/cli_tests/config_selection.rs

Comment on lines +63 to +83

fn config_flag_loads_specified_file() -> Result<()> {
    let _env_lock = EnvLock::acquire();
    let _cwd_guard = CwdGuard::acquire()?;
    let project = tempdir().context("create project directory")?;
    let home = tempdir().context("create fake home directory")?;
    let _user_scope = sandbox_user_scope(&home)?;
    let _config_guard = EnvVarGuard::remove("NETSUKE_CONFIG");
    let _legacy_guard = EnvVarGuard::remove("NETSUKE_CONFIG_PATH");
    let _theme_guard = EnvVarGuard::remove("NETSUKE_THEME");

    let custom = project.path().join("custom.toml");
    fs::write(&custom, "theme = \"unicode\"\n").context("write explicit config file")?;
    std::env::set_current_dir(project.path()).context("change to project directory")?;

    let merged = parse_and_merge(&["netsuke", "--config", "custom.toml"])?;
    ensure!(
        merged.theme == Some(ThemePreference::Unicode),
        "explicit --config file should be loaded"
    );
    Ok(())
}

❌ New issue: Code Duplication
The module contains 4 functions with similar structure: config_flag_loads_specified_file,config_flag_skips_project_discovery,config_flag_takes_precedence_over_netsuke_config_env,netsuke_config_env_takes_precedence_over_legacy

@leynos
Copy link
Copy Markdown
Owner Author

leynos commented Apr 21, 2026

@coderabbitai Please suggest a fix for this issue and supply a prompt for an AI coding agent to enable it to apply the fix. Include the file and symbol names indicated in the issue at the head of your response.

src/cli/config_merge.rs

Comment on file

    composer: &mut MergeComposer,
    errors: &mut Vec<Arc<ortho_config::OrthoError>>,
    directory: Option<&Path>,
    cli: &Cli,

❌ New issue: Bumpy Road Ahead
push_file_layers has 2 blocks with nested conditional logic. Any nesting of 2 or deeper is considered. Threshold is 2 blocks per function

@coderabbitai

This comment was marked as resolved.

@coderabbitai

This comment was marked as resolved.

…lication

- Added ConfigTestHarness struct to unify repeated env lock, temp dirs, cwd guard, and env var setup in CLI integration tests.
- Updated tests in cli_tests/config_selection.rs and related modules to use ConfigTestHarness, improving readability and maintainability.
- Fixed test cwd teardown hazards by properly dropping guards after assertions, stabilizing parallel test execution.
- Simplified load_layers_from_path calls in config_merge.rs with helper push_layers_result for cleaner error handling.
- Documented observations and decisions related to tests and config path handling in docs/execplans/3-11-3-expose-config-path-and-netsuke-config.md.

These changes improve test suite stability and code clarity without altering external behavior.

Co-authored-by: devboxerhub[bot] <devboxerhub[bot]@users.noreply.github.com>
@leynos leynos changed the title Expose --config path and NETSUKE_CONFIG precedence Expose --config <PATH> and NETSUKE_CONFIG precedence Apr 21, 2026
codescene-delta-analysis[bot]

This comment was marked as outdated.

@leynos
Copy link
Copy Markdown
Owner Author

leynos commented Apr 21, 2026

@coderabbitai Please suggest a fix for this issue and supply a prompt for an AI coding agent to enable it to apply the fix. Include the file and symbol names indicated in the issue at the head of your response. Ensure that this is validated against the current version of the codegraph.

If further refinement to address this finding would be deleterious, please supply a clear explanatory one to two paragraph markdown message I can paste into the CodeScene web ui's diagnostic suppression function so this diagnostic can be silenced.

tests/cli_tests/config_selection.rs

Comment on lines +96 to +112

fn config_flag_loads_specified_file() -> Result<()> {
    let h = ConfigTestHarness::setup()?;
    let _config_guard = EnvVarGuard::remove("NETSUKE_CONFIG");
    let _legacy_guard = EnvVarGuard::remove("NETSUKE_CONFIG_PATH");
    let _theme_guard = EnvVarGuard::remove("NETSUKE_THEME");

    let custom_path = h.write_config("custom.toml", "theme = \"unicode\"\n")?;
    let custom_arg = custom_path.to_string_lossy().into_owned();

    let merged = parse_and_merge(&["netsuke", "--config", &custom_arg])?;
    ensure!(
        merged.theme == Some(ThemePreference::Unicode),
        "explicit --config file should be loaded"
    );
    let _project_root = h.project.path();
    Ok(())
}

❌ New issue: Code Duplication
The module contains 2 functions with similar structure: config_flag_loads_specified_file,config_flag_skips_project_discovery

@coderabbitai

This comment was marked as resolved.

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.

1 participant