Repository navigation
docs: Ship the MkDocs documentation site with the installation - #7747
petrasovaa wants to merge 1 commit into
Conversation
Build the site at install and bindist time in both build systems so mkdocs does not become a dependency of the default build. When mkdocs is missing at install time, install a previously built site if there is one, otherwise skip the site with a warning; g.manual and the GUI then keep using their fallbacks. Implemented with AI assistance (Claude Fable).
| " | ||
| find_program(MKDOCS_EXECUTABLE mkdocs) | ||
| if(MKDOCS_EXECUTABLE) | ||
| message(STATUS \"Building the MkDocs documentation site\") | ||
| set(ENV{SITE_NAME} \"GRASS ${GRASS_VERSION_MAJOR}.${GRASS_VERSION_MINOR} Documentation\") | ||
| set(ENV{COPYRIGHT} \"© 2003-${GRASS_VERSION_DATE} GRASS Development Team, GRASS ${GRASS_VERSION_NUMBER} Documentation\") | ||
| execute_process( | ||
| COMMAND \${MKDOCS_EXECUTABLE} build | ||
| WORKING_DIRECTORY ${OUTDIR}/${GRASS_INSTALL_MKDOCSDIR} | ||
| RESULT_VARIABLE mkdocs_status) | ||
| if(NOT mkdocs_status EQUAL 0) | ||
| message(WARNING \"mkdocs build failed; the documentation site will be incomplete or missing\") | ||
| endif() | ||
| elseif(EXISTS \"${OUTDIR}/${GRASS_INSTALL_MKDOCSDIR}/site\") | ||
| message(STATUS \"mkdocs not found; installing the previously built documentation site\") | ||
| else() | ||
| message(WARNING \"mkdocs not found, the documentation site will not be installed. To include it, install the Python packages listed in man/mkdocs/requirements.txt and run cmake --install again.\") | ||
| endif() | ||
| " |
There was a problem hiding this comment.
That looks weird to me, to have the code as string, but that's probably in order to not parse it when it would error out.
Packagers will probably have to patch this if they split out docs to another package.
Do we know the extra time it takes at install time?
There was a problem hiding this comment.
And are we actually going through that code path in CI somewhere?
There was a problem hiding this comment.
And are we actually going through that code path in CI somewhere?
AI:
documentation.yml:149 runs make install before its "Get mkdocs" step (documentation.yml:227-229), so it too hits the warning branch, then pip-installs mkdocs and runs mkdocs build by hand at line 239. So CI covers mkdocs build itself, but not the new install glue.
Details
Reviewed PR #7747 (docs: Ship the MkDocs documentation site with the installation, petrasovaa:ship-mkdocs-installation) — 5 files, ~60 added lines.
Answers to your two review comments (not posted)
"Are we actually going through that code path in CI somewhere?" — Only the failure/fallback branch, never the success branch. No CI job has mkdocs on PATH at install time:
cmake.yml:87(cmake --install) installs no Python packages at all → hits the finalelse()"mkdocs not found" warning.build_ubuntu-{22,24}.04[_without_x].shandmacos_install.sh(make install) → same warning branch.documentation.yml:149runsmake installbefore its "Get mkdocs" step (documentation.yml:227-229), so it too hits the warning branch, then pip-installs mkdocs and runsmkdocs buildby hand at line 239. So CI coversmkdocs builditself, but not the new install glue.- Dockerfiles (
docker/*/Dockerfile, rootDockerfile) → no mkdocs either. osgeo4w.ymlnever runsmake install(onlymake), andmake bindistis not run by any workflow — that newbuild-mkdocscall is entirely untested.
To actually cover it, the cheapest option is pip install -r man/mkdocs/requirements.txt before the install step in one job (cmake.yml is the natural one, it is already the only cmake --install coverage).
"Do we know the extra time it takes at install time?" — From the latest successful Documentation run on main (run 33915975818, 2026-09-04), the "Run mkdocs" step took 88 s on a 4-core GitHub runner, and that covers core plus addons docs with the social-card plugin enabled; core-only will be somewhat less, so roughly a minute added to every make install / cmake --install. For size, that run's mkdocs-site artifact is 170 MB compressed (includes addons and the Sphinx libpython tree), consistent with the 120-200 MB estimate in the PR description. Also worth noting the cost is paid on every install — mkdocs has no incremental build and the code never skips an up-to-date site.
Findings
include/Make/Install.make:60— A failed/interrupted mkdocs build only warns, but mkdocs clearssite_dirbefore failing, so an empty/partialdocs/mkdocs/sitestill gets installed;scripts/g.manual/g.manual.py:79andgui/wxpython/gui_core/ghelp.py:759branch on that directory's existence alone, so g.manual fatals "No HTML manual page entry" for every tool instead of using the intactdocs/htmlfallback. The failure branch should deletesite/.CMakeLists.txt:395— Same defect on the CMake side:message(WARNING)then the followinginstall(DIRECTORY ...MKDOCSDIR/)ships the partial site.include/Make/Install.make:36—build-mkdocsruns beforeinstall-check-parent/writable/prefix, so a non-rootmake installto/usr/localrenders the whole site (~90 s) and only then aborts with "install directory is not writable".include/Make/Install.make:59— Docs are built into the build tree, notDESTDIR; with a system-packaged mkdocs onPATH,sudo make installleaves root-owned files in the user'sdist.$ARCH/docs/mkdocs/site, breaking later unprivilegedmake/make clean. Contradicts the comment's assumption that mkdocs is simply not found under sudo. (CMakeinstall(CODE)has the same property.)CMakeLists.txt:382— Unconditional re-render on everycmake --install, and CPack runs the same install script, so packaging pays it repeatedly.CMakeLists.txt:383— CI coverage gap as described above.
No bugs found in the SITE_NAME change itself: GRASS_VERSION_MAJOR/MINOR are defined in both include/Make/Grass.make and the top-level CMake scope, docs is already in BIN_DIST_FILES so bindist ships the site, the new build-mkdocs make target does not collide (only the top-level Makefile includes Install.make), and the CMake install(CODE) escaping/ordering (\${MKDOCS_EXECUTABLE} at install time, configure-time ${OUTDIR}, WORKING_DIRECTORY matching mkdocs_dir from man/CMakeLists.txt:130) is correct; a non-numeric RESULT_VARIABLE from a bad working directory also correctly lands in the warning branch.
Part of the transition to markdown-based documentation.
TL;DR:
make install/make bindistandcmake --installnow build and ship the MkDocs documentation site, which g.manual and the GUI then use; ifmkdocsis missing, the site is skipped with a warning and nothing else changes.Ship the MkDocs documentation site with the installation. g.manual and the GUI help viewer already prefer $GISBASE/docs/mkdocs/site` when it exists, so installs pick it up automatically; the legacy HTML pages remain as fallback until a later phase removes them.
The site is built at install time rather than in the default build, so
mkdocs(man/mkdocs/requirements.txt) does not become a build dependency and CI is unaffected:make installandmake bindistbuild the site into the dist tree via a new top-levelbuild-mkdocstarget; the install copy then includes it.install(CODE)step runsmkdocs buildduringcmake --install.When
mkdocsis not onPATHat install time (e.g. it is in a user environment but the install runs undersudo), a site built beforehand (make -C man build-mkdocsor thebuild-mkdocsCMake target) is still installed; without one, the site is skipped with a warning. A failed build likewise warns instead of aborting the install.Also align the local targets'
SITE_NAMEwith the site published by the documentation workflow: the title is nowGRASS <major>.<minor> Documentationeverywhere, while the exact version (includingdev) stays in the copyright footer.Note for packagers: the site adds roughly 120-200 MB, temporarily double accounting next to the legacy HTML pages until those are removed.
Implemented with AI assistance (Claude Fable).