Merge pull request 'docs: bring back structured clan options' (#5191) from docs-clan-options into main

Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/5191
This commit is contained in:
hsjobeki
2025-09-17 13:20:42 +00:00
5 changed files with 88 additions and 16 deletions

View File

@@ -103,19 +103,9 @@ nav:
- Reference:
- Overview: reference/index.md
- Clan Service API: reference/clanServices/clan-service-author-interface.md
- Clan Options: reference/options/clan.md
- Clan Inventory Options: reference/options/clan_inventory.md
- clan.core (Machine Options):
- Overview: reference/clan.core/index.md
- reference/clan.core/backups.md
- reference/clan.core/deployment.md
- reference/clan.core/facts.md
- reference/clan.core/networking.md
- reference/clan.core/postgresql.md
- reference/clan.core/settings.md
- reference/clan.core/sops.md
- reference/clan.core/state.md
- reference/clan.core/vars.md
- Clan Service API: reference/clanServices/clan-service-author-interface.md
- clan.core (Machine Options):
@@ -185,7 +175,7 @@ nav:
- reference/clanServices/zerotier.md
- Community: community/services/index.md
- Clan Options: "/options"
- Search Clan Options: "/options"
docs_dir: site
site_dir: out

View File

@@ -72,6 +72,7 @@
# A file that contains the links to all clanModule docs
export CLAN_MODULES_VIA_SERVICE=${clanModulesViaService}
export CLAN_SERVICE_INTERFACE=${self'.legacyPackages.clan-service-module-interface}/share/doc/nixos/options.json
export CLAN_OPTIONS_PATH=${self'.legacyPackages.clan-options}/share/doc/nixos/options.json
mkdir $out

View File

@@ -27,6 +27,7 @@
import json
import os
import sys
from dataclasses import dataclass, field
from pathlib import Path
from typing import Any
@@ -40,6 +41,7 @@ from clan_lib.services.modules import (
# Get environment variables
CLAN_CORE_PATH = Path(os.environ["CLAN_CORE_PATH"])
CLAN_CORE_DOCS = Path(os.environ["CLAN_CORE_DOCS"])
CLAN_OPTIONS_PATH = Path(os.environ["CLAN_OPTIONS_PATH"])
# Options how to author clan.modules
# perInstance, perMachine, ...
@@ -441,6 +443,84 @@ Typically needed by module authors to define roles, behavior and metadata for di
of.write(output)
def produce_inventory_docs() -> None:
if not CLAN_OPTIONS_PATH:
msg = f"Environment variables are not set correctly: CLAN_OPTIONS_PATH={CLAN_OPTIONS_PATH}. Expected a path to the optionsJSON"
raise ClanError(msg)
if not OUT:
msg = f"Environment variables are not set correctly: $out={OUT}"
raise ClanError(msg)
output = """# Inventory
This provides an overview of the available options of the `inventory` model.
It can be set via the `inventory` attribute of the [`clan`](./clan.md#inventory) function, or via the [`clan.inventory`](./clan.md#inventory) attribute of flake-parts.
"""
# Inventory options are already included under the clan attribute
# We just omitted them in the clan docs, because we want a separate output for the inventory model
with Path(CLAN_OPTIONS_PATH).open() as f:
options: dict[str, dict[str, Any]] = json.load(f)
clan_root_option = options_to_tree(options)
# Find the inventory options
inventory_opt: None | Option = None
for opt in clan_root_option.suboptions:
if opt.name == "inventory":
inventory_opt = opt
break
if not inventory_opt:
print("No inventory options found.")
sys.exit(1)
# Render the inventory options
# This for loop excludes the root node
for option in inventory_opt.suboptions:
output += options_docs_from_tree(option, init_level=2)
outfile = Path(OUT) / "options/clan_inventory.md"
outfile.parent.mkdir(parents=True, exist_ok=True)
with Path.open(outfile, "w") as of:
of.write(output)
def produce_clan_options_docs() -> None:
if not CLAN_OPTIONS_PATH:
msg = f"Environment variables are not set correctly: CLAN_OPTIONS_PATH={CLAN_OPTIONS_PATH}. Expected a path to the optionsJSON"
raise ClanError(msg)
if not OUT:
msg = f"Environment variables are not set correctly: $out={OUT}"
raise ClanError(msg)
output = """# Clan Options
This provides an overview of the available options
Those can be set via [`clan-core.lib.clan`](./clan.md#inventory) function,
or via the [`clan`](./clan.md) attribute of flake-parts.
"""
# Inventory options are already included under the clan attribute
# We just omitted them in the clan docs, because we want a separate output for the inventory model
with Path(CLAN_OPTIONS_PATH).open() as f:
options: dict[str, dict[str, Any]] = json.load(f)
clan_root_option = options_to_tree(options)
# Render the inventory options
# This for loop excludes the root node
# Exclude inventory options
for option in clan_root_option.suboptions:
if "inventory" in option.name:
continue
output += options_docs_from_tree(option, init_level=2)
outfile = Path(OUT) / "options/clan.md"
outfile.parent.mkdir(parents=True, exist_ok=True)
with Path.open(outfile, "w") as of:
of.write(output)
@dataclass
class Option:
name: str
@@ -555,6 +635,7 @@ def options_docs_from_tree(
if __name__ == "__main__":
produce_clan_core_docs()
produce_inventory_docs()
produce_clan_options_docs()
produce_clan_service_author_docs()
produce_clan_service_docs()

View File

@@ -24,7 +24,7 @@ in
};
in
{
legacyPackages.clan-internals-docs = jsonDocs.optionsJSON;
legacyPackages.clan-options = jsonDocs.optionsJSON;
# Run: nix-unit --extra-experimental-features flakes --flake .#legacyPackages.x86_64-linux.evalTests-build-clan
legacyPackages.evalTests-build-clan = import ./tests.nix {

View File

@@ -84,7 +84,7 @@ in
- The module MUST have at least `features = [ "inventory" ]` in the frontmatter section.
- The module MUST have a subfolder `roles` with at least one `{roleName}.nix` file.
For further information see: [Module Authoring Guide](../../guides/authoring/clanServices/index.md).
For further information see: [Module Authoring Guide](../../guides/services/community.md).
???+ example
```nix