Files
truenas-truecloud-patch/tests/test_docs.py
T
flan 252696f1de
CI / shell (shellcheck + syntax) (push) Successful in 8s
CI / python 3.11 (push) Successful in 13s
CI / python 3.13 (push) Successful in 14s
CI / python 3.12 (push) Successful in 14s
docs: split the 969-line README; put Install at the top
Install was at line 517 of 969, under the boot sequence, the snapshot lifecycle and
the release process. Someone deciding whether to trust this with their backups should
not have to scroll past any of that.

README is now 211 lines: what it does, the minimum version, install, the support
matrix, updating, uninstall. Everything else moved to docs/ (nested snapshots, how it
works, recovery, CLI, releasing).

A test enforces it: every internal link resolves, Install stays near the top, and the
README does not grow back. Moving Markdown breaks cross-references -- it broke eight
of them here, including one in a recovery doc, where the person following the link is
by definition already having a bad day.
2026-07-13 18:34:44 +00:00

97 lines
3.5 KiB
Python

"""The docs must not lie about themselves.
The README was 969 lines with the install instructions at line 517. Splitting it into
docs/ fixed that and broke every cross-reference in the process -- which is the normal
outcome of moving Markdown around, and exactly why this is a test rather than a
careful afternoon.
A dead link in a recovery doc is worse than a dead link anywhere else: the person
following it is, by definition, already having a bad day.
"""
import os
import re
import pytest
ROOT = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
DOCS = os.path.join(ROOT, "docs")
LINK_RE = re.compile(r"\[([^\]]+)\]\(([^)]+)\)")
HEADING_RE = re.compile(r"^#{1,6}\s+(.*)$", re.M)
def markdown_files():
files = [os.path.join(ROOT, "README.md"), os.path.join(ROOT, "CHANGELOG.md")]
if os.path.isdir(DOCS):
files += [os.path.join(DOCS, f) for f in sorted(os.listdir(DOCS))
if f.endswith(".md")]
return files
def anchors(text):
"""GitHub/Gitea slugs for every heading in `text`."""
out = set()
for h in HEADING_RE.findall(text):
slug = re.sub(r"[^a-z0-9 -]", "", h.lower()).replace(" ", "-")
out.add(slug)
return out
@pytest.mark.parametrize("path", markdown_files(), ids=os.path.basename)
def test_every_internal_link_resolves(path):
with open(path, encoding="utf-8") as fh:
text = fh.read()
here = anchors(text)
base = os.path.dirname(path)
broken = []
for label, target in LINK_RE.findall(text):
if target.startswith(("http://", "https://", "mailto:")):
continue
rel, _, anchor = target.partition("#")
if not rel: # same-file anchor
if anchor and anchor not in here:
broken.append(f"[{label}](#{anchor}) — no such heading here")
continue
dest = os.path.normpath(os.path.join(base, rel))
if not os.path.exists(dest):
broken.append(f"[{label}]({target}) — file does not exist")
continue
if anchor and dest.endswith(".md"):
with open(dest, encoding="utf-8") as fh:
if anchor not in anchors(fh.read()):
broken.append(f"[{label}]({target}) — no such heading there")
assert not broken, "broken links in {}:\n {}".format(
os.path.basename(path), "\n ".join(broken)
)
class TestTheReadmeStaysAReadme:
def test_install_is_near_the_top(self):
# It was at line 517 of 969, under a wall of internals. Somebody deciding
# whether to use this should not have to scroll past the boot sequence.
with open(os.path.join(ROOT, "README.md"), encoding="utf-8") as fh:
lines = fh.read().splitlines()
install = next(i for i, ln in enumerate(lines, 1) if ln.startswith("## Install"))
assert install < 40, f"## Install is at line {install}"
def test_the_readme_does_not_grow_back(self):
with open(os.path.join(ROOT, "README.md"), encoding="utf-8") as fh:
n = len(fh.read().splitlines())
assert n < 300, (
f"README is {n} lines. Detail belongs in docs/ — the README is what "
f"someone reads before they trust this with their backups."
)
def test_the_minimum_version_is_stated_before_the_install_command(self):
with open(os.path.join(ROOT, "README.md"), encoding="utf-8") as fh:
text = fh.read()
assert "24.10" in text[:text.index("## Install")], (
"the minimum TrueNAS version must be visible above the install steps"
)