Refactor component terminology to programs in config and manifest
- Updated the terminology from "components" to "programs" across the codebase, including in config loading, saving, and manifest specifications. - Introduced a new `stacks.py` file to handle lifecycle actions for development stacks, implementing handlers for Python and React Vite stacks. - Adjusted tests to reflect the new program structure and ensure proper functionality. - Revised documentation to align with the new terminology and structure, ensuring clarity on the purpose and configuration of programs, services, and jobs.
This commit is contained in:
@@ -11,7 +11,7 @@ from castle_core.config import (
|
||||
resolve_env_vars,
|
||||
save_config,
|
||||
)
|
||||
from castle_core.manifest import ComponentSpec, JobSpec, ServiceSpec
|
||||
from castle_core.manifest import ProgramSpec, JobSpec, ServiceSpec
|
||||
|
||||
|
||||
class TestLoadConfig:
|
||||
@@ -22,14 +22,14 @@ class TestLoadConfig:
|
||||
config = load_config(castle_root)
|
||||
assert isinstance(config, CastleConfig)
|
||||
assert config.gateway.port == 18000
|
||||
assert "test-tool" in config.components
|
||||
assert "test-tool" in config.programs
|
||||
assert "test-svc" in config.services
|
||||
assert "test-job" in config.jobs
|
||||
|
||||
def test_load_produces_typed_specs(self, castle_root: Path) -> None:
|
||||
"""Each section produces the correct spec type."""
|
||||
config = load_config(castle_root)
|
||||
assert isinstance(config.components["test-tool"], ComponentSpec)
|
||||
assert isinstance(config.programs["test-tool"], ProgramSpec)
|
||||
assert isinstance(config.services["test-svc"], ServiceSpec)
|
||||
assert isinstance(config.jobs["test-job"], JobSpec)
|
||||
|
||||
@@ -86,21 +86,21 @@ class TestSaveConfig:
|
||||
config2 = load_config(castle_root)
|
||||
|
||||
assert config2.gateway.port == config.gateway.port
|
||||
assert set(config2.components.keys()) == set(config.components.keys())
|
||||
assert set(config2.programs.keys()) == set(config.programs.keys())
|
||||
assert set(config2.services.keys()) == set(config.services.keys())
|
||||
assert set(config2.jobs.keys()) == set(config.jobs.keys())
|
||||
|
||||
def test_save_adds_component(self, castle_root: Path) -> None:
|
||||
"""Adding a component and saving persists it."""
|
||||
config = load_config(castle_root)
|
||||
config.components["new-lib"] = ComponentSpec(
|
||||
config.programs["new-lib"] = ProgramSpec(
|
||||
id="new-lib", description="A new library"
|
||||
)
|
||||
save_config(config)
|
||||
|
||||
config2 = load_config(castle_root)
|
||||
assert "new-lib" in config2.components
|
||||
assert config2.components["new-lib"].description == "A new library"
|
||||
assert "new-lib" in config2.programs
|
||||
assert config2.programs["new-lib"].description == "A new library"
|
||||
|
||||
def test_preserves_manage_systemd(self, castle_root: Path) -> None:
|
||||
"""Roundtrip preserves manage.systemd even with all defaults."""
|
||||
|
||||
@@ -6,7 +6,7 @@ import pytest
|
||||
from castle_core.manifest import (
|
||||
BuildSpec,
|
||||
CaddySpec,
|
||||
ComponentSpec,
|
||||
ProgramSpec,
|
||||
ExposeSpec,
|
||||
HttpExposeSpec,
|
||||
HttpInternal,
|
||||
@@ -24,12 +24,12 @@ from castle_core.manifest import (
|
||||
)
|
||||
|
||||
|
||||
class TestComponentSpec:
|
||||
class TestProgramSpec:
|
||||
"""Tests for component (software catalog) model."""
|
||||
|
||||
def test_minimal(self) -> None:
|
||||
"""Minimal component just needs an id."""
|
||||
c = ComponentSpec(id="bare")
|
||||
c = ProgramSpec(id="bare")
|
||||
assert c.description is None
|
||||
assert c.source is None
|
||||
assert c.install is None
|
||||
@@ -38,7 +38,7 @@ class TestComponentSpec:
|
||||
|
||||
def test_tool_component(self) -> None:
|
||||
"""Component with tool and install specs."""
|
||||
c = ComponentSpec(
|
||||
c = ProgramSpec(
|
||||
id="my-tool",
|
||||
description="A tool",
|
||||
source="my-tool/",
|
||||
@@ -50,7 +50,7 @@ class TestComponentSpec:
|
||||
|
||||
def test_frontend_component(self) -> None:
|
||||
"""Component with build spec."""
|
||||
c = ComponentSpec(
|
||||
c = ProgramSpec(
|
||||
id="my-app",
|
||||
build=BuildSpec(commands=[["pnpm", "build"]], outputs=["dist/"]),
|
||||
)
|
||||
@@ -58,12 +58,12 @@ class TestComponentSpec:
|
||||
|
||||
def test_source_dir_from_source(self) -> None:
|
||||
"""source_dir uses source field."""
|
||||
c = ComponentSpec(id="x", source="components/x/")
|
||||
c = ProgramSpec(id="x", source="components/x/")
|
||||
assert c.source_dir == "components/x"
|
||||
|
||||
def test_source_dir_none(self) -> None:
|
||||
"""source_dir returns None when no source available."""
|
||||
c = ComponentSpec(id="x")
|
||||
c = ProgramSpec(id="x")
|
||||
assert c.source_dir is None
|
||||
|
||||
|
||||
@@ -171,7 +171,7 @@ class TestModelSerialization:
|
||||
|
||||
def test_dump_component_excludes_none(self) -> None:
|
||||
"""model_dump with exclude_none drops None fields."""
|
||||
c = ComponentSpec(id="test", description="Test")
|
||||
c = ProgramSpec(id="test", description="Test")
|
||||
data = c.model_dump(exclude_none=True, exclude={"id"})
|
||||
assert "description" in data
|
||||
assert "install" not in data
|
||||
|
||||
Reference in New Issue
Block a user