Skip to content

feat(configs): list configuration environment variables - #4350

Open
ParthibanRajasekaran wants to merge 43 commits into
apache:masterfrom
ParthibanRajasekaran:codex/issue-4322-config-env-vars
Open

ParthibanRajasekaran wants to merge 43 commits into
apache:masterfrom
ParthibanRajasekaran:codex/issue-4322-config-env-vars

Conversation

@ParthibanRajasekaran

Copy link
Copy Markdown

Implement --list-config-env-vars flag for iggy-server, iggy-connectors, and iggy-mcp.

Closes #4322

Problem

Users need a way to discover supported environment variables before loading configuration, useful for:

  • CI/CD pipeline automation
  • Configuration validation
  • Documentation generation
  • Troubleshooting configuration issues

Solution

Added --list-config-env-vars flag to all three binaries that:

  • Exits early (before dotenv, config loading, logging, runtimes)
  • Works even with missing configuration files
  • Outputs sorted, deduplicated IGGY_-prefixed variable names only (no values)
  • Writes nothing to stderr
  • Exits successfully with code 0

Implementation Details

  • ConfigEnv derive macro now exposes env_templates() method
  • Each binary calls ::env_templates() to collect derived variables
  • Manual variables (IGGY_CONFIG_PATH, IGGY_ENV_PATH, etc.) are chained in
  • Output is sorted and deduplicated before printing

Testing

Integration test validates:

  • All three binaries support the flag
  • Early exit with missing config/dotenv files
  • Clean stdout with no stderr output
  • Sorted and deduplicated output
  • Successful exit status (code 0)
  • All names start with IGGY_

@github-actions

Copy link
Copy Markdown

Thanks for the PR. It is labeled S-waiting-on-review and queued for review.

Slash commands (own line, regular comment) move it around the queue:

  • /ready - back to S-waiting-on-review after addressing feedback
  • /author - flip to S-waiting-on-author while you finish changes
  • /request-review @user-or-team - request a reviewer
  • /pin - exempt the PR from the stale bot, /unpin to undo

See CONTRIBUTING.md for details.

@github-actions github-actions Bot added the S-waiting-on-review PR is waiting on a reviewer label Sep 29, 2026
1. Documentation: Expand --list-config-env-vars help text to document
   template syntax (<N> for vector indices, <KEY> for connector keys,
   <FIELD> for plugin config fields) and behavior (early exit before
   any startup). Enables users to understand templates without reading code.

2. Consistency: Unify print_config_env_vars() across all three binaries
   to use static &'static str templates consistently, reducing allocations
   and code complexity in connectors binary.

3. Test coverage: Add comprehensive subprocess tests for edge cases:
   - Vector index template expansion (<N> and nested <N>_..._<N>)
   - Connector SINK/SOURCE and PLUGIN_CONFIG template formatting
   - Deduplication correctness across multiple runs
   - Early exit with invalid environment values (no validation before exit)

These improvements ensure implementation matches issue apache#4322 scope:
"Document the flag and placeholders in --help and configuration docs"
"Subprocess tests verify... index bounds and sink/source templates"
Ensures compliance with CONTRIBUTING.md code quality requirements.
@ParthibanRajasekaran

Copy link
Copy Markdown
Author

/ready

@hubcio

hubcio commented Sep 29, 2026

Copy link
Copy Markdown
Contributor

/skill team-review-slim

@github-actions github-actions 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.

Summary: The templates mirror the compiled env mappings and each listing covers the names its binary reads. The findings are duplication, documentation placement, a missing consistency test, an unused template field, and a panic when the listing's stdout closes early.

The head moved while this review ran (b98113ace reviewed, 5d2981aac now), so the findings stay in this body instead of on lines.

Counts: critical 0, warning 0, nit 5, simplification 5

Findings without an anchor on a changed line:

  • core/server/src/main.rs:116 simplification: print_config_env_vars copies 7 of the 14 names in SERVER_PROCESS_ENV_VARS, so the listing omits the other 7 and drifts on the next edit. Chain the constant instead of the literals.
  • core/connectors/runtime/src/main.rs:160 simplification: The listing hardcodes the IGGY_CONNECTORS_{TYPE}_{KEY}_ prefix that the runtime builds in ConnectorEnvProvider::with_connector_base_config. Reuse one prefix builder here, so the listing cannot drift from the names the runtime reads.
  • core/connectors/runtime/src/main.rs:168 simplification: The function builds three collections to produce one list: names, sink_source_templates and all_names. Collect into a single Vec<​String> and chain the sink and source templates into it.
  • core/configs/src/configs_impl/env_mapping.rs:41 simplification: max_elements records each placeholder's limit, but no production code reads it: the derive only copies it and the listing prints names alone. Print the limit beside each name, or drop the field and the limits chain.
  • core/integration/tests/config_env_listing.rs:127 simplification: config_env_listing_deduplicates_output reruns all three binaries to prove deduplication, but config_env_listing_exits_before_startup_for_each_binary already asserts strictly increasing output for the same binaries. Delete the test.
  • core/configs_derive/src/config_env.rs:398 nit: The template walk mirrors the mapping walk, and no test ties the two together, so one edit can desync the listing. Add a test that strips index digits from every env_mappings() name and looks it up in env_templates().
  • core/server/src/args.rs:95 nit: The help lists <​KEY> and <​FIELD>, but iggy-server prints neither. Only iggy-connectors emits those placeholders and its help explains none, so move the legend there.
  • core/server/src/args.rs:94 nit: --help prints this comment as written, so the backticks around <​N>, <​KEY> and <​FIELD> reach the operator's terminal. Drop the backticks.
  • core/integration/tests/config_env_listing.rs:154 nit: TcpConfig has no port field, so IGGY_TCP_PORT names no setting and the comment about an invalid port value is wrong. Drop the line, as the invalid IGGY_HTTP_ADDRESS already covers the case.
  • core/server/src/main.rs:127 nit: If the reader closes stdout early, this println! loop panics on the failed write and exits 101, as --list-config-env-vars | head does. Write with writeln! and stop on the first write error.

This review was generated by Claude Code 2.1.284 on deepseek-flash[1m]. Review the output before you act on it.

@hubcio

hubcio commented Sep 29, 2026 •

Copy link
Copy Markdown
Contributor

please use feat(configs) in the title. check .github/workflows/pr-title.yml

@codecov

codecov Bot commented Sep 29, 2026 •

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 92.59259% with 12 lines in your changes missing coverage. Please review.
✅ Project coverage is 74.63%. Comparing base (2d7fddb) to head (2a44277).

Files with missing lines Patch % Lines
core/configs/src/configs_impl/env_listing.rs 75.00% 3 Missing and 1 partial ⚠️
core/connectors/runtime/src/main.rs 89.18% 0 Missing and 4 partials ⚠️
core/ai/mcp/src/main.rs 87.50% 0 Missing and 2 partials ⚠️
core/configs_derive/src/config_env.rs 95.83% 0 Missing and 1 partial ⚠️
core/server/src/main.rs 92.30% 0 Missing and 1 partial ⚠️
Additional details and impacted files
@@              Coverage Diff              @@
##             master    #4350       +/-   ##
=============================================
- Coverage     87.96%   74.63%   -13.33%     
+ Complexity     1579     1578        -1     
=============================================
  Files          1290     1289        -1     
  Lines        230145   209753    -20392     
  Branches     193480   173089    -20391     
=============================================
- Hits         202440   156557    -45883     
- Misses        22980    48499    +25519     
+ Partials       4725     4697       -28     
Components Coverage Δ
Rust Core 72.81% <92.59%> (-16.26%) ⬇️
Java SDK 68.72% <ø> (-0.02%) ⬇️
C# SDK 77.61% <ø> (-0.02%) ⬇️
Python SDK 91.24% <ø> (ø)
PHP SDK 85.67% <ø> (ø)
Node SDK 96.57% <ø> (-0.03%) ⬇️
Go SDK 70.29% <ø> (+0.10%) ⬆️
Files with missing lines Coverage Δ
core/configs/src/configs_impl/env_mapping.rs 100.00% <100.00%> (ø)
...ore/configs/src/configs_impl/typed_env_provider.rs 91.06% <100.00%> (+0.02%) ⬆️
core/configs/src/server_config/cluster.rs 99.11% <100.00%> (+<0.01%) ⬆️
core/configs/src/server_config/server.rs 92.50% <100.00%> (+0.23%) ⬆️
core/connectors/runtime/src/configs/connectors.rs 65.10% <ø> (ø)
...s/runtime/src/configs/connectors/local_provider.rs 61.29% <100.00%> (+0.31%) ⬆️
core/server/src/server_error.rs 77.77% <ø> (ø)
core/configs_derive/src/config_env.rs 92.85% <95.83%> (-0.43%) ⬇️
core/server/src/main.rs 76.56% <92.30%> (+4.01%) ⬆️
core/ai/mcp/src/main.rs 72.05% <87.50%> (+2.38%) ⬆️
... and 2 more

... and 303 files with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@ParthibanRajasekaran ParthibanRajasekaran changed the title feat: list configuration environment variables feat(configs): list configuration environment variables Sep 29, 2026
@ParthibanRajasekaran

Copy link
Copy Markdown
Author

@hubcio PR title updated as per suggestion and the PR is now ready for review

…_vars

Use writeln! with error handling instead of println! to ensure the print_config_env_vars function
handles early pipe closure correctly, improving test coverage to 100%.
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
@ParthibanRajasekaran

Copy link
Copy Markdown
Author

/ready

@hubcio hubcio left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

the head does not compile at e9feb351a. please build and run prek run locally before the next push.

nit: core/server/README.md:30 says --replica-id is the only command line argument, but the server already had three flags and this PR adds a fourth. list the flags, or point to iggy-server --help.

Comment thread core/configs_derive/src/config_env.rs
Comment thread core/connectors/runtime/src/main.rs Outdated
Comment thread core/server/src/main.rs Outdated
Comment thread core/connectors/runtime/src/main.rs Outdated
Comment thread core/server/src/main.rs Outdated
Comment thread core/server/src/main.rs Outdated
Comment thread core/connectors/runtime/src/main.rs Outdated
Comment thread core/connectors/runtime/src/main.rs Outdated
Comment thread core/integration/tests/config_env_listing.rs Outdated
Comment thread core/configs_derive/src/config_env.rs
@github-actions github-actions Bot added S-waiting-on-author PR is waiting on author response and removed S-waiting-on-review PR is waiting on a reviewer labels Sep 30, 2026
@ParthibanRajasekaran

Copy link
Copy Markdown
Author

/ready

@hubcio

hubcio commented Oct 1, 2026 •

Copy link
Copy Markdown
Contributor

why arent you using precommit hooks? please dont push broken code to PR.

see CONTRIBUTING.md. besides precommit hooks you are required to run tests locally + they have to be passing.

ParthibanRajasekaran and others added 2 commits October 1, 2026 18:52
Applied consistent code formatting across all modified files to pass
precommit hook checks.

@hubcio hubcio left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

the tests don't build at cf9b0bf6: cargo check -p configs --tests fails with E0432, cargo fmt --all -- --check fails in 9 files, and clippy fails in the connectors main.rs. please run fmt, clippy with -D warnings and prek run locally before the next push.

Comment thread core/configs/src/configs_impl/env_mapping.rs Outdated
Comment thread core/connectors/runtime/src/main.rs Outdated
Comment thread core/server/src/server_error.rs Outdated
Comment thread core/integration/tests/config_env_listing/mod.rs Outdated
Comment thread core/connectors/runtime/src/main.rs Outdated
Comment thread core/integration/tests/config_env_listing/mod.rs Outdated
Comment thread core/configs/src/configs_impl/env_mapping.rs Outdated
Comment thread core/configs/src/configs_impl/env_listing.rs
Comment thread core/configs/src/configs_impl/env_listing.rs
Comment thread core/connectors/runtime/src/main.rs Outdated
@github-actions github-actions Bot added S-waiting-on-author PR is waiting on author response and removed S-waiting-on-review PR is waiting on a reviewer labels Oct 1, 2026
@ParthibanRajasekaran

Copy link
Copy Markdown
Author

/ready

@github-actions github-actions Bot added S-waiting-on-review PR is waiting on a reviewer and removed S-waiting-on-author PR is waiting on author response labels Oct 3, 2026

@hubcio hubcio left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

one warning left, the rest are nits and simplifications.

outside the diff:

  • nit: the connectors and MCP READMEs (core/connectors/runtime/README.md:48, core/ai/mcp/README.md:57) don't mention --list-config-env-vars. add a line each, with <KEY>, <N> and <FIELD> only in the connectors one.

"{name} is read by a sibling binary before its config loads, so the scan must skip it"
);
}
let runtime_env_vars = super::super::CONNECTORS_RUNTIME_ENV_VARS

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

warning: this test now takes its names from the same lists is_runtime_env_var reads, so it still passes if a path name drops out, and a debug build then panics when that var is set. pin the four literal names again.

@@ -625,19 +620,13 @@ mod tests {
#[test]

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

nit: the doc comment above still says the list check holds in both build profiles, but the assert! loop is gone and a release build now asserts nothing. restore the check or drop that sentence.

/// call, one error policy. A closed writer (e.g. `iggy-server --list-config-env-vars | head -1`)
/// is expected, not a failure: on `BrokenPipe` this stops writing and returns `Ok(())`. Any
/// other I/O error is real and is propagated so the caller exits non-zero.
pub fn print_env_var_names<I, S, W>(names: I, writer: &mut W) -> std::io::Result<()>

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

nit: the writer param is in now, but nothing drives it - add two unit tests with writers that fail with BrokenPipe (expect Ok) and StorageFull (expect Err).

pub const MCP_CONFIG_PATH_ENV: &str = "IGGY_MCP_CONFIG_PATH";
pub const MCP_ENV_PATH_ENV: &str = "IGGY_MCP_ENV_PATH";
pub const MCP_RUNTIME_ENV_VARS: &[&str] =
&["IGGY_DISPLAY_CONFIG", MCP_CONFIG_PATH_ENV, MCP_ENV_PATH_ENV];

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

nit: "IGGY_DISPLAY_CONFIG" is still a literal here and at line 58, but file_provider.rs:29 already has DISPLAY_CONFIG_ENV. make it pub(crate) and use it in both lists.


impl EnvVarTemplate {
/// Expands this template into every concrete mapping it represents.
pub fn expand(&self) -> Vec<EnvVarMapping> {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

nit: expand has one caller (expand_env_templates) and leaks two strings per mapping on every call - make it private and note the leak on expand_env_templates.

.arg("--list-config-env-vars")
.timeout(LIST_ENV_VARS_TIMEOUT);

for (key, value) in env {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

simplification: assert_cmd's Command has envs and args, so these two loops can be .envs(env).args(extra_args) on the builder.

assert!(
names
.iter()
.any(|name| name.contains("IGGY_CLUSTER_NODES_<N>_")),

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

simplification: the checks at lines 167, 192 and 198 are implied by the longer ones at 175, 216 and 220 - drop them.

let ty = &info.element_type;
let segment = &info.field_env_segment;
let field_name = &info.field_name;
if info.is_vec {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

simplification: the Vec and plain branches emit the same loop and differ only in the <N> segment and the limits - pick those at macro time and emit one loop.

let env_mappings_impl = if nested_fields.is_empty() && !has_prefix {
// Simple case: no nested fields, no prefix transformation needed
});
let template_prefix_application = if has_prefix {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

simplification: the prefix is known at macro time (generate_const_definitions already uses it), so bake it into the literals and drop this runtime pass that leaks a prefixed copy of every name.

/// via `--list-config-env-vars`, but still non-config. Included in
/// `SERVER_PROCESS_ENV_VARS` to suppress "unknown env var" warnings during
/// config scanning.
pub const SERVER_SCAN_ONLY_ENV_VARS: &[&str] = &[

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

simplification: keep scan-only and advertised as two disjoint lists and expose the union through one pub fn for the scan, the tests and the harness - then this const can be private too.

@github-actions github-actions Bot added S-waiting-on-author PR is waiting on author response and removed S-waiting-on-review PR is waiting on a reviewer labels Oct 4, 2026

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

S-waiting-on-author PR is waiting on author response

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add --list-config-env-vars to binaries that use the configs crate

2 participants