feat: supabase stack seeds a requires on the substrate at create
A stack's substrate dependency now becomes a real encoded `requires` at `castle program create` time (STACK_REQUIRES), so the relationship graph shows it. This keeps `stack` uncoupled from the runtime model — the stack declares the edge once at creation; the graph only ever reads the encoded `requires`, never the stack.
This commit is contained in:
@@ -16,6 +16,7 @@ from castle_cli.manifest import (
|
|||||||
ManageSpec,
|
ManageSpec,
|
||||||
PathDeployment,
|
PathDeployment,
|
||||||
ProgramSpec,
|
ProgramSpec,
|
||||||
|
Requirement,
|
||||||
RunPython,
|
RunPython,
|
||||||
SystemdDeployment,
|
SystemdDeployment,
|
||||||
SystemdSpec,
|
SystemdSpec,
|
||||||
@@ -38,6 +39,14 @@ STACK_BUILD_OUTPUTS: dict[str, str] = {
|
|||||||
"react-vite": "dist",
|
"react-vite": "dist",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Substrate a stack's apps depend on — seeded as a `requires` at creation so the
|
||||||
|
# relationship graph shows it. This keeps `stack` uncoupled from the runtime model:
|
||||||
|
# the stack declares the edge once here; the graph only ever reads the encoded
|
||||||
|
# `requires`, never the stack. See docs/relationships.md.
|
||||||
|
STACK_REQUIRES: dict[str, list[Requirement]] = {
|
||||||
|
"supabase": [Requirement(kind="deployment", ref="supabase")],
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
def next_available_port(config: object) -> int:
|
def next_available_port(config: object) -> int:
|
||||||
"""Find the next available port starting from 9001 (9000 is reserved for gateway)."""
|
"""Find the next available port starting from 9001 (9000 is reserved for gateway)."""
|
||||||
@@ -111,6 +120,8 @@ def run_create(args: argparse.Namespace) -> int:
|
|||||||
source=str(project_dir),
|
source=str(project_dir),
|
||||||
stack=stack,
|
stack=stack,
|
||||||
build=build,
|
build=build,
|
||||||
|
# Seed the stack's substrate dependency (e.g. supabase) as a real `requires`.
|
||||||
|
requires=list(STACK_REQUIRES.get(stack or "", [])),
|
||||||
)
|
)
|
||||||
if kind == "tool":
|
if kind == "tool":
|
||||||
# A PATH-managed deployment: installed via `uv tool install`, no unit/route.
|
# A PATH-managed deployment: installed via `uv tool install`, no unit/route.
|
||||||
@@ -120,7 +131,10 @@ def run_create(args: argparse.Namespace) -> int:
|
|||||||
elif kind == "static":
|
elif kind == "static":
|
||||||
# A caddy-managed static deployment: no systemd unit, served from the build dir.
|
# A caddy-managed static deployment: no systemd unit, served from the build dir.
|
||||||
config.deployments[name] = CaddyDeployment(
|
config.deployments[name] = CaddyDeployment(
|
||||||
id=name, manager="caddy", program=name, root=static_root or "dist",
|
id=name,
|
||||||
|
manager="caddy",
|
||||||
|
program=name,
|
||||||
|
root=static_root or "dist",
|
||||||
description=description,
|
description=description,
|
||||||
)
|
)
|
||||||
elif kind == "service":
|
elif kind == "service":
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ from castle_core.manifest import ( # noqa: F401 — explicit re-exports for typ
|
|||||||
Reach,
|
Reach,
|
||||||
ReadinessHttpGet,
|
ReadinessHttpGet,
|
||||||
RemoteDeployment,
|
RemoteDeployment,
|
||||||
|
Requirement,
|
||||||
RestartPolicy,
|
RestartPolicy,
|
||||||
RunCommand,
|
RunCommand,
|
||||||
RunCompose,
|
RunCompose,
|
||||||
|
|||||||
@@ -107,6 +107,9 @@ class TestCreateCommand:
|
|||||||
comp = config.programs["guestbook"]
|
comp = config.programs["guestbook"]
|
||||||
assert comp.stack == "supabase"
|
assert comp.stack == "supabase"
|
||||||
assert comp.build is not None and comp.build.outputs == ["public"]
|
assert comp.build is not None and comp.build.outputs == ["public"]
|
||||||
|
# The supabase stack seeds a `requires` on the substrate so the graph shows
|
||||||
|
# the dependency (stack stays uncoupled — it just declares the edge once).
|
||||||
|
assert [(r.kind, r.ref) for r in comp.requires] == [("deployment", "supabase")]
|
||||||
dep = config.deployments["guestbook"]
|
dep = config.deployments["guestbook"]
|
||||||
assert dep.manager == "caddy"
|
assert dep.manager == "caddy"
|
||||||
assert dep.root == "public"
|
assert dep.root == "public"
|
||||||
|
|||||||
Reference in New Issue
Block a user