Refactor tests #6

Merged
didericis merged 9 commits from refactor-tests into main 2026-05-11 19:26:28 -04:00
4 changed files with 12 additions and 22 deletions
Showing only changes of commit f943e14891 - Show all commits
+1 -11
View File
@@ -104,7 +104,7 @@ class DockerBottleBackend(BottleBackend):
prompt_file.write_text("") prompt_file.write_text("")
prompt_file.chmod(0o600) prompt_file.chmod(0o600)
proxy_plan = self.prepare_proxy(spec, stage_dir) proxy_plan = self._proxy.prepare(bottle, slug, stage_dir)
resolved = resolve_env(manifest, spec.agent_name) resolved = resolve_env(manifest, spec.agent_name)
self._write_env_files(resolved, env_file, args_file) self._write_env_files(resolved, env_file, args_file)
prompt_file.write_text(agent.prompt) prompt_file.write_text(agent.prompt)
@@ -151,16 +151,6 @@ class DockerBottleBackend(BottleBackend):
args_lines = [f"-e\n{name}" for name in resolved.forwarded] args_lines = [f"-e\n{name}" for name in resolved.forwarded]
args_file.write_text("\n".join(args_lines) + ("\n" if args_lines else "")) args_file.write_text("\n".join(args_lines) + ("\n" if args_lines else ""))
def prepare_proxy(self, spec: BottleSpec, stage_dir: Path) -> pipelock.PipelockProxyPlan:
"""Decide where the pipelock yaml lives in `stage_dir`, delegate
to PipelockProxy to write it, and return the resolved
PipelockProxyPlan for the launch step to consume. Stage-only:
no Docker resources created yet."""
yaml_path = stage_dir / "pipelock.yaml"
bottle = spec.manifest.bottle_for(spec.agent_name)
slug = docker_mod.slugify(spec.agent_name)
return self._proxy.prepare(bottle, slug, yaml_path)
@contextmanager @contextmanager
def launch(self, plan: BottlePlan) -> Iterator[DockerBottle]: def launch(self, plan: BottlePlan) -> Iterator[DockerBottle]:
"""Build, launch, and provision a Docker bottle. Teardown on exit.""" """Build, launch, and provision a Docker bottle. Teardown on exit."""
+3 -2
View File
@@ -177,9 +177,9 @@ class PipelockProxy(ABC):
and lives on concrete subclasses.""" and lives on concrete subclasses."""
def prepare( def prepare(
self, bottle: Bottle, slug: str, yaml_path: Path self, bottle: Bottle, slug: str, stage_dir: Path
) -> PipelockProxyPlan: ) -> PipelockProxyPlan:
"""Write the pipelock yaml config (mode 600) to `yaml_path` """Write the pipelock yaml config (mode 600) under `stage_dir`
and return the plan for `.start`. and return the plan for `.start`.
`slug` is the agent-derived identifier (lowercased, `slug` is the agent-derived identifier (lowercased,
@@ -188,6 +188,7 @@ class PipelockProxy(ABC):
(`claude-bottle-pipelock-<slug>`), the internal/egress (`claude-bottle-pipelock-<slug>`), the internal/egress
networks. It's stored on the returned plan so the backend's networks. It's stored on the returned plan so the backend's
start step can derive the sidecar's container name.""" start step can derive the sidecar's container name."""
yaml_path = stage_dir / "pipelock.yaml"
self._build_pipelock_yaml(bottle, yaml_path) self._build_pipelock_yaml(bottle, yaml_path)
return PipelockProxyPlan(yaml_path=yaml_path, slug=slug) return PipelockProxyPlan(yaml_path=yaml_path, slug=slug)
@@ -68,8 +68,7 @@ class TestPipelockSidecarSmoke(unittest.TestCase):
def test_prepare_and_start_yield_healthy_sidecar(self): def test_prepare_and_start_yield_healthy_sidecar(self):
proxy = DockerPipelockProxy() proxy = DockerPipelockProxy()
yaml_path = self.work_dir / "pipelock.yaml" prep = proxy.prepare(fixture_minimal().bottles["dev"], self.slug, self.work_dir)
prep = proxy.prepare(fixture_minimal().bottles["dev"], self.slug, yaml_path)
self.internal_net = network_create_internal(self.slug) self.internal_net = network_create_internal(self.slug)
self.egress_net = network_create_egress(self.slug) self.egress_net = network_create_egress(self.slug)
+7 -7
View File
@@ -66,11 +66,10 @@ class TestRenderAndWrite(unittest.TestCase):
self.assertIn(required, text) self.assertIn(required, text)
def test_prepare_writes_file_at_mode_600(self): def test_prepare_writes_file_at_mode_600(self):
yaml_path = self.out_dir / "min.yaml" plan = DockerPipelockProxy().prepare(
DockerPipelockProxy().prepare( fixture_minimal().bottles["dev"], "demo", self.out_dir
fixture_minimal().bottles["dev"], "demo", yaml_path
) )
self.assertEqual(0o600, os.stat(yaml_path).st_mode & 0o777) self.assertEqual(0o600, os.stat(plan.yaml_path).st_mode & 0o777)
def test_prepare_does_not_leak_env_names_or_values(self): def test_prepare_does_not_leak_env_names_or_values(self):
manifest = Manifest.from_json_obj({ manifest = Manifest.from_json_obj({
@@ -85,9 +84,10 @@ class TestRenderAndWrite(unittest.TestCase):
}, },
"agents": {"demo": {"skills": [], "prompt": "", "bottle": "dev"}}, "agents": {"demo": {"skills": [], "prompt": "", "bottle": "dev"}},
}) })
yaml_path = self.out_dir / "secret.yaml" plan = DockerPipelockProxy().prepare(
DockerPipelockProxy().prepare(manifest.bottles["dev"], "demo", yaml_path) manifest.bottles["dev"], "demo", self.out_dir
content = yaml_path.read_text() )
content = plan.yaml_path.read_text()
self.assertNotIn("literal-value-should-not-appear", content) self.assertNotIn("literal-value-should-not-appear", content)
self.assertNotIn("MY_SECRET", content) self.assertNotIn("MY_SECRET", content)
self.assertNotIn("prompt-message", content) self.assertNotIn("prompt-message", content)