From 51fdce7eea5363554c8ac84b625abdabd0341e8d Mon Sep 17 00:00:00 2001 From: Paul Payne Date: Sat, 27 Jun 2026 12:46:51 -0700 Subject: [PATCH] feat: Add support for secret environment keys in info display and run command execution --- cli/src/castle_cli/commands/info.py | 3 +++ cli/src/castle_cli/commands/run_cmd.py | 19 +++++++++++++++++++ 2 files changed, 22 insertions(+) diff --git a/cli/src/castle_cli/commands/info.py b/cli/src/castle_cli/commands/info.py index 83641d8..3f6dcd1 100644 --- a/cli/src/castle_cli/commands/info.py +++ b/cli/src/castle_cli/commands/info.py @@ -144,6 +144,8 @@ def run_info(args: argparse.Namespace) -> int: print(f" {BOLD}env{RESET}:") for key, val in deployed.env.items(): print(f" {key}={val}") + if deployed.secret_env_keys: + print(f" {BOLD}secrets{RESET}: {', '.join(deployed.secret_env_keys)}") else: print(f"\n {DIM}not deployed (run 'castle deploy'){RESET}") @@ -205,6 +207,7 @@ def _info_json( "runner": deployed.runner, "run_cmd": deployed.run_cmd, "env": deployed.env, + "secret_env_keys": deployed.secret_env_keys, "port": deployed.port, "managed": deployed.managed, } diff --git a/cli/src/castle_cli/commands/run_cmd.py b/cli/src/castle_cli/commands/run_cmd.py index a5ede82..988dd9e 100644 --- a/cli/src/castle_cli/commands/run_cmd.py +++ b/cli/src/castle_cli/commands/run_cmd.py @@ -12,11 +12,29 @@ import os import subprocess from pathlib import Path +from castle_core.generators.systemd import secret_env_path from castle_core.registry import REGISTRY_PATH, load_registry from castle_cli.config import load_config +def _load_secret_env(name: str) -> dict[str, str]: + """Read a deployment's generated secret env file (KEY=value lines), if any. + + Secrets are kept out of the registry, so a foreground run merges them from the + file systemd/docker would otherwise load, matching the deployed environment. + """ + path = secret_env_path(name) + if not path.exists(): + return {} + out: dict[str, str] = {} + for line in path.read_text().splitlines(): + if "=" in line and not line.startswith("#"): + key, val = line.split("=", 1) + out[key] = val + return out + + def _run_program(name: str, extra: list[str]) -> int | None: """Run a program's declared `run` command in the foreground. @@ -76,5 +94,6 @@ def run_run(args: argparse.Namespace) -> int: cmd = list(deployed.run_cmd) + extra_args env = dict(os.environ) env.update(deployed.env) + env.update(_load_secret_env(name)) print(f"Running {name}: {' '.join(cmd)}") return subprocess.run(cmd, env=env).returncode