All checks were successful
continuous-integration/drone/push Build is passing
One loader: runner/harness/meta.py::load(recipe) -> RecipeMeta (frozen dataclass, attribute access), backed by the declarative KEYS registry (14 final keys + 3 P2-deprecated). The ONLY exec() of tests/<recipe>/recipe_meta.py. Validation per the locked decision: unknown ALL-CAPS top-level name or type mismatch = MetaError (hard error at load); underscore-prefixed names recipe-private; callables only on hook-typed keys. Migrated all six legacy loaders (spec §4 L1–L6): - run_recipe_ci.py::_load_meta deleted; orchestrator loads once, passes meta down - tests/conftest.py::_recipe_meta deleted; meta fixture returns full RecipeMeta (R3) - lifecycle.py::_recipe_extra_env/_recipe_meta_flag deleted; deploy_app takes meta - deps.py::declared_deps deleted; callers read meta.DEPS - canonical.py::is_enrolled reads through meta.load() - screenshot.py now actually receives SCREENSHOT through the orchestrator path (R2 fix; proven by unit test through the real load path) Mumble private constants underscore-prefixed (_WELCOME_TEXT_MARKER/_MAX_USERS) + importers fixed. New tests/unit/test_meta.py (all-recipes-load-clean typo gate, MetaError cases, spec §2 baseline defaults, underscore exemption, doc sync). Docs §4 key table now GENERATED from the registry (scripts/gen-meta-docs.py); drift fails CI. Verified on cc-ci: cc-ci-run -m pytest tests/unit -q -> 175 passed; scripts/lint.sh -> PASS.
72 lines
2.2 KiB
Python
72 lines
2.2 KiB
Python
#!/usr/bin/env python3
|
|
"""Render the harness.meta KEYS registry to the markdown key-reference table in
|
|
docs/recipe-customization.md §4 (rcust P1.5; kills the R5 doc-drift class).
|
|
|
|
Usage:
|
|
python3 scripts/gen-meta-docs.py # rewrite the table in-place between the markers
|
|
python3 scripts/gen-meta-docs.py --print # print the rendered table to stdout (used by the
|
|
# doc-sync unit test, tests/unit/test_meta.py)
|
|
|
|
The table lives between `<!-- META-TABLE-START -->` / `<!-- META-TABLE-END -->` markers; a unit
|
|
test asserts the committed table equals this rendering, so editing it by hand fails CI.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
import os
|
|
import sys
|
|
|
|
ROOT = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
|
sys.path.insert(0, os.path.join(ROOT, "runner"))
|
|
from harness.meta import KEYS # noqa: E402
|
|
|
|
DOC = os.path.join(ROOT, "docs", "recipe-customization.md")
|
|
START = "<!-- META-TABLE-START -->"
|
|
END = "<!-- META-TABLE-END -->"
|
|
|
|
|
|
def _default_repr(v) -> str:
|
|
if v is None:
|
|
return "`None`"
|
|
return f"`{v!r}`"
|
|
|
|
|
|
def render() -> str:
|
|
lines = [
|
|
START,
|
|
"",
|
|
"_This table is GENERATED from the `runner/harness/meta.py` KEYS registry by"
|
|
" `scripts/gen-meta-docs.py` — do not edit by hand (a unit test pins the sync)._",
|
|
"",
|
|
"| Key | Type | Default | Meaning |",
|
|
"|---|---|---|---|",
|
|
]
|
|
for k in KEYS:
|
|
doc = k.doc.replace("|", "\\|")
|
|
name = f"`{k.name}`" + (" **(deprecated)**" if k.deprecated else "")
|
|
lines.append(f"| {name} | `{k.type}` | {_default_repr(k.default)} | {doc} |")
|
|
lines += ["", END]
|
|
return "\n".join(lines)
|
|
|
|
|
|
def main() -> int:
|
|
table = render()
|
|
if "--print" in sys.argv:
|
|
print(table)
|
|
return 0
|
|
with open(DOC) as f:
|
|
text = f.read()
|
|
if START not in text or END not in text:
|
|
print(f"{DOC}: missing {START}/{END} markers", file=sys.stderr)
|
|
return 1
|
|
head, _, rest = text.partition(START)
|
|
_, _, tail = rest.partition(END)
|
|
with open(DOC, "w") as f:
|
|
f.write(head + table + tail)
|
|
print(f"{DOC}: key table rewritten from the registry ({len(KEYS)} keys)")
|
|
return 0
|
|
|
|
|
|
if __name__ == "__main__":
|
|
raise SystemExit(main())
|