Rename Castle -> Wild PC across the repo
Repo-side rename only (Phases 1-3 of the migration plan); the live box (~/.castle, systemd units, /data/castle, domains) is a separate cutover. - Slug `castle` -> `wildpc`: CLI command, module names (wildpc_core/cli/api), dist names, entry point `wildpc = wildpc_cli.main:main`. - Identifiers: CastleConfig/NATSClient/DirError/MDNS -> Wildpc*. - Env/constants: CASTLE_* -> WILDPC_*; ~/.castle -> ~/.wildpc, castle.yaml -> wildpc.yaml, /data/castle -> /data/wildpc. - Systemd UNIT_PREFIX castle- -> wildpc-; own programs castle-api/gateway/etc. - Display prose "Castle" -> "Wild PC" in docs, agent-guide files, README, frontend. - Package dirs and bootstrap yaml renamed via git mv; lockfiles regenerated; redundant nested uv.lock files dropped (workspace root lock is authoritative). Tests: core 273, cli 47, wildpc-api 120 all pass. Frontend type-checks + builds. Fixed a stale test fixture (secret_env_path kind arg) broken pre-rename.
This commit is contained in:
@@ -5,14 +5,14 @@ from __future__ import annotations
|
||||
from pathlib import Path
|
||||
from unittest.mock import patch
|
||||
|
||||
from castle_core.deploy import _build_run_cmd, _build_stop_cmd
|
||||
from castle_core.manifest import RunCompose, RunContainer, RunNode, RunPython
|
||||
from wildpc_core.deploy import _build_run_cmd, _build_stop_cmd
|
||||
from wildpc_core.manifest import RunCompose, RunContainer, RunNode, RunPython
|
||||
|
||||
|
||||
def test_python_runner_uses_uv_run_from_source(tmp_path: Path) -> None:
|
||||
"""A python service with a real source dir launches via `uv run --project`."""
|
||||
run = RunPython(launcher="python", program="my-svc")
|
||||
with patch("castle_core.deploy.shutil.which", return_value="/usr/bin/uv"):
|
||||
with patch("wildpc_core.deploy.shutil.which", return_value="/usr/bin/uv"):
|
||||
cmd = _build_run_cmd("my-svc", run, {}, [], source_dir=tmp_path)
|
||||
assert cmd == [
|
||||
"/usr/bin/uv",
|
||||
@@ -26,7 +26,7 @@ def test_python_runner_uses_uv_run_from_source(tmp_path: Path) -> None:
|
||||
|
||||
def test_python_runner_appends_args(tmp_path: Path) -> None:
|
||||
run = RunPython(launcher="python", program="my-svc", args=["--flag", "x"])
|
||||
with patch("castle_core.deploy.shutil.which", return_value="/usr/bin/uv"):
|
||||
with patch("wildpc_core.deploy.shutil.which", return_value="/usr/bin/uv"):
|
||||
cmd = _build_run_cmd("my-svc", run, {}, [], source_dir=tmp_path)
|
||||
assert cmd[-2:] == ["--flag", "x"]
|
||||
assert cmd[:5] == ["/usr/bin/uv", "run", "--project", str(tmp_path), "--no-dev"]
|
||||
@@ -36,7 +36,7 @@ def test_python_runner_falls_back_to_path_without_source() -> None:
|
||||
"""No resolvable source → PATH lookup of the script (no uv run)."""
|
||||
run = RunPython(launcher="python", program="my-svc")
|
||||
with patch(
|
||||
"castle_core.deploy.shutil.which", return_value="/home/u/.local/bin/my-svc"
|
||||
"wildpc_core.deploy.shutil.which", return_value="/home/u/.local/bin/my-svc"
|
||||
):
|
||||
cmd = _build_run_cmd("my-svc", run, {}, [], source_dir=None)
|
||||
assert cmd == ["/home/u/.local/bin/my-svc"]
|
||||
@@ -46,7 +46,7 @@ def test_python_runner_warns_when_unresolvable() -> None:
|
||||
"""No source and not on PATH → a warning, bare program name as last resort."""
|
||||
run = RunPython(launcher="python", program="my-svc")
|
||||
messages: list[str] = []
|
||||
with patch("castle_core.deploy.shutil.which", return_value=None):
|
||||
with patch("wildpc_core.deploy.shutil.which", return_value=None):
|
||||
cmd = _build_run_cmd("my-svc", run, {}, messages, source_dir=None)
|
||||
assert cmd == ["my-svc"]
|
||||
assert any("my-svc" in m for m in messages)
|
||||
@@ -55,7 +55,7 @@ def test_python_runner_warns_when_unresolvable() -> None:
|
||||
def test_node_runner_bakes_source_dir(tmp_path: Path) -> None:
|
||||
"""A node service runs the script in its source dir via `--dir` (no unit cwd)."""
|
||||
run = RunNode(launcher="node", script="gateway:watch:raw", package_manager="pnpm")
|
||||
with patch("castle_core.deploy.shutil.which", return_value="/usr/bin/pnpm"):
|
||||
with patch("wildpc_core.deploy.shutil.which", return_value="/usr/bin/pnpm"):
|
||||
cmd = _build_run_cmd("oc", run, {}, [], source_dir=tmp_path)
|
||||
assert cmd == ["/usr/bin/pnpm", "--dir", str(tmp_path), "run", "gateway:watch:raw"]
|
||||
|
||||
@@ -64,7 +64,7 @@ def test_node_runner_appends_args(tmp_path: Path) -> None:
|
||||
run = RunNode(
|
||||
launcher="node", script="start", package_manager="pnpm", args=["--port", "18789"]
|
||||
)
|
||||
with patch("castle_core.deploy.shutil.which", return_value="/usr/bin/pnpm"):
|
||||
with patch("wildpc_core.deploy.shutil.which", return_value="/usr/bin/pnpm"):
|
||||
cmd = _build_run_cmd("oc", run, {}, [], source_dir=tmp_path)
|
||||
assert cmd == [
|
||||
"/usr/bin/pnpm",
|
||||
@@ -80,7 +80,7 @@ def test_node_runner_appends_args(tmp_path: Path) -> None:
|
||||
def test_node_runner_without_source_omits_dir() -> None:
|
||||
"""No resolvable source → bare `pnpm run` (package manager still PATH-resolved)."""
|
||||
run = RunNode(launcher="node", script="start", package_manager="pnpm")
|
||||
with patch("castle_core.deploy.shutil.which", return_value="/usr/bin/pnpm"):
|
||||
with patch("wildpc_core.deploy.shutil.which", return_value="/usr/bin/pnpm"):
|
||||
cmd = _build_run_cmd("oc", run, {}, [], source_dir=None)
|
||||
assert cmd == ["/usr/bin/pnpm", "run", "start"]
|
||||
|
||||
@@ -88,8 +88,8 @@ def test_node_runner_without_source_omits_dir() -> None:
|
||||
def test_container_secrets_use_env_file_not_argv() -> None:
|
||||
"""Secrets go through --env-file; plain vars stay as -e; no secret in argv."""
|
||||
run = RunContainer(launcher="container", image="img:latest", env={"PLAIN": "1"})
|
||||
env_file = Path("/home/u/.castle/secrets/env/castle-svc.service.env")
|
||||
with patch("castle_core.deploy.shutil.which", return_value="/usr/bin/docker"):
|
||||
env_file = Path("/home/u/.wildpc/secrets/env/wildpc-svc.service.env")
|
||||
with patch("wildpc_core.deploy.shutil.which", return_value="/usr/bin/docker"):
|
||||
cmd = _build_run_cmd("svc", run, {"PORT": "9001"}, [], secret_env_file=env_file)
|
||||
joined = " ".join(cmd)
|
||||
assert "--env-file" in cmd
|
||||
@@ -102,7 +102,7 @@ def test_container_secrets_use_env_file_not_argv() -> None:
|
||||
|
||||
def test_container_without_secrets_has_no_env_file() -> None:
|
||||
run = RunContainer(launcher="container", image="img:latest")
|
||||
with patch("castle_core.deploy.shutil.which", return_value="/usr/bin/docker"):
|
||||
with patch("wildpc_core.deploy.shutil.which", return_value="/usr/bin/docker"):
|
||||
cmd = _build_run_cmd("svc", run, {}, [], secret_env_file=None)
|
||||
assert "--env-file" not in cmd
|
||||
|
||||
@@ -120,42 +120,42 @@ def test_container_placeholders_expand_in_run_fields() -> None:
|
||||
ph = {
|
||||
"name": "svc",
|
||||
"port": "5432",
|
||||
"data_dir": "/data/castle/svc",
|
||||
"tls_dir": "/data/castle/svc/tls",
|
||||
"data_dir": "/data/wildpc/svc",
|
||||
"tls_dir": "/data/wildpc/svc/tls",
|
||||
}
|
||||
with patch("castle_core.deploy.shutil.which", return_value="/usr/bin/docker"):
|
||||
with patch("wildpc_core.deploy.shutil.which", return_value="/usr/bin/docker"):
|
||||
cmd = _build_run_cmd("svc", run, {}, [], placeholders=ph)
|
||||
joined = " ".join(cmd)
|
||||
assert "DATA=/data/castle/svc/x" in joined # env expanded
|
||||
assert "/data/castle/svc/tls:/tls:ro" in joined # volume expanded
|
||||
assert "DATA=/data/wildpc/svc/x" in joined # env expanded
|
||||
assert "/data/wildpc/svc/tls:/tls:ro" in joined # volume expanded
|
||||
assert "svc:5432" in cmd # arg expanded
|
||||
|
||||
|
||||
def test_container_double_dollar_escapes_placeholder() -> None:
|
||||
"""$${key} passes a literal ${key} through to the container's own shell/env
|
||||
instead of castle expanding it (docker-compose-style escape)."""
|
||||
instead of wildpc expanding it (docker-compose-style escape)."""
|
||||
run = RunContainer(
|
||||
launcher="container",
|
||||
image="img:latest",
|
||||
args=["sh", "-c", "exec myd --advertise $${name}:${port}"],
|
||||
)
|
||||
ph = {"name": "svc", "port": "5432"}
|
||||
with patch("castle_core.deploy.shutil.which", return_value="/usr/bin/docker"):
|
||||
with patch("wildpc_core.deploy.shutil.which", return_value="/usr/bin/docker"):
|
||||
cmd = _build_run_cmd("svc", run, {}, [], placeholders=ph)
|
||||
# castle expands ${port} but leaves $${name} as a literal ${name} for the shell
|
||||
# wildpc expands ${port} but leaves $${name} as a literal ${name} for the shell
|
||||
assert "exec myd --advertise ${name}:5432" in cmd
|
||||
|
||||
|
||||
def test_compose_runner_up_with_resolved_file(tmp_path: Path) -> None:
|
||||
"""A compose service runs `docker compose -p <project> -f <abs-file> up`."""
|
||||
run = RunCompose(launcher="compose", file="docker-compose.yml")
|
||||
with patch("castle_core.deploy.shutil.which", return_value="/usr/bin/docker"):
|
||||
with patch("wildpc_core.deploy.shutil.which", return_value="/usr/bin/docker"):
|
||||
cmd = _build_run_cmd("supabase", run, {}, [], source_dir=tmp_path)
|
||||
assert cmd == [
|
||||
"/usr/bin/docker",
|
||||
"compose",
|
||||
"-p",
|
||||
"castle-supabase",
|
||||
"wildpc-supabase",
|
||||
"-f",
|
||||
str(tmp_path / "docker-compose.yml"),
|
||||
"up",
|
||||
@@ -165,8 +165,8 @@ def test_compose_runner_up_with_resolved_file(tmp_path: Path) -> None:
|
||||
def test_compose_runner_secrets_never_hit_argv(tmp_path: Path) -> None:
|
||||
"""Compose reads env from the process (systemd), not --env-file/-e — argv is clean."""
|
||||
run = RunCompose(launcher="compose", file="docker-compose.yml")
|
||||
env_file = Path("/home/u/.castle/secrets/env/castle-supabase.service.env")
|
||||
with patch("castle_core.deploy.shutil.which", return_value="/usr/bin/docker"):
|
||||
env_file = Path("/home/u/.wildpc/secrets/env/wildpc-supabase.service.env")
|
||||
with patch("wildpc_core.deploy.shutil.which", return_value="/usr/bin/docker"):
|
||||
cmd = _build_run_cmd(
|
||||
"supabase", run, {"PORT": "8000"}, [], source_dir=tmp_path,
|
||||
secret_env_file=env_file,
|
||||
@@ -179,7 +179,7 @@ def test_compose_runner_secrets_never_hit_argv(tmp_path: Path) -> None:
|
||||
|
||||
def test_compose_project_name_override(tmp_path: Path) -> None:
|
||||
run = RunCompose(launcher="compose", file="stack.yml", project_name="myproj")
|
||||
with patch("castle_core.deploy.shutil.which", return_value="/usr/bin/docker"):
|
||||
with patch("wildpc_core.deploy.shutil.which", return_value="/usr/bin/docker"):
|
||||
cmd = _build_run_cmd("s", run, {}, [], source_dir=tmp_path)
|
||||
assert cmd[:6] == [
|
||||
"/usr/bin/docker", "compose", "-p", "myproj", "-f", str(tmp_path / "stack.yml"),
|
||||
@@ -189,13 +189,13 @@ def test_compose_project_name_override(tmp_path: Path) -> None:
|
||||
def test_compose_stop_cmd_is_down(tmp_path: Path) -> None:
|
||||
"""The teardown command mirrors up but ends in `down` (same project + file)."""
|
||||
run = RunCompose(launcher="compose", file="docker-compose.yml")
|
||||
with patch("castle_core.deploy.shutil.which", return_value="/usr/bin/docker"):
|
||||
with patch("wildpc_core.deploy.shutil.which", return_value="/usr/bin/docker"):
|
||||
stop = _build_stop_cmd("supabase", run, tmp_path)
|
||||
assert stop == [
|
||||
"/usr/bin/docker",
|
||||
"compose",
|
||||
"-p",
|
||||
"castle-supabase",
|
||||
"wildpc-supabase",
|
||||
"-f",
|
||||
str(tmp_path / "docker-compose.yml"),
|
||||
"down",
|
||||
|
||||
Reference in New Issue
Block a user