refactor: Enhance component info and list commands with deployed state from registry
This commit is contained in:
@@ -13,6 +13,19 @@ BOLD = "\033[1m"
|
||||
RESET = "\033[0m"
|
||||
CYAN = "\033[96m"
|
||||
DIM = "\033[2m"
|
||||
GREEN = "\033[92m"
|
||||
RED = "\033[91m"
|
||||
|
||||
|
||||
def _load_deployed_component(name: str) -> object | None:
|
||||
"""Try to load a specific deployed component from registry."""
|
||||
try:
|
||||
from castle_core.registry import load_registry
|
||||
|
||||
registry = load_registry()
|
||||
return registry.deployed.get(name)
|
||||
except (FileNotFoundError, ValueError):
|
||||
return None
|
||||
|
||||
|
||||
def run_info(args: argparse.Namespace) -> int:
|
||||
@@ -25,6 +38,7 @@ def run_info(args: argparse.Namespace) -> int:
|
||||
return 1
|
||||
|
||||
manifest = config.components[name]
|
||||
deployed = _load_deployed_component(name)
|
||||
|
||||
if getattr(args, "json", False):
|
||||
data = manifest.model_dump(exclude_none=True)
|
||||
@@ -32,6 +46,14 @@ def run_info(args: argparse.Namespace) -> int:
|
||||
claude_md = _find_claude_md(config.root, manifest.source_dir or name)
|
||||
if claude_md:
|
||||
data["claude_md"] = claude_md
|
||||
if deployed:
|
||||
data["deployed"] = {
|
||||
"runner": deployed.runner,
|
||||
"run_cmd": deployed.run_cmd,
|
||||
"env": deployed.env,
|
||||
"port": deployed.port,
|
||||
"managed": deployed.managed,
|
||||
}
|
||||
print(json.dumps(data, indent=2))
|
||||
return 0
|
||||
|
||||
@@ -107,6 +129,21 @@ def run_info(args: argparse.Namespace) -> int:
|
||||
for cap in manifest.consumes:
|
||||
print(f" - {cap.type}" + (f" ({cap.name})" if cap.name else ""))
|
||||
|
||||
# Deployed state from registry
|
||||
if deployed:
|
||||
print(f"\n {GREEN}{BOLD}deployed{RESET}")
|
||||
print(f" {'─' * 36}")
|
||||
print(f" {BOLD}run_cmd{RESET}: {' '.join(deployed.run_cmd)}")
|
||||
if deployed.port is not None:
|
||||
print(f" {BOLD}port{RESET}: {deployed.port}")
|
||||
print(f" {BOLD}managed{RESET}: {deployed.managed}")
|
||||
if deployed.env:
|
||||
print(f" {BOLD}env{RESET}:")
|
||||
for key, val in deployed.env.items():
|
||||
print(f" {key}={val}")
|
||||
else:
|
||||
print(f"\n {DIM}not deployed (run 'castle deploy {name}'){RESET}")
|
||||
|
||||
# Show CLAUDE.md if it exists
|
||||
source_dir = manifest.source_dir or name
|
||||
claude_md = _find_claude_md(config.root, source_dir)
|
||||
|
||||
@@ -4,14 +4,19 @@ from __future__ import annotations
|
||||
|
||||
import argparse
|
||||
import json
|
||||
import logging
|
||||
|
||||
from castle_cli.config import load_config
|
||||
from castle_cli.manifest import Role
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
# Terminal colors
|
||||
BOLD = "\033[1m"
|
||||
RESET = "\033[0m"
|
||||
DIM = "\033[2m"
|
||||
GREEN = "\033[92m"
|
||||
RED = "\033[91m"
|
||||
|
||||
ROLE_COLORS: dict[str, str] = {
|
||||
Role.SERVICE: "\033[92m", # green
|
||||
@@ -24,9 +29,21 @@ ROLE_COLORS: dict[str, str] = {
|
||||
}
|
||||
|
||||
|
||||
def _load_deployed() -> dict[str, object] | None:
|
||||
"""Try to load deployed state from registry, return None if unavailable."""
|
||||
try:
|
||||
from castle_core.registry import load_registry
|
||||
|
||||
registry = load_registry()
|
||||
return registry.deployed
|
||||
except (FileNotFoundError, ValueError):
|
||||
return None
|
||||
|
||||
|
||||
def run_list(args: argparse.Namespace) -> int:
|
||||
"""List all components."""
|
||||
config = load_config()
|
||||
deployed = _load_deployed()
|
||||
|
||||
components = config.components
|
||||
|
||||
@@ -40,11 +57,16 @@ def run_list(args: argparse.Namespace) -> int:
|
||||
entry: dict = {
|
||||
"name": name,
|
||||
"roles": [r.value for r in manifest.roles],
|
||||
"deployed": deployed is not None and name in deployed,
|
||||
}
|
||||
if manifest.description:
|
||||
entry["description"] = manifest.description
|
||||
if manifest.expose and manifest.expose.http:
|
||||
entry["port"] = manifest.expose.http.internal.port
|
||||
if deployed and name in deployed:
|
||||
dep = deployed[name]
|
||||
if dep.port is not None:
|
||||
entry["port"] = dep.port
|
||||
output.append(entry)
|
||||
print(json.dumps(output, indent=2))
|
||||
return 0
|
||||
@@ -72,8 +94,18 @@ def run_list(args: argparse.Namespace) -> int:
|
||||
port_str = ""
|
||||
if manifest.expose and manifest.expose.http:
|
||||
port_str = f" :{manifest.expose.http.internal.port}"
|
||||
|
||||
# Show deployed status indicator
|
||||
if deployed is not None:
|
||||
status = f"{GREEN}●{RESET}" if name in deployed else f"{RED}○{RESET}"
|
||||
else:
|
||||
status = f"{DIM}?{RESET}"
|
||||
|
||||
desc = f" {DIM}{manifest.description}{RESET}" if manifest.description else ""
|
||||
print(f" {BOLD}{name}{RESET}{port_str}{desc}")
|
||||
print(f" {status} {BOLD}{name}{RESET}{port_str}{desc}")
|
||||
|
||||
if deployed is None:
|
||||
print(f"\n{DIM}(no registry — run 'castle deploy' to generate){RESET}")
|
||||
|
||||
print()
|
||||
return 0
|
||||
|
||||
Reference in New Issue
Block a user