Skip to content

Commit

Permalink
docs: add plantuml (#158)
Browse files Browse the repository at this point in the history
PlantUML can be used to draw images, especially uml-like images.

Signed-off-by: Alexander Lanin <[email protected]>
  • Loading branch information
AlexanderLanin authored Jan 23, 2025
1 parent edb023b commit 49d8db4
Show file tree
Hide file tree
Showing 15 changed files with 375 additions and 39 deletions.
5 changes: 5 additions & 0 deletions .bazelrc
Original file line number Diff line number Diff line change
@@ -1 +1,6 @@
build --java_language_version=17
build --tool_java_language_version=17
build --java_runtime_version=remotejdk_17
build --tool_java_runtime_version=remotejdk_17

test --test_output=errors
10 changes: 9 additions & 1 deletion MODULE.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ use_repo(python)

###############################################################################
#
# pip dependencies
# docs dependencies (Sphinx)
#
###############################################################################
pip = use_extension("@rules_python//python/extensions:pip.bzl", "pip")
Expand All @@ -50,6 +50,14 @@ use_repo(pip, "pip_sphinx")
# `py_binary`. But more importantly, it provides `py_venv`.
bazel_dep(name = "aspect_rules_py", version = "1.0.0")

http_jar = use_repo_rule("@bazel_tools//tools/build_defs/repo:http.bzl", "http_jar")

http_jar(
name = "plantuml",
sha256 = "6f38f70455d08438979451c2257cd5d58647c6460094bb829bc2a12878d47331",
url = "https://github.com/plantuml/plantuml/releases/download/v1.2025.0/plantuml-1.2025.0.jar",
)

###############################################################################
#
# Packaging dependencies
Expand Down
61 changes: 38 additions & 23 deletions docs/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -45,9 +45,11 @@ load("@rules_python//python:defs.bzl", "py_library")
load("@rules_python//python:pip.bzl", "compile_pip_requirements")
load("@rules_python//sphinxdocs:sphinx.bzl", "sphinx_build_binary", "sphinx_docs")

# all_requirements include esbonio which we don't need most of the time.
# Hint: the names are e.g. "@@rules_python~~pip~pip_sphinx//esbonio:pkg"
sphinx_requirements = [name for name in all_requirements if not "esbonio" in name]
sphinx_requirements = all_requirements + [
"@rules_python//python/runfiles",
":plantuml_for_python",
"//docs/_tooling/sphinx_extensions",
]

sphinx_docs(
name = "docs",
Expand All @@ -57,6 +59,10 @@ sphinx_docs(
"**/*.rst",
"**/*.html",
"**/*.css",
"**/*.puml",
# Include the docs tooling itself
# Note: we don't use py_library here to make it as close as possible to docs:incremental.
"**/*.py",
]),
config = ":conf.py",
extra_opts = [
Expand All @@ -69,24 +75,14 @@ sphinx_docs(
tags = [
"manual",
],
tools = [
":plantuml",
],
)

sphinx_build_binary(
name = "sphinx_build",
deps = sphinx_requirements + [
":extensions",
"//docs/_tooling/sphinx_extensions",
],
)

py_library(
name = "extensions",
srcs =
glob([
"_tooling/conf_extras/*.py",
"_tooling/extensions/*.py",
]),
imports = ["."],
deps = sphinx_requirements,
)

# In order to update the requirements, change the `requirements.txt` file and run:
Expand Down Expand Up @@ -124,17 +120,36 @@ pkg_tar(
py_binary(
name = "incremental",
srcs = ["_tooling/incremental.py"],
deps = sphinx_requirements + [
":extensions",
"//docs/_tooling/sphinx_extensions",
],
deps = sphinx_requirements,
)

# Virtual python environment for working on the documentation (esbonio).
# incl. python support when working on conf.py and sphinx extensions.
py_venv(
name = "ide_support",
venv_name = ".venv_docs",
# Until release of esbonio 1.x, we need to install it ourselves so the VS Code extension can find it.
deps = sphinx_requirements + [requirement("esbonio")],
deps = sphinx_requirements,
)

java_binary(
name = "plantuml",
jvm_flags = ["-Djava.awt.headless=true"],
main_class = "net.sourceforge.plantuml.Run",
runtime_deps = [
"@plantuml//jar",
],
)

# This makes it possible for py_venv to depend on plantuml.
# Note: py_venv can only depend on py_library.
# TODO: Investigate if this can be simplified with a custom bzl rule
# which replaces / wraps py_venv.
# see https://github.com/aspect-build/rules_py/blob/main/py/private/py_venv.bzl
# see https://github.com/bazelbuild/rules_python/blob/main/sphinxdocs/private/sphinx.bzl
py_library(
name = "plantuml_for_python",
srcs = ["_tooling/dummy.py"],
data = [
":plantuml",
],
)
13 changes: 13 additions & 0 deletions docs/_tooling/dummy.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# *******************************************************************************
# Copyright (c) 2024 Contributors to the Eclipse Foundation
#
# See the NOTICE file(s) distributed with this work for additional
# information regarding copyright ownership.
#
# This program and the accompanying materials are made available under the
# terms of the Apache License Version 2.0 which is available at
# https://www.apache.org/licenses/LICENSE-2.0
#
# SPDX-License-Identifier: Apache-2.0
# *******************************************************************************
"""intentionally empty"""
110 changes: 110 additions & 0 deletions docs/_tooling/extensions/score_plantuml.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
# *******************************************************************************
# Copyright (c) 2024 Contributors to the Eclipse Foundation
#
# See the NOTICE file(s) distributed with this work for additional
# information regarding copyright ownership.
#
# This program and the accompanying materials are made available under the
# terms of the Apache License Version 2.0 which is available at
# https://www.apache.org/licenses/LICENSE-2.0
#
# SPDX-License-Identifier: Apache-2.0
# *******************************************************************************

"""
This extension sets up PlantUML within the SCORE Bazel environment.
The complexity arises, as the plantuml binary is only available through Bazel.
However going through `bazel run //docs:plantuml` for every PlantUML diagram
is simply too slow.
This extension determines the path to the plantuml binary and sets it up in the
Sphinx configuration.
In addition it sets common PlantUML options, like output to svg_obj.
"""

import sys
from pathlib import Path

from sphinx.application import Sphinx
from sphinx.util import logging

try:
from python.runfiles import Runfiles
except ImportError:
sys.exit(
"ERROR: This script must be run from within the virtual environment "
"which can be generated by `bazel run //docs:ide_support`. "
"It can also be run indirectly via bazel, e.g. "
"`bazel run //docs:incremental`."
)

logger = logging.getLogger(__name__)


def get_plantuml_path() -> Path:
"""Determine the path to the plantuml binary."""

runfiles_dir = get_runfiles_dir()

plantuml = runfiles_dir / ".." / "plantuml"
# Note: this MUST NOT be resolved as we need the "something.runfiles/../"
# piece as part of the path! This way the bazel plantuml script will find
# the runfiles.

if not plantuml.exists():
sys.exit(
f"Could not find plantuml binary at {plantuml}. "
"Have a look at README.md for instructions on how to build docs."
)

return plantuml


def get_runfiles_dir() -> Path:
if r := Runfiles.Create():
# Runfiles are only available when running in Bazel.
# bazel build and bazel run are both supported.
# i.e. `bazel build //docs:docs` and `bazel run //docs:incremental`.
logger.debug("Using runfiles to determine plantuml path.")

runfiles_dir = Path(r.EnvVars()["RUNFILES_DIR"])
if not runfiles_dir.exists():
sys.exit(
f"Could not find runfiles at {runfiles_dir}. Have a look at "
"README.md for instructions on how to build docs."
)

else:
# The only way to land here is when running from within the virtual
# environment created by the `docs:ide_support` rule in the BUILD file.
# i.e. esbonio or manual sphinx-build execution within the virtual
# environment.
# We'll still use the plantuml binary from the bazel build.
# But we need to find it first.
logger.debug("Running outside bazel.")

git_root = Path(__file__).resolve().parents[3]
assert (
git_root / ".git"
).exists(), f"Could not find git root. Assumed path: {git_root}"

runfiles_dir = git_root / "bazel-bin" / "docs" / "ide_support.runfiles"
if not runfiles_dir.exists():
sys.exit(
f"Could not find ide_support.runfiles at {runfiles_dir}. "
"Have a look at README.md for instructions on how to build docs."
)

return runfiles_dir


def setup(app: Sphinx):
app.config.plantuml = str(get_plantuml_path())
app.config.plantuml_output_format = "svg_obj"

logger.debug(f"PlantUML binary found at {app.config.plantuml}")

# The extension is not even active at runtime.
return {"parallel_read_safe": True, "parallel_write_safe": True}
10 changes: 5 additions & 5 deletions docs/_tooling/requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,9 @@ sphinxcontrib-plantuml
pytest
pydata-sphinx-theme
sphinx-design
sphinxcontrib-plantuml


# esbonio >= 1 comes bundled with the esbonio extension >= 1.
# esbonio<1 is required for the esbonio extension <1
# So what we need to install here is esbonio<1
esbonio<1
# Until release of esbonio 1.x, we need to install it ourselves so the VS Code esbonio-extension
# can find it.
# esbonio >= 1 comes bundled with the esbonio-extension >= 1.
# esbonio<1 is required for the esbonio-extension <1
5 changes: 5 additions & 0 deletions docs/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
# For the full list of built-in configuration values, see the documentation:
# https://www.sphinx-doc.org/en/master/usage/configuration.html

import os
import sys

# sys.path extension for local files is needed, because the conf.py file is not
Expand All @@ -34,9 +35,12 @@
# -- General configuration ---------------------------------------------------
# https://www.sphinx-doc.org/en/master/usage/configuration.html#general-configuration

sys.path.insert(0, os.path.abspath("_tooling/extensions"))
extensions = [
"sphinx_design",
"sphinx_needs",
"sphinxcontrib.plantuml",
"score_plantuml",
]

exclude_patterns = [
Expand All @@ -61,6 +65,7 @@
# Enable numref
numfig = True


# -- Options for HTML output -------------------------------------------------
# https://www.sphinx-doc.org/en/master/usage/configuration.html#options-for-html-output

Expand Down
7 changes: 1 addition & 6 deletions docs/features/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,4 @@ Features
:maxdepth: 1
:glob:

infrastructure/index.rst
integration/index.rst
analysis-infra/index.rst
communication/index.rst
frameworks/index.rst
persistency/index.rst
*/index
6 changes: 3 additions & 3 deletions docs/features/infrastructure/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
# SPDX-License-Identifier: Apache-2.0
# *******************************************************************************
.. _infrastructure_feratures:
.. _infrastructure_feature:

################
Infrastructure
Expand All @@ -36,5 +36,5 @@ that are used for development.
:titlesonly:
:maxdepth: 1

bazel_registry.rst
config_as_code.rst
bazel_registry
config_as_code
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading

0 comments on commit 49d8db4

Please sign in to comment.