chore(devx): Phase 4 — font-pinned canonical rendering stack for visual tests - #403
Conversation
Phase 3 of the DevX plan: - setup_capybara.rb: CHROME_BIN and CHROMEDRIVER_PATH env overrides for machines where Chrome is not auto-discoverable (agent containers, custom installs). Proven end-to-end: color_system test green in a container using Playwright Chromium + a matching chromedriver. - Dirty-baseline guard promoted from bin/qtest to system-test load: every runner (bin/test, bin/dtest, rake tasks) now refuses to start while test/fixtures/screenshots is dirty - snap_diff rewrites the committed baselines in place on every run, so a dirty start is unjudgeable and one `git add -A` from committing corrupted baselines. Companion task `rake test:screenshots:reset`; bypass with ALLOW_DIRTY_SCREENSHOTS=1. Degrades to a no-op without git. - Force encoding "bom|utf-8" on all 11 File.read sites in lib/ (course_validators.rb, sync/post_storage.rb): validators crashed with "invalid byte sequence in US-ASCII" under non-UTF-8 locales. LANG=C bin/validate-course now passes. Verification: guard aborts on a dirtied PNG with the fix message and passes clean; reset task restores; course_validators unit suite green (32 runs); full validator run green under LANG=C. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01PXHeUErqoiyH9xN1mjC8cH
Phase 4 of the DevX plan. The linux/ screenshot baselines were recorded on Alpine/musl, which renders text 3-28% differently from every glibc Linux (dev machines, agent containers, CI runners) - the root cause of "25 failures on any non-blessed machine". Define ONE pinned stack and install it identically everywhere: - .dev/Dockerfile: ruby:3.4-alpine -> ruby:4.0-slim (glibc; also retires the third stray Ruby version). Pinned Chrome for Testing + matching chromedriver from .dev/cft-version (141.0.7390.37), wired via the CHROME_BIN/CHROMEDRIVER_PATH hooks from Phase 3. Browser runtime libs resolved across Debian's t64 package renames. - .dev/fonts.conf: deterministic fontconfig (hintslight, grayscale AA, no embedded bitmaps, no autohint) installed as /etc/fonts/local.conf in the image; fonts-noto-core + freefont + dejavu pinned as the font set. - bin/setup-test-env: installs the identical stack on bare-metal Linux (CfT cached in ~/.cache/jt-cft/<version>, same fonts + fontconfig); `eval "$(bin/setup-test-env --print-env)"` exports the browser env. Verified bare-metal in this container: CfT 141.0.7390.37 + matching driver install cleanly, fontconfig lands, and a system screenshot test runs green through the pinned stack. NOT yet done (this container cannot pull Docker Hub images through the agent proxy): build the new image and re-record linux/ baselines via FORCE_SCREENSHOT_UPDATE=true bin/dtest - that one-time re-baseline must ride this PR from a Docker-capable machine before merge. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01PXHeUErqoiyH9xN1mjC8cH
… cft-version and fonts.conf The repo .gitignore ignores all dotfiles (.*); tracked files under .dev/ survived, but the two NEW rendering-stack pins were silently excluded from the previous commit - the exact trap documented in .okf for .agents/. Added the !.dev negation and committed both files. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01PXHeUErqoiyH9xN1mjC8cH
|
Warning Review limit reached
Next review available in: 33 minutes Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available. How can I continue?After more reviews become available, a review can be triggered using the To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews. How do review limits work?CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability. For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window. Please refer docs for additional details. Review details⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (6)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01PXHeUErqoiyH9xN1mjC8cH
Summary
Phase 4 of the approved DevX plan — the fix for "
bin/rake test:criticalis red on every machine that isn't blessed". Root cause: thelinux/screenshot baselines are recorded by an Alpine/musl Docker image whose text rendering diverges 3–28% from every glibc Linux (the documented reason a CI screenshot job was removed in #386). This PR defines ONE pinned rendering stack and installs it identically in the Docker recorder and on bare metal:.dev/Dockerfile:ruby:3.4-alpine→ruby:4.0-slim(glibc — Chrome for Testing is glibc-only, so Alpine could never host the pinned browser; also retires the third stray Ruby version). Installs pinned Chrome for Testing + matching chromedriver from.dev/cft-version(141.0.7390.37), wired through theCHROME_BIN/CHROMEDRIVER_PATHhooks from Phase 3 (chore(devx): Phase 3 — test portability + baseline overwrite safety #400 — this PR is stacked on it and auto-retargets to master when it merges). Browser runtime libs are resolved across Debian'st64package renames so the build works on either side of the transition..dev/fonts.conf: deterministic fontconfig (hintslight, grayscale antialiasing, no embedded bitmaps, no autohint) installed as/etc/fonts/local.conf; font set pinned tofonts-noto-core+fonts-freefont-ttf+fonts-dejavu-core.bin/setup-test-env: installs the identical stack on bare-metal Linux — CfT cached under~/.cache/jt-cft/<version>/, same fonts and fontconfig;eval "$(bin/setup-test-env --print-env)"exports the browser env vars..gitignore:!.devnegation (the blanket.*rule silently dropped the two new pin files from the first commit — the documented.agents/trap, now recorded for.dev/too).Verified in this container (bare-metal side)
bin/setup-test-envend-to-end: CfT 141.0.7390.37 + matching chromedriver download and report their versions; fonts install; fontconfig lands at/etc/fonts/local.conf.color_system_test: 1 run, 3 assertions, 0 failures).This agent container cannot pull Docker Hub images through its proxy, so the image build and re-baseline could not run here:
bin/docker-rebuild(orbin/dc build t) — build the new Debian imageFORCE_SCREENSHOT_UPDATE=true bin/dtest— re-record alllinux/baselines on the new stackeval "$(bin/setup-test-env --print-env)" && bin/rake test:critical→ 0 environmental screenshot failuresUntil the re-baseline lands, the committed
linux/baselines are still Alpine-rendered andbin/dteston the new image will report diffs — expected, not a regression.Part of the phased DevX series: #397, #399, #400 (base), #401.
🤖 Generated with Claude Code
https://claude.ai/code/session_01PXHeUErqoiyH9xN1mjC8cH
Generated by Claude Code