Pre-push mkdocs strict-mode gate¶
A pre-push hook runs mkdocs build --strict locally whenever a push touches docs/ or mkdocs.yml, so documentation breakage fails on your machine instead of in CI.
CI runs the same build (the docs.yml lane) on every such push. Before this hook landed, audit slice G found that 38 of 50 master pushes failed that lane for trivial breakage: broken anchors, orphan pages, missing nav entries.
See ADR-0466 for the decision record.
Quick start¶
# Install all pre-push hooks (idempotent):
make hooks-install
# Run the mkdocs check manually (without pushing):
scripts/git-hooks/pre-push-mkdocs-strict.sh # runs directly
# Install the docs toolchain if mkdocs is not on PATH:
pip install -r docs/requirements.txt
How the hook works¶
- Scope check — if the push does not touch
docs/ormkdocs.yml, the hook exits 0 immediately (no latency on non-docs pushes). If the framework selects no documentation paths, the check does not run. A direct script invocation also skips a confirmed non-doc change before checking for MkDocs. It consumes the complete changed-path list, including large diffs, and runs the build if Git cannot determine that list. Documentation changes must pass the build. - Toolchain check — once documentation is selected, missing
mkdocsblocks the push with an installation hint. Install viapip install -r docs/requirements.txtin the active environment. - Build — runs
mkdocs build --strictagainst a temporary--site-dir. The temporary directory is cleaned up on exit regardless of outcome. The build is never--quiet: that flag raises the log level to ERROR, so the WARNINGs--strictcounts are never emitted and a site with broken anchors builds with exit code 0. The hook also blocks when the output holds aWARNINGorERRORline, andscripts/ci/tests/test_pre_push_mkdocs_strict.py(run by thedocs.ymlworkflow) fails on the quiet form. - Result — on success, a single confirmation line is printed. On failure, the mkdocs WARNING and ERROR lines are printed to stderr and the push is blocked with exit code 1.
Bypassing the hook¶
| Situation | Command |
|---|---|
| Skip this hook only | SKIP=mkdocs-strict git push |
| Skip all pre-push hooks | git push --no-verify |
The targeted bypass (SKIP=mkdocs-strict) is preferred: it still runs the PR-body deliverables gate and other pre-push hooks.
Warning
Bypassing is for the maintainer only. Agents never bypass hooks (operational rule 6 of the agent harness forbids the skip-hooks push flag and LEFTHOOK=0).
Troubleshooting¶
"mkdocs not found on PATH"¶
Install the docs toolchain:
"WARNING - Doc file … contains a link … but the target"¶
The exact anchor, page, or nav entry that broke is printed. Fix the broken reference in the doc file and push again. Common causes:
- Renamed a heading → update all links that reference its anchor.
- Added a new page but forgot to add it to
mkdocs.ymlnav:. - Moved a file → update any cross-links that point at the old path.
"mkdocs build --strict" passes locally but fails in CI¶
The CI lane uses docs/requirements.txt pinned versions. Ensure your local installation matches:
If CI still fails after a local pass, check the CI log for the exact warning — the validation: block in mkdocs.yml (see ADR-0403) governs which categories are warn vs. info.
Wire-up details¶
Three parts make up the wiring:
- Hook stage.
make install-hooksinstalls a regular dispatcher for the framework'spre-pushstage..pre-commit-config.yamlregistersmkdocs-strictas an independent check, so a skipped PR-body check cannot skip this build. - Selection. The check is selected by changed
docs/ormkdocs.ymlpaths in Git's pushed-ref range. A direct invocation ofpre-push-mkdocs-strict.shselects documentation changes relative toorigin/master, and runs conservatively when that base is unavailable. The build validates the active working tree, as other local source checks do; CI validates the submitted commit in a clean checkout. - Migration. Installations predating ADR-1241 must rerun
make install-hooks, particularly if an old source symlink points into a removed worktree. See local hooks for migration and custom-hook preservation.