@@ -178,17 +178,63 @@ jobs:
178178 # Cleanup empty directories
179179 find . -type d -empty -delete
180180
181- # Check for meaningful changes, ignoring:
182- # - lastupdated date lines in HTML (Sphinx build-time timestamps)
183- # - epub/pdf binaries (they regenerate automatically alongside HTML)
184- meaningful_html=$(git diff HEAD -- '*.html' | grep -E '^[+-]' | grep -v '^[+-]{3}' | grep -ivE 'lastupdated|Last updated on' | wc -l)
185- other_changes=$(git diff --name-only HEAD | grep -cvE '\.(html|epub|pdf)$' || true)
181+ # ----------------------------------------------------------------
182+ # Prune build-only noise so the PR carries exclusively real content
183+ # changes. A rebuilt page differs every night even when its content
184+ # is identical, because of:
185+ # - Sphinx build-time timestamps (lastupdated / "Last updated on")
186+ # - mermaid diagram zoom ids (random UUID regenerated each build)
187+ # Files whose ENTIRE diff is noise are reverted to HEAD; files with a
188+ # real change are kept untouched (noise lines ride along, harmless).
189+ # ----------------------------------------------------------------
190+ NOISE='lastupdated|Last updated on|data-zoom-id'
191+
192+ # Read-only diffs must not take .git/index.lock: a `git diff` that
193+ # refreshes the index while a `git checkout` writes it races on the
194+ # lock. GIT_OPTIONAL_LOCKS=0 suppresses the refresh write; we also
195+ # materialise each file list fully before running any checkout, and
196+ # batch the reverts into a single checkout call.
197+ export GIT_OPTIONAL_LOCKS=0
198+
199+ # 1) Collect HTML files whose only changes are noise, then revert them.
200+ : > /tmp/revert-html.txt
201+ git diff --name-only HEAD -- '*.html' > /tmp/changed-html.txt
202+ while IFS= read -r f; do
203+ [ -n "$f" ] || continue
204+ real=$(git diff HEAD -- "$f" | grep -E '^[+-]' | grep -vE '^[+-]{3}' | grep -ivE "$NOISE" | wc -l)
205+ [ "$real" -eq 0 ] && printf '%s\n' "$f" >> /tmp/revert-html.txt
206+ done < /tmp/changed-html.txt
207+ if [ -s /tmp/revert-html.txt ]; then
208+ xargs -a /tmp/revert-html.txt -r git checkout HEAD --
209+ fi
210+
211+ # 2) PDF/ePub binaries regenerate every build with no content change.
212+ # Keep them only for a version folder that still has a real HTML
213+ # change after step 1; otherwise revert them too. Runs after the
214+ # HTML revert so the per-folder check sees the pruned tree.
215+ : > /tmp/revert-bin.txt
216+ git diff --name-only HEAD -- '*.pdf' '*.epub' > /tmp/changed-bin.txt
217+ while IFS= read -r f; do
218+ [ -n "$f" ] || continue
219+ case "$f" in
220+ server/*)
221+ vdir="server/$(printf '%s' "${f#server/}" | cut -d/ -f1)"
222+ remaining=$(git diff --name-only HEAD -- "$vdir" | grep -vE '\.(epub|pdf)$' | wc -l)
223+ [ "$remaining" -eq 0 ] && printf '%s\n' "$f" >> /tmp/revert-bin.txt
224+ ;;
225+ *) printf '%s\n' "$f" >> /tmp/revert-bin.txt ;;
226+ esac
227+ done < /tmp/changed-bin.txt
228+ if [ -s /tmp/revert-bin.txt ]; then
229+ xargs -a /tmp/revert-bin.txt -r git checkout HEAD --
230+ fi
186231
187- if [ "$meaningful_html" -gt 0 ] || [ "$other_changes" -gt 0 ]; then
232+ # Anything real left to deploy? (tracked diffs or brand-new files)
233+ if [ -n "$(git status --porcelain)" ]; then
188234 echo "has_changes=true" >> $GITHUB_OUTPUT
189235 else
190236 echo "has_changes=false" >> $GITHUB_OUTPUT
191- echo "::notice::Skipping deploy PR: only lastupdated timestamps or epub/pdf binaries changed"
237+ echo "::notice::Skipping deploy PR: only build noise ( timestamps, mermaid ids, binaries) changed"
192238 fi
193239
194240 - name : Strip noindex from stable docs
0 commit comments