Skip to content

Conversation

@omertuc
Copy link
Contributor

@omertuc omertuc commented Aug 12, 2025

We want to support environment variable replacement in the configuration similarly to how it is done in llama-stack.

Example use case / motivation:

The config, which since 3f7ed75 can contain a password to a database, requires users to move their entire config to a Kubernetes secret, as it now contains sensitive information, rather than a configmap. If instead we supported environment variable replacement, users could keep their config in a configmap and just set the password in a secret as k8s allows you to load secret values as environment variables in pods.

Since users of lightspeed-stack are already familiar with the syntax for environment variable replacement from llama-stack, we can use the same function from llama-stack to handle this.

Description

Type of change

  • Refactor
  • New feature
  • Bug fix
  • CVE fix
  • Optimization
  • Documentation Update
  • Configuration Update
  • Bump-up service version
  • Bump-up dependent library
  • Bump-up library or tool used for development (does not change the final image)
  • CI configuration change
  • Konflux configuration change
  • Unit tests improvement
  • Integration tests improvement
  • End to end tests improvement

Related Tickets & Documents

  • Related Issue #
  • Closes #

Checklist before requesting a review

  • I have performed a self-review of my code.
  • PR has passed all pre-merge test jobs.
  • If it is a core feature, I have added thorough tests.

Testing

  • Please provide detailed steps to perform tests related to this code change.
  • How were the fix/results from this change verified? Please provide relevant screenshots or results.

Checked that it works. Since it's a borrowed function, testing seems unnecessary

Summary by CodeRabbit

  • New Features
    • Configuration files now support environment variable placeholders. You can reference variables (e.g., ${DB_PASSWORD}, ${API_URL}) in your YAML config, and they will be substituted from your environment at load time.
    • Works transparently with existing configurations—no changes to keys or structure required. This helps keep sensitive or environment-specific values out of your config files while preserving current behavior.

We want to support environment variable replacement in the configuration
similarly to how it is done in llama-stack.

Example use case / motivation:

The config, which since 3f7ed75 can
contain a password to a database, requires users to move their entire
config to a Kubernetes secret, as it now contains sensitive information,
rather than a configmap. If instead we supported environment variable
replacement, users could keep their config in a configmap and just set
the password in a secret as k8s allows you to load secret values as
environment variables in pods.

Since users of lightspeed-stack are already familiar with the syntax
for environment variable replacement from llama-stack, we can use the
same function from llama-stack to handle this.
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Aug 12, 2025

Walkthrough

Adds environment variable substitution during configuration loading by invoking replace_env_vars on the YAML-loaded config dict within AppConfig.load_configuration. No changes to public interfaces or other behavior.

Changes

Cohort / File(s) Summary of Changes
Configuration Loading
src/configuration.py
Import replace_env_vars from llama_stack.core.stack and apply it to the YAML-loaded config dict before instantiating the Configuration model; no public API/signature changes.

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant AppConfig
    participant YAMLLoader
    participant EnvSubst as replace_env_vars
    participant Model as Configuration

    User->>AppConfig: load_configuration(path)
    AppConfig->>YAMLLoader: load YAML
    YAMLLoader-->>AppConfig: config_dict
    AppConfig->>EnvSubst: replace_env_vars(config_dict)
    EnvSubst-->>AppConfig: config_dict (resolved)
    AppConfig->>Model: instantiate(Configuration, dict)
    Model-->>AppConfig: configuration instance
    AppConfig-->>User: AppConfig with resolved config
Loading

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~7 minutes

Poem

I nibbled through configs, hop-hop hooray,
Swapped ${SECRETS} with carrots today.
YAML burrows cleaned, envs tucked tight,
Now settings sparkle in moonlit byte.
Thump goes my paw—deploys take flight!

✨ Finishing Touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

CodeRabbit Commands (Invoked using PR/Issue comments)

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

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Status, Documentation and Community

  • Visit our Status Page to check the current availability of CodeRabbit.
  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (1)
src/configuration.py (1)

6-9: llama-stack dependency pinned—confirm replace_env_vars API stability

  • pyproject.toml (lines 28–29) declares and pins
    • llama-stack==0.2.17
    • llama-stack-client==0.2.17
  • src/configuration.py
    • line 8: from llama_stack.core.stack import replace_env_vars
    • line 46: uses replace_env_vars(config_dict)

Ensure that replace_env_vars is part of llama-stack’s stable, public API. If it isn’t guaranteed to remain stable, introduce a thin wrapper in this repo to isolate future upstream changes.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 2004d97 and af75acc.

📒 Files selected for processing (1)
  • src/configuration.py (3 hunks)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: build-pr
  • GitHub Check: e2e_tests

Comment on lines 43 to 49
"""Load configuration from YAML file."""
with open(filename, encoding="utf-8") as fin:
config_dict = yaml.safe_load(fin)
config_dict = replace_env_vars(config_dict)
logger.info("Loaded configuration: %s", config_dict)
self.init_from_dict(config_dict)

Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

⚠️ Potential issue

Stop logging full configuration (secrets leak) and harden env-var substitution handling.

Now that secrets can come from env vars, logging the entire config at info level risks leaking credentials. Also, yaml.safe_load can return None on empty files; passing that into replace_env_vars will likely error.

  • Do not log the full configuration.
  • Handle None from yaml.safe_load.
  • Add defensive error handling around replace_env_vars to fail fast with a clear message.

Apply this diff:

         with open(filename, encoding="utf-8") as fin:
-            config_dict = yaml.safe_load(fin)
-            config_dict = replace_env_vars(config_dict)
-            logger.info("Loaded configuration: %s", config_dict)
+            config_dict = yaml.safe_load(fin) or {}
+            try:
+                config_dict = replace_env_vars(config_dict)
+            except Exception as e:
+                logger.error("Failed to apply environment variable substitution: %s", e)
+                raise
+            # Avoid logging secrets; log only the top-level sections/keys.
+            logger.info("Loaded configuration sections: %s", list(config_dict.keys()))
             self.init_from_dict(config_dict)

Optional follow-ups I can help with:

  • Add unit tests covering nested env-var replacement, missing variables behavior, and type casting to ensure values still validate against Configuration. Want me to draft these?
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
"""Load configuration from YAML file."""
with open(filename, encoding="utf-8") as fin:
config_dict = yaml.safe_load(fin)
config_dict = replace_env_vars(config_dict)
logger.info("Loaded configuration: %s", config_dict)
self.init_from_dict(config_dict)
"""Load configuration from YAML file."""
with open(filename, encoding="utf-8") as fin:
config_dict = yaml.safe_load(fin) or {}
try:
config_dict = replace_env_vars(config_dict)
except Exception as e:
logger.error("Failed to apply environment variable substitution: %s", e)
raise
# Avoid logging secrets; log only the top-level sections/keys.
logger.info("Loaded configuration sections: %s", list(config_dict.keys()))
self.init_from_dict(config_dict)
🤖 Prompt for AI Agents
In src/configuration.py around lines 43 to 49, stop logging the entire
configuration (to avoid leaking secrets), handle yaml.safe_load possibly
returning None, and add defensive error handling around replace_env_vars to fail
fast with a clear message; specifically, treat a None result from safe_load as
an empty dict (or raise a clear error), wrap the call to replace_env_vars in a
try/except that catches exceptions and raises/ logs a concise ValueError with
context (but do not include config contents or secret values), and replace the
info-level log of the full config with a non-sensitive message (e.g.,
"configuration loaded" or a debug log of a sanitized summary) before calling
self.init_from_dict.

Copy link
Member

@maorfr maorfr left a comment

Choose a reason for hiding this comment

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

/lgtm

Copy link
Contributor

@tisnik tisnik left a comment

Choose a reason for hiding this comment

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

LGTM

@tisnik tisnik merged commit 701065b into lightspeed-core:main Aug 12, 2025
18 checks passed
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.

3 participants