feat: Add new tools and configurations for Castle platform
- Introduced `uv.lock` for dependency management with various packages including `pytest`, `colorama`, and `pluggy`. - Added `pyrightconfig.json` for Python type checking configuration. - Expanded `recommendations.md` with detailed scaling recommendations and project management strategies. - Created shared `ruff.toml` for consistent linting across projects. - Developed `Castle Tools` with various utilities including Android backup, browser automation, document conversion, and search tools. - Implemented `backup-collect` and `schedule` tools for system administration tasks. - Enhanced `search` functionality with indexing and querying capabilities using Tantivy. - Added comprehensive documentation for each tool, including usage examples and installation instructions.
This commit is contained in:
96
cli/src/castle_cli/commands/run_cmd.py
Normal file
96
cli/src/castle_cli/commands/run_cmd.py
Normal file
@@ -0,0 +1,96 @@
|
||||
"""castle run - run a component in the foreground."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import argparse
|
||||
import os
|
||||
import shutil
|
||||
import subprocess
|
||||
import sys
|
||||
|
||||
from castle_cli.config import load_config, resolve_env_vars
|
||||
|
||||
|
||||
def run_run(args: argparse.Namespace) -> int:
|
||||
"""Run a component in the foreground (dev mode)."""
|
||||
config = load_config()
|
||||
name = args.name
|
||||
|
||||
if name not in config.components:
|
||||
print(f"Error: component '{name}' not found in castle.yaml")
|
||||
return 1
|
||||
|
||||
manifest = config.components[name]
|
||||
run = manifest.run
|
||||
|
||||
if run is None:
|
||||
print(f"Error: component '{name}' has no run spec")
|
||||
return 1
|
||||
|
||||
# Build command
|
||||
extra_args = getattr(args, "extra", []) or []
|
||||
cmd = _build_command(run, extra_args)
|
||||
if cmd is None:
|
||||
print(f"Error: unsupported runner '{run.runner}' for foreground execution")
|
||||
return 1
|
||||
|
||||
# Working directory
|
||||
cwd = config.root / (run.cwd or name)
|
||||
if not cwd.exists():
|
||||
print(f"Error: working directory '{cwd}' does not exist")
|
||||
return 1
|
||||
|
||||
# Merge environment
|
||||
env = dict(os.environ)
|
||||
resolved = resolve_env_vars(run.env, manifest)
|
||||
env.update(resolved)
|
||||
|
||||
# Run in foreground
|
||||
result = subprocess.run(cmd, cwd=cwd, env=env)
|
||||
return result.returncode
|
||||
|
||||
|
||||
def _build_command(run: object, extra_args: list[str]) -> list[str] | None:
|
||||
"""Build command list from RunSpec."""
|
||||
match run.runner:
|
||||
case "python_uv_tool":
|
||||
uv = shutil.which("uv") or "uv"
|
||||
cmd = [uv, "run", run.tool]
|
||||
cmd.extend(run.args)
|
||||
cmd.extend(extra_args)
|
||||
return cmd
|
||||
case "python_module":
|
||||
python = run.python or sys.executable
|
||||
cmd = [python, "-m", run.module]
|
||||
cmd.extend(run.args)
|
||||
cmd.extend(extra_args)
|
||||
return cmd
|
||||
case "command":
|
||||
cmd = list(run.argv)
|
||||
cmd.extend(extra_args)
|
||||
return cmd
|
||||
case "container":
|
||||
runtime = shutil.which("podman") or shutil.which("docker") or "podman"
|
||||
cmd = [runtime, "run", "--rm", "-it"]
|
||||
for cp, hp in run.ports.items():
|
||||
cmd.extend(["-p", f"{hp}:{cp}"])
|
||||
for vol in run.volumes:
|
||||
cmd.extend(["-v", vol])
|
||||
for key, val in run.env.items():
|
||||
cmd.extend(["-e", f"{key}={val}"])
|
||||
if run.workdir:
|
||||
cmd.extend(["-w", run.workdir])
|
||||
cmd.append(run.image)
|
||||
if run.command:
|
||||
cmd.extend(run.command)
|
||||
cmd.extend(run.args)
|
||||
cmd.extend(extra_args)
|
||||
return cmd
|
||||
case "node":
|
||||
pm = run.package_manager
|
||||
cmd = [pm, "run", run.script]
|
||||
cmd.extend(run.args)
|
||||
cmd.extend(extra_args)
|
||||
return cmd
|
||||
case _:
|
||||
return None
|
||||
Reference in New Issue
Block a user