Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Docs: add esbonio for preview/linting of sphinx documentation #88

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
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
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,6 @@ MODULE.bazel.lock

# Ruff
.ruff_cache

# docs:incremental and docs:ide_support build artifacts
/_build
34 changes: 32 additions & 2 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,39 @@
"editor.rulers": [
100
],

//
//
// RST Settings
"[restructuredtext]": {
"editor.tabSize": 3,
"editor.tabSize": 3,
},
//
//
// Esbonio 0.x (Current)
// see https://github.com/swyddfa/esbonio/blob/0.x/docs/lsp/getting-started.rst
// and https://github.com/swyddfa/esbonio/blob/0.x/docs/lsp/editors/vscode/_configuration.rst
"esbonio.server.pythonPath": "${workspaceFolder}/.venv_docs/bin/python",
"esbonio.sphinx.srcDir": "${workspaceFolder}/docs",
"esbonio.sphinx.confDir": "${workspaceFolder}/docs",
"esbonio.sphinx.buildDir": "${workspaceFolder}/_build",
"esbonio.server.logLevel": "info",
// Do not auto-install. We'll use the one in the venv.
"esbonio.server.installBehavior": "nothing",
// Enable port forwarding for preview if working on remote workstation
"remote.autoForwardPorts": true,
"remote.autoForwardPortsSource": "process",
//
//
// Esbonio 1.x (Preview)
"esbonio.sphinx.pythonCommand": [
".venv_docs/bin/python"
],
"esbonio.sphinx.buildCommand": [
"docs",
"_build",
"--jobs",
"auto"
],
// default is "error", which doesn't show anything.
"esbonio.logging.level": "warning"
}
4 changes: 4 additions & 0 deletions MODULE.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,10 @@ pip.parse(
)
use_repo(pip, "pip_sphinx")

# Additional Python rules provided by aspect, e.g. an improved version of
# `py_binary`. But more importantly, it provides `py_venv`.
bazel_dep(name = "aspect_rules_py", version = "1.0.0")

###############################################################################
#
# Packaging dependencies
Expand Down
58 changes: 52 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,60 @@ $ bazel run //:format.fix

## Documentation

Use //docs:docs target to build the documentation.
```
$ bazel build //docs:docs
Score supports multiple methods for generating documentation, tailored to different workflows:
1. **Bazel-based builds** for clean, sandboxed outputs.
2. **Incremental builds** for quick iterations during development.
3. **IDE integration** for live previews, live warnings and even faster iterations.

### Bazel-based Build

This method ensures clean and isolated documentation builds in a controlled Bazel environment.
It is best suited for CI pipelines or production-ready outputs, although it takes longer compared to
incremental builds.

```sh
bazel build //docs:docs
```
The output will be located in bazel-bin/docs/docs/_build/html.

The output directory can be found under ```bazel-bin/docs/docs/_build/html```.

If you need to update pip dependencies, after modifying the requirements file, regenerate the lock file:
### Incremental build

For local changes and faster feedback, use the incremental build.
This method generates the documentation directly in the _build directory.

```sh
bazel run //docs:incremental
```
bazel run //docs:requirements.update
Unlike IDE integration, which renders only the current file, this approach is ideal for quickly
verifying edits across the entire documentation during development.


### IDE integration

For live previews, warnings, and linting during development,
integrate Esbonio with your IDE (e.g., VS Code):

```sh
bazel run //docs:ide_support
```

VS Code: Install the Esbonio extension in VS Code. After installation, restart your IDE.
You should now have live preview available when you open a `.rst` file.
Note: if the extension was already installed when you ran the `ide_support` command,
you will need to restart your IDE.

For features like type detection in conf.py or extensions,
point your IDE to the .venv_docs virtual environment.

Re-run //docs:ide_support if you update Sphinx extensions or other dependencies.

### Notes
#### Output Locations
* Bazel builds output to bazel-bin/docs/docs/_build/html.
* Incremental builds output to _build.

#### Troubleshooting
* Restart your IDE if live previews or warnings are not working after running ide_support.
* Ensure your virtual environment is up-to-date by re-running //docs:ide_support when dependencies
change.
54 changes: 53 additions & 1 deletion docs/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,44 @@
# SPDX-License-Identifier: Apache-2.0
# *******************************************************************************

# Multiple approaches are available to build the same documentation output:
#
# 1. **Esbonio via IDE support (`ide_support` target)**:
# - Listed first as it offers the least flexibility in implementation.
# - Designed for live previews and quick iterations when editing documentation.
# - Integrates with IDEs like VS Code but requires the Esbonio extension.
# - Requires a virtual environment with consistent dependencies (see 2).
#
# 2. **Directly running Sphinx in the virtual environment**:
# - As mentioned above, a virtual environment is required for running esbonio.
# - Therefore, the same environment can be used to run Sphinx directly.
# - Option 1: Run Sphinx manually via `.venv_docs/bin/python -m sphinx docs _build --jobs auto`.
# - Option 2: Use the `incremental` target, which simplifies this process.
# - Usable in CI pipelines to validate the virtual environment used by Esbonio.
# - Ideal for quickly generating documentation during development.
#
# 3. **Bazel-based build (`docs` target)**:
# - Runs the documentation build in a Bazel sandbox, ensuring clean, isolated builds.
# - Less convenient for frequent local edits but ensures build reproducibility.
#
# **Consistency**:
# When modifying Sphinx extensions or configuration, ensure all three methods
# (Esbonio, incremental, and Bazel) work as expected to avoid discrepancies.
#
# For user-facing documentation, refer to `/README.md`.

load("@aspect_rules_py//py:defs.bzl", "py_venv")
load("@pip_sphinx//:requirements.bzl", "all_requirements", "requirement")
load("@rules_pkg//pkg:mappings.bzl", "pkg_files")
load("@rules_pkg//pkg:tar.bzl", "pkg_tar")
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] + [":extensions"]

sphinx_docs(
name = "docs",
srcs = glob([
Expand All @@ -43,7 +74,7 @@ sphinx_docs(

sphinx_build_binary(
name = "sphinx_build",
deps = [":extensions"] + all_requirements,
deps = sphinx_requirements,
)

py_library(
Expand All @@ -55,6 +86,11 @@ py_library(
imports = ["."],
)

# In order to update the requirements, change the `requirements.txt` file and run:
# `bazel run //docs:requirements`.
# This will update the `requirements_lock.txt` file.
# To upgrade all dependencies to their latest versions, run:
# `bazel run //docs:requirements -- --upgrade`.
compile_pip_requirements(
name = "requirements",
src = "requirements.txt",
Expand All @@ -80,3 +116,19 @@ pkg_tar(
name = "github-pages",
srcs = [":html_files"],
)

# Run-time build of documentation, incl. incremental build support.
py_binary(
name = "incremental",
srcs = ["incremental.py"],
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")],
)
2 changes: 0 additions & 2 deletions docs/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,6 @@

templates_path = ["_templates"]

suppress_warnings = ["config.cache"]

# Enable numref
numfig = True

Expand Down
42 changes: 42 additions & 0 deletions docs/incremental.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
# *******************************************************************************
# 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
# *******************************************************************************

import os
import sys

try:
from sphinx.cmd.build import main as sphinx_main
except ImportError:
sys.exit(
"This script must be run from Bazel via `bazel run //docs:incremental`"
" (sphinx not installed)."
)

workspace = os.getenv("BUILD_WORKSPACE_DIRECTORY")
if not workspace:
sys.exit(
"This script must be run from Bazel via `bazel run //docs:incremental`"
" (BUILD_WORKSPACE_DIRECTORY not set)."
)

# sphinx will print relative paths to the current directory.
# Change to the workspace root so that the paths are readable and clickable.
os.chdir(workspace)
sphinx_main(
[
"docs",
"_build",
"--jobs",
"auto",
]
)
11 changes: 8 additions & 3 deletions docs/requirements.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
--extra-index-url https://pypi.org/simple/

Sphinx==8.1.3
sphinx-needs==4.1.0
pydata-sphinx-theme==0.16.0
Sphinx
sphinx-needs
pydata-sphinx-theme

# 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
29 changes: 29 additions & 0 deletions docs/requirements_lock.txt
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,9 @@ attrs==24.2.0 \
--hash=sha256:5cfb1b9148b5b086569baec03f20d7b6bf3bcacc9a42bebf87ffaaca362f6346 \
--hash=sha256:81921eb96de3191c8258c199618104dd27ac608d9366f5e35d011eae1867ede2
# via
# cattrs
# jsonschema
# lsprotocol
# referencing
babel==2.15.0 \
--hash=sha256:08706bdad8d0a3413266ab61bd6c34d0c28d6e1e7badf40a2cebe67644e2e1fb \
Expand All @@ -30,6 +32,12 @@ beautifulsoup4==4.12.3 \
--hash=sha256:74e3d1928edc070d21748185c46e3fb33490f22f52a3addee9aee0f4f7781051 \
--hash=sha256:b80878c9f40111313e55da8ba20bdba06d8fa3969fc68304167741bbf9e082ed
# via pydata-sphinx-theme
cattrs==24.1.2 \
--hash=sha256:67c7495b760168d931a10233f979b28dc04daf853b30752246f4f8471c6d68d0 \
--hash=sha256:8028cfe1ff5382df59dd36474a86e02d817b06eaf8af84555441bac915d2ef85
# via
# lsprotocol
# pygls
certifi==2024.7.4 \
--hash=sha256:5a1e7645bc0ec61a09e26c36f6106dd4cf40c6db3a1fb6352b0244e7fb057c7b \
--hash=sha256:c198e21b1289c2ab85ee4e67bb4b4ef3ead0892059901a8d5b622f24a1101e90
Expand Down Expand Up @@ -132,6 +140,10 @@ docutils==0.20.1 \
# via
# pydata-sphinx-theme
# sphinx
esbonio==0.16.5 \
--hash=sha256:04ba926e3603f7b1fde1abc690b47afd60749b64b1029b6bce8e1de0bb284921 \
--hash=sha256:acab2e16c6cf8f7232fb04e0d48514ce50566516b1f6fcf669ccf2f247e8b10f
# via -r docs/requirements.txt
idna==3.7 \
--hash=sha256:028ff3aadf0609c1fd278d8ea3089299412a7a8b9bd005dd08b9f8285bcb5cfc \
--hash=sha256:82fee1fc78add43492d3a1898bfa6d8a904cc97d8427f683ed8e798d07761aa0
Expand All @@ -152,6 +164,10 @@ jsonschema-specifications==2024.10.1 \
--hash=sha256:0f38b83639958ce1152d02a7f062902c41c8fd20d558b0c34344292d417ae272 \
--hash=sha256:a09a0680616357d9a0ecf05c12ad234479f549239d0f5b55f3deea67475da9bf
# via jsonschema
lsprotocol==2023.0.1 \
--hash=sha256:c75223c9e4af2f24272b14c6375787438279369236cd568f596d4951052a60f2 \
--hash=sha256:cc5c15130d2403c18b734304339e51242d3018a05c4f7d0f198ad6e0cd21861d
# via pygls
markupsafe==2.1.5 \
--hash=sha256:00e046b6dd71aa03a41079792f8473dc494d564611a8f89bbbd7cb93295ebdcf \
--hash=sha256:075202fa5b72c86ad32dc7d0b56024ebdbcf2048c0ba09f1cde31bfdd57bcfff \
Expand Down Expand Up @@ -218,17 +234,29 @@ packaging==24.1 \
--hash=sha256:026ed72c8ed3fcce5bf8950572258698927fd1dbda10a5e981cdf0ac37f4f002 \
--hash=sha256:5b8f2217dbdbd2f7f384c41c628544e6d52f2d0f53c6d0c3ea61aa5d1d7ff124
# via sphinx
platformdirs==4.3.6 \
--hash=sha256:357fb2acbc885b0419afd3ce3ed34564c13c9b95c89360cd9563f73aa5e2b907 \
--hash=sha256:73e575e1408ab8103900836b97580d5307456908a03e92031bab39e4554cc3fb
# via esbonio
pydata-sphinx-theme==0.16.0 \
--hash=sha256:18c810ee4e67e05281e371e156c1fb5bb0fa1f2747240461b225272f7d8d57d8 \
--hash=sha256:721dd26e05fa8b992d66ef545536e6cbe0110afb9865820a08894af1ad6f7707
# via -r docs/requirements.txt
pygls==1.3.1 \
--hash=sha256:140edceefa0da0e9b3c533547c892a42a7d2fd9217ae848c330c53d266a55018 \
--hash=sha256:6e00f11efc56321bdeb6eac04f6d86131f654c7d49124344a9ebb968da3dd91e
# via esbonio
pygments==2.18.0 \
--hash=sha256:786ff802f32e91311bff3889f6e9a86e81505fe99f2735bb6d60ae0c5004f199 \
--hash=sha256:b8e6aca0523f3ab76fee51799c488e38782ac06eafcf95e7ba832985c8e7b13a
# via
# accessible-pygments
# pydata-sphinx-theme
# sphinx
pyspellchecker==0.8.1 \
--hash=sha256:3478ca8484d1c2db0c93d12b3c986cd17958c69f47b3ed7ef4d3f4201e591776 \
--hash=sha256:d91e9e1064793ae1ee8e71b06ca40eeb8e5923437c54291a8e041b447792b640
# via esbonio
referencing==0.35.1 \
--hash=sha256:25b42124a6c8b632a425174f24087783efb348a6f1e0008e63cd4466fedf703c \
--hash=sha256:eda6d3234d62814d1c64e305c1331c9a3a6132da475ab6382eaa997b21ee75de
Expand Down Expand Up @@ -353,6 +381,7 @@ sphinx==8.1.3 \
--hash=sha256:43c1911eecb0d3e161ad78611bc905d1ad0e523e4ddc202a58a821773dc4c927
# via
# -r docs/requirements.txt
# esbonio
# pydata-sphinx-theme
# sphinx-data-viewer
# sphinx-needs
Expand Down
Loading