Repository: pytest-dev/pytest-asyncio (language: python)

Issue:
Unify documentation build process for local and CI environment
Currently, the documentation can be built locally using `tox run -e docs` or as part of the CI via readthedocs. However, the build processes are different. This makes it hard to reproduce readthedocs builds locally.

The goal of this issue is to have the same build process for docs, both locally and in the CI.

see https://github.com/pytest-dev/pytest-asyncio/pull/912


Discussion / hints:
Hello @seifertm ,
I'm the author of #912, can I take this up?
Would be a good introduction to using ReadTheDocs and CI pipelines.

Fix patch:
diff --git a/.readthedocs.yaml b/.readthedocs.yaml
index efff237b..8ffb4b25 100644
--- a/.readthedocs.yaml
+++ b/.readthedocs.yaml
@@ -1,19 +1,29 @@
 ---
-# Read the Docs configuration file for Sphinx projects
-# See https://docs.readthedocs.io/en/stable/config-file/v2.html for details
 
 version: 2
+
 build:
-  os: ubuntu-22.04
+  os: ubuntu-24.04
   tools:
-    python: '3.12'
-
-sphinx:
-  configuration: docs/source/conf.py
-  fail_on_warning: true
-
-python:
-  install:
-  - requirements: dependencies/default/constraints.txt
-  - requirements: dependencies/docs/constraints.txt
-  - path: .
+    python: >-
+      3.12
+  commands:
+  - >-
+    PYTHONWARNINGS=error
+    python3 -Im venv "${READTHEDOCS_VIRTUALENV_PATH}"
+  - >-
+    PYTHONWARNINGS=error
+    "${READTHEDOCS_VIRTUALENV_PATH}"/bin/python -Im
+    pip install tox
+  - >-
+    PYTHONWARNINGS=error
+    "${READTHEDOCS_VIRTUALENV_PATH}"/bin/python -Im
+    tox -e docs --notest -vvvvv
+  - >-
+    PYTHONWARNINGS=error
+    "${READTHEDOCS_VIRTUALENV_PATH}"/bin/python -Im
+    tox -e docs --skip-pkg-install -q
+    --
+    "${READTHEDOCS_OUTPUT}"/html
+    -b html
+    -D language=en
diff --git a/docs/Makefile b/docs/Makefile
deleted file mode 100644
index d0c3cbf1..00000000
--- a/docs/Makefile
+++ /dev/null
@@ -1,20 +0,0 @@
-# Minimal makefile for Sphinx documentation
-#
-
-# You can set these variables from the command line, and also
-# from the environment for the first two.
-SPHINXOPTS    ?=
-SPHINXBUILD   ?= sphinx-build
-SOURCEDIR     = source
-BUILDDIR      = build
-
-# Put it first so that "make" without argument is like "make help".
-help:
-	@$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
-
-.PHONY: help Makefile
-
-# Catch-all target: route all unknown targets to Sphinx using the new
-# "make mode" option.  $(O) is meant as a shortcut for $(SPHINXOPTS).
-%: Makefile
-	@$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
diff --git a/docs/source/concepts.rst b/docs/concepts.rst
similarity index 100%
rename from docs/source/concepts.rst
rename to docs/concepts.rst
diff --git a/docs/source/concepts_function_scope_example.py b/docs/concepts_function_scope_example.py
similarity index 100%
rename from docs/source/concepts_function_scope_example.py
rename to docs/concepts_function_scope_example.py
diff --git a/docs/source/concepts_module_scope_example.py b/docs/concepts_module_scope_example.py
similarity index 100%
rename from docs/source/concepts_module_scope_example.py
rename to docs/concepts_module_scope_example.py
diff --git a/docs/source/conf.py b/docs/conf.py
similarity index 100%
rename from docs/source/conf.py
rename to docs/conf.py
diff --git a/docs/source/how-to-guides/change_default_fixture_loop.rst b/docs/how-to-guides/change_default_fixture_loop.rst
similarity index 100%
rename from docs/source/how-to-guides/change_default_fixture_loop.rst
rename to docs/how-to-guides/change_default_fixture_loop.rst
diff --git a/docs/source/how-to-guides/change_fixture_loop.rst b/docs/how-to-guides/change_fixture_loop.rst
similarity index 100%
rename from docs/source/how-to-guides/change_fixture_loop.rst
rename to docs/how-to-guides/change_fixture_loop.rst
diff --git a/docs/source/how-to-guides/change_fixture_loop_example.py b/docs/how-to-guides/change_fixture_loop_example.py
similarity index 100%
rename from docs/source/how-to-guides/change_fixture_loop_example.py
rename to docs/how-to-guides/change_fixture_loop_example.py
diff --git a/docs/source/how-to-guides/class_scoped_loop_example.py b/docs/how-to-guides/class_scoped_loop_example.py
similarity index 100%
rename from docs/source/how-to-guides/class_scoped_loop_example.py
rename to docs/how-to-guides/class_scoped_loop_example.py
diff --git a/docs/source/how-to-guides/index.rst b/docs/how-to-guides/index.rst
similarity index 100%
rename from docs/source/how-to-guides/index.rst
rename to docs/how-to-guides/index.rst
diff --git a/docs/source/how-to-guides/module_scoped_loop_example.py b/docs/how-to-guides/module_scoped_loop_example.py
similarity index 100%
rename from docs/source/how-to-guides/module_scoped_loop_example.py
rename to docs/how-to-guides/module_scoped_loop_example.py
diff --git a/docs/source/how-to-guides/multiple_loops.rst b/docs/how-to-guides/multiple_loops.rst
similarity index 100%
rename from docs/source/how-to-guides/multiple_loops.rst
rename to docs/how-to-guides/multiple_loops.rst
diff --git a/docs/source/how-to-guides/multiple_loops_example.py b/docs/how-to-guides/multiple_loops_example.py
similarity index 100%
rename from docs/source/how-to-guides/multiple_loops_example.py
rename to docs/how-to-guides/multiple_loops_example.py
diff --git a/docs/source/how-to-guides/package_scoped_loop_example.py b/docs/how-to-guides/package_scoped_loop_example.py
similarity index 100%
rename from docs/source/how-to-guides/package_scoped_loop_example.py
rename to docs/how-to-guides/package_scoped_loop_example.py
diff --git a/docs/source/how-to-guides/session_scoped_loop_example.py b/docs/how-to-guides/session_scoped_loop_example.py
similarity index 100%
rename from docs/source/how-to-guides/session_scoped_loop_example.py
rename to docs/how-to-guides/session_scoped_loop_example.py
diff --git a/docs/source/how-to-guides/uvloop.rst b/docs/how-to-guides/uvloop.rst
similarity index 100%
rename from docs/source/how-to-guides/uvloop.rst
rename to docs/how-to-guides/uvloop.rst
diff --git a/docs/source/index.rst b/docs/index.rst
similarity index 100%
rename from docs/source/index.rst
rename to docs/index.rst
diff --git a/docs/make.bat b/docs/make.bat
deleted file mode 100644
index dc1312ab..00000000
--- a/docs/make.bat
+++ /dev/null
@@ -1,35 +0,0 @@
-@ECHO OFF
-
-pushd %~dp0
-
-REM Command file for Sphinx documentation
-
-if "%SPHINXBUILD%" == "" (
-	set SPHINXBUILD=sphinx-build
-)
-set SOURCEDIR=source
-set BUILDDIR=build
-
-%SPHINXBUILD% >NUL 2>NUL
-if errorlevel 9009 (
-	echo.
-	echo.The 'sphinx-build' command was not found. Make sure you have Sphinx
-	echo.installed, then set the SPHINXBUILD environment variable to point
-	echo.to the full path of the 'sphinx-build' executable. Alternatively you
-	echo.may add the Sphinx directory to PATH.
-	echo.
-	echo.If you don't have Sphinx installed, grab it from
-	echo.https://www.sphinx-doc.org/
-	exit /b 1
-)
-
-if "%1" == "" goto help
-
-%SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O%
-goto end
-
-:help
-%SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O%
-
-:end
-popd
diff --git a/docs/source/reference/changelog.rst b/docs/reference/changelog.rst
similarity index 100%
rename from docs/source/reference/changelog.rst
rename to docs/reference/changelog.rst
diff --git a/docs/source/reference/configuration.rst b/docs/reference/configuration.rst
similarity index 100%
rename from docs/source/reference/configuration.rst
rename to docs/reference/configuration.rst
diff --git a/docs/source/reference/decorators/index.rst b/docs/reference/decorators/index.rst
similarity index 100%
rename from docs/source/reference/decorators/index.rst
rename to docs/reference/decorators/index.rst
diff --git a/docs/source/reference/fixtures/event_loop_example.py b/docs/reference/fixtures/event_loop_example.py
similarity index 100%
rename from docs/source/reference/fixtures/event_loop_example.py
rename to docs/reference/fixtures/event_loop_example.py
diff --git a/docs/source/reference/fixtures/event_loop_policy_example.py b/docs/reference/fixtures/event_loop_policy_example.py
similarity index 100%
rename from docs/source/reference/fixtures/event_loop_policy_example.py
rename to docs/reference/fixtures/event_loop_policy_example.py
diff --git a/docs/source/reference/fixtures/event_loop_policy_parametrized_example.py b/docs/reference/fixtures/event_loop_policy_parametrized_example.py
similarity index 100%
rename from docs/source/reference/fixtures/event_loop_policy_parametrized_example.py
rename to docs/reference/fixtures/event_loop_policy_parametrized_example.py
diff --git a/docs/source/reference/fixtures/index.rst b/docs/reference/fixtures/index.rst
similarity index 100%
rename from docs/source/reference/fixtures/index.rst
rename to docs/reference/fixtures/index.rst
diff --git a/docs/source/reference/functions.rst b/docs/reference/functions.rst
similarity index 100%
rename from docs/source/reference/functions.rst
rename to docs/reference/functions.rst
diff --git a/docs/source/reference/index.rst b/docs/reference/index.rst
similarity index 100%
rename from docs/source/reference/index.rst
rename to docs/reference/index.rst
diff --git a/docs/source/reference/markers/class_scoped_loop_custom_policies_strict_mode_example.py b/docs/reference/markers/class_scoped_loop_custom_policies_strict_mode_example.py
similarity index 100%
rename from docs/source/reference/markers/class_scoped_loop_custom_policies_strict_mode_example.py
rename to docs/reference/markers/class_scoped_loop_custom_policies_strict_mode_example.py
diff --git a/docs/source/reference/markers/class_scoped_loop_strict_mode_example.py b/docs/reference/markers/class_scoped_loop_strict_mode_example.py
similarity index 100%
rename from docs/source/reference/markers/class_scoped_loop_strict_mode_example.py
rename to docs/reference/markers/class_scoped_loop_strict_mode_example.py
diff --git a/docs/source/reference/markers/class_scoped_loop_with_fixture_strict_mode_example.py b/docs/reference/markers/class_scoped_loop_with_fixture_strict_mode_example.py
similarity index 100%
rename from docs/source/reference/markers/class_scoped_loop_with_fixture_strict_mode_example.py
rename to docs/reference/markers/class_scoped_loop_with_fixture_strict_mode_example.py
diff --git a/docs/source/reference/markers/function_scoped_loop_strict_mode_example.py b/docs/reference/markers/function_scoped_loop_strict_mode_example.py
similarity index 100%
rename from docs/source/reference/markers/function_scoped_loop_strict_mode_example.py
rename to docs/reference/markers/function_scoped_loop_strict_mode_example.py
diff --git a/docs/source/reference/markers/index.rst b/docs/reference/markers/index.rst
similarity index 100%
rename from docs/source/reference/markers/index.rst
rename to docs/reference/markers/index.rst
diff --git a/docs/source/reference/markers/module_scoped_loop_strict_mode_example.py b/docs/reference/markers/module_scoped_loop_strict_mode_example.py
similarity index 100%
rename from docs/source/reference/markers/module_scoped_loop_strict_mode_example.py
rename to docs/reference/markers/module_scoped_loop_strict_mode_example.py
diff --git a/docs/source/support.rst b/docs/support.rst
similarity index 100%
rename from docs/source/support.rst
rename to docs/support.rst
diff --git a/setup.cfg b/setup.cfg
index c04d3884..ac2f2adc 100644
--- a/setup.cfg
+++ b/setup.cfg
@@ -65,7 +65,7 @@ show_missing = true
 [tool:pytest]
 python_files = test_*.py *_example.py
 addopts = -rsx --tb=short
-testpaths = docs/source tests
+testpaths = docs tests
 asyncio_mode = auto
 junit_family=xunit2
 filterwarnings =
diff --git a/tox.ini b/tox.ini
index 665c2fff..79e96fa6 100644
--- a/tox.ini
+++ b/tox.ini
@@ -26,14 +26,48 @@ allowlist_externals =
     make
 
 [testenv:docs]
+allowlist_externals =
+    git
 extras = docs
 deps =
      --requirement dependencies/docs/requirements.txt
      --constraint dependencies/docs/constraints.txt
 change_dir = docs
-commands = make html
-allowlist_externals =
-    make
+description = Build The Docs with {basepython}
+commands =
+    # Retrieve possibly missing commits:
+    -git fetch --unshallow
+    -git fetch --tags
+
+    # Build the html docs with Sphinx:
+    {envpython} -Im sphinx \
+      -j auto \
+      {tty:--color} \
+      -a \
+      -T \
+      -n \
+      -W --keep-going \
+      -d "{temp_dir}{/}.doctrees" \
+      . \
+      {posargs:"{envdir}{/}docs_out" -b html}
+
+    # Print out the output docs dir and a way to serve html:
+    -{envpython} -c\
+    'import pathlib;\
+    docs_dir = pathlib.Path(r"{envdir}") / "docs_out";\
+    index_file = docs_dir / "index.html";\
+    print("\n" + "=" * 120 +\
+    f"\n\nOpen the documentation with:\n\n\
+    \t$ python3 -Im webbrowser \N\{QUOTATION MARK\}file://\{index_file\}\N\{QUOTATION MARK\}\n\n\
+    To serve docs, use\n\n\
+    \t$ python3 -Im http.server --directory \
+    \N\{QUOTATION MARK\}\{docs_dir\}\N\{QUOTATION MARK\} 0\n\n" +\
+    "=" * 120)'
+changedir = {toxinidir}{/}docs
+isolated_build = true
+passenv =
+    SSH_AUTH_SOCK
+skip_install = false
 
 [gh-actions]
 python =


Test patch:
diff --git a/docs/source/how-to-guides/run_class_tests_in_same_loop.rst b/docs/how-to-guides/run_class_tests_in_same_loop.rst
similarity index 100%
rename from docs/source/how-to-guides/run_class_tests_in_same_loop.rst
rename to docs/how-to-guides/run_class_tests_in_same_loop.rst
diff --git a/docs/source/how-to-guides/run_module_tests_in_same_loop.rst b/docs/how-to-guides/run_module_tests_in_same_loop.rst
similarity index 100%
rename from docs/source/how-to-guides/run_module_tests_in_same_loop.rst
rename to docs/how-to-guides/run_module_tests_in_same_loop.rst
diff --git a/docs/source/how-to-guides/run_package_tests_in_same_loop.rst b/docs/how-to-guides/run_package_tests_in_same_loop.rst
similarity index 100%
rename from docs/source/how-to-guides/run_package_tests_in_same_loop.rst
rename to docs/how-to-guides/run_package_tests_in_same_loop.rst
diff --git a/docs/source/how-to-guides/run_session_tests_in_same_loop.rst b/docs/how-to-guides/run_session_tests_in_same_loop.rst
similarity index 100%
rename from docs/source/how-to-guides/run_session_tests_in_same_loop.rst
rename to docs/how-to-guides/run_session_tests_in_same_loop.rst
diff --git a/docs/source/how-to-guides/test_item_is_async.rst b/docs/how-to-guides/test_item_is_async.rst
similarity index 100%
rename from docs/source/how-to-guides/test_item_is_async.rst
rename to docs/how-to-guides/test_item_is_async.rst
diff --git a/docs/source/how-to-guides/test_item_is_async_example.py b/docs/how-to-guides/test_item_is_async_example.py
similarity index 100%
rename from docs/source/how-to-guides/test_item_is_async_example.py
rename to docs/how-to-guides/test_item_is_async_example.py
diff --git a/docs/source/how-to-guides/test_session_scoped_loop_example.py b/docs/how-to-guides/test_session_scoped_loop_example.py
similarity index 100%
rename from docs/source/how-to-guides/test_session_scoped_loop_example.py
rename to docs/how-to-guides/test_session_scoped_loop_example.py
diff --git a/docs/source/reference/decorators/pytest_asyncio_fixture_example.py b/docs/reference/decorators/pytest_asyncio_fixture_example.py
similarity index 100%
rename from docs/source/reference/decorators/pytest_asyncio_fixture_example.py
rename to docs/reference/decorators/pytest_asyncio_fixture_example.py
diff --git a/docs/source/reference/markers/function_scoped_loop_pytestmark_strict_mode_example.py b/docs/reference/markers/function_scoped_loop_pytestmark_strict_mode_example.py
similarity index 100%
rename from docs/source/reference/markers/function_scoped_loop_pytestmark_strict_mode_example.py
rename to docs/reference/markers/function_scoped_loop_pytestmark_strict_mode_example.py