From 93008a777551f37fe9e07a3902fd76e29ec84e35 Mon Sep 17 00:00:00 2001 From: Yuriy Andamasov Date: Mon, 11 May 2026 11:02:46 +0300 Subject: ci(ai-validation): add :(glob) pathspec magic so top-level docs/*.md match MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit CRITICAL BUG discovered during smoke verify of PR #1977 (a draft PR touching docs/quick-start.md). The prepare job ran SUCCESS but validate SKIPPED because has_md_changes was false: $ git diff origin/rolling...HEAD --name-only -- 'docs/**/*.md' (empty) $ git diff origin/rolling...HEAD --name-only -- ':(glob)docs/**/*.md' docs/quick-start.md Root cause: git's default pathspec syntax uses fnmatch with FNM_PATHNAME (slashes are not crossed by `*`). The `**` glob is NOT recognized in default pathspec — it's treated as plain `**` (two consecutive asterisks). For `docs/**/*.md` this means git requires at least one `/` between `docs/` and `*.md`, so: - docs/configuration/service/foo.md → MATCHES (1+ subdir) - docs/quick-start.md → NO MATCH (0 subdirs) - docs/index.md → NO MATCH (0 subdirs) - docs/cli.md → NO MATCH (0 subdirs) - docs/copyright.md → NO MATCH (0 subdirs) - docs/coverage.md → NO MATCH (0 subdirs) - docs/404.md → NO MATCH (0 subdirs) - docs/documentation.md → NO MATCH (0 subdirs) 7 top-level files silently bypass validation on every PR that touches them. Adding the `:(glob)` magic prefix opts in to true shell-style ** semantics (also recognised by git's pathspec parser per gitignore-pattern rules): - docs/**/*.md → :(glob)docs/**/*.md - docs/**/*.rst → :(glob)docs/**/*.rst Three pathspec usages updated in the prepare job; comment references to "docs/**/*.md" left unchanged (they read as informal shorthand). Paired PR on VyOS-Networks/vyos-docs-opus-reviewer adjusts the canonical scripts/ai-validation.yml identically. --- .github/workflows/ai-validation.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to '.github/workflows') diff --git a/.github/workflows/ai-validation.yml b/.github/workflows/ai-validation.yml index b4736fe1..b21d2320 100644 --- a/.github/workflows/ai-validation.yml +++ b/.github/workflows/ai-validation.yml @@ -78,8 +78,8 @@ jobs: # blobs for files that no longer exist in the merge ref. # Deletions still appear in diff-md.patch (full diff) but not # in changed-md.txt (which drives the bundling step). - git diff "$BASE...HEAD" --name-only --diff-filter=ACMRT -z -- 'docs/**/*.md' > changed-md.z - git diff "$BASE...HEAD" --name-only --diff-filter=ACMRT -z -- 'docs/**/*.rst' > changed-rst.z + git diff "$BASE...HEAD" --name-only --diff-filter=ACMRT -z -- ':(glob)docs/**/*.md' > changed-md.z + git diff "$BASE...HEAD" --name-only --diff-filter=ACMRT -z -- ':(glob)docs/**/*.rst' > changed-rst.z # Reject paths containing line-disrupting control bytes (LF, CR, # other 0x01-0x1F + 0x7F) before generating the newline-delimited # *.txt manifests. NUL itself can't appear in a git pathname @@ -106,7 +106,7 @@ jobs: done tr '\0' '\n' < changed-md.z > changed-md.txt tr '\0' '\n' < changed-rst.z > changed-rst.txt - git diff "$BASE...HEAD" -- 'docs/**/*.md' > diff-md.patch + git diff "$BASE...HEAD" -- ':(glob)docs/**/*.md' > diff-md.patch # Bundle .md files via git's blob store (NOT the filesystem). # The fork's merge ref can contain symlinks (mode 120000) committed # to docs/**/*.md that resolve to absolute paths on the runner. -- cgit v1.2.3