Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions codebase_rag/cli.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import asyncio
from importlib.metadata import version as get_version
from pathlib import Path

import typer
Expand Down Expand Up @@ -34,6 +35,15 @@
)


def _version_callback(value: bool) -> None:
if value:
app_context.console.print(
cs.CLI_MSG_VERSION.format(version=get_version("code-graph-rag")),
highlight=False,
)
raise typer.Exit()


def validate_models_early() -> None:
try:
orchestrator_config = settings.active_orchestrator_config
Expand All @@ -58,6 +68,14 @@ def _update_and_validate_models(orchestrator: str | None, cypher: str | None) ->

@app.callback()
def _global_options(
version: bool | None = typer.Option(
None,
"--version",
"-v",
help=ch.HELP_VERSION,
callback=_version_callback,
is_eager=True,
),
quiet: bool = typer.Option(
False,
"--quiet",
Expand Down
1 change: 1 addition & 0 deletions codebase_rag/cli_help.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ class CLICommandName(StrEnum):
HELP_REPO_PATH_INDEX = "Path to the target repository to index."
HELP_REPO_PATH_OPTIMIZE = "Path to the repository to optimize"
HELP_REPO_PATH_WATCH = "Path to the repository to watch."
HELP_VERSION = "Show the version and exit."

HELP_UPDATE_GRAPH = "Update the knowledge graph by parsing the repository"
HELP_CLEAN_DB = "Clean the database before updating (use when adding first repo)"
Expand Down
1 change: 1 addition & 0 deletions codebase_rag/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -234,6 +234,7 @@ class GoogleProviderType(StrEnum):
CLI_MSG_EXPORTING_DATA = "Exporting graph data..."
CLI_MSG_OPTIMIZATION_TERMINATED = "\nOptimization session terminated by user."
CLI_MSG_MCP_TERMINATED = "\nMCP server terminated by user."
CLI_MSG_VERSION = "code-graph-rag version {version}"
CLI_MSG_HINT_TARGET_REPO = (
"\nHint: Make sure TARGET_REPO_PATH environment variable is set."
)
Expand Down
26 changes: 26 additions & 0 deletions codebase_rag/tests/test_cli_smoke.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
import subprocess
import sys
from importlib.metadata import version as get_version
from pathlib import Path

import pytest

from codebase_rag import constants as cs


def test_help_command_works() -> None:
repo_root = Path(__file__).parent.parent.parent
Expand Down Expand Up @@ -32,3 +35,26 @@ def test_import_cli_module() -> None:
assert hasattr(cli, "app"), "CLI module missing app attribute"
except ImportError as e:
pytest.fail(f"Failed to import cli module: {e}")


def test_version_flag() -> None:
repo_root = Path(__file__).parent.parent.parent

for flag in ["--version", "-v"]:
result = subprocess.run(
[sys.executable, "-m", "codebase_rag.cli", flag],
check=False,
cwd=repo_root,
capture_output=True,
text=True,
timeout=30,
)

assert result.returncode == 0, (
f"{flag} exited with code {result.returncode}: {result.stderr}"
)
expected = cs.CLI_MSG_VERSION.format(version=get_version("code-graph-rag"))
assert result.stdout.strip() == expected, (
f"{flag} output did not match expected format: {repr(result.stdout)}"
)
assert result.stderr == "", f"Unexpected stderr for {flag}: {result.stderr}"
Copy link
Contributor

Choose a reason for hiding this comment

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

medium

The assertion assert result.stderr == "", f"Unexpected stderr for {flag}: {result.stderr}" is good for ensuring clean output. However, in some environments, typer.echo might write to stderr instead of stdout depending on how the output stream is configured or redirected. While typer.echo typically writes to stdout, it's safer to check if stderr is empty or contains only expected output, especially when dealing with CLI tools that might have subtle differences in output streams across platforms or configurations. For this specific case, since typer.echo is used, it's highly probable it will write to stdout, but it's a good practice to be aware of this potential edge case.