Skip to content

Docs: Refactor Reproducible Builds page (Diátaxis) #10030

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

Merged
merged 3 commits into from
Feb 17, 2023
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
2 changes: 1 addition & 1 deletion docs/user/config-file/v2.rst
Original file line number Diff line number Diff line change
Expand Up @@ -294,7 +294,7 @@ Configuration for Conda support.
conda.environment
`````````````````

The path to the Conda environment file, relative to the root of the project.
The path to the Conda `environment file <https://conda.io/projects/conda/en/latest/user-guide/tasks/manage-environments.html>`_, relative to the root of the project.

:Type: ``path``
:Required: ``true``
Expand Down
172 changes: 41 additions & 131 deletions docs/user/guides/reproducible-builds.rst
Original file line number Diff line number Diff line change
@@ -1,43 +1,33 @@
Reproducible Builds
===================

Your docs depend on tools and other dependencies to be built.
Your documentation depends on a number of dependencies to be built.
If your docs don't have reproducible builds,
an update in a dependency can break your builds when least expected,
or make your docs look different from your local version.
This guide will help you to keep your builds working over time, and in a reproducible way.
This guide will help you to keep your builds working over time,
so that you can focus on content.

.. contents:: Contents
:local:
:depth: 3

Building your docs
------------------
Use a ``.readthedocs.yaml`` configuration file
----------------------------------------------

To test your build process, you can build them locally in a clean environment
(this is without any dependencies installed).
Then you should make sure you are running those same steps on Read the Docs.

You can configure how your project is built from the web interface (:guilabel:`Admin` tab),
or by :ref:`using a configuration file <guides/reproducible-builds:using a configuration file>` (recommended).
If you aren't familiar with these tools, check our docs:
We recommend using a :doc:`configuration file </config-file/v2>` to manage your documentation.
Our config file *provides you per version settings*,
and *those settings live in your Git repository*.

- :doc:`/intro/getting-started-with-sphinx`
- :doc:`/intro/getting-started-with-mkdocs`
- :doc:`/config-file/v2`
This allows you to validate changes using :doc:`pull requests </pull-requests>`,
and ensures versions build the same over time.

.. note::
Use a requirements file for Python dependencies
-----------------------------------------------

You can see the exact commands that are run on Read the Docs by going to the :guilabel:`Builds` tab of your project.

Using a configuration file
--------------------------

If you use the web interface to configure your project,
the options are applied to *all* versions and builds of your docs,
and can be lost after changing them over time.
Using a :doc:`configuration file </config-file/v2>` **provides you per version settings**,
and **those settings live in your repository**.
We recommend using a Pip :ref:`pip:requirements-file-format` or Conda :ref:`Environment file <config-file/v2:conda.environment>` to pin Python dependencies.
This allows you to ensure that top-level dependencies and extensions don't change.

A configuration file with explicit dependencies looks like this:

Expand Down Expand Up @@ -68,130 +58,27 @@ A configuration file with explicit dependencies looks like this:
sphinx_rtd_theme==1.1.1
readthedocs-sphinx-search==0.1.1

Don't rely on implicit dependencies
-----------------------------------

By default Read the Docs will install the tool you chose to build your docs,
and other dependencies, this is done so new users can build their docs without much configuration.

We highly recommend not to assume these dependencies will always be present or that their versions won't change.
Always declare your dependencies explicitly using a :ref:`configuration file <guides/reproducible-builds:using a configuration file>`,
for example:

✅ Good:
Your project is declaring the Python version explicitly,
and its dependencies using a requirements file.

.. code-block:: yaml
:caption: .readthedocs.yaml

version: 2

build:
os: "ubuntu-22.04"
tools:
python: "3.11"

sphinx:
configuration: docs/conf.py

python:
install:
- requirements: docs/requirements.txt

❌ Bad:
Your project is relying on the default Python version and default installed dependencies.

.. code-block:: yaml
:caption: .readthedocs.yaml

version: 2

sphinx:
configuration: docs/conf.py

Pinning dependencies
--------------------

As you shouldn't rely on implicit dependencies,
you shouldn't rely on undefined versions of your dependencies.
Some examples:

✅ Good:
The specified versions will be used for all your builds,
in all platforms, and won't be updated unexpectedly.

.. code-block::
:caption: docs/requirements.txt

sphinx==5.3.0
sphinx_rtd_theme==1.1.1
readthedocs-sphinx-search==0.1.2

.. code-block:: yaml
:caption: docs/environment.yaml

name: docs
channels:
- conda-forge
- defaults
dependencies:
- sphinx==5.3.0
- nbsphinx==0.8.10
- pip:
- sphinx_rtd_theme==1.1.1

❌ Bad:
The latest or any other already installed version will be used,
and your builds can fail or change unexpectedly any time.

.. code-block::
:caption: docs/requirements.txt

sphinx
sphinx_rtd_theme
readthedocs-sphinx-search

.. code-block:: yaml
:caption: docs/environment.yaml

name: docs
channels:
- conda-forge
- defaults
dependencies:
- sphinx
- nbsphinx
- pip:
- sphinx_rtd_theme

Check the `pip user guide`_ for more information about requirements files,
or our Conda docs about :ref:`environment files <guides/conda:creating the \`\`environment.yml\`\`>`.

.. _`pip user guide`: https://pip.pypa.io/en/stable/user_guide/#requirements-files

.. tip::

Remember to update your docs' dependencies from time to time to get new improvements and fixes.
It also makes it easy to manage in case a version reaches its end of support date.


Pinning transitive dependencies
-------------------------------
Pin your transitive dependencies
--------------------------------

Once you have pinned your own dependencies,
the next things to worry about are the dependencies of your dependencies.
These are called *transitive dependencies*,
and they can upgrade without warning if you do not pin these packages as well.

We recommend `pip-tools`_ to help address this problem.
It allows you to specify a ``requirements.in`` file with your first-level dependencies,
It allows you to specify a ``requirements.in`` file with your top-level dependencies,
and it generates a ``requirements.txt`` file with the full set of transitive dependencies.

.. _pip-tools: https://pip-tools.readthedocs.io/en/latest/

✅ Good:
All your transitive dependencies will stay defined,
All your transitive dependencies are defined,
which ensures new package releases will not break your docs.

.. code-block::
Expand Down Expand Up @@ -252,3 +139,26 @@ and it generates a ``requirements.txt`` file with the full set of transitive dep
# via sphinx
urllib3==1.26.13
# via requests

Conclusion
-----------

If you followed this guide,
you have pinned:

* tool versions (Python, Node)
* top-level dependencies (Sphinx, Sphinx extensions)
* transitive dependencies (Pytz, Jinja2)

This will ensure your builds don't fail because of a random tool or dependency update.
You do still need to ensure you're upgrading your dependencies from time to time,
but you can do it on your own schedule.

.. seealso::

:doc:`/config-file/v2`
Configuration File Reference
:doc:`/builds`
Build process information
:doc:`/build-customization`
Customizing builds to do more