fix(lint): stop SIGPIPE from faking missing sections (#710)

`grep -q` exits at its first match without draining stdin, killing the
piping `echo` with SIGPIPE. Under `set -o pipefail` that 141 becomes the
pipeline's status, which is indistinguishable from "no match" — so a
section that is present gets reported missing. The race only surfaces on
bodies large enough that `echo` is still writing when `grep` bails, which
made the warning set differ between identical runs (full repo: 106/87/90
warnings across three runs; now a stable 59).

Feed both checks from a herestring so there is no writer to signal.

Co-authored-by: Jaak Vaher <jaak.vaher@cyber.ee>
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Jaak Vaher
2026-07-11 22:00:09 +03:00
committed by GitHub
parent 9f3e401ccd
commit 134b4d08e6
+6 -2
View File
@@ -91,7 +91,7 @@ lint_file() {
# 2. Check required frontmatter fields
for field in "${REQUIRED_FRONTMATTER[@]}"; do
if ! echo "$frontmatter" | grep -qE "^${field}:"; then
if ! grep -qE -- "^${field}:" <<<"$frontmatter"; then
echo "ERROR $file: missing frontmatter field '${field}'"
errors=$((errors + 1))
fi
@@ -101,8 +101,12 @@ lint_file() {
local body
body=$(awk 'BEGIN{n=0} /^---$/{n++; next} n>=2{print}' "$file")
# Feed grep from a herestring, not a pipe: `grep -q` exits at the first match
# without draining its input, which kills a piping `echo` with SIGPIPE. Under
# `set -o pipefail` that 141 becomes the pipeline's status and is indistinguishable
# from "no match", so a large body raced its way to a spurious WARN.
for section in "${RECOMMENDED_SECTIONS[@]}"; do
if ! echo "$body" | grep -qi "$section"; then
if ! grep -qi -- "$section" <<<"$body"; then
echo "WARN $file: missing recommended section '${section}'"
warnings=$((warnings + 1))
fi