-
Notifications
You must be signed in to change notification settings - Fork 89
194 lines (178 loc) · 8.28 KB
/
Copy pathdocs.yml
File metadata and controls
194 lines (178 loc) · 8.28 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
# Documentation validation.
#
# Builds the modernized docs (docs-src/build.py: Markdown -> HTML + man + PDF)
# and runs the validators that lock in the reverse-DocBook migration's
# guarantees. Modeled on ci.yml/fuzz.yml conventions: hard gates block PRs,
# advisory tiers are continue-on-error, and heavy work (PDF/TeX-free but slow,
# external link check) is scheduled-only or best-effort so per-PR jobs stay
# fast.
#
# Tooling comes from the flake dev shell (nix develop) so CI matches local
# exactly -- pandoc, weasyprint, poppler-utils, mandoc, codespell, lychee and
# write-good are all pinned there.
#
# HARD gates (fail the PR): build (HTML+man), no-loss, completeness, spelling,
# internal link-check, man-lint.
# ADVISORY (continue-on-error): prose (write-good), external link-check.
# BEST-EFFORT (scheduled / continue-on-error): PDF build + validation (slow).
name: Docs
on:
push:
branches: [master]
pull_request:
paths:
- 'docs-src/**'
- '.github/workflows/docs.yml'
- 'flake.nix'
- 'dist/RELEASE'
workflow_dispatch:
schedule:
# Weekly (Mon 05:23 UTC): the full run including the slow PDF build and the
# external link check, which are best-effort/skipped on per-PR runs.
- cron: '23 5 * * 1'
concurrency:
group: docs-${{ github.ref }}
cancel-in-progress: true
permissions:
contents: read
jobs:
# ----------------------------------------------------------------------------
# Build HTML + man (fast, always) and run the hard gates that depend on the
# generated output. PDF is built here only on schedule/dispatch (see the
# `pdf` job) so a PR isn't gated on the ~4-minute weasyprint pass.
# ----------------------------------------------------------------------------
build:
name: build + gates (html, man, no-loss, completeness, spelling, links, man-lint)
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Install Nix (flakes enabled)
uses: cachix/install-nix-action@v27
with:
extra_nix_config: |
experimental-features = nix-command flakes
# 1. BUILD (hard): HTML + man with 0 errors. --no-pdf keeps the PR fast;
# the PDF path is exercised by the `pdf` job (scheduled/best-effort).
- name: Build HTML + man
run: nix develop --command bash -c 'cd docs-src && python3 build.py --no-pdf'
# build.py self-check guards the md->man reshape, PDF book discovery, and
# the .md->.html link rewrite (unit-level, no external tools).
- name: build.py self-check
run: nix develop --command bash -c 'cd docs-src && python3 build.py --selfcheck'
# 2. NO-LOSS GATE (hard): every migrated tree still retains its source
# content (word-multiset retention + no code/section drop). Locks the
# "nothing lost" guarantee against future edits.
- name: No-loss gate (all trees)
run: nix develop --command bash -c 'python3 docs-src/_migrate/verify_all.py'
# 3. COMPLETENESS GATE (hard): every public db.h function is documented
# (28/28), and every uncovered method is on the frozen allowlist -- a
# NEW undocumented API fails.
- name: Completeness gate (API coverage)
run: nix develop --command bash -c 'python3 docs-src/_migrate/man_coverage.py --ci'
# 4. SPELLING (hard on NEW typos): codespell, baselined against the legacy
# typo backlog so only newly-introduced typos fail.
- name: Spelling gate (codespell, baselined)
run: nix develop --command bash -c 'python3 docs-src/_migrate/spellcheck.py'
# 6. INTERNAL LINK CHECK (hard): every link into migrated content must
# resolve. Deferred-tree + un-migrated-asset links are excluded (see
# docs-src/_migrate/lychee.toml). External links are the advisory job.
- name: Internal link check (lychee, offline)
run: |
nix develop --command bash -c \
'shopt -s globstar; lychee --offline --config docs-src/_migrate/lychee.toml --no-progress "docs-build/html/**/*.html"'
# 7. MAN-LINT (hard): 0 ERRORS from mandoc across every generated .3
# (STYLE/WARNING are fine).
- name: Man-lint (mandoc -Tlint, 0 ERRORS)
run: |
nix develop --command bash -c '
e=0
for f in docs-build/man/man3/*.3; do
if mandoc -Tlint "$f" 2>&1 | grep -q "ERROR"; then
echo "ERRORS in $f:"; mandoc -Tlint "$f" 2>&1 | grep "ERROR" | head -3
e=$((e+1))
fi
done
echo "man pages with ERRORs: $e"
test "$e" -eq 0'
# ----------------------------------------------------------------------------
# 5. PROSE (advisory): write-good passive-voice / wordiness counts. This is
# decades-old technical prose -- surface the numbers, never gate.
# ----------------------------------------------------------------------------
prose:
name: prose advisory (write-good)
runs-on: ubuntu-latest
continue-on-error: true
steps:
- uses: actions/checkout@v4
- name: Install Nix (flakes enabled)
uses: cachix/install-nix-action@v27
with:
extra_nix_config: |
experimental-features = nix-command flakes
- name: write-good suggestion counts (per tree)
run: |
nix develop --command bash -c '
shopt -s globstar
total=0
for d in docs-src/api/* docs-src/guides/*; do
[ -d "$d" ] || continue
n=$(write-good "$d"/**/*.md 2>/dev/null | grep -c "on line" || true)
printf "%-40s %5s suggestions\n" "$d" "$n"
total=$((total+n))
done
echo "::notice title=Prose (write-good)::$total advisory suggestion(s) across docs-src"'
# ----------------------------------------------------------------------------
# PDF (best-effort / scheduled): weasyprint renders one PDF per book (~4 min
# over all 13). Not a per-PR gate -- runs on schedule/dispatch, or on a PR
# that touches build.py's PDF path. continue-on-error so a rendering hiccup
# informs without blocking.
# ----------------------------------------------------------------------------
pdf:
name: pdf build + validate (best-effort)
runs-on: ubuntu-latest
continue-on-error: true
if: github.event_name == 'schedule' || github.event_name == 'workflow_dispatch' || github.event_name == 'push'
steps:
- uses: actions/checkout@v4
- name: Install Nix (flakes enabled)
uses: cachix/install-nix-action@v27
with:
extra_nix_config: |
experimental-features = nix-command flakes
- name: Build all outputs (incl. PDF)
run: nix develop --command bash -c 'cd docs-src && timeout 900 python3 build.py'
- name: Validate PDFs (non-empty, page count, title-page version)
run: nix develop --command bash -c 'python3 docs-src/_migrate/validate_pdf.py'
- name: Upload PDFs
if: always()
uses: actions/upload-artifact@v4
with:
name: docs-pdf
path: docs-build/pdf/*.pdf
if-no-files-found: ignore
# ----------------------------------------------------------------------------
# External link check (advisory / scheduled): lychee WITH network, so it
# depends on the reachability of third-party sites. Never gates; scheduled
# and dispatch only so PRs don't wait on the network.
# ----------------------------------------------------------------------------
external-links:
name: external link check (advisory)
runs-on: ubuntu-latest
continue-on-error: true
if: github.event_name == 'schedule' || github.event_name == 'workflow_dispatch'
steps:
- uses: actions/checkout@v4
- name: Install Nix (flakes enabled)
uses: cachix/install-nix-action@v27
with:
extra_nix_config: |
experimental-features = nix-command flakes
- name: Build HTML
run: nix develop --command bash -c 'cd docs-src && python3 build.py --no-pdf'
- name: Check external links (network, advisory)
run: |
nix develop --command bash -c '
shopt -s globstar
lychee --no-progress --scheme http --scheme https \
--exclude "localhost" --max-concurrency 8 \
"docs-build/html/**/*.html" || true'