Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
67 changes: 26 additions & 41 deletions docs.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -109,13 +109,10 @@ def docs_bundle(name, source_dir = None, data = [], entry_doc = "index", bundles
source_dir: optional directory holding this bundle's own doc sources. It is
globbed like `docs()` (same file kinds) and the contents are stored after
stripping the `source_dir` prefix. Leave it unset for a pure aggregator.
data:
Files owned by this bundle that are not discovered as documentation
sources. Use this for generated RST or other generated files that are
part of the bundle payload and belong at the bundle's eventual mount
location. Use ``docs(data = [...])`` only for project-level inputs
outside a bundle. Both forms make their files available to a build;
only bundle data travels with a mounted bundle.
data: Files owned by this bundle that are not discovered as documentation
sources. This includes generated RST, literalinclude inputs, and assets
that belong at the bundle's eventual mount location. Omitting
``source_dir`` creates a bundle containing only these files.
entry_doc: bundle-relative docname attached when this bundle is mounted.
Defaults to `index`.
bundles: nested bundles to compose, each a dict
Expand Down Expand Up @@ -221,12 +218,9 @@ def docs(
source_dir: The source directory containing documentation files. Defaults to "docs".
project: optional project name, prefer setting this here if you can avoid having a conf.py
project_url: Optional project URL, prefer setting this here if you can avoid having a conf.py
data: Additional files needed by the project-level documentation build.
These files are outside any bundle and have no bundle mount path. If a
file should travel with rendered or composable documentation, declare
it in a `docs_bundle` and place that bundle through `bundles` instead.
Generated documentation and assets are not staged into the workspace
source tree for `bazel run`; use a data-only `docs_bundle` for those.
data: Additional files owned by this project's root ``:docs_bundle``.
This is shorthand for declaring the files in that root bundle; mounted
child content belongs in the child ``docs_bundle(data = [...])``.
deps: Additional dependencies for the documentation build.
external_needs: List of external needs targets to include in the documentation build.
scan_code: Deprecated. Explicit source files or filegroups to scan for source
Expand All @@ -249,11 +243,9 @@ def docs(
Note: a bundle label may also point at another module's auto-exposed
bundle, e.g. "@score_process_description//:docs_bundle".

The short rule is about ownership and placement, not build availability:
use a bundle for anything that should travel as one portable mount. A
bundle may be data-only when its deliverable is generated/supporting data
rather than source RST. Use ``docs(data = [...])`` only for project-level
inputs that do not belong to a bundle mount.
``docs(data = [...])`` owns files in the root ``:docs_bundle``. A child
bundle uses the same ``data`` attribute and may omit ``source_dir`` when it
contains only generated or supporting files.
"""
# HINT: keep documentation sync docs/reference/bazel_macros.rst

Expand Down Expand Up @@ -282,31 +274,23 @@ def docs(
# list-valued attributes such as ``data`` and ``tools``.
metamodel_label = [metamodel] if metamodel else []

data_library_label_for_sphinx_docs = []
root_bundle_data_for_sphinx = []
if data:
# ``docs_bundle`` can carry data, including as a pure-data bundle. That
# data belongs to the bundle payload and is resolved at its eventual
# mount. These ``docs(data = [...])`` inputs are intentionally
# project-level instead: they support the project build or its
# literalinclude examples and are not assigned to a bundle mount. Both
# kinds of data are build inputs; without the staging below, project-
# level inputs would
# remain only execution inputs for Sphinx's tools rather than files
# below Sphinx's source directory, where standard ``literalinclude``
# looks for them.
#
# ``sphinx_docs_library`` is the generic rules_python/rules_sphinxdocs
# mechanism for adding such files to the sandboxed needs source tree.
# Preserve their workspace-relative paths so one ordinary
# literalinclude works in that Sphinx action. The interactive run
# target reads the workspace source tree directly; generated files
# belong in a data-only docs_bundle instead.
# TODO: Replace this adapter once the mounts manifest can preserve a
# data file's destination path below the root documentation tree.
# The bundle provider records ownership and propagation. Sphinx uses
# its standard library provider to map the same files into the
# sandboxed source tree while preserving workspace-relative paths for
# literalinclude.
sphinx_docs_library(
name = "_docs_data",
name = "_root_bundle_data_for_sphinx",
srcs = data,
strip_prefix = "",
# rules_sphinxdocs treats an empty strip_prefix as the package
# path. An unmatched prefix preserves the workspace-relative paths
# used by this macro's direct documentation sources.
strip_prefix = "__root_bundle_data__",
)
data_library_label_for_sphinx_docs = [":_docs_data"]
root_bundle_data_for_sphinx = [":_root_bundle_data_for_sphinx"]

mounts_manifest_label = []
if bundles:
Expand Down Expand Up @@ -346,6 +330,7 @@ def docs(
docs_bundle(
name = "docs_bundle",
source_dir = source_dir,
data = data,
entry_doc = "index",
bundles = bundles,
scan_code = scan_code,
Expand Down Expand Up @@ -472,7 +457,7 @@ def docs(
# complete bundle as srcs would also expose those files as raw Sphinx
# sources and make every nested need appear twice.
srcs = [sphinx_sources],
deps = data_library_label_for_sphinx_docs,
deps = root_bundle_data_for_sphinx,
config = sphinx_config,
extra_opts = [
"-W",
Expand All @@ -490,7 +475,7 @@ def docs(
) + (["--define=score_metamodel_yaml=$(location " + str(metamodel) + ")"] if metamodel else []),
formats = ["needs"],
sphinx = ":sphinx_build",
tools = data + external_needs + metamodel_label + [":sourcelinks_json", ":docs_bundle"] + mounts_manifest_label,
tools = external_needs + metamodel_label + [":sourcelinks_json", ":docs_bundle"] + mounts_manifest_label,
visibility = ["//visibility:public"],
# Persistent workers cause stale symlinks after dependency version
# changes, corrupting the Bazel cache.
Expand Down
11 changes: 5 additions & 6 deletions docs/how-to/bundles/examples.rst
Original file line number Diff line number Diff line change
Expand Up @@ -54,9 +54,9 @@ If the parent is mounted at ``guides/example``, its page is rendered at
Mount generated documentation
-----------------------------

Use a data-only bundle when a build action produces the documentation rather
than a source-tree ``.rst`` file. It has no ``source_dir``; its generated files
are the bundle's complete payload. You can generate and mount a page like this:
When a build action produces documentation rather than a source-tree ``.rst``
file, create a bundle without ``source_dir``. Its generated files are the
bundle's complete payload. You can generate and mount a page like this:

.. code-block:: starlark

Expand Down Expand Up @@ -89,9 +89,8 @@ See the `complete generated-data fixture on GitHub
<https://github.com/eclipse-score/docs-as-code/tree/main/src/tests/docs_bzl/scenarios/data_files_runfiles>`_.

The generated page is rendered at ``data_test/index.html`` and is added to the
consuming project's index page's toctree. Although this bundle is data-only,
it is mounted and navigated in exactly the same way as a bundle with source
files.
consuming project's index page's toctree. It is mounted and navigated in
exactly the same way as a bundle with source files.

Mount documentation from another module
----------------------------------------
Expand Down
30 changes: 12 additions & 18 deletions docs/how-to/generated_docs.rst
Original file line number Diff line number Diff line change
Expand Up @@ -23,21 +23,16 @@ with a ``docs_bundle`` and mount the bundle into your documentation tree.
You find a `complete working example <https://github.com/eclipse-score/docs-as-code/tree/main/src/extensions/score_metamodel/docs/>`_
in the :ref:`metamodel-reference`.

Which ``data`` attribute?
-------------------------
Supporting files belong to bundles
----------------------------------

For a mounted documentation bundle, put the generated files in
``docs_bundle(data = [...])``. Those files are part of the bundle payload: they
travel with the bundle and are resolved below its eventual ``mount_at`` path.
``docs(data = [...])`` adds files to the root ``:docs_bundle`` exposed by the
macro. A mounted documentation bundle declares its own files with
``docs_bundle(data = [...])``. In both cases the files are bundle payload and,
when mounted, are resolved below the bundle's ``mount_at`` path.

``docs(data = [...])`` is different. It adds files to the project-level
``docs()`` build, outside any bundle, and therefore gives those files no bundle
mount path. Use it only for inputs that belong to the project-level build. If
the file is documentation, an image, or a supporting asset for a bundle, put
it in that bundle instead.

For this how-to, the rule is simple: generated documentation belongs in
``docs_bundle(data = [...])``.
For this how-to, generated documentation belongs in
``docs_bundle(data = [...])`` because it is mounted as a child bundle.

Step 1: Generate the RST Files
------------------------------
Expand Down Expand Up @@ -81,11 +76,10 @@ Do not use ``srcs`` — that is for handwritten sources in the source tree.
data = [":generate_design_rst"],
)

This is a **data-only bundle**: it has no ``source_dir`` because 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. A bundle with both handwritten sources and
generated files can use ``source_dir`` and ``data`` together.
This bundle has no ``source_dir`` because all of its documentation is
generated. The generated ``index.rst`` becomes the bundle's entry page and
travels with the bundle when it is mounted. A bundle with both handwritten
sources and generated files can use ``source_dir`` and ``data`` together.

Verify:
``bazel build :design_bundle`` must succeed.
Expand Down
45 changes: 18 additions & 27 deletions docs/reference/bazel_macros.rst
Original file line number Diff line number Diff line change
Expand Up @@ -25,25 +25,18 @@ See :doc:`commands <commands>` for the targets/commands it creates.

The macro must be called from the repository root package.

Supporting files: project inputs and bundle payloads
----------------------------------------------------

There are two ``data`` attributes, and they belong to different documentation
trees:

* ``docs_bundle(data = [...])`` puts files in a bundle payload. The files
travel with that bundle and are resolved below the bundle's eventual
``mount_at`` path. Use this for generated documentation, images, and other
assets needed by a mounted bundle.
* ``docs(data = [...])`` puts files in the project-level ``docs()`` build,
outside any bundle. These files have no bundle mount path. Use this only for
inputs needed by the project-level build itself. ``bazel run`` does not copy
generated data into the workspace source tree; generated documentation or
assets must use ``docs_bundle(data = [...])``.

If a file belongs to a mounted bundle, use ``docs_bundle(data = [...])``.
Both attributes make files available to a build; they differ in which
documentation tree carries the files and where they are resolved.
Supporting files
----------------

Documentation supporting files always belong to a ``docs_bundle``. The
``data`` argument of ``docs()`` is shorthand for adding files to the root
``:docs_bundle`` that the macro exposes. A mounted module puts its files in
its own ``docs_bundle(data = [...])``; those files travel with that bundle and
are resolved below its eventual ``mount_at`` path.

A bundle with ``data`` but no ``source_dir`` is simply a bundle whose content
is generated or supporting files. It uses the same ownership and placement
mechanism as every other bundle.

Minimal example (root ``BUILD``)
--------------------------------
Expand Down Expand Up @@ -83,11 +76,10 @@ Minimal example (root ``BUILD``)
it remains authoritative and these values are not used.

- ``data`` (list of bazel labels)
Extra runfiles / data targets that should be made available to the documentation targets.
The items in ``data`` are added to the py_binaries and to the Sphinx tooling so they are
available at build time. These are project-level inputs; they are not part of
a bundle and do not receive a bundle mount path. Use ``docs_bundle(data = [...])``
for files that belong to mounted documentation.
Supporting files for this project's root ``:docs_bundle``. The files are
available to the documentation targets and travel when another project
mounts this project's public bundle. Put files belonging to a mounted child
in that child's ``docs_bundle(data = [...])`` instead.

.. note::

Expand Down Expand Up @@ -185,9 +177,8 @@ Signature: ``docs_bundle(name, source_dir = None, data = [], entry_doc = "index"
the bundle payload and are available at the bundle's eventual mount path;
they are useful for generated documentation sources such as a generated
``index.rst``. If ``source_dir`` is omitted and ``data`` contains the
bundle's deliverable, the result is a data-only bundle. Use this attribute
for any file that belongs with the mounted bundle. Use
``docs(data = [...])`` only for project-level inputs outside a bundle.
bundle's deliverable, the result is a bundle containing only supporting
files. Use this attribute for every file that belongs with a mounted bundle.

- ``entry_doc`` (string, optional)
Bundle-relative docname used as the canonical navigation entry. It defaults to
Expand Down
1 change: 1 addition & 0 deletions src/tests/docs_bzl/scenarios/basic_docs/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -17,5 +17,6 @@ docs(
source_dir = "docs",
project = "Basic Test",
project_url = "https://github.com/eclipse-score/docs-as-code",
data = ["supporting-example.txt"],
test_sources = ["src/tests/docs_bzl/scenarios/basic_docs"],
)
2 changes: 2 additions & 0 deletions src/tests/docs_bzl/scenarios/basic_docs/docs/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,5 @@

Basic Test
==========

.. literalinclude:: ../supporting-example.txt

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah thanks... thats bug #778

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So this needs fixing?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah, but unrelated to this PR. This PR will simplify the fix as we have fewer concepts to take care of.

Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
The root bundle owns this supporting file.
1 change: 1 addition & 0 deletions src/tests/docs_bzl/test_basic_docs.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ def test_basic_docs_builds_html():


def test_basic_docs_builds_needs_without_conf_py():
"""Root docs data supports literalinclude in the sandboxed Sphinx build."""
result = run_scenario("build", "basic_docs", ":needs_json")

# With no docs/conf.py the generated config is used; it must set a non-empty
Expand Down
Loading