Repository navigation
Expand file tree
/
Copy path.readthedocs.yaml
More file actions
142 lines (138 loc) · 7.59 KB
/
Copy path.readthedocs.yaml
File metadata and controls
142 lines (138 loc) · 7.59 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
# .readthedocs.yaml
# Read the Docs configuration file
# See https://docs.readthedocs.io/en/stable/config-file/v2.html for details
# Required
version: 2
# Set the version of Python and other tools you might need
build:
os: ubuntu-24.04
tools:
python: "3.11"
jobs:
# On PR builds, skip the Sphinx build when the PR doesn't touch any
# files that affect documentation output. Reduces queue pressure on
# the shared RTD build slots when several PRs are open at once.
# Tag/branch builds (master, stable, etc.) always run.
# The guard matches doc/ but excludes doc/.claude/ (Claude Code skills
# and agent files), which never participate in the Sphinx build, so a
# PR that changes only those paths skips the build instead of running one.
# Code sources (python/ray/) are intentionally not matched, so a
# code-only PR skips this PR preview. The RTD PR check is not a required
# merge gate, and the post-merge master build and the Buildkite doc_build
# still render docstring-driven API-reference changes. This trades a
# non-gating premerge preview for less pressure on the shared RTD slots.
# A PR that needs the preview anyway, such as one that edits docstrings,
# opts in with a line that starts with @rtd-build in any commit message on
# the PR. Ray squash-merges with the PR title and body, so the line never
# reaches master.
# See https://docs.readthedocs.com/platform/stable/guides/build/skip-build.html
#
# Some constructs are avoided deliberately because RTD's job runner
# silently drops scripts that contain them: use echo (not printf
# with a backslash-escape format string), avoid backslash escapes
# in general, and keep shell comments out of this block so that
# backticks/$() inside comments don't confuse the preprocessor.
# The runner also strips the surrounding single quotes from arguments,
# so use git's :! exclude shorthand rather than :(exclude): unquoted
# parentheses reach /bin/sh (dash) and abort the script with a syntax error.
post_checkout:
- |
if [ "${READTHEDOCS_VERSION_TYPE:-}" != "external" ]; then
echo "Not a PR build (version type: '${READTHEDOCS_VERSION_TYPE:-unset}'); building docs."
exit 0
fi
git fetch --depth=500 origin master 2>/dev/null || true
if ! git merge-base origin/master HEAD >/dev/null 2>&1; then
echo "Could not determine merge-base with origin/master; building docs to be safe."
exit 0
fi
if git log --format=%B origin/master..HEAD | grep -q '^[[:space:]]*@rtd-build'; then
echo "A commit message in this PR requests a build with @rtd-build; building docs."
exit 0
fi
if git diff --quiet origin/master...HEAD -- doc/ ':!doc/.claude/' .readthedocs.yaml; then
echo "No doc-affecting files changed in this PR; skipping Sphinx build."
echo "Files changed in PR:"
git diff --name-only origin/master...HEAD
exit 183
fi
echo "Doc-affecting files changed; building docs. Changed doc-relevant paths:"
git diff --name-only origin/master...HEAD -- doc/ ':!doc/.claude/' .readthedocs.yaml
# Override the html build step so every build runs a full clean Sphinx
# build via the doc/Makefile html target, for PR (external) previews and
# branch/tag builds alike.
#
# The incremental-from-master-cache path added in #64277 is disabled for
# now. On every PR preview Sphinx discards the restored cache because a
# config value differs between the environment that produced the cache and
# the RTD build environment, so it rebuilds all documents anyway while
# still paying the cache download and extract cost, and it risks a second
# clean rebuild when the incremental leg trips a warning. A clean build is
# faster and lower-variance in practice today. Re-enable the incremental
# path only once cache reuse is confirmed (Sphinx logs "N changed" rather
# than "NNNN added") and stale-artifact pruning lands for PRs that rename
# or delete sources. The rtd and rtd-fallback Makefile targets and
# doc/load_doc_cache.py stay in the tree for that re-enable.
# Raise pip's retry budget for the dependency install below.
# files.pythonhosted.org has been returning intermittent 502s
# (https://github.com/pypi/support/issues/11895), and one failed wheel fetch
# fails the whole docs build. pip defaults to 5 retries with exponential
# backoff, which gives up in about 8 seconds of sleeping.
#
# Written as a config file rather than PIP_RETRIES because the install step
# is python.install below, run by Read the Docs rather than by us, and each
# job command runs in its own shell so an export here would not reach it.
# pip reads this path on every invocation in the build, including that one.
#
# Only the retry count is raised. The observed failures are immediate 502
# responses rather than hangs, so a larger timeout would only lengthen the
# worst case without making a fetch more likely to succeed.
pre_install:
- mkdir -p ~/.config/pip
- |
echo "[global]" > ~/.config/pip/pip.conf
echo "retries = 10" >> ~/.config/pip/pip.conf
cat ~/.config/pip/pip.conf
# Build with doc/Makefile's default SPHINX_JOBS of auto, one Sphinx write
# worker per CPU, the same as local builds and the Buildkite doc build.
#
# This job used to pin SPHINX_JOBS=2 (#65643). The builder has a
# 7,130,316,800 byte cgroup memory ceiling (about 6.64 GiB, the documented
# Business limit), each worker holds its own copy of the build environment,
# and at -j auto the build peaked within about 600 MB of that ceiling and
# was sometimes OOM-killed. When the kernel kills a write worker the parent
# Sphinx process reports only a bare EOFError from
# multiprocessing/connection.py, naming no document.
#
# Most of that memory was a leak: MyST {eval-rst} blocks pickled the whole
# build environment into each page's doctree, and every worker loaded those
# doctrees back. doc/source/_ext/myst_eval_rst_doctree.py fixes it (#66784).
# After the fix, a local build with this job's flags, summing RSS across the
# Sphinx processes, peaked at 4.74 GB at -j 4 against 2.67 GB at -j 2, and
# took 425 seconds against 914. Summed RSS overstates the cgroup figure,
# since it counts pages shared between forked workers more than once.
#
# If EOFError failures come back, memory is the first suspect: set
# SPHINX_JOBS=2 on the make command below.
#
# PYTHONFAULTHANDLER=1 makes Python dump the stack of every thread to
# stderr when the process receives a fatal signal such as SIGSEGV. Since
# 2026-09-23 some builds have died with a bare "Segmentation fault (core
# dumped)" from make about 7 seconds into sphinx-build, right after
# autosummary starts, while the same commit and the same installed package
# versions pass on a retry. Without the handler the log names no module or
# frame, so there is nothing to act on or to hand to Read the Docs support.
# The handler costs nothing unless a fatal signal arrives.
build:
html:
- |
PYTHONFAULTHANDLER=1 make -C doc html HTMLDIR="$READTHEDOCS_OUTPUT/html"
# Build documentation in the docs/ directory with Sphinx
sphinx:
configuration: doc/source/conf.py
fail_on_warning: true
# We recommend specifying your dependencies to enable reproducible builds:
# https://docs.readthedocs.io/en/stable/guides/reproducible-builds.html
python:
install:
- requirements: doc/requirements-doc.lock.txt