Stage 3: App — program/deployment model & controls
- ProgramActions: install/uninstall (activate) shown only for tools and no-service frontends. Daemons activate via a service/job, so the program page no longer offers a misleading Install/Uninstall (which secretly enabled/disabled the service). - Program page: new Deployments section listing the services/jobs that run the program, as links (a program → 0-N services/jobs). - Service page: 'Runs' row from the run_target summary field (the old code dug into manifest.run, which was empty pre-Stage-1), a Host row for proxy_host, and a convenience link to the referenced program. - lifecycle.activate on a daemon with no service now errors toward 'castle expose' instead of silently installing its binary to PATH. core 94 green; ruff + app build clean.
This commit is contained in:
@@ -155,6 +155,17 @@ async def activate(name: str, config: CastleConfig, root: Path) -> ActionResult:
|
||||
if comp is not None and comp.behavior == "frontend":
|
||||
return await run_action("install", name, comp, root)
|
||||
|
||||
# A daemon with no service can't be "activated" — installing its binary to
|
||||
# PATH doesn't run it. Direct the user to declare a service instead.
|
||||
if comp is not None and comp.behavior == "daemon":
|
||||
return ActionResult(
|
||||
name,
|
||||
"activate",
|
||||
"error",
|
||||
f"'{name}' is a daemon with no service. Run "
|
||||
f"'castle expose {name} --port <PORT>' to deploy it as a service.",
|
||||
)
|
||||
|
||||
# Tool: install to PATH.
|
||||
if comp is not None:
|
||||
return await run_action("install", name, comp, root)
|
||||
|
||||
Reference in New Issue
Block a user