From 3b0a8fe33b3f4abc03f46b8ae0873aed3e2a2f26 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tao=20Bojl=C3=A9n?= Date: Sat, 20 Jun 2026 12:43:41 +0100 Subject: [PATCH] docs(spec): record confirmed CI browser recipe from green spike Spike proved nix chromium + executablePath + dejavu_fonts works headless in Tangled CI (DOM, layout, computed style all functional). Replace the spike-first risk section with the settled recipe. Co-Authored-By: Claude Opus 4.8 (1M context) --- .../specs/2026-06-20-a11y-axe-ci-design.md | 47 +++++++++++++------ 1 file changed, 33 insertions(+), 14 deletions(-) diff --git a/docs/superpowers/specs/2026-06-20-a11y-axe-ci-design.md b/docs/superpowers/specs/2026-06-20-a11y-axe-ci-design.md index daa7d53..48630b0 100644 --- a/docs/superpowers/specs/2026-06-20-a11y-axe-ci-design.md +++ b/docs/superpowers/specs/2026-06-20-a11y-axe-ci-design.md @@ -252,6 +252,9 @@ stays fast and untouched. Add a **separate** workflow `.tangled/workflows/e2e.ym that runs in parallel and also gates PRs. It runs the **whole** Playwright suite (a11y + regression), not just axe: +**nixery deps:** `erlang`, `nodejs`, `chromium`, `fontconfig`, `dejavu_fonts`, +`cacert`, plus the Elixir-1.20 fetch the existing `ci.yml` already does. + 1. Build the production docs artifact (mirrors the Dockerfile build stage): `MIX_ENV=docs`, `mix deps.get`, asset deps (`cd assets && npm install`), `mix assets.build`, `mix compile`, `MIX_ENV=docs mix release shadix_docs`. @@ -261,26 +264,42 @@ that runs in parallel and also gates PRs. It runs the **whole** Playwright suite (Release endpoint has `server: true`, `check_origin: false`, no watchers, no code reloader — a genuine production instance.) 3. Wait for `http://localhost:8080/` to return 200 (poll with a timeout). -4. `cd test/e2e && npm ci && npx playwright test` against `baseURL=:8080`. +4. Provision fonts (see below), then + `cd test/e2e && npm ci && npx playwright test` against `baseURL=:8080`. Non-zero exit → red build (loud failure). **Not Docker.** The Tangled engine is `nixery` (builds a nix container per job); it has no Docker daemon, so building/running the image in CI is not easier. The Dockerfile remains the reference recipe; CI runs the same `mix` steps natively. -### Top implementation risk — spike first - -The nixery job has **no browser**. Headless Chromium on Nix typically needs -`nixpkgs.playwright-driver.browsers` + `PLAYWRIGHT_BROWSERS_PATH` (and matching -`@playwright/test` version) rather than `npx playwright install --with-deps`, -which fails to provision system libs on Nix. - -**Spike this in isolation before building anything else.** Stand up a minimal -Tangled job that just launches headless Chromium and loads a page. If it can't be -made to work, the CI half changes (fallback: run Playwright from its official -container image / a pinned browser image instead of the nixery engine). Everything -else (specs, endpoint, scope hook) is independent of how the browser is -provisioned and can proceed regardless. +### Browser provisioning — CONFIRMED via spike (2026-06-20) + +A throwaway spike (`a11y-ci-spike` branch, `.tangled/workflows/a11y-spike.yml` + +`test/e2e-spike/`) proved the recipe end-to-end in the real Tangled CI. **This is +settled, not a risk.** The recipe: + +- Pull **`chromium`** from `nixpkgs-unstable` and drive it via Playwright's + `executablePath = $(command -v chromium)` — **not** `playwright install` + (which can't provision system libs on Nix) and **not** `playwright-driver` + version-matching. Set `PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD=1`. +- Launch args: `--no-sandbox --disable-dev-shm-usage` (CI container can't sandbox). +- **Fonts are mandatory.** The minimal nix image ships none, so Chromium lays + text out at **zero height** (empty `innerText`) and color-contrast checks would + be meaningless. Add `fontconfig` + `dejavu_fonts`, copy the font dir into + `$HOME/.fonts`, write a minimal `FONTCONFIG_FILE` pointing at it + a writable + cachedir, run `fc-cache -f`. (Env doesn't persist across Tangled steps, so do + font setup in the same step as the Playwright run.) + +Confirmed working: DOM content, **layout** (non-zero box), and **computed style +resolution** — exactly what axe's color-contrast and visibility rules require. +Spike findings folded into the harness: assert via `textContent` / web-first +assertions, never layout-dependent `innerText`. The `playwright.config.mjs` +`launchOptions` carries `executablePath` (from env) + the two args; `global-setup` +or the workflow handles fonts. + +> Possible later refinement: swap `dejavu_fonts` for the docs site's actual UI +> font so rendered widths match production more closely. Not needed for axe +> correctness — colors, not glyph shapes, drive contrast — so out of scope now. ## Files -- 2.51.2