mirror of
https://github.com/kevinveenbirkenbach/computer-playbook.git
synced 2026-11-06 02:54:26 +00:00
Add cli/build/readme: derives each role README's managed sections from templates/roles/README.md.j2.tmpl (the Cosmos mermaid diagram from meta/services.yml, an invokable-gated Quick Setup, and Credits). The Cosmos diagram shows dependencies, every declared service, and dependents (roles that consume this one, matched by role name and by provides provision-name in both directions). Role nodes carry deploy-mode emoji markers (compose/swarm/host); disabled and shared services get a stop mark; dependents are capped at 12. test_readme enforces the Quick Setup body is byte-exact with the template render. `make readme-generate` and `make cosmos` regenerate; `make cosmos` also runs inside `make quality`. Refactor: utils/symbol_glossary.py is the single source of truth for the word/emoji mapping (unique project-wide), consumed by the complexity matrix and the Cosmos builder. utils/roles/deploy.py holds role_has_stack and role_deploy_modes, shared by both so the logic never drifts. Add `make lint-mermaid` and its CI workflow, rendering every diagram via mermaid-cli; the render step provisions chrome-headless-shell and unzip on demand so it works in the minimal container. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
39 lines
1.5 KiB
Python
39 lines
1.5 KiB
Python
"""Deploy-shape helpers shared by the complexity matrix and the Cosmos builder.
|
|
|
|
Both need the same facts about a role: whether it ships its own container
|
|
stack, and which deploy modes it supports. Keeping the logic here means the two
|
|
callers never drift.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
from pathlib import Path
|
|
|
|
from utils.roles.meta_lookup import get_role_mode_enabled
|
|
|
|
|
|
def role_has_stack(role_dir: Path) -> bool:
|
|
"""True iff the role renders its own container stack, i.e. ships a
|
|
``templates/*compose*.yml.j2``. Host-only roles (backup cron, wireguard,
|
|
swapfile) and pure service-injectors carry no compose template and return
|
|
False. Presence (not an ``image`` key) is the signal so build-from-source
|
|
stacks that pull no registry image still count as a stack."""
|
|
templates = Path(role_dir) / "templates"
|
|
return templates.is_dir() and any(templates.rglob("*compose*.yml.j2"))
|
|
|
|
|
|
def role_deploy_modes(role_dir: Path, role_name: str | None = None) -> dict[str, bool]:
|
|
"""Return the deploy modes a role supports, keyed by mode with its
|
|
``modes.<mode>.enabled`` SPOT value.
|
|
|
|
A stack role (ships a compose template) is offered ``compose`` and
|
|
``swarm``; a host-only role is offered ``host``. The two are mutually
|
|
exclusive: swarm needs a stack, host configures the machine instead.
|
|
"""
|
|
role_dir = Path(role_dir)
|
|
modes = ("compose", "swarm") if role_has_stack(role_dir) else ("host",)
|
|
return {
|
|
mode: get_role_mode_enabled(role_dir, mode=mode, role_name=role_name)
|
|
for mode in modes
|
|
}
|