From 6322666b7e40d6ddb3b416b224efc80d912fff20 Mon Sep 17 00:00:00 2001 From: Derek Ardolf <204508229+scriptautomate-bc@users.noreply.github.com> Date: Sat, 5 Sep 2026 00:50:10 +0000 Subject: [PATCH 1/6] feat(docs): add git-derived lastmod to sitemap Add sphinx-sitemap to the docs extensions and requirements, and set html_baseurl/sitemap_show_lastmod so every emitted page gets a sourced from git commit time. autodoc-registered .py module dependencies are picked up automatically via sphinx-last-updated-by-git, so a docstring or signature edit correctly bumps the rendered page's lastmod. The URL segment is keyed off WEBSITE_RELEASE (falling back to major_version), which every builddocs job already sets correctly, so this needs no per-branch edits on merge-forward. --- doc/conf.py | 11 +++++++++++ requirements/static/ci/docs.txt | 1 + requirements/static/ci/py3.10/docs.lock | 5 +++++ requirements/static/ci/py3.11/docs.lock | 5 +++++ requirements/static/ci/py3.12/docs.lock | 5 +++++ requirements/static/ci/py3.13/docs.lock | 5 +++++ requirements/static/ci/py3.14/docs.lock | 5 +++++ requirements/static/ci/py3.9/docs.lock | 5 +++++ 8 files changed, 42 insertions(+) diff --git a/doc/conf.py b/doc/conf.py index c944f58dcb5d..bf370fef5c49 100644 --- a/doc/conf.py +++ b/doc/conf.py @@ -186,6 +186,7 @@ def _safe_urlsplit(url, scheme="", allow_fragments=True): "salthttpanchors", "saltrepo", "myst_parser", + "sphinx_sitemap", #'saltautodoc', # Must be AFTER autodoc ] @@ -403,6 +404,16 @@ def _safe_urlsplit(url, scheme="", allow_fragments=True): html_show_sphinx = True html_show_copyright = True +# Deployed URL segment: /en// for release branches, /en/master/ for master. +# WEBSITE_RELEASE is already set correctly by every builddocs job; major_version +# (line 89) is the right default, which keeps this merge-forward safe with no per-branch edits. +docs_url_segment = os.environ.get("WEBSITE_RELEASE", major_version) +html_baseurl = f"https://docs.saltproject.io/en/{docs_url_segment}/" +sitemap_url_scheme = "{link}" # segment already in html_baseurl +sitemap_locales = [None] +sitemap_show_lastmod = True # max(rst commit time, autodoc'd .py commit times) +sitemap_excludes = ["search.html", "genindex.html", "http-routingtable.html"] + ### Latex options latex_documents = [ diff --git a/requirements/static/ci/docs.txt b/requirements/static/ci/docs.txt index c75fb3aa0477..6d0b36ac5739 100644 --- a/requirements/static/ci/docs.txt +++ b/requirements/static/ci/docs.txt @@ -5,6 +5,7 @@ myst-docutils[linkify] sphinxcontrib-httpdomain>=1.8.1,<2.0.0; python_version < '3.10' sphinxcontrib-httpdomain>=2.0.0; python_version >= '3.10' sphinxcontrib-spelling +sphinx-sitemap>=2.9.0 cherrypy jinja2 pydata-sphinx-theme diff --git a/requirements/static/ci/py3.10/docs.lock b/requirements/static/ci/py3.10/docs.lock index a2bcc01fde49..3a5f60de99d1 100644 --- a/requirements/static/ci/py3.10/docs.lock +++ b/requirements/static/ci/py3.10/docs.lock @@ -359,8 +359,13 @@ sphinx==7.0.1 # via # -r requirements/static/ci/docs.txt # pydata-sphinx-theme + # sphinx-last-updated-by-git # sphinxcontrib-httpdomain # sphinxcontrib-spelling +sphinx-last-updated-by-git==0.3.8 + # via sphinx-sitemap +sphinx-sitemap==2.9.0 + # via -r requirements/static/ci/docs.txt sphinxcontrib-applehelp==1.0.4 # via sphinx sphinxcontrib-devhelp==1.0.2 diff --git a/requirements/static/ci/py3.11/docs.lock b/requirements/static/ci/py3.11/docs.lock index 1a780076747c..4d686f2d346e 100644 --- a/requirements/static/ci/py3.11/docs.lock +++ b/requirements/static/ci/py3.11/docs.lock @@ -354,8 +354,13 @@ sphinx==7.0.1 # via # -r requirements/static/ci/docs.txt # pydata-sphinx-theme + # sphinx-last-updated-by-git # sphinxcontrib-httpdomain # sphinxcontrib-spelling +sphinx-last-updated-by-git==0.3.8 + # via sphinx-sitemap +sphinx-sitemap==2.9.0 + # via -r requirements/static/ci/docs.txt sphinxcontrib-applehelp==1.0.4 # via sphinx sphinxcontrib-devhelp==1.0.2 diff --git a/requirements/static/ci/py3.12/docs.lock b/requirements/static/ci/py3.12/docs.lock index 3bb7f815125d..cd555abab83a 100644 --- a/requirements/static/ci/py3.12/docs.lock +++ b/requirements/static/ci/py3.12/docs.lock @@ -352,8 +352,13 @@ sphinx==9.1.0 # via # -r requirements/static/ci/docs.txt # pydata-sphinx-theme + # sphinx-last-updated-by-git # sphinxcontrib-httpdomain # sphinxcontrib-spelling +sphinx-last-updated-by-git==0.3.8 + # via sphinx-sitemap +sphinx-sitemap==2.9.0 + # via -r requirements/static/ci/docs.txt sphinxcontrib-applehelp==2.0.0 # via sphinx sphinxcontrib-devhelp==2.0.0 diff --git a/requirements/static/ci/py3.13/docs.lock b/requirements/static/ci/py3.13/docs.lock index bfbe0bafb14b..1c884205e47b 100644 --- a/requirements/static/ci/py3.13/docs.lock +++ b/requirements/static/ci/py3.13/docs.lock @@ -350,8 +350,13 @@ sphinx==9.1.0 # via # -r requirements/static/ci/docs.txt # pydata-sphinx-theme + # sphinx-last-updated-by-git # sphinxcontrib-httpdomain # sphinxcontrib-spelling +sphinx-last-updated-by-git==0.3.8 + # via sphinx-sitemap +sphinx-sitemap==2.9.0 + # via -r requirements/static/ci/docs.txt sphinxcontrib-applehelp==2.0.0 # via sphinx sphinxcontrib-devhelp==2.0.0 diff --git a/requirements/static/ci/py3.14/docs.lock b/requirements/static/ci/py3.14/docs.lock index 8660baeeb199..d25d3d319314 100644 --- a/requirements/static/ci/py3.14/docs.lock +++ b/requirements/static/ci/py3.14/docs.lock @@ -350,8 +350,13 @@ sphinx==9.1.0 # via # -r requirements/static/ci/docs.txt # pydata-sphinx-theme + # sphinx-last-updated-by-git # sphinxcontrib-httpdomain # sphinxcontrib-spelling +sphinx-last-updated-by-git==0.3.8 + # via sphinx-sitemap +sphinx-sitemap==2.9.0 + # via -r requirements/static/ci/docs.txt sphinxcontrib-applehelp==2.0.0 # via sphinx sphinxcontrib-devhelp==2.0.0 diff --git a/requirements/static/ci/py3.9/docs.lock b/requirements/static/ci/py3.9/docs.lock index 7f70637a8a63..c091aa129585 100644 --- a/requirements/static/ci/py3.9/docs.lock +++ b/requirements/static/ci/py3.9/docs.lock @@ -363,8 +363,13 @@ sphinx==7.0.1 # via # -r requirements/static/ci/docs.txt # pydata-sphinx-theme + # sphinx-last-updated-by-git # sphinxcontrib-httpdomain # sphinxcontrib-spelling +sphinx-last-updated-by-git==0.3.8 + # via sphinx-sitemap +sphinx-sitemap==2.9.0 + # via -r requirements/static/ci/docs.txt sphinxcontrib-applehelp==1.0.4 # via sphinx sphinxcontrib-devhelp==1.0.2 From a74cae9797661f5fd4355690e4bc7fdc466afa4d Mon Sep 17 00:00:00 2001 From: Derek Ardolf <204508229+scriptautomate-bc@users.noreply.github.com> Date: Sat, 5 Sep 2026 00:50:17 +0000 Subject: [PATCH 2/6] ci(docs): fetch full git history for sitemap lastmod generation The build job's checkout was depth-1, which causes sphinx-last-updated-by-git to either fail the build under -W or silently emit sitemap entries with no lastmod. Use fetch-depth: 0 with a blobless filter to keep the clone cheap while preserving commit history. --- .github/workflows/build-docs.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/build-docs.yml b/.github/workflows/build-docs.yml index 9a252819e6aa..6358eb26f31e 100644 --- a/.github/workflows/build-docs.yml +++ b/.github/workflows/build-docs.yml @@ -37,6 +37,9 @@ jobs: steps: - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 + with: + fetch-depth: 0 + filter: blob:none - uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5 with: python-version: '3.14' From db56332a2466f5844a579020e945cafe94972897 Mon Sep 17 00:00:00 2001 From: Derek Ardolf <204508229+scriptautomate-bc@users.noreply.github.com> Date: Sat, 5 Sep 2026 00:50:23 +0000 Subject: [PATCH 3/6] chore(docs): remove unused, broken sitemap Makefile target It clobbers the extension list (dropping saltdomain and autodoc), hardcodes html_baseurl to en/latest/, and needs sphinx-sitemap, which was in no requirements or lock file. It is superseded by the sitemap now generated as part of the regular html build. --- doc/Makefile | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/doc/Makefile b/doc/Makefile index 5aa4dd9e21d2..81db03b255eb 100644 --- a/doc/Makefile +++ b/doc/Makefile @@ -16,7 +16,7 @@ ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . # the i18n builder cannot share the environment and doctrees with the others I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . -.PHONY: help clean check_sphinx-build html dirhtml singlehtml pickle json htmlhelp qthelp devhelp latex latexpdf text man changes linkcheck linkcheck-audit sitemap doctest +.PHONY: help clean check_sphinx-build html dirhtml singlehtml pickle json htmlhelp qthelp devhelp latex latexpdf text man changes linkcheck linkcheck-audit doctest help: @echo "Please use \`make ' where is one of" @@ -42,7 +42,6 @@ help: @echo " pseudoxml to make pseudoxml-XML files for display purposes" @echo " linkcheck to check all external links for integrity" @echo " linkcheck-audit to run the wrapped audit (strips the catch-all ignore) and emit a CSV" - @echo " sitemap to build the HTML output with sphinx-sitemap and emit a sitemap.xml" @echo " doctest to run all doctests embedded in the documentation (if enabled)" clean: @@ -182,13 +181,6 @@ linkcheck-audit: @echo @echo "Link audit complete; CSV report at $(BUILDDIR)/linkcheck-audit/report.csv." -sitemap: check_sphinx-build - $(SPHINXBUILD) -b html -D extensions=sphinx_sitemap \ - -D html_baseurl=https://docs.saltproject.io/en/latest/ \ - $(ALLSPHINXOPTS) $(BUILDDIR)/sitemap - @echo - @echo "Sitemap generated under $(BUILDDIR)/sitemap/sitemap.xml." - doctest: check_sphinx-build $(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest @echo "Testing of doctests in the sources finished, look at the " \ From 91b5bfa9a15ccad518139e8c52cc3e94cee0ebdd Mon Sep 17 00:00:00 2001 From: Derek Ardolf <204508229+scriptautomate-bc@users.noreply.github.com> Date: Sat, 5 Sep 2026 01:23:17 +0000 Subject: [PATCH 4/6] docs(changelog): add towncrier entries for sitemap lastmod work --- changelog/70241.added.md | 1 + changelog/70241.removed.md | 1 + 2 files changed, 2 insertions(+) create mode 100644 changelog/70241.added.md create mode 100644 changelog/70241.removed.md diff --git a/changelog/70241.added.md b/changelog/70241.added.md new file mode 100644 index 000000000000..98a1aa45d434 --- /dev/null +++ b/changelog/70241.added.md @@ -0,0 +1 @@ +Added `` timestamps to the generated docs `sitemap.xml`, sourced from each page's git commit time (and, for autodoc pages, the newest commit among the Python modules that page documents). The docs build job's checkout now fetches full git history (via a blobless clone) since the timestamps cannot be computed from a shallow clone. diff --git a/changelog/70241.removed.md b/changelog/70241.removed.md new file mode 100644 index 000000000000..b7634aed78fa --- /dev/null +++ b/changelog/70241.removed.md @@ -0,0 +1 @@ +Removed the unused, broken `sitemap` target from `doc/Makefile`. It clobbered the extension list (dropping `saltdomain` and autodoc), hardcoded `html_baseurl` to `en/latest/`, and required `sphinx-sitemap`, which was in no requirements or lock file. The docs build now emits a sitemap directly as part of the regular HTML build. From b7d2c58bc889cdc73a99a0845ab2a7b2dbbc4edf Mon Sep 17 00:00:00 2001 From: Derek Ardolf <204508229+scriptautomate-bc@users.noreply.github.com> Date: Sat, 5 Sep 2026 01:36:51 +0000 Subject: [PATCH 5/6] fix(docs): skip sitemap lastmod for man-only builds sphinx-last-updated-by-git runs a git log against every page's dependencies whenever sitemap_show_lastmod is enabled, regardless of builder. CI jobs that only build man pages (e.g. the release-patch step in ci.yml's prepare-release job) use a shallow checkout, so this turned into a hard "git.too_shallow" failure under -W, which cascaded into the docs build jobs failing since they never got their release-patch artifact. Man pages have no sitemap consumer, so skip lastmod there instead of widening every man-page-generating job's checkout. --- doc/conf.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/doc/conf.py b/doc/conf.py index bf370fef5c49..4e67213a4f83 100644 --- a/doc/conf.py +++ b/doc/conf.py @@ -411,7 +411,11 @@ def _safe_urlsplit(url, scheme="", allow_fragments=True): html_baseurl = f"https://docs.saltproject.io/en/{docs_url_segment}/" sitemap_url_scheme = "{link}" # segment already in html_baseurl sitemap_locales = [None] -sitemap_show_lastmod = True # max(rst commit time, autodoc'd .py commit times) +sitemap_show_lastmod = not building_man_only # max(rst commit time, autodoc'd .py commit times) +# Skipped for man-only builds: sphinx-last-updated-by-git runs a git log against +# every page's dependencies, and CI jobs that only build man pages (e.g. the +# release-patch step in ci.yml) use a shallow checkout, which turns into a hard +# "git.too_shallow" failure under -W. Man pages have no sitemap consumer anyway. sitemap_excludes = ["search.html", "genindex.html", "http-routingtable.html"] ### Latex options From d90c8e22ba8ab642b0afe3117ff4250ed71af901 Mon Sep 17 00:00:00 2001 From: scriptautomate-bc <204508229+scriptautomate-bc@users.noreply.github.com> Date: Wed, 9 Sep 2026 18:03:56 -0500 Subject: [PATCH 6/6] docs(lint): black reformat --- doc/conf.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/doc/conf.py b/doc/conf.py index 4e67213a4f83..995a194c93cf 100644 --- a/doc/conf.py +++ b/doc/conf.py @@ -2,6 +2,7 @@ """ Sphinx documentation for Salt """ + import os import sys import urllib.parse @@ -411,7 +412,9 @@ def _safe_urlsplit(url, scheme="", allow_fragments=True): html_baseurl = f"https://docs.saltproject.io/en/{docs_url_segment}/" sitemap_url_scheme = "{link}" # segment already in html_baseurl sitemap_locales = [None] -sitemap_show_lastmod = not building_man_only # max(rst commit time, autodoc'd .py commit times) +sitemap_show_lastmod = ( + not building_man_only +) # max(rst commit time, autodoc'd .py commit times) # Skipped for man-only builds: sphinx-last-updated-by-git runs a git log against # every page's dependencies, and CI jobs that only build man pages (e.g. the # release-patch step in ci.yml) use a shallow checkout, which turns into a hard