Skip to content

Auto-document config schema #2198

Description

@brynpickering

We currently have static tables in the docs describing the config schema, which easily falls out of sync when changes are made to the schema.

I've investigated a few options for auto-generating docs from the existing schema file and found nothing that plays nicely with mkdocs Material.

https://github.com/coveooss/json-schema-for-humans

Most actively developed project for this kind of work, although they've failed to sort out their deployment pipeline for some months so they've released v2 but pypi is stuck on v1.5 right now.

I like how it stores the schema entry details in tabular form, even though it is limited on what can be included in the table (the default value can't be included, for some reason).

schema MD could be generated with the CLI call:

generate-schema-doc --expand-buttons --config template_name=md --config show_toc=false --config show_breadcrumbs=False config/schema.default.json doc/schema.md  

This leads to a very verbose and un-nested output. md_nested might generate a nicer output but the nested blocks aren't rendering properly when I try it locally. V2 also has the techdocs template which is described as being optimized for TechDocs/MkDocs Material with collapsible admonitions.. I tried this out on a clone of latest and it produced a markdown file with mostly HTML blocks, which mkdocs Material couldn't actually render properly 🤪

Could also generate a HTML version and have it using JS to add dynamic components:

generate-schema-doc --expand-buttons --config template_name=js --config show_toc=false --config show_breadcrumbs=False config/schema.default.json doc/schema.html  
  • in schema.md:
--8<-- "doc/schema.html"

This is nicer but adds JS bloat and uses an entirely different theme with no sidebar ToC for the page.

https://github.com/sbrunner/jsonschema2md

Less well maintained but I'm a conda-forge feedstock maintainer for it so could ensure conda-forge always remains up-to-date, at least.

Schema MD could be generated with the CLI call:

jsonschema2md config/schema.default.json doc/schema.md --examples-as-yaml --collapse-children 

Or there is a pre-commit hook to create it, which would mitigate the need to have it as a doc dependency.

Annoyingly --collapse-children provides nice nesting in theory but mkdocs Material doesn't like the markdown/HTML mashup that is the schema.md file it creates, leading to the admonitions not working as expected. It also doesn't set the entries as headers so you also don't get a ToC unless you post-process the md file to transform the top-level key list entries to sub-headings.

Ideal schema entry

I think the ideal schema entries would be:

  • collapsed at each nesting;
  • using mkdocs Material tabs to show the schema and a YAML example of that entry separately. How that works on deep nesting, I'm not sure;
  • for cases of AnyOf, neither of the above packages produces a particularly nice result and my preference would be to use python type hinting style (option1 | option2);
  • as in json-schema-for-humans, when the same sub-schema is repeated, it calls back to the first instance of it (e.g. all the data entries share the same sub-schema)
  • the sidebar ToC allows you to go to each top-level key but does not apply sub-sub-headings to the nested entries under those.

For YAML example, we can just embed the default YAML in the schema itself as an example, e.g.:

scenario: ScenarioConfig = Field(
    default_factory=ScenarioConfig,
    description="Scenario configuration defining wildcards for the workflow.",
    json_schema_extra={"examples": [{"scenario": ScenarioConfig().model_dump()}]},
)

Then you get a free YAML snippet when auto-generating the docs from the schema. Allows for more elaborate examples to also be given (in which default empty config has some actual content)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions