Skip to content

Commit 844d148

Browse files
Sphinx Versioning (#61)
* Sphinx Versioning * Linking latest dir rather than copying * Function signaturevariable name fixed * source validaton for latest * Try catch for git tags absence Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * Lint and format issue solve * lint fix * Indentation fix Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * Updating publish workflow (#59) * Introduce Sphinx Versioning (#57) * Sphinx Versioning * Linking latest dir rather than copying * Function signaturevariable name fixed * source validaton for latest * Try catch for git tags absence Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * Lint and format issue solve * lint fix * Indentation fix Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --------- Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * Lint fix * fetch tags in ci * Readme fix * Remove force --------- Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * Support local builds for a single version and redirect root to latest (#60) * Introduce Sphinx Versioning (#57) * Sphinx Versioning * Linking latest dir rather than copying * Function signaturevariable name fixed * source validaton for latest * Try catch for git tags absence Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * Lint and format issue solve * lint fix * Indentation fix Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --------- Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * Lint fix * fetch tags in ci * Readme fix * Remove force * Local build single version * Redirect the root to latest * Documentation update * Apply suggestions from code review Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --------- Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --------- Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
1 parent 3a50df9 commit 844d148

File tree

4 files changed

+73
-7
lines changed

4 files changed

+73
-7
lines changed

.github/workflows/publish.yml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,8 @@ jobs:
7676
steps:
7777
- name: Checkout
7878
uses: actions/checkout@v5
79+
with:
80+
fetch-depth: 0 # Fetch all history for sphinx-multiversion
7981

8082
- name: Set up Python
8183
uses: actions/setup-python@v5
@@ -143,6 +145,9 @@ jobs:
143145
- name: Configure Pages
144146
uses: actions/configure-pages@v5
145147

148+
- name: Fetch Git tags
149+
run: git fetch --tags
150+
146151
- name: Build documentation
147152
run: python run.py build-docs
148153

README.md

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -68,13 +68,25 @@ python run.py build
6868
python run.py build-docs
6969
```
7070

71-
> ***Note: When releasing a new version, update ``switcher.json`` in ``docs/source/_static/``
72-
to include the new tag in the version dropdown for documentation.***
71+
> ***Note: When releasing a new version, update ``switcher.json`` in ``docs/source/_static/`` to include the new tag in the version dropdown for documentation.***
7372
7473
Options:
7574
- `--skip-build` (`-s`): Skip building before generating docs
75+
- `--local` (`-l`): Build documentation locally for a single version (skips multi-version build)
7676

77-
The documentation can be accessed locally by opening the index.html in the docs/build/html/ folder.
77+
The documentation can be accessed locally by serving the docs/build/html/ folder:
78+
```sh
79+
cd docs/build/html
80+
python -m http.server 8000
81+
```
82+
83+
Then open http://localhost:8000 in your browser. The root automatically redirects to the latest version documentation.
84+
85+
**Versioned Documentation:**
86+
- Each git tag creates a separate documentation version (e.g., `/v26.0.5/`)
87+
- A `/latest/` directory points to the newest version
88+
- Root (`/`) automatically redirects to `/latest/`
89+
- Run `git fetch --tags` before building to ensure all version tags are available
7890

7991
### Running the Formatter
8092

docs/source/readme.rst

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1258,10 +1258,31 @@ The project includes a ``run.py`` script with several useful commands:
12581258
- ``python run.py build-docs`` - Build versioned documentation (HTML uses git tags for the
12591259
navigation dropdown; run ``git fetch --tags`` locally before building)
12601260

1261+
- ``--skip-build`` (``-s``): Skip building the package before generating docs
1262+
- ``--local`` (``-l``): Build documentation locally for a single version (skips multi-version build)
1263+
12611264
.. note::
12621265
When releasing a new version, update ``switcher.json`` in ``docs/source/_static/``
12631266
to include the new tag in the version dropdown.
12641267

1268+
**Viewing Documentation Locally**
1269+
1270+
After building, serve the documentation using Python's built-in HTTP server:
1271+
1272+
.. code-block:: bash
1273+
1274+
cd docs/build/html
1275+
python -m http.server 8000
1276+
1277+
Then open http://localhost:8000 in your browser.
1278+
1279+
**Versioned Documentation Features:**
1280+
1281+
- Each git tag creates a separate documentation version (e.g., ``/v26.0.5/``)
1282+
- A ``/latest/`` directory points to the newest version (symlink on Unix, copy on Windows)
1283+
- Root (``/``) automatically redirects to ``/latest/`` for convenience
1284+
- Version switcher dropdown in the navigation bar allows switching between versions
1285+
12651286
Contributing
12661287
============
12671288

run.py

Lines changed: 32 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
Usage:
88
run.py clean-up
99
run.py build [-P | --publish] [-i | --install]
10-
run.py build-docs [-t <target> | --target=<target>] [-s | --skip-build]
10+
run.py build-docs [-t <target> | --target=<target>] [-s | --skip-build] [-l | --local]
1111
run.py format [--check]
1212
run.py install [-s | --skip-build]
1313
run.py install-package-requirements
@@ -51,6 +51,7 @@
5151
--all Run all tests.
5252
--repo-url=<url> Custom PyPI repository URL.
5353
--github-api-url=<url> Custom GitHub API URL.
54+
-l, --local Build documentation locally (single version).
5455
"""
5556

5657
import os
@@ -328,6 +329,31 @@ def build_mo():
328329
)
329330

330331

332+
def create_root_redirect(build_output: str) -> None:
333+
"""Create an index.html in the versioned HTML build output root that redirects to /latest/."""
334+
index_path = os.path.join(build_output, 'index.html')
335+
redirect_html = """<!DOCTYPE html>
336+
<html>
337+
<head>
338+
<meta charset="utf-8">
339+
<title>Redirecting to latest documentation...</title>
340+
<meta http-equiv="refresh" content="0; url=./latest/">
341+
<link rel="canonical" href="./latest/">
342+
<script>window.location.replace("./latest/");</script>
343+
</head>
344+
<body>
345+
<p>Redirecting to <a href="./latest/">latest documentation</a>...</p>
346+
</body>
347+
</html>
348+
"""
349+
try:
350+
with open(index_path, 'w', encoding='utf-8') as f:
351+
f.write(redirect_html)
352+
logging.info("Created root redirect: index.html -> latest/")
353+
except Exception as err:
354+
logging.warning("Could not create root redirect index.html: %s", err)
355+
356+
331357
def create_latest_alias(build_output: str) -> None:
332358
"""Create a 'latest' alias pointing to the newest version using symlinks when possible."""
333359
version_dirs = [d for d in os.listdir(build_output) if d.startswith('v')]
@@ -373,7 +399,7 @@ def version_key(v):
373399
shutil.copytree(latest_src, latest_dest)
374400

375401

376-
def build_docs(target, skip_build):
402+
def build_docs(target, skip_build, local=False):
377403
"""Build Documentation"""
378404

379405
if not skip_build:
@@ -386,7 +412,7 @@ def build_docs(target, skip_build):
386412
shutil.rmtree(DOCS_BUILD_DIR)
387413

388414
try:
389-
if target == 'html':
415+
if target == 'html' and not local:
390416
build_output = os.path.join(DOCS_BUILD_DIR, 'html')
391417
try:
392418
# fmt: off
@@ -409,6 +435,7 @@ def build_docs(target, skip_build):
409435
raise
410436
# fmt: on
411437
create_latest_alias(build_output)
438+
create_root_redirect(build_output)
412439
else:
413440
# For other targets such as latex, pdf, etc.
414441
run_command(
@@ -737,8 +764,9 @@ def main():
737764
elif args.get('build-docs'):
738765
target = args.get('--target') or args.get('-t') or 'html'
739766
skip_build = args.get('--skip-build') or args.get('-s')
767+
local = args.get('--local') or args.get('-l')
740768

741-
build_docs(target=target, skip_build=skip_build)
769+
build_docs(target=target, skip_build=skip_build, local=local)
742770

743771
elif args.get('install-package-requirements'):
744772
install_package(target_path=os.path.join(ROOT_DIR, SITE_PACKAGES))

0 commit comments

Comments
 (0)