Skip to content

Commit 8dc405f

Browse files
committed
docs: report manpage NAME drift as a CI warning
The pin keeps the build correct, but a translated command name still drifts from the filename and is worth seeing. scripts/manpage-name-check.sh scans the built man tree and reports any page whose .TH name disagrees with its filename. It never fails; in CI it writes a job summary of the drift and one warning pointing to it (per-page annotations are capped by GitHub and just hide the count). A CI step runs it after the doc build. The NAME lines live in Weblate.
1 parent bb54eb0 commit 8dc405f

2 files changed

Lines changed: 68 additions & 0 deletions

File tree

.github/workflows/ci.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -175,6 +175,8 @@ jobs:
175175
run: |
176176
set -x
177177
.github/scripts/build-doc.sh
178+
- name: Check manpage names match filenames
179+
run: scripts/manpage-name-check.sh docs/build/man
178180
- name: Verify no untracked or modified files after build
179181
run: |
180182
#*.po and documentation.pot are modifyed by build. Ignore them for now.

scripts/manpage-name-check.sh

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
#!/bin/bash
2+
# Report man pages whose rendered NAME does not match their filename.
3+
# asciidoctor takes the .TH name from the page's NAME section, the build pins the filename with -o, so a translated NAME just leaves the two disagreeing.
4+
# Never fails the build: under GitHub Actions it writes a job summary of the drift and one warning pointing to it, otherwise plain lines.
5+
# The NAME lines are managed in Weblate, so fixes go there.
6+
# Argument: the built man tree to scan (default docs/build/man).
7+
8+
set -u
9+
10+
ROOT="${1:-docs/build/man}"
11+
12+
if [ ! -d "$ROOT" ]; then
13+
echo "I: $ROOT not found, build the man pages first"
14+
exit 0
15+
fi
16+
17+
# Lowercase and drop the roff backslash .TH escapes into names.
18+
norm() { local s=${1//\\/}; printf '%s' "${s,,}"; }
19+
20+
count=0
21+
summary=""
22+
while IFS= read -r -d '' f; do
23+
# Skip .so alias stubs: redirects with no .TH of their own.
24+
case "$(head -n 1 "$f")" in
25+
".so "*) continue ;;
26+
esac
27+
th=$(sed -ne 's/^\.TH "\([^"]*\)".*/\1/p' "$f" | head -n 1)
28+
[ -n "$th" ] || continue
29+
base=${f##*/}
30+
stem=${base%.*}
31+
[ "$(norm "$th")" = "$(norm "$stem")" ] && continue
32+
33+
rel=${f#"$ROOT"/}
34+
lang=${rel%%/*}
35+
case "$lang" in man[0-9]*) lang=en ;; esac
36+
# Plain line for a local run. In CI the full list goes to the job summary
37+
# below; per-page annotations are capped by GitHub and just hide the count.
38+
[ -n "${GITHUB_ACTIONS:-}" ] || printf 'W: %s: %s has NAME %s\n' "$lang" "$stem" "$th"
39+
summary="${summary}| ${lang} | ${stem} | ${th} |"$'\n'
40+
count=$((count + 1))
41+
done < <(find "$ROOT" -type f -name '*.[0-9]' -print0 | sort -z)
42+
43+
echo "I: $count manpage NAME/filename mismatch(es)"
44+
45+
if [ -n "${GITHUB_STEP_SUMMARY:-}" ]; then
46+
{
47+
echo "## Manpage NAME mismatches: $count"
48+
if [ "$count" -gt 0 ]; then
49+
echo
50+
echo "Translated NAME lines that drifted from the command name."
51+
echo "The left side of a NAME line is a command identifier and must"
52+
echo "stay verbatim; fix these in Weblate."
53+
echo
54+
echo "| lang | page | rendered NAME |"
55+
echo "| ---- | ---- | ------------- |"
56+
printf '%s' "$summary"
57+
fi
58+
} >> "$GITHUB_STEP_SUMMARY"
59+
fi
60+
61+
# One annotation pointing at the summary, rather than one per page.
62+
if [ -n "${GITHUB_ACTIONS:-}" ] && [ "$count" -gt 0 ]; then
63+
echo "::warning title=manpage NAME drift::$count manpage NAME line(s) disagree with their filename, see the job summary for the list"
64+
fi
65+
66+
exit 0

0 commit comments

Comments
 (0)