Skip to content

fix: respect Bazel package boundaries when mounting docs bundles #781

Description

@AlexanderLanin

Problem

docs_bundle(source_dir = "docs") discovers its own sources with Bazel glob(). Bazel excludes subdirectories that are separate packages because they contain a BUILD file.

The generated mount manifest, however, contains only the physical source_dir. At runtime, sphinx-mounts walks that directory recursively and does not know Bazel package boundaries. If a child package below docs/ is mounted as its own bundle, its files are mounted twice:

  • once through the parent directory mount;
  • once through the explicit child bundle mount.

This produces sphinx-mounts: docname conflict warnings during bazel run //:docs.

Scope: both supported composition levels

This is not limited to a bundle mounted directly by docs(). The same failure occurs at both levels whenever the child bundle source directory is physically below the parent source directory:

  1. A docs_bundle inside docs(): docs() creates a primary docs_bundle, while Sphinx walks the live source_dir and score_mounts mounts the child bundle. The child documentation can therefore be discovered once by Sphinx through the primary tree and once by the explicit mount.
  2. A docs_bundle inside another docs_bundle: the parent bundle is mounted in directory mode and recursively walks its source directory, while the child bundle is mounted as a separate manifest entry. The parent mount discovers the child documentation and the child mount discovers it again.

Logical nesting with physically disjoint source directories does not trigger this particular collision. The problem is the mismatch between Bazel package-aware source ownership and recursive directory discovery.

Expected behavior

The runtime must expose exactly the source files selected by each owning docs_bundle, at every composition level:

  • the primary Sphinx source tree must not discover files owned by nested packages;
  • a parent directory mount must not discover files owned by a nested child bundle; and
  • the explicit child mount must remain responsible for the child files.

This must hold for both bazel run ...:docs and sandboxed needs_json builds, without duplicate documents or Need IDs.

Reproduction: child bundle mounted by docs()

docs/
  index.rst
  features/
    foo/
      BUILD
      index.rst

Parent:

docs(
    source_dir = "docs",
    bundles = [{
        "bundle": "//docs/features/foo:docs",
        "mount_at": "features/foo",
    }]
)

Child:

docs_bundle(name = "docs", source_dir = ".")

Bazel's parent glob("docs/**/*") excludes docs/features/foo/**, but the current mount rooted at docs/ includes it anyway.

Reproduction: child bundle inside another docs_bundle

parent-docs/
  index.rst
  child/
    BUILD
    index.rst

Parent bundle:

docs_bundle(
    name = "parent",
    source_dir = "parent-docs",
    bundles = [{
        "bundle": "//child:docs",
        "mount_at": "child",
    }]
)

Child bundle:

docs_bundle(name = "docs", source_dir = ".")

When parent is mounted by a consumer, its directory entry rooted at parent-docs/ recursively discovers child/index.rst, and the explicit child entry mounts the same document again.

Proposed direction

Extend the bundle mount metadata with each source entry's selected file list (or excluded nested package roots). The runtime must honor that selection for every directory-mode bundle mount and also constrain primary Sphinx discovery for the docs() source tree. Add integration scenarios for both composition levels and assert that bazel run ...:docs and needs_json succeed without duplicate documents.

Related

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions