igneum/infra/build-server/overlap-browser.sh
igneum-labs 9336a2b725 Text-overlap sweep (tools/ci/overlap-check.mjs) and the first fixes it found: the home hero's step pill no longer sits on the caption (pill at the corners' baseline, caption above it, at every width), the address page title wraps, the ledger's status badges wrap, the litepaper's mobile contents bar bleeds by the real gutter, the verify harness table scrolls (7 October 2026, 15:5x UK)
The sweep renders every served page in a headless Chromium at 390, 768, 1024, 1280 and 1600 in light and dark (the hero at rest and at each step), reads every visible run of text and flags text covered by another element, clipped by overflow hidden, or past the viewport; a fixture with one deliberate overlap of each kind is flagged before any sweep is trusted. It runs on a build box when this machine has no browser (infra/build-server/overlap-browser.sh installs Chromium there without root).

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-10-07 13:55:13 +00:00

57 lines
4 KiB
Bash

#!/usr/bin/env bash
# A headless Chromium for the text-overlap sweep (tools/ci/overlap-check.mjs) on a build box, without root. The build user
# has no sudo, so Playwright's `install --with-deps` cannot add the X and GTK libraries Chromium links; this script downloads
# the same Ubuntu packages with apt-get download (no root needed), unpacks them into a sysroot and points LD_LIBRARY_PATH
# at it, plus two font packages behind a private fontconfig file (the box ships no fonts at all: fc-list is empty, and
# text with no font has no width). Idempotent; re-run after a box re-provision.
#
# infra/build-server/overlap-browser.sh on the box (run-from-mac.sh copies and runs it; or ssh and run by hand)
# . /srv/builds/_bin/overlap/env.sh what a caller sources before `node tools/ci/overlap-check.mjs`
#
# Installed 7 October 2026 on igneum-build-2 (Ubuntu 24.04.5, node 22): playwright 1.56 with chromium 1194 (headless shell
# and full), 36 packages in the sysroot, Liberation and DejaVu fonts. A page with 20 px sans-serif text measured 23 px high
# through it, so glyphs have real metrics there.
set -euo pipefail
ROOT="${OVERLAP_ROOT:-/srv/builds/_bin/overlap}"
PW_VERSION="${PW_VERSION:-1.56}"
mkdir -p "$ROOT/debs" "$ROOT/sysroot" "$ROOT/fonts" "$ROOT/fc-cache"
cd "$ROOT"
[ -f package.json ] || npm init -y >/dev/null
if ! node -e "require('playwright')" 2>/dev/null; then npm i --no-audit --no-fund "playwright@$PW_VERSION" | tail -1; fi
# the browser download (Playwright keeps it under ~/.cache/ms-playwright; a second run finds it and does nothing)
PLAYWRIGHT_SKIP_VALIDATE_HOST_REQUIREMENTS=1 npx playwright install chromium 2>&1 | tail -1 || true
PKGS="libatk1.0-0t64 libatk-bridge2.0-0t64 libatspi2.0-0t64 libx11-6 libxcomposite1 libxdamage1 libxext6 libxfixes3 libxrandr2 libgbm1 libxcb1
libasound2t64 libxrender1 libxau6 libxdmcp6 libwayland-server0 libwayland-client0 libcups2t64 libcairo2 libpango-1.0-0 libpangocairo-1.0-0
libpangoft2-1.0-0 libharfbuzz0b libfribidi0 libthai0 libdatrie1 libpixman-1-0 libxcb-render0 libxcb-shm0 libavahi-client3 libavahi-common3
libxi6 libfontconfig1 libgraphite2-3 fonts-liberation fonts-dejavu-core"
cd "$ROOT/debs"
# shellcheck disable=SC2086
apt-get download $PKGS 2>&1 | grep -v '^Get:' | tail -1 || true
for d in ./*.deb; do dpkg -x "$d" "$ROOT/sysroot"; done
find "$ROOT/sysroot" -name '*.ttf' -exec cp -n {} "$ROOT/fonts/" \;
cat >"$ROOT/fonts.conf" <<EOF
<?xml version="1.0"?><!DOCTYPE fontconfig SYSTEM "fonts.dtd">
<fontconfig><dir>$ROOT/fonts</dir><cachedir>$ROOT/fc-cache</cachedir>
<alias><family>sans-serif</family><prefer><family>Liberation Sans</family></prefer></alias>
<alias><family>serif</family><prefer><family>Liberation Serif</family></prefer></alias>
<alias><family>monospace</family><prefer><family>Liberation Mono</family></prefer></alias></fontconfig>
EOF
cat >"$ROOT/env.sh" <<EOF
export LD_LIBRARY_PATH=$ROOT/sysroot/usr/lib/x86_64-linux-gnu\${LD_LIBRARY_PATH:+:\$LD_LIBRARY_PATH}
export FONTCONFIG_FILE=$ROOT/fonts.conf
export NODE_PATH=$ROOT/node_modules\${NODE_PATH:+:\$NODE_PATH}
export IGNEUM_PLAYWRIGHT_DIR=$ROOT
EOF
# shellcheck disable=SC1091
. "$ROOT/env.sh"
SHELL_BIN="$(ls -d "$HOME"/.cache/ms-playwright/chromium_headless_shell-*/chrome-linux/headless_shell | tail -1)"
if ldd "$SHELL_BIN" | grep -q 'not found'; then echo "overlap-browser: libraries still missing:"; ldd "$SHELL_BIN" | grep 'not found'; exit 1; fi
cat >"$ROOT/smoke.cjs" <<'EOF2'
const { chromium } = require("playwright");
(async () => { const b = await chromium.launch({ args: ["--no-sandbox"] }); const p = await b.newPage();
await p.setContent('<p id=a style="font:20px sans-serif">Hello overlap world</p>');
const h = await p.evaluate(() => document.getElementById("a").getBoundingClientRect().height); await b.close();
if (!(h > 15 && h < 40)) { console.error("overlap-browser: text has no metrics (height " + h + ")"); process.exit(1); }
console.log("overlap-browser: ready at " + __dirname + " (20 px text measures " + h + " px; source " + __dirname + "/env.sh)"); })();
EOF2
cd "$ROOT" && node smoke.cjs