feat: Enhance node runner to execute scripts in source directory and update tests
This commit is contained in:
@@ -465,7 +465,16 @@ def _build_run_cmd(
|
|||||||
cmd.extend(run.args) # type: ignore[union-attr]
|
cmd.extend(run.args) # type: ignore[union-attr]
|
||||||
return cmd
|
return cmd
|
||||||
case "node":
|
case "node":
|
||||||
cmd = [run.package_manager, "run", run.script] # type: ignore[union-attr]
|
# Like the python runner bakes `--project <source>` into `uv run`, the
|
||||||
|
# node runner bakes `--dir <source>` so the package manager runs the
|
||||||
|
# script in the program's source dir — the systemd unit carries no
|
||||||
|
# WorkingDirectory, so a bare `pnpm run` would otherwise execute in the
|
||||||
|
# service's (wrong) cwd. Resolve the package manager to an absolute path.
|
||||||
|
pm = shutil.which(run.package_manager) or run.package_manager # type: ignore[union-attr]
|
||||||
|
cmd = [pm]
|
||||||
|
if source_dir and source_dir.is_dir():
|
||||||
|
cmd.extend(["--dir", str(source_dir)])
|
||||||
|
cmd.extend(["run", run.script]) # type: ignore[union-attr]
|
||||||
if run.args: # type: ignore[union-attr]
|
if run.args: # type: ignore[union-attr]
|
||||||
cmd.extend(run.args) # type: ignore[union-attr]
|
cmd.extend(run.args) # type: ignore[union-attr]
|
||||||
return cmd
|
return cmd
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ from pathlib import Path
|
|||||||
from unittest.mock import patch
|
from unittest.mock import patch
|
||||||
|
|
||||||
from castle_core.deploy import _build_run_cmd
|
from castle_core.deploy import _build_run_cmd
|
||||||
from castle_core.manifest import RunContainer, RunPython
|
from castle_core.manifest import RunContainer, RunNode, RunPython
|
||||||
|
|
||||||
|
|
||||||
def test_python_runner_uses_uv_run_from_source(tmp_path: Path) -> None:
|
def test_python_runner_uses_uv_run_from_source(tmp_path: Path) -> None:
|
||||||
@@ -52,6 +52,39 @@ def test_python_runner_warns_when_unresolvable() -> None:
|
|||||||
assert any("my-svc" in m for m in messages)
|
assert any("my-svc" in m for m in messages)
|
||||||
|
|
||||||
|
|
||||||
|
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(runner="node", script="gateway:watch:raw", package_manager="pnpm")
|
||||||
|
with patch("castle_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"]
|
||||||
|
|
||||||
|
|
||||||
|
def test_node_runner_appends_args(tmp_path: Path) -> None:
|
||||||
|
run = RunNode(
|
||||||
|
runner="node", script="start", package_manager="pnpm", args=["--port", "18789"]
|
||||||
|
)
|
||||||
|
with patch("castle_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",
|
||||||
|
"start",
|
||||||
|
"--port",
|
||||||
|
"18789",
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
def test_node_runner_without_source_omits_dir() -> None:
|
||||||
|
"""No resolvable source → bare `pnpm run` (package manager still PATH-resolved)."""
|
||||||
|
run = RunNode(runner="node", script="start", package_manager="pnpm")
|
||||||
|
with patch("castle_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"]
|
||||||
|
|
||||||
|
|
||||||
def test_container_secrets_use_env_file_not_argv() -> 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."""
|
"""Secrets go through --env-file; plain vars stay as -e; no secret in argv."""
|
||||||
run = RunContainer(runner="container", image="img:latest", env={"PLAIN": "1"})
|
run = RunContainer(runner="container", image="img:latest", env={"PLAIN": "1"})
|
||||||
|
|||||||
Reference in New Issue
Block a user