Skip to content

Conversation

@tisnik
Copy link
Contributor

@tisnik tisnik commented Aug 25, 2025

Description

Dump config operation does not need to connect to Llama Stack

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

Summary by CodeRabbit

  • New Features
    • Added an immediate configuration dump mode: using -d/--dump-configuration now outputs the configuration as JSON and exits without starting the server or performing version checks, enabling faster config inspection for scripts/CI.
    • Ensured version checks run early during normal startup so the server only starts after compatibility is validated.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Aug 25, 2025

Warning

Rate limit exceeded

@tisnik has exceeded the limit for the number of commits or files that can be reviewed per hour. Please wait 0 minutes and 19 seconds before requesting another review.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

📥 Commits

Reviewing files that changed from the base of the PR and between 5e50c15 and 9cb65a2.

📒 Files selected for processing (1)
  • src/lightspeed_stack.py (1 hunks)

Walkthrough

Adds an early-exit for -d/--dump-configuration to write configuration JSON and return before client creation, version checks, and UVicorn startup. For the normal path, the code now creates the AsyncLlamaStackClient, runs a Llama Stack version check, then starts UVicorn unconditionally after the check.

Changes

Cohort / File(s) Summary
Startup flow & dump handling
src/lightspeed_stack.py
Move dump-configuration handling earlier to produce JSON and return immediately; create AsyncLlamaStackClient in the non-dump path; run check_llama_stack_version(client) via asyncio.run() after client creation; start UVicorn unconditionally after the version check; add clarifying comment before the version check.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  participant CLI as CLI Args
  participant Main as main()
  participant Cfg as Config
  participant Client as AsyncLlamaStackClient
  participant Llama as Llama Stack Checker
  participant UVI as UVicorn

  Note over Main: Application startup

  Main->>Cfg: parse args & build configuration
  alt Dump mode (-d/--dump-configuration)
    Main->>Cfg: dump configuration -> configuration.json
    Note over Main: log success / exit early (no client, no version check, no UVicorn)
    Main-->>Main: return / SystemExit on failure
  else Normal mode
    Main->>Client: create AsyncLlamaStackClient
    Note right of Main: Version compatibility check (new)
    Main->>Llama: asyncio.run(check_llama_stack_version(client))
    Llama-->>Main: compatibility result
    alt Version compatible
      Main->>UVI: start UVicorn server (unconditional after check)
    else Version incompatible
      Main-->>Main: handle/report error (startup prevented)
    end
  end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Poem

I nibble configs, tidy and bright,
Dump the carrots, then sleep at night.
No client stirring when flags are set,
I check the versions, then the server's met.
A hop, a thump, the startup's right. 🥕

✨ 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: 0

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
src/lightspeed_stack.py (2)

61-65: Do not log full configuration objects; likely secret/API-key leakage.

These info logs will stringify the entire configuration, which (per models/client config) can include api_key and TLS key password. That’s a security risk and may leak credentials into logs.

Suggested approach (outside this range):

  • Replace with a simple “loaded from path” message at INFO and move any detailed config to DEBUG with redaction.
logger.info("Loaded configuration from %s", args.config_file)

if args.verbose:
    safe = configuration.configuration.model_dump(
        exclude={"llama_stack": {"api_key"},
                 "service": {"tls_config": {"tls_key_password"}}}
    )
    logger.debug("Configuration (redacted): %s", safe)

Or drop the detailed config log entirely.


29-35: Wire up -v/--verbose to adjust logging level

The --verbose flag is parsed but never used, so it currently has no effect. After parsing arguments in main(), set the root logger and its handlers to DEBUG when args.verbose is true, otherwise keep INFO.

• In src/lightspeed_stack.py, immediately after line 59 (args = parser.parse_args()), insert:

level = logging.DEBUG if args.verbose else logging.INFO
root = logging.getLogger()
root.setLevel(level)
for h in root.handlers:
    h.setLevel(level)

This ensures -v/--verbose actually makes the output verbose.

🧹 Nitpick comments (5)
src/lightspeed_stack.py (5)

67-71: Early-return for dump mode is correct; add error handling and an explicit success log.

Right now a filesystem error (permissions, read-only FS, etc.) would raise and print a stack trace. Also, there’s no positive confirmation that the dump completed. Wrap the dump in try/except and exit non‑zero on failure.

Apply this diff within this block:

     if args.dump_configuration:
-        configuration.configuration.dump()
-        return
+        try:
+            configuration.configuration.dump()
+            logger.info("Configuration dumped to configuration.json")
+        except Exception as exc:
+            logger.error("Failed to dump configuration: %s", exc)
+            raise SystemExit(1)
+        return

Optional follow-ups (outside this range):

  • Add an output path flag so users can choose the target file, defaulting to configuration.json.
# in create_argument_parser()
parser.add_argument(
    "-o", "--output", dest="dump_output", metavar="FILE",
    help="write dumped configuration to FILE (default: configuration.json)",
    default="configuration.json",
)
  • Use it in dump mode:
filename = args.dump_output
configuration.configuration.dump(filename)
logger.info("Configuration dumped to %s", filename)

79-81: Handle version-check failures cleanly and use a non-zero exit code.

If the Llama Stack is incompatible or unreachable, this currently raises and prints a traceback. Gracefully log and exit to make the UX tighter.

Apply this diff:

-    # check if the Llama Stack version is supported by the service
-    asyncio.run(check_llama_stack_version(client))
+    # check if the Llama Stack version is supported by the service
+    try:
+        asyncio.run(check_llama_stack_version(client))
+    except Exception as exc:
+        logger.error("Llama Stack version check failed: %s", exc)
+        raise SystemExit(2)

Optional: avoid creating two event loops by combining client init + version check into one coroutine:

async def _init_and_check(cfg):
    holder = AsyncLlamaStackClientHolder()
    await holder.load(cfg.llama_stack)
    await check_llama_stack_version(holder.get_client())

# then:
asyncio.run(_init_and_check(configuration.configuration))

29-35: Nit: store_true options should default to False, not None.

Using None works (falsy), but the conventional and clearer default for store_true flags is False.

Suggested adjustments (outside this range):

parser.add_argument("-v", "--verbose", action="store_true", default=False, help="make it verbose")
parser.add_argument("-d", "--dump-configuration", action="store_true", default=False,
                    help="dump actual configuration into JSON file and quit")

Also applies to: 37-43


73-81: Optional: avoid multiple event loops by batching async startup steps.

You call asyncio.run twice (once for client init, once for version check). It’s fine, but a single run with a small orchestrator coroutine is cleaner and slightly cheaper.

Example (outside this range):

async def _startup(cfg):
    holder = AsyncLlamaStackClientHolder()
    await holder.load(cfg.llama_stack)
    await check_llama_stack_version(holder.get_client())

asyncio.run(_startup(configuration.configuration))

67-71: Add a regression test for dump mode to ensure no Llama Stack connection or Uvicorn startup occurs.

Safeguard the refactor by asserting that neither client loading nor Uvicorn is called when -d is provided.

Example pytest (outside this range):

import builtins
import json
from unittest.mock import patch
from src import lightspeed_stack as ls

def test_dump_mode_skips_client_and_uvicorn(tmp_path, monkeypatch):
    out = tmp_path / "conf.json"
    # simulate CLI args
    monkeypatch.setenv("PYTHONWARNINGS", "ignore")  # avoid noise
    with patch.object(ls, "create_argument_parser") as cap:
        p = ls.ArgumentParser()
        p.add_argument("-d", "--dump-configuration", action="store_true", default=True)
        p.add_argument("-c", "--config", default="lightspeed-stack.yaml")
        cap.return_value = p

        # stub configuration dump target
        class Cfg:
            def dump(self, filename="configuration.json"):
                with open(out, "w", encoding="utf-8") as f:
                    f.write("{}")

        class Ctx:
            configuration = Cfg()
            llama_stack_configuration = object()
            service_configuration = object()
            def load_configuration(self, _): pass

        with patch.object(ls, "configuration", Ctx()), \
             patch("runners.uvicorn.start_uvicorn") as start, \
             patch("client.AsyncLlamaStackClientHolder.load") as load:
            ls.main()
            start.assert_not_called()
            load.assert_not_called()
            assert out.exists()

Want me to open a follow-up PR with this test?

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between f742e1d and 50acf61.

📒 Files selected for processing (1)
  • src/lightspeed_stack.py (1 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
src/lightspeed_stack.py (5)
src/configuration.py (2)
  • configuration (55-60)
  • service_configuration (63-68)
src/models/config.py (1)
  • dump (316-319)
src/client.py (3)
  • AsyncLlamaStackClientHolder (18-50)
  • load (23-42)
  • get_client (44-50)
src/utils/llama_stack_version.py (1)
  • check_llama_stack_version (22-31)
src/runners/uvicorn.py (1)
  • start_uvicorn (12-31)
⏰ 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
🔇 Additional comments (1)
src/lightspeed_stack.py (1)

82-83: LGTM: Unconditional Uvicorn startup is safely gated by the early return.

This matches the PR goal: dump mode exits before reaching service startup.

@tisnik tisnik force-pushed the dump-config-does-not-need-to-connect-to-llama-stack branch 3 times, most recently from bd1e375 to 73dcf3d Compare August 25, 2025 07:30
@tisnik tisnik force-pushed the dump-config-does-not-need-to-connect-to-llama-stack branch from 73dcf3d to 9cb65a2 Compare August 25, 2025 07:32
@tisnik tisnik merged commit 3e1552e into lightspeed-core:main Aug 25, 2025
18 checks passed
@tisnik tisnik changed the title Dump config operation does not need to connect to Llama Stack LCORE-585: Dump config operation does not need to connect to Llama Stack Aug 25, 2025
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