mirror of
https://github.com/tiennm99/tsuki.git
synced 2026-05-24 12:26:42 +00:00
test: expand smoke suite to 32 checks + Hugo CI matrix
scripts/smoke-tests.sh: - Per-kind CSS budget (home/post/list/archives/search), each ≤ 4200 B gz - theme-color light/dark meta tags - aria-pressed SSR on theme-toggle - breadcrumbs nav + BreadcrumbList JSON-LD presence on post, absence on home - prev/next nav + rel=prev attribute - linkToSection aria-label on heading anchors - Speculation Rules absent by default - llm.txt artifact present - Pagefind UI preload-swap pattern on /search/ - Giscus preconnect gating (absent when comments disabled) - Per-kind CSS bundle routing (home loads home.css but not single.css; post loads single.css but not home.css) - code-copy.js gating (post loads it, home does not) .github/workflows/pages.yml: - Build matrix on Hugo 0.146.0 (theme.toml floor) + 0.154.0 (current). Smoke + htmltest run on both. Artifact upload + deploy gated on the current version only. - Drop the redundant standalone CSS-budget step; smoke-tests.sh now enforces per-kind budgets.
This commit is contained in:
@@ -17,8 +17,11 @@ concurrency:
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
env:
|
||||
HUGO_VERSION: 0.154.0
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
# Floor (theme.toml min_version) + current pinned. Deploy artifact is uploaded only from the current version.
|
||||
hugo: ["0.146.0", "0.154.0"]
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
with:
|
||||
@@ -28,7 +31,7 @@ jobs:
|
||||
- name: Setup Hugo (extended)
|
||||
uses: peaceiris/actions-hugo@v3
|
||||
with:
|
||||
hugo-version: ${{ env.HUGO_VERSION }}
|
||||
hugo-version: ${{ matrix.hugo }}
|
||||
extended: true
|
||||
|
||||
- name: Setup Node
|
||||
@@ -47,21 +50,7 @@ jobs:
|
||||
- name: Build Pagefind index
|
||||
run: npx pagefind --site exampleSite/public
|
||||
|
||||
- name: Assert CSS bundle budget (≤ 4200 B gz)
|
||||
run: |
|
||||
css=$(find exampleSite/public -name 'tsuki.bundle.*.css' -print -quit)
|
||||
if [ -z "$css" ]; then
|
||||
echo "::error::Could not locate tsuki.bundle.*.css under exampleSite/public"
|
||||
exit 1
|
||||
fi
|
||||
sz=$(gzip -9 -c "$css" | wc -c)
|
||||
echo "tsuki bundle gz: ${sz} B (limit 4200)"
|
||||
if [ "$sz" -gt 4200 ]; then
|
||||
echo "::error::CSS bundle exceeds 4200 B gz budget (was ${sz} B)"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
- name: Smoke tests (SEO + a11y + features regression guard)
|
||||
- name: Smoke tests (SEO + a11y + per-kind CSS budget + features regression guard)
|
||||
run: ./scripts/smoke-tests.sh exampleSite/public
|
||||
|
||||
- name: htmltest (broken internal links + HTML5 validation)
|
||||
@@ -71,6 +60,8 @@ jobs:
|
||||
config: .htmltest.yml
|
||||
|
||||
- name: Upload artifact
|
||||
# Only upload from the current Hugo version; the floor-version run is for compatibility check.
|
||||
if: matrix.hugo == '0.154.0'
|
||||
uses: actions/upload-pages-artifact@v5
|
||||
with:
|
||||
path: exampleSite/public
|
||||
|
||||
+73
-11
@@ -61,21 +61,83 @@ assert "reading time byline" 'reading-time' "$po
|
||||
# Discovery (Phase 5)
|
||||
assert "related-posts aside" 'class=related-posts' "$post"
|
||||
|
||||
# CSS budget (Phase 1) — duplicates the workflow assert; included so local runs catch it too.
|
||||
css=$(find "$public_dir" -name 'tsuki.bundle.*.css' -print -quit || true)
|
||||
if [ -n "$css" ]; then
|
||||
sz=$(gzip -9 -c "$css" | wc -c)
|
||||
if [ "$sz" -gt 4200 ]; then
|
||||
echo "::error::CSS bundle gz ${sz} B exceeds 4200 B budget"
|
||||
fail=1
|
||||
else
|
||||
echo " ok [CSS budget] ${sz} B / 4200 B"
|
||||
fi
|
||||
# v0.3.0 feature surface
|
||||
assert "theme-color meta (light)" 'name=theme-color content="#fbfaf7"' "$home"
|
||||
assert "theme-color meta (dark)" 'name=theme-color content="#14151a"' "$home"
|
||||
assert "aria-pressed SSR" 'data-theme-toggle [^>]*aria-pressed=false|aria-pressed=false [^>]*data-theme-toggle' "$home"
|
||||
assert "breadcrumbs nav on post" 'class=breadcrumbs' "$post"
|
||||
assert "BreadcrumbList JSON-LD" '"@type":"BreadcrumbList"' "$post"
|
||||
assert "no breadcrumbs on home" 'class=breadcrumbs' "$home" 0
|
||||
assert "prev/next nav" 'class=prev-next' "$post"
|
||||
assert "rel=prev on post" 'rel=prev' "$post"
|
||||
assert "linkToSection aria-label" 'class=heading-anchor [^>]*aria-label' "$post"
|
||||
assert "no speculationrules by default" 'speculationrules' "$home" 0
|
||||
|
||||
# llm.txt artifact
|
||||
if [ -f "$public_dir/llm.txt" ]; then
|
||||
echo " ok [llm.txt artifact present]"
|
||||
else
|
||||
echo "::error::Could not locate tsuki.bundle.*.css"
|
||||
echo "::error::FAIL [llm.txt artifact present] expected $public_dir/llm.txt"
|
||||
fail=1
|
||||
fi
|
||||
|
||||
# Pagefind preload-swap on search (rel=preload as=style)
|
||||
if [ -f "$public_dir/search/index.html" ]; then
|
||||
assert "Pagefind preload swap" 'rel=preload as=style href=[^ >]*pagefind' "$public_dir/search/index.html"
|
||||
fi
|
||||
|
||||
# Giscus preconnect: comments disabled in demo → must NOT emit
|
||||
assert "no giscus preconnect (disabled)" 'preconnect[^>]*giscus' "$post" 0
|
||||
|
||||
# Per-page CSS bundle gating: home gets home.css, post does NOT
|
||||
assert "home loads home.css" 'home\.min\.[0-9a-f]+\.css' "$home"
|
||||
assert "post does not load home.css" 'home\.min\.[0-9a-f]+\.css' "$post" 0
|
||||
assert "post loads single.css" 'tsuki\.single\.min\.[0-9a-f]+\.css' "$post"
|
||||
assert "home does not load single.css" 'tsuki\.single\.min\.[0-9a-f]+\.css' "$home" 0
|
||||
|
||||
# code-copy.js gate: only post pages should load it
|
||||
assert "post loads code-copy.js" 'code-copy\.[0-9a-f]+\.js' "$post"
|
||||
assert "home does not load code-copy.js" 'code-copy\.[0-9a-f]+\.js' "$home" 0
|
||||
|
||||
# Per-kind CSS budget — every page kind's total stylesheet payload ≤ 4200 B gz.
|
||||
# Iterate over each kind's representative HTML, extract its <link rel=stylesheet> CSS,
|
||||
# sum gzipped sizes (excluding third-party like /pagefind/), assert each kind under budget.
|
||||
check_kind_css_budget() {
|
||||
local label="$1" html="$2"
|
||||
[ -f "$html" ] || { echo " skip [$label CSS budget] no HTML at $html"; return; }
|
||||
local total=0 missing=0
|
||||
while IFS= read -r href; do
|
||||
# strip query string + leading slash + baseURL prefix
|
||||
local rel="${href#/tsuki/}"
|
||||
rel="${rel#/}"
|
||||
local fpath="$public_dir/$rel"
|
||||
if [ -f "$fpath" ]; then
|
||||
local sz
|
||||
sz=$(gzip -9 -c "$fpath" | wc -c)
|
||||
total=$((total + sz))
|
||||
else
|
||||
missing=$((missing + 1))
|
||||
fi
|
||||
done < <(grep -oE 'rel=stylesheet href=[^ >]+\.css' "$html" | grep -v '/pagefind/' | sed -E 's|rel=stylesheet href=||')
|
||||
if [ "$total" -gt 4200 ]; then
|
||||
echo "::error::[$label CSS budget] ${total} B gz exceeds 4200 B"
|
||||
fail=1
|
||||
else
|
||||
echo " ok [$label CSS budget] ${total} B / 4200 B (${missing} third-party skipped)"
|
||||
fi
|
||||
}
|
||||
|
||||
# Pick representative HTML per kind from the build.
|
||||
list_html="$public_dir/post/index.html"
|
||||
search_html="$public_dir/search/index.html"
|
||||
archives_html="$public_dir/archives/index.html"
|
||||
|
||||
check_kind_css_budget "home" "$home"
|
||||
check_kind_css_budget "post" "$post"
|
||||
[ -f "$list_html" ] && check_kind_css_budget "list" "$list_html"
|
||||
[ -f "$archives_html" ] && check_kind_css_budget "archives" "$archives_html"
|
||||
[ -f "$search_html" ] && check_kind_css_budget "search" "$search_html"
|
||||
|
||||
echo
|
||||
[ "$fail" -eq 0 ] && echo "All smoke tests passed." || echo "Smoke tests failed."
|
||||
exit "$fail"
|
||||
|
||||
Reference in New Issue
Block a user