Skip to content

Commit 15ecdcf

Browse files
dstrodtmanclaude
authored andcommitted
[doc][ci] Skip RTD builds for PRs that don't touch doc sources (ray-project#63431)
## Description Adds a `build.jobs.post_checkout` block to `.readthedocs.yaml` that exits with code 183 on PR ("external") builds when the diff doesn't touch any files that affect documentation output. Tag and branch builds (master, stable, etc.) always run. ## Why Today, every PR to `ray-project/ray` triggers a full Sphinx build on Read the Docs, regardless of what the PR touches. A PR that only changes C++, Java, Bazel, release tooling, or CI config produces the same docs build as a PR that rewrites `doc/`. When several PRs land in quick succession, this overflows the project's concurrent build slots on RTD. RTD's `finish_inactive_builds` periodic task then marks the older queued builds as `FAILED` with the message *"This build was terminated due to inactivity"* (see [readthedocs.org#4386](readthedocs/readthedocs.org#4386) — the name is misleading; the build isn't inactive, it just couldn't get a worker within ~1080 seconds). Contributors then see red checks on their PRs that have nothing to do with their changes. [Auto-cancellation of older builds for the same PR](https://blog.readthedocs.com/cancel-old-builds/) has been on by default in RTD since October 2022, but that only helps when you push twice to one PR — not across multiple open PRs. This change complements that by reducing the load from cross-PR concurrency. ## What the filter does On every PR build, it computes the diff against `origin/master` and exits 183 — RTD's [skip-build sentinel](https://docs.readthedocs.com/platform/stable/guides/build/skip-build.html) — only when **none** of the changed files match: - `doc/` — Sphinx sources, BUILD files, doc-only requirements. - `python/ray/` — anything `autodoc` could pull (kept intentionally broad). - `rllib/` — same. - `.readthedocs.yaml` — this config itself, so changes to it always test. If even one file falls in the allow-list, the build runs as before. If the diff can't be computed (shallow clone, fetch failure), the build runs. ## What this skips in practice PRs that don't touch any of the four paths above. Concrete examples: - C++ / Cython changes under `src/`, `cpp/`. - Java changes under `java/`. - Bazel changes under `bazel/`, top-level `BUILD.bazel`, `WORKSPACE`. - CI changes under `ci/`, `.buildkite/` (except `.buildkite/doc.rayci.yml` which isn't read by Sphinx but is excluded from the allow-list since it doesn't change RTD output). - Release tooling under `release/`. - Docker changes under `docker/`. - Top-level scripts and configs. ## What still triggers a build - All content under `doc/`. - Any `python/ray/**` change, because `autodoc` could pick it up. - Any `rllib/**` change, same reason. - The RTD config itself. The filter is deliberately conservative — broad inclusion, narrow exclusion. Better to do an unnecessary build than to miss a doc change. ## Test plan - Manual trace of the bash logic against representative paths: ✅ passes (Ray serve, RLlib, doc content, `.readthedocs.yaml`, mixed PRs all trigger BUILD; Java+C++, Docker, release, `python/setup.py`, empty diff all SKIP). - YAML syntax validated locally with `yaml.safe_load`. - This PR itself touches `.readthedocs.yaml`, so it will exercise the BUILD path on the RTD preview. ## Future work If queue pressure persists after this lands, two further levers: 1. Narrow the `python/ray/**` allow-list to exclude paths that don't appear in any `autodoc` directive (`python/ray/tests/`, `python/ray/_private/` candidates). Higher maintenance cost. 2. File an RTD support request to ask about the project's concurrent-build limit on the current plan. ## Related issues None linked. --------- Signed-off-by: Douglas Strodtman <douglas@anyscale.com> Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
1 parent 992281e commit 15ecdcf

1 file changed

Lines changed: 31 additions & 0 deletions

File tree

.readthedocs.yaml

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,37 @@ build:
1010
os: ubuntu-24.04
1111
tools:
1212
python: "3.10"
13+
jobs:
14+
# On PR builds, skip the Sphinx build when the PR doesn't touch any
15+
# files that affect documentation output. Reduces queue pressure on
16+
# the shared RTD build slots when several PRs are open at once.
17+
# Tag/branch builds (master, stable, etc.) always run.
18+
# See https://docs.readthedocs.com/platform/stable/guides/build/skip-build.html
19+
#
20+
# Some constructs are avoided deliberately because RTD's job runner
21+
# silently drops scripts that contain them: use echo (not printf
22+
# with a backslash-escape format string), avoid backslash escapes
23+
# in general, and keep shell comments out of this block so that
24+
# backticks/$() inside comments don't confuse the preprocessor.
25+
post_checkout:
26+
- |
27+
if [ "${READTHEDOCS_VERSION_TYPE:-}" != "external" ]; then
28+
echo "Not a PR build (version type: '${READTHEDOCS_VERSION_TYPE:-unset}'); building docs."
29+
exit 0
30+
fi
31+
git fetch --depth=500 origin master 2>/dev/null || true
32+
if ! git merge-base origin/master HEAD >/dev/null 2>&1; then
33+
echo "Could not determine merge-base with origin/master; building docs to be safe."
34+
exit 0
35+
fi
36+
if git diff --quiet origin/master...HEAD -- doc/ python/ray/ rllib/ .readthedocs.yaml; then
37+
echo "No doc-affecting files changed in this PR; skipping Sphinx build."
38+
echo "Files changed in PR:"
39+
git diff --name-only origin/master...HEAD
40+
exit 183
41+
fi
42+
echo "Doc-affecting files changed; building docs. Changed doc-relevant paths:"
43+
git diff --name-only origin/master...HEAD -- doc/ python/ray/ rllib/ .readthedocs.yaml
1344
1445
# Build documentation in the docs/ directory with Sphinx
1546
sphinx:

0 commit comments

Comments
 (0)