feat: deployment-scoped requires + UI editors, gateway nav, services filter
Model:
- Drop `requires` from ProgramSpec; requires is now deployment-only.
Collapse Requirement to {ref, bind} with kind defaulting to "deployment"
(drop the unused `version`). System-package preconditions stay on the
program as `system_dependencies`, synthesized into {kind: system} for the
functional check. relations.py/deploy.py read only the deployment's requires.
- create.py seeds a stack's substrate dependency onto the deployment, not the
program. Docs + tests updated.
UI:
- Add a `requires` editor (useRequires) on service, job, and static detail
pages — edit service→service deps (ref + optional bind env var).
- Restore the gateway route table "Open" column: a kind-aware in-app link to
each route's deployment.
- Reformat the reach control: name baked into each option
(localhost:PORT (local) / <name>.<domain> (internal) / <name>.<pubdomain> (public)).
- Services page: sort statics in with systemd services by name, add a
search + kind-filter bar mirroring the programs page.
This commit is contained in:
@@ -503,18 +503,12 @@ def _target_url(config: CastleConfig, target_name: str) -> str | None:
|
||||
return _public_url(config, target_name, getattr(dep, "http_exposed", False), tport)
|
||||
|
||||
|
||||
def _requires_env(
|
||||
config: CastleConfig, dep: DeploymentSpec, config_key: str
|
||||
) -> dict[str, str]:
|
||||
"""Env generated FROM a deployment's ``requires`` — a ``{kind: deployment,
|
||||
bind: VAR}`` requirement sets ``VAR`` to the target's URL. Env is derived from
|
||||
the dependency, never scraped back into one (see docs/relationships.md)."""
|
||||
prog = config.programs.get(config_key)
|
||||
reqs = list(getattr(dep, "requires", []) or [])
|
||||
if prog:
|
||||
reqs += list(prog.requires)
|
||||
def _requires_env(config: CastleConfig, dep: DeploymentSpec) -> dict[str, str]:
|
||||
"""Env generated FROM a deployment's ``requires`` — a ``{ref, bind: VAR}``
|
||||
requirement sets ``VAR`` to the target deployment's URL. Env is derived from the
|
||||
dependency, never scraped back into one (see docs/relationships.md)."""
|
||||
out: dict[str, str] = {}
|
||||
for r in reqs:
|
||||
for r in getattr(dep, "requires", []) or []:
|
||||
if r.kind == "deployment" and r.bind:
|
||||
url = _target_url(config, r.ref)
|
||||
if url:
|
||||
@@ -676,7 +670,7 @@ def _build_deployed(
|
||||
raw_env = dict(dep.defaults.env) if (dep.defaults and dep.defaults.env) else {}
|
||||
# Env generated from `requires` ({kind: deployment, bind: VAR} → target URL).
|
||||
# An explicit defaults.env value always wins — a hand-set var is never clobbered.
|
||||
for var, url in _requires_env(config, dep, config_key).items():
|
||||
for var, url in _requires_env(config, dep).items():
|
||||
raw_env.setdefault(var, url)
|
||||
public_url = _public_url(config, name, expose, port)
|
||||
ctx = _env_context(
|
||||
|
||||
Reference in New Issue
Block a user