summaryrefslogtreecommitdiff
path: root/scripts
diff options
context:
space:
mode:
authorYuriy Andamasov <yuriy@vyos.io>2026-05-14 00:48:16 +0300
committerMergify <37929162+mergify[bot]@users.noreply.github.com>2026-05-14 05:08:54 +0000
commit1bee89e529774a072aa3905ab84d988f2085975b (patch)
treec36ebd10c70e00f99e61b54872ec41d78aa40a00 /scripts
parentf86a67230b63ddb99a75a70d7ba0fed24514f379 (diff)
downloadvyos-documentation-1bee89e529774a072aa3905ab84d988f2085975b.tar.gz
vyos-documentation-1bee89e529774a072aa3905ab84d988f2085975b.zip
ci(doc-linter): exclude docs/_rst_legacy/ and docs/_build/ from lint scope
`is_docs_path()` returned True for any path under `docs/`, including the archived RST shadows under `docs/_rst_legacy/` and the build output under `docs/_build/`. Sphinx excludes both from the build (per `docs/conf.py`'s exclude_patterns) and AGENTS marks `_rst_legacy` as reference-only. The linter shouldn't process either. Add a `DOCS_EXCLUDED_SUBDIRS = ('_build', '_rst_legacy')` constant. After confirming a path is under `docs/`, walk each excluded subtree and reject the path if it's contained. Also unify the auto-discover walk fallback to call `is_docs_path()` for the filter — previously it had its own hand-rolled `"_build" not in path` check that didn't handle `_rst_legacy` at all and would have walked the entire legacy archive. Prune `dirs[:]` in-place at each walk level so we don't descend into the excluded subtrees in the first place — optimization on top of correctness. Reverted the `_dirs` -> `dirs` rename here because we now mutate it. Test coverage: 10 hand-coded `is_docs_path()` cases — all pass: - `docs/configuration/foo.md` -> True - `docs/_rst_legacy/foo.rst` -> False (was True) - `docs/_rst_legacy/subdir/rst-foo.rst` -> False (was True) - `docs/_build/html/index.html` -> False (was True) - `docs/_include/foo.txt` -> True (live snippets stay in scope) - `docs` -> True - `AGENTS.md`, `README.md`, `.github/copilot-instructions.md`, `scripts/doc-linter.py` -> False (already correct) Tracked as item 4 of the rolling-side cleanup backlog from PR #2014 / #2019 / #2020 reviews. 🤖 Generated by [robots](https://vyos.io) (cherry picked from commit 379ed4757b62a7c1df965a59bc4f1fd0cef2d3e8)
Diffstat (limited to 'scripts')
-rw-r--r--scripts/doc-linter.py35
1 files changed, 28 insertions, 7 deletions
diff --git a/scripts/doc-linter.py b/scripts/doc-linter.py
index 1da215a5..e352615c 100644
--- a/scripts/doc-linter.py
+++ b/scripts/doc-linter.py
@@ -30,9 +30,15 @@ SUPPORTED_EXTS = ('.md', '.rst', '.txt')
# meta, not docs content, and are out of scope.
DOCS_ROOT = 'docs'
+# Subtrees under docs/ that are excluded from the build (per docs/conf.py)
+# and therefore also excluded from lint.
+DOCS_EXCLUDED_SUBDIRS = ('_build', '_rst_legacy')
+
def is_docs_path(path):
- """Return True iff `path` resolves under the repo's `docs/` tree.
+ """Return True iff `path` resolves under the repo's `docs/` tree AND
+ is not inside one of the build-excluded subtrees (``_build``,
+ ``_rst_legacy``).
Accepts both repo-relative and absolute paths. Both `path` and
`DOCS_ROOT` are resolved with `os.path.realpath`, so symlinks are
@@ -46,10 +52,19 @@ def is_docs_path(path):
abs_path = os.path.realpath(path)
abs_docs = os.path.realpath(DOCS_ROOT)
try:
- return os.path.commonpath([abs_path, abs_docs]) == abs_docs
+ if os.path.commonpath([abs_path, abs_docs]) != abs_docs:
+ return False
except ValueError:
# commonpath raises on mixed drives (Windows) or empty input.
return False
+ for excluded in DOCS_EXCLUDED_SUBDIRS:
+ abs_excluded = os.path.realpath(os.path.join(DOCS_ROOT, excluded))
+ try:
+ if os.path.commonpath([abs_path, abs_excluded]) == abs_excluded:
+ return False
+ except ValueError:
+ continue
+ return True
# MyST / Markdown fenced code block: leading whitespace + 3+ backticks or 3+ colons.
# Same character and length-or-greater closes.
@@ -303,12 +318,18 @@ def main():
if handle_file_action(file) is False:
bool_error = False
else:
- for root, _dirs, files in os.walk(DOCS_ROOT):
- path = root.split(os.sep)
+ # In-place dirs prune: skip descending into build-excluded subtrees.
+ # is_docs_path() also rejects paths under those subtrees, so the
+ # prune is an optimization (avoids walking thousands of archived
+ # legacy RST files) and the filter is correctness.
+ for root, dirs, files in os.walk(DOCS_ROOT):
+ dirs[:] = [d for d in dirs if d not in DOCS_EXCLUDED_SUBDIRS]
for file in files:
- if file.endswith(SUPPORTED_EXTS) and "_build" not in path:
- fpath = '/'.join(path)
- filepath = f"{fpath}/{file}"
+ filepath = os.path.join(root, file)
+ if (
+ file.endswith(SUPPORTED_EXTS)
+ and is_docs_path(filepath)
+ ):
if handle_file_action(filepath) is False:
bool_error = False