Pin Read the Docs builds and versions to stop docs drift
Pin the build environment in readthedocs.yml and map repository tags to Read the Docs versions to keep documentation reproducible and aligned with releases.
15 Sept 2026, 16:55 UTC

Docs that build locally but break on Read the Docs, or a release page that still shows the previous API, is a reproducibility problem. The fix is to treat the documentation build as a versioned artifact: pin the build environment in readthedocs.yml and map repository tags to Read the Docs versions.
The drift problem
Read the Docs builds in isolated containers. Without an explicit declaration, the build image, default Python version and system packages can change over time. That means a Sphinx build that works on a developer laptop can fail on the platform after an image update, and readers can land on a default version that does not match the library they installed.
Versioning is first-class in Read the Docs. The project can serve multiple versions from branches and tags with a version selector in the UI and a configurable default version. If the mapping between code releases and documentation versions is implicit, older releases disappear or the selector shows the wrong default.
Make builds reproducible with readthedocs.yml
readthedocs.yml at the repository root declares the build environment, dependency installation and build command. Declaring these explicitly moves the build from implicit to repeatable across contributors and over time.
Pin image, Python and install steps
Place readthedocs.yml in the repository root. Repository write access is required to commit the file, and project admin access on Read the Docs is required to see the build configuration in the admin UI.
version: 2
build:
os: ubuntu-22.04
tools:
python: "3.11"
python:
install:
- requirements: requirements-docs.txt
sphinx:
configuration: docs/conf.py
builder: html
This declares an operating system image, a specific Python version and an explicit requirements file. The build runs in an isolated container using those declarations. If the platform updates its default images, the pinned values keep the build stable until you choose to move.
Risks to note: pinning is version-sensitive. Images and toolchains are updated by Read the Docs over time, so a very old pin can eventually become unsupported. Changing readthedocs.yml does not apply instantly; a new commit or a manual build trigger is needed for the change to be used.
Mirror releases to versions, not branches
For libraries with tagged releases, map tags to documentation versions. In the Read the Docs web UI, project admin settings expose active versions, default version and repository integration. Enable versions from tags and set a stable default, for example the latest release tag, rather than main.
A practical engineering decision is to keep the docs source in the same repository as the code and tag the docs with the release tag. That way the documentation built for v1.2.3 comes from the commit tagged v1.2.3.
Check the result by opening the published docs and verifying the version selector lists the expected tags or branches and that the default version matches the intended stable release. In the project builds page, compare the declared python version and install steps in readthedocs.yml with the build log summary to confirm the declared environment was used.
Trade-off: reproducibility vs maintenance
Explicit pins improve reproducibility but add maintenance. Each dependency upgrade requires a change to readthedocs.yml and a new build. Version dropdown visibility also depends on project settings and repository integration; misconfiguration can hide older versions from readers even if builds succeed.
Do not assume the build will stay green forever. Review the build log after platform announcements about image deprecations, and keep the requirements-docs.txt minimal and reproducible.
Actionable next steps: commit a readthedocs.yml with pinned os, python and install steps; configure versions to build from tags and set a sensible default; verify the version selector on the live docs and the build log in the project admin UI. Revisit pins on a regular cadence rather than after a breakage.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.