Skip to content

Commit a326b68

Browse files
authored
docs: show PR warning banner and fix links doc source pages (#1521)
This fixes a few issues with the RTD doc building: * Warning banner is now shown for PR requests * Pages now link to the github source * The footer now shows the git commit they were built at This works by passing the RTD environment variables to the sphinx build process, which allows the conf.py file to get their values. Env vars are passed by a new flag, `--//sphinxdocs:extra_env`, which allows passing arbitrary environment variable values into the sphinx build process. To make future usage of the RTD env vars easier, the build process passes along all the `READTHEDOCS*` environment variables. Fixes #1516
1 parent 723a80a commit a326b68

File tree

5 files changed

+96
-11
lines changed

5 files changed

+96
-11
lines changed

.readthedocs.yml

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,4 +8,7 @@ build:
88
commands:
99
- env
1010
- npm install -g @bazel/bazelisk
11-
- bazel run --config=rtd --//sphinxdocs:extra_defines=version=$READTHEDOCS_VERSION //docs/sphinx:readthedocs_install
11+
- bazel version
12+
# Put the actual build behind a shell script because its easier to modify than
13+
# the yaml config.
14+
- docs/sphinx/readthedocs_build.sh

docs/sphinx/conf.py

Lines changed: 52 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
# Configuration file for the Sphinx documentation builder.
22

3+
import os
4+
35
# -- Project information
46
project = "rules_python"
57
copyright = "2023, The Bazel Authors"
@@ -27,6 +29,29 @@
2729
"sphinx_rtd_theme", # Necessary to get jquery to make flyout work
2830
]
2931

32+
# Adapted from the template code:
33+
# https://github.com/readthedocs/readthedocs.org/blob/main/readthedocs/doc_builder/templates/doc_builder/conf.py.tmpl
34+
if os.environ.get("READTHEDOCS") == "True":
35+
# Must come first because it can interfere with other extensions, according
36+
# to the original conf.py template comments
37+
extensions.insert(0, "readthedocs_ext.readthedocs")
38+
39+
if os.environ.get("READTHEDOCS_VERSION_TYPE") == "external":
40+
# Insert after the main extension
41+
extensions.insert(1, "readthedocs_ext.external_version_warning")
42+
readthedocs_vcs_url = "http://github.com/bazelbuild/rules_python/pull/{}".format(
43+
os.environ.get("READTHEDOCS_VERSION", "")
44+
)
45+
# The build id isn't directly available, but it appears to be encoded
46+
# into the host name, so we can parse it from that. The format appears
47+
# to be `build-X-project-Y-Z`, where:
48+
# * X is an integer build id
49+
# * Y is an integer project id
50+
# * Z is the project name
51+
_build_id = os.environ.get("HOSTNAME", "build-0-project-0-rules-python")
52+
_build_id = _build_id.split("-")[1]
53+
readthedocs_build_url = f"https://readthedocs.org/projects/rules-python/builds/{_build_id}"
54+
3055
exclude_patterns = ["_includes/*"]
3156
templates_path = ["_templates"]
3257
primary_domain = None # The default is 'py', which we don't make much use of
@@ -69,6 +94,33 @@
6994
html_theme = "sphinx_rtd_theme"
7095
html_theme_options = {}
7196

97+
# The html_context settings are part of the jinja context used by the themes.
98+
html_context = {
99+
# This controls whether the flyout menu is shown. It is always false
100+
# because:
101+
# * For local builds, the flyout menu is empty and doesn't show in the
102+
# same place as for RTD builds. No point in showing it locally.
103+
# * For RTD builds, the flyout menu is always automatically injected,
104+
# so having it be True makes the flyout show up twice.
105+
"READTHEDOCS": False,
106+
'PRODUCTION_DOMAIN': "readthedocs.org",
107+
# This is the path to a page's source (after the github user/repo/commit)
108+
"conf_py_path": "/docs/sphinx/",
109+
'github_user': 'bazelbuild',
110+
'github_repo': 'rules_python',
111+
# The git version that was checked out, e.g. the tag or branch name
112+
'github_version': os.environ.get("READTHEDOCS_GIT_IDENTIFIER", ""),
113+
# For local builds, the github link won't work. Disabling it replaces
114+
# it with a "view source" link to view the source Sphinx saw, which
115+
# is useful for local development.
116+
'display_github': os.environ.get("READTHEDOCS") == "True",
117+
'commit': os.environ.get("READTHEDOCS_GIT_COMMIT_HASH", "unknown commit"),
118+
119+
# Used by readthedocs_ext.external_version_warning extension
120+
# This is the PR number being built
121+
'current_version': os.environ.get("READTHEDOCS_VERSION", ""),
122+
}
123+
72124
# Keep this in sync with the stardoc templates
73125
html_permalinks_icon = "¶"
74126

@@ -86,7 +138,6 @@
86138

87139
suppress_warnings = ["myst.header", "myst.xref_missing"]
88140

89-
90141
def setup(app):
91142
# Pygments says it supports starlark, but it doesn't seem to actually
92143
# recognize `starlark` as a name. So just manually map it to python.

docs/sphinx/readthedocs_build.sh

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
#!/bin/bash
2+
3+
set -eou pipefail
4+
5+
declare -a extra_env
6+
while IFS='=' read -r -d '' name value; do
7+
if [[ "$name" == READTHEDOCS* ]]; then
8+
extra_env+=("--//sphinxdocs:extra_env=$name=$value")
9+
fi
10+
done < <(env -0)
11+
12+
# In order to get the build number, we extract it from the host name
13+
extra_env+=("--//sphinxdocs:extra_env=HOSTNAME=$HOSTNAME")
14+
15+
set -x
16+
bazel run \
17+
"--//sphinxdocs:extra_defines=version=$READTHEDOCS_VERSION" \
18+
"${extra_env[@]}" \
19+
//docs/sphinx:readthedocs_install

sphinxdocs/BUILD.bazel

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,19 +13,24 @@
1313
# limitations under the License.
1414

1515
load("@bazel_skylib//:bzl_library.bzl", "bzl_library")
16-
load("//sphinxdocs/private:sphinx.bzl", "sphinx_defines_flag")
16+
load("//sphinxdocs/private:sphinx.bzl", "repeated_string_list_flag")
1717

1818
package(
1919
default_visibility = ["//:__subpackages__"],
2020
)
2121

2222
# Additional -D values to add to every Sphinx build.
2323
# This is usually used to override the version when building
24-
sphinx_defines_flag(
24+
repeated_string_list_flag(
2525
name = "extra_defines",
2626
build_setting_default = [],
2727
)
2828

29+
repeated_string_list_flag(
30+
name = "extra_env",
31+
build_setting_default = [],
32+
)
33+
2934
bzl_library(
3035
name = "sphinx_bzl",
3136
srcs = ["sphinx.bzl"],

sphinxdocs/private/sphinx.bzl

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,7 @@ _sphinx_docs = rule(
155155
),
156156
"strip_prefix": attr.string(doc = "Prefix to remove from input file paths."),
157157
"_extra_defines_flag": attr.label(default = "//sphinxdocs:extra_defines"),
158+
"_extra_env_flag": attr.label(default = "//sphinxdocs:extra_env"),
158159
},
159160
)
160161

@@ -201,30 +202,36 @@ def _run_sphinx(ctx, format, source_path, inputs, output_prefix):
201202
args.add("-E") # Don't try to use cache files. Bazel can't make use of them.
202203
args.add("-a") # Write all files; don't try to detect "changed" files
203204
args.add_all(ctx.attr.extra_opts)
204-
args.add_all(ctx.attr._extra_defines_flag[_SphinxDefinesInfo].value, before_each = "-D")
205+
args.add_all(ctx.attr._extra_defines_flag[_FlagInfo].value, before_each = "-D")
205206
args.add(source_path)
206207
args.add(output_dir.path)
207208

209+
env = dict([
210+
v.split("=", 1)
211+
for v in ctx.attr._extra_env_flag[_FlagInfo].value
212+
])
213+
208214
ctx.actions.run(
209215
executable = ctx.executable.sphinx,
210216
arguments = [args],
211217
inputs = inputs,
212218
outputs = [output_dir],
213219
mnemonic = "SphinxBuildDocs",
214220
progress_message = "Sphinx building {} for %{{label}}".format(format),
221+
env = env,
215222
)
216223
return output_dir
217224

218-
_SphinxDefinesInfo = provider(
219-
doc = "Provider for the extra_defines flag value",
225+
_FlagInfo = provider(
226+
doc = "Provider for a flag value",
220227
fields = ["value"],
221228
)
222229

223-
def _sphinx_defines_flag_impl(ctx):
224-
return _SphinxDefinesInfo(value = ctx.build_setting_value)
230+
def _repeated_string_list_flag_impl(ctx):
231+
return _FlagInfo(value = ctx.build_setting_value)
225232

226-
sphinx_defines_flag = rule(
227-
implementation = _sphinx_defines_flag_impl,
233+
repeated_string_list_flag = rule(
234+
implementation = _repeated_string_list_flag_impl,
228235
build_setting = config.string_list(flag = True, repeatable = True),
229236
)
230237

0 commit comments

Comments
 (0)