Skip to content
Draft
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
5 changes: 4 additions & 1 deletion docs.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,7 @@ def docs(
source_dir = "docs",
project = None,
project_url = None,
module = "",
data = [],
deps = [],
external_needs = [],
Expand All @@ -199,6 +200,7 @@ 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
module: Optional module name that is allowed in the feature part of requirement IDs.
data: Additional data files to include in the documentation build.
deps: Additional dependencies for the documentation build.
external_needs: List of external needs targets to include in the documentation build.
Expand Down Expand Up @@ -320,6 +322,7 @@ def docs(
"TEST_SOURCES": str(test_sources),
"DATA": str(data),
"EXTERNAL_NEEDS_FILES": str(external_needs),
"REQUIRED_IN_ID": module,
# `bazel run` starts from a runfiles tree, so this logical path is
# resolved by score_mounts through ``RUNFILES_DIR``.
"MOUNTS_MANIFEST": "$(rlocationpath :_mounts_manifest)" if bundles else "",
Expand Down Expand Up @@ -409,7 +412,7 @@ def docs(
"--define=external_needs_source=" + str(data + external_needs),
"--define=score_sourcelinks_json=$(location :sourcelinks_json)",
"--define=score_source_code_linker_plain_links=1",
] + (
] + (["--define=required_in_id=" + module] if module else []) + (
# ``sphinx_docs`` is a sandboxed build action, so it needs the
# action-input path rather than the runfiles-relative spelling.
["--define=mounts_manifest=$(location :_mounts_manifest)"] if bundles else []
Expand Down
11 changes: 6 additions & 5 deletions docs/how-to/write_docs.rst
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ The feature part is validated by checking that at least one of the following is

* A segment of the feature part (split on ``_`` and ``-``) appears in the document's directory path
* The initials of the feature part's segments appear in the document's directory path
* The feature part contains a string explicitly allowed via ``required_in_id`` in ``conf.py``
* The feature part contains the module name configured via ``module`` in ``docs()``

**Examples** — given a requirement in ``internals/safety/fmea/requirements.rst``:

Expand All @@ -108,9 +108,10 @@ The feature part is validated by checking that at least one of the following is
- ``blabla`` has no relation to the path ``internals/safety/fmea``

To explicitly allow a feature part that intentionally doesn't match the path
(e.g. in a single module repository), add a matching string to ``required_in_id`` in ``conf.py``:
(e.g. in a single module repository), pass the matching module name:

.. code-block:: python
.. code-block:: starlark

# conf.py
required_in_id = ["persistenc"]
docs(
module = "persistenc",
)
4 changes: 4 additions & 0 deletions docs/reference/bazel_macros.rst
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,10 @@ Minimal example (root ``BUILD``)
and supplies the Docs-as-Code baseline version and extensions. If a ``conf.py``
exists, it remains authoritative and these values are not used.

- ``module`` (string, optional)
The module name allowed in the feature part of requirement IDs when it
intentionally does not match the document path.

- ``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
Expand Down
2 changes: 1 addition & 1 deletion src/extensions/score_metamodel/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -233,7 +233,7 @@ def _clear_needs_defaults(app: Sphinx):
def setup(app: Sphinx) -> dict[str, str | bool]:
app.add_config_value("external_needs_source", "", rebuild="env")
app.add_config_value("score_metamodel_yaml", "", rebuild="env")
app.add_config_value("required_in_id", [], rebuild="env")
app.add_config_value("required_in_id", "", rebuild="env")
config_setdefault(app.config, "needs_id_required", True)
config_setdefault(app.config, "needs_id_regex", "^[A-Za-z0-9_-]{6,}")

Expand Down
16 changes: 5 additions & 11 deletions src/extensions/score_metamodel/checks/id_contains_feature.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,11 +58,9 @@ def id_contains_feature(app: Sphinx, need: NeedItem, log: CheckLogger):
for featurepart in featureparts
if featureparts and featurepart and docname
)
allowed_parts_from_config = app.config.required_in_id
found_part_from_config = any(
part_from_config.lower() in feature.lower()
for part_from_config in allowed_parts_from_config
if allowed_parts_from_config
required_in_id = app.config.required_in_id
found_part_from_config = bool(
required_in_id and required_in_id.lower() in feature.lower()
)

# allow abbreviation of the feature
Expand All @@ -72,17 +70,13 @@ def id_contains_feature(app: Sphinx, need: NeedItem, log: CheckLogger):
foundinitials = bool(initials) and docname and initials in docname.lower()
if not (foundfeatpart or foundinitials or found_part_from_config):
parts_display = ", ".join(f"'{p}'" for p in featureparts)
config_display = (
", ".join(f"'{p}'" for p in allowed_parts_from_config)
if allowed_parts_from_config
else "[]"
)
config_display = f"'{required_in_id}'" if required_in_id else "not set"

fix_options = [f"rename the feature part to match a segment of '{docname}'"]
if initials:
fix_options.append(f"use correct abbreviation '{initials}'")
fix_options.append(
f"Add an allowed part to `required_in_id` in conf.py (currently: {config_display})"
f"Set `module` in docs() to an allowed part (currently: {config_display})"
)

combined_msg = (
Expand Down
4 changes: 2 additions & 2 deletions src/extensions/score_metamodel/tests/rst/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,8 @@
"sphinx_needs",
"score_metamodel",
]
# Required to test this for the check in id_contains_feature
required_in_id = ["blabla"]
# Required to test this for the check in id_contains_feature.
required_in_id = "blabla"
needs_external_needs = [
{
"base_url": "https://eclipse-score.github.io/process_description/main/",
Expand Down
4 changes: 4 additions & 0 deletions src/incremental.py
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,10 @@ def _mounted_watch_dirs(
f"--define=mounts_manifest={os.environ.get('MOUNTS_MANIFEST', '')}",
]

required_in_id = os.environ.get("REQUIRED_IN_ID", "")
if required_in_id:
base_arguments.append(f"--define=required_in_id={required_in_id}")

generated_config = os.environ.get("SPHINX_CONFIG_FILE", "")
if generated_config:
# Under ``bazel run`` this is a runfiles-relative path. Sphinx wants
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,5 +18,6 @@ load("//:docs.bzl", "docs")
# rather than docs(metamodel=...), because the metamodel= wiring does not reach
# the :needs_json target in the current docs.bzl (regression from #484).
docs(
module = "producer",
source_dir = "docs",
)
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,3 @@
score_metamodel_yaml = os.path.join(
os.path.dirname(os.path.abspath(__file__)), "metamodel.yaml"
)

# The producer need id `test_req__producer__demo` has three "__"-parts. The
# id_contains_feature check requires the feature part ("producer") to appear in
# the docname or in required_in_id; the fixture lives in index.rst, so we declare
# it here.
required_in_id = ["producer"]
Original file line number Diff line number Diff line change
Expand Up @@ -14,5 +14,6 @@
load("//:docs.bzl", "docs")

docs(
module = "local",
source_dir = "docs",
)
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,3 @@
project_url = "https://example.invalid/local-version-mismatch"
extensions = ["score_sphinx_bundle"]
score_metamodel_yaml = os.path.join(os.path.dirname(__file__), "metamodel.yaml")
required_in_id = ["local"]
3 changes: 1 addition & 2 deletions src/tests/docs_bzl/test_cross_module_compatibility.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ def _write_cross_module_consumer(
)
workspace.joinpath("BUILD").write_text(
"""load("@score_docs_as_code//:docs.bzl", "docs")
docs(source_dir = "docs", bundles = [{"bundle": "@score_docs_compatibility_fixture//:docs_bundle", "mount_at": "fixture"}])
docs(source_dir = "docs", module = "host", bundles = [{"bundle": "@score_docs_compatibility_fixture//:docs_bundle", "mount_at": "fixture"}])
""",
encoding="utf-8",
)
Expand All @@ -47,7 +47,6 @@ def _write_cross_module_consumer(
project_url = "https://example.invalid/cross-module-consumer"
extensions = ["score_sphinx_bundle"]
score_metamodel_yaml = os.path.join(os.path.dirname(__file__), "metamodel.yaml")
required_in_id = ["host", "fixture"]
{compatibility_config}
""",
encoding="utf-8",
Expand Down
Loading