-
Notifications
You must be signed in to change notification settings - Fork 0
138 lines (121 loc) · 4.79 KB
/
Copy pathci.yml
File metadata and controls
138 lines (121 loc) · 4.79 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
name: CI
on:
push:
branches: [main]
pull_request:
branches: [main]
permissions:
contents: read
concurrency:
group: ci-${{ github.ref }}
cancel-in-progress: true
jobs:
check:
name: Lint, Typecheck, Build
runs-on: ubuntu-latest
timeout-minutes: 10
steps:
- name: Checkout
uses: actions/checkout@v5
- name: Setup pnpm
uses: pnpm/action-setup@v4
- name: Setup Node.js
uses: actions/setup-node@v5
with:
node-version: 24
cache: pnpm
- name: Install dependencies
run: pnpm install --frozen-lockfile
- name: Lint
run: pnpm lint
- name: Format
run: pnpm format:check
- name: Typecheck
run: pnpm typecheck
- name: Build
run: pnpm build
- name: No word runs into a tag
run: pnpm check:spacing
- name: No inline styles ship
# style-src 'self' refuses a style attribute as firmly as a <style>
# block, so one would be a silent rendering bug rather than an error. The
# copied docs are the likely source: markdown renders an aligned table
# column as a style attribute on every cell.
run: |
if grep -rl 'style="' dist --include='*.html'; then
echo "A page carries an inline style attribute, which the CSP refuses." >&2
exit 1
fi
echo "No inline styles."
- name: The copied docs match the repository
# src/docs holds copies of documents that are written in the tool's
# repository. A copy that has fallen behind says something the
# repository no longer does, on this site's authority, so a difference
# from main fails here and the fix is `pnpm sync:docs`.
run: node scripts/sync-docs.mjs --check
- name: The markdown twins are real
# Generated from the built HTML, so they cannot drift from the pages.
# What they can do is come out empty if the conversion breaks, and an
# empty twin tells a reader the page says almost nothing. Derived from
# what was built rather than from a list of page names, because a list
# here would pass while a whole new section shipped with no twin at all.
run: |
bad=0
for page in $(find dist -name '*.html' ! -name '404.html' | sort); do
file="${page%.html}.md"
if [ ! -f "$file" ]; then
echo "$page has no twin at $file." >&2
bad=1
continue
fi
if [ "$(wc -c < "$file")" -lt 1000 ]; then
echo "$file is too small to be the page it claims to be." >&2
bad=1
fi
if grep -qE '</[a-z]+>' "$file"; then
echo "$file still carries HTML tags, so the conversion is wrong:" >&2
grep -nE '</[a-z]+>' "$file" | head -3 >&2
bad=1
fi
done
[ "$bad" -eq 0 ] || exit 1
echo "Every built page has a twin, and every twin is readable."
- name: No client JavaScript ships
# The site's Content-Security-Policy says script-src 'none'. If a build
# ever emits a script this fails here rather than in a browser console
# on a page that has already shipped.
#
# One exception, and only one: a `type="application/ld+json"` block is a
# data block that never executes, so script-src has nothing to act on.
# It is allowed, and each one is parsed here to prove it really is data
# rather than something wearing the type attribute.
run: |
if find dist -name '*.js' -o -name '*.mjs' | grep -q .; then
echo "A JavaScript file was emitted, which the CSP forbids:" >&2
find dist -name '*.js' -o -name '*.mjs' >&2
exit 1
fi
python3 - <<'CHECK'
import json
import re
import sys
from pathlib import Path
LD = re.compile(
r'<script[^>]*\btype=["\']application/ld\+json["\'][^>]*>(.*?)</script>',
re.S | re.I,
)
problems = []
for page in sorted(Path("dist").rglob("*.html")):
html = page.read_text(encoding="utf-8")
for block in LD.findall(html):
try:
json.loads(block)
except json.JSONDecodeError as bad:
problems.append(f"{page}: the JSON-LD block does not parse: {bad}")
if "<script" in LD.sub("", html):
problems.append(f"{page}: a script tag that is not JSON-LD")
if problems:
print("The CSP forbids this:", *problems, sep="\n ", file=sys.stderr)
sys.exit(1)
CHECK
echo "No client JavaScript, as the header promises."