Skip to content

v2.12.1 - Production Build Tests

Choose a tag to compare

@localnerve localnerve released this 06 Sep 17:30
· 30 commits to main since this release
24e4f09

v2.12.1 — Production Build Test Mode

This release adds a production test mode: TEST_BUILD=prod builds and runs the full production app image — fingerprinted assets, minified bundles, hash-locked CSP, Trusted Types enforcement, HSTS via TLS — behind a TLS reverse proxy, and runs the entire Playwright suite against it. Dev-mode tests keep running exactly as before; prod mode exists to verify that what real users get is actually what we ship. The subtle build-vs-runtime dependencies this required are documented in Testing Architecture — Subtle Dependencies.

New

  • Production test pipeline — npm run test:prod (plus test:prod:firefox and test:prod:webkit) builds a production Docker image, serves it under TLS (Caddy in the devcontainer), and runs the full Playwright suite against it. A new runtime-prod-cover Dockerfile stage ships the production build with devDependencies so the server can run under c8 (npm run start:cover) and server-side coverage is collected from a production-like app, not just the instrumented dev build.
  • Mode-distinct image tags — dev and prod test images use separate tags (jam-build-test / jam-build-test-prod), so switching modes never silently reuses a stale, wrong-mode image. FORCE_BUILD=1 rebuilds either; in build-only runs it also short-circuits teardown for bare hosts.
  • Pre-build endpoint validation — prod mode resolves the authorizer and app endpoints before building (they are baked into the client bundle and CSP at build time) and validates them up front, failing fast with a clear message instead of a mysterious CSP violation later.
  • Testing architecture documentation — docs/testing-architecture.md documents the multi-tier testing dependencies: build-time vs runtime endpoint resolution, __authorizerOverrides, dev-vs-prod CSP enforcement differences, and the coverage pipeline.

Changed

  • Trusted Types rule for prod test mode — prod pages enforce require-trusted-types-for 'script' with a hash-locked CSP, which blocks DOM <script> injection into app pages (and the reserved default policy deliberately has no createScript hook, so no named policy can satisfy the sink either). The harness now runs all page-side code through page.evaluate() / page.addInitScript() — the browser automation protocol, which sits outside both script-src and Trusted Types enforcement. This is a standing rule: the test image's CSP stays byte-identical to a real deployment; we never weaken it to make tests pass.
  • Service worker coverage instrumentation is mode-gated — the production SW is now instrumented with SW_INSTRUMENT only when building a prod test image (Dockerfile: SW_INSTRUMENT=${TEST_BUILD:+1}, passed as a build arg by services.js). Real deployments never set TEST_BUILD, so they ship a clean, uninstrumented worker.
  • Brittle webspecs assertions made mode-agnostic — the "assets do not carry page-only security headers" test now reads stylesheet URLs from the rendered DOM (el.href) instead of regexing raw HTML, since prod minification strips attribute quotes; the web-manifest tests read the manifest link from the DOM and accept fingerprinted filenames.
  • Fingerprinting exclusions — llms.txt and everything under .well-known/ are now excluded from asset revisioning in src/build/revision.js, alongside the existing robots.txt/sitemap.xml exclusions, so well-known protocol endpoints keep their stable URLs in prod builds.

Housekeeping

  • Dev dependency updates: @playwright/test 1.63.x, eslint 10.10.x, sass 1.104.x, stylelint 17.15.x, autoprefixer 10.5.5, @localnerve/sass-asset-functions 7.17.x; assorted doc link fixes.

Deployment Notes

  • No changes to real deployments: production builds are untouched unless TEST_BUILD=prod is explicitly set, and that flag only affects the test image (SW instrumentation). The fingerprinting exclusions do change prod output — llms.txt and .well-known/* paths are no longer fingerprinted, which is the intended behavior.
  • Prod test mode requires TLS (HSTS and secure-context APIs are part of what it verifies): in the devcontainer the existing Caddy sites are used as-is; elsewhere, point BASE_URL and AUTHZ_URL at your TLS proxy's https URLs. Only one app container (dev or prod) can run at a time — they share a network alias and port.

What's Changed

  • @2.12.1 - Production Build Test Mode, fixes, updates by @localnerve in #117

Full Changelog: v2.12.0...v2.12.1