Integrate Generated Documentation#

When a script or tool creates documentation content at build time, collect it with a docs_bundle and mount the bundle into your documentation tree.

You find a complete working example in the Metamodel.

Which bundle attribute?#

For generated documentation, put the generated files in docs_bundle(srcs = [...]). This follows Bazel’s normal srcs semantics: the files are inputs that Sphinx processes, even when they are generated by another build action.

Use docs_bundle(data = [...]) for runtime or supporting files that belong at the bundle’s mount but are not themselves documentation sources. The docs(data = [...]) argument is shorthand for supporting files in the root :docs_bundle; it is not a substitute for docs_bundle(srcs = [...]).

For this how-to, the rule is simple: generated documentation belongs in docs_bundle(srcs = [...]).

Step 1: Generate the RST Files#

Use a genrule (or any build action) that writes RST files.

Listing 1 In your BUILD file#
genrule(
    name = "generate_design_rst",
    srcs = ["design_model.yaml"],
    outs = ["generated/index.rst"],
    cmd = "$(location :design_rst_tool) --output $(location generated/index.rst) $<",
    tools = [":design_rst_tool"],
)

If your tool writes many files (a second RST, a Mermaid .mmd diagram, or any other companion asset), add all of them to outs. Sphinx directives in the RST (for example .. mermaid:: arch.mmd) use relative paths because all files stay in the same generated directory.

Make sure the generated files include an index.rst at the root of the output directory.

Verify:

bazel build :generate_design_rst must succeed. Inspect the output at bazel-bin/<package>/generated/index.rst.

Step 2: Declare the Bundle#

Wrap the generated files in a docs_bundle with the srcs attribute. Explicit srcs may point to generated files; they are not limited to handwritten sources.

Listing 2 In your BUILD file#
docs_bundle(
    name = "design_bundle",
    srcs = [":generate_design_rst"],
)

This is a source bundle without a source_dir: all of its documentation is generated. It is still a normal mountable bundle. The generated index.rst becomes the bundle’s entry page and travels with the bundle when it is mounted. All explicit source files must share one parent directory.

Verify:

bazel build :design_bundle must succeed. The bundle now holds the generated file but does not yet place it anywhere.

Step 3: Mount the Bundle#

Add the bundle to your docs() call.

Listing 3 In your BUILD file#
docs(
    source_dir = "docs",
    bundles = [{
        "bundle": ":design_bundle",
        "mount_at": "design",
        "attach_to": "index",
    }],
)

The generated page becomes design/index.html in the output. mount_at sets the target path; attach_to adds the page to that document’s toctree (defaults to the parent index when omitted).

Verify:

bazel run //:docs must succeed. Open _build/design/index.html and confirm the generated content.

Common Issues#

The bundle is mounted but the generated file does not appear, or Sphinx warns about files not in any toctree. Make sure the genrule’s outs uses a subdirectory (for example generated/index.rst) and not a bare index.rst. score_mounts mounts the parent directory of the genrule output. Without a subdirectory, it mounts the genrule output root — which often contains other build artifacts and causes Sphinx warnings.

Attach-to target is missing. attach_to must point to a document that exists in the consuming project’s documentation tree. When unsure, point it at "index" (the consuming project’s root index.rst).