Skip to content

chore(release): prepare v0.1.5 fix-forward #673

chore(release): prepare v0.1.5 fix-forward

chore(release): prepare v0.1.5 fix-forward #673

Workflow file for this run

# sq-ymr2e.10 — ADVISORY CI lane: visual-regression key layouts in the pinned container.
#
# Runs the Playwright toHaveScreenshot suite (site/e2e/visual/**) against the committed
# Linux-only baselines. The renderer is the DIGEST-PINNED official Playwright container —
# site/scripts/vr.sh wraps `docker run` on that image, so this job, `npm run vr` on a dev box,
# and the baselines themselves all rasterize in the byte-identical environment
# (research/web-gui-test-program.md §4). The wasm build runs on the HOST (normal toolchain +
# cargo cache); only the browser/render step is containerised.
#
# ADVISORY (continue-on-error on the visual step; the whole word `advisory` in the job NAME also
# is declared in .github/advisory-registry.json). Per the checked-in gating/probation policy
# `.github/E2E-GATING-POLICY.md` (bead sq-ymr2e.12; design §6.3) the visual subset promotes
# SEPARATELY and LAST — pixel snapshots are the most brittleness-prone lane, so it earns its own
# probation window (50 consecutive green runs spanning ≥10 distinct PRs, or two weeks — whichever
# is longer) AFTER the functional lanes are stable. It is NOT a required check and never
# enters the merge queue. Promotion is the one-line flip in §4 of that policy. On failure it
# uploads the readable *-actual/*-expected/*-diff artifacts.
#
# SCOPE: path-scoped to site/** + the root workspace lock inputs (same reasoning as
# site-e2e.yml — `npm ci` resolves from the root lockfile) + this workflow. A Rust-/docs-only
# PR never triggers this lane.
name: site-visual
on:
pull_request:
# + ready_for_review so the un-draft moment re-runs this lane.
types: [opened, synchronize, reopened, ready_for_review]
paths:
- "site/**"
- "package.json"
- "package-lock.json"
- ".github/workflows/site-visual.yml"
push:
branches: [main]
paths:
- "site/**"
- "package.json"
- "package-lock.json"
- ".github/workflows/site-visual.yml"
# Least-privilege default (Scorecard TokenPermissions): read-only; this lane never writes.
permissions:
contents: read
# One in-flight run per PR/branch; cancel a superseded run.
concurrency:
group: site-visual-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: true
jobs:
site-visual:
name: visual key layouts (container-pinned, advisory)
runs-on: ubuntu-latest
timeout-minutes: 35
defaults:
run:
working-directory: site
steps:
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
# Node 22 — npm cache keys off the REPO-ROOT lockfile (site/ is a workspace member).
- uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
with:
node-version: 22
cache: npm
cache-dependency-path: package-lock.json
- name: Install npm dependencies (from the repo-root workspace lock)
run: npm ci
# Rust stable + wasm32 + wasm-pack: the /try workbench capture waits on the REAL
# engine-ready state, so the lean wasm bundle is built from source (mirrors
# site-e2e-hero.yml, sharing its cargo cache key family for a warm rebuild).
- uses: dtolnay/rust-toolchain@29eef336d9b2848a0b548edc03f92a220660cdb8 # stable
with:
targets: wasm32-unknown-unknown
- uses: Swatinem/rust-cache@e18b497796c12c097a38f9edb9d0641fb99eee32 # v2
with:
# CI-economy (2026-07-18 directive 2b): this wasm lane compiles
# the same sparq-wasm dependency stack as the other js/pages/gui/site wasm
# lanes — ONE shared dependency cache across them keeps demand inside the
# 10 GB Actions-cache budget (sq-3sbrr doctrine: save on push-to-main
# only, so PR runs are restore-only and never churn the shared budget).
shared-key: site-wasm
save-if: ${{ github.ref == 'refs/heads/main' }}
# Prebuilt, SHA-pinned, exactly-versioned wasm-pack (sq-khm3f, #5776): a
# `cargo install` recompiles it from crates.io and flakes on a registry blip.
- name: Install wasm-pack
uses: jetli/wasm-pack-action@0d096b08b4e5a7de8c28de67e11e945404e9eefa # v0.4.0
with:
version: v0.15.0
# PR #3511 review finding 5: redundant second cargo cache REMOVED —
# the Swatinem/rust-cache above (shared-key: site-wasm) already caches
# ~/.cargo/registry + ~/.cargo/git + the workspace target/ across the js/pages/
# gui/site wasm lanes, restore-only off main. The former PR-scoped
# `actions/cache` covered the same paths and only churned the shared 10 GB
# Actions-cache budget with a duplicate PR-scoped copy.
- name: Build lean wasm bundle
run: cd ../js && npm run build:wasm:lean
- name: Sync wasm bundle into site/public/wasm/
run: npm run sync-wasm
# #3773 — the determinism grep gate (whole e2e/ tree, visual specs included) is
# HARD-gated in site-e2e-foundation.yml's `determinism-gate` job, on the same `site/**`
# path filter. It used to run HERE too, inside this advisory job, where the "HARD — must
# pass" comment it carried was simply false; a duplicate non-gating run adds nothing.
# The visual suite, rendered inside the digest-pinned Playwright container (vr.sh pulls
# the image by digest; the run fails fast if the locked @playwright/test version drifted
# from the pin). ADVISORY: continue-on-error per §6.3 until the lane earns gating.
- name: Visual key layouts vs committed baselines (digest-pinned container)
id: vr
run: npm run vr
continue-on-error: true
# Readable failure artifacts: Playwright writes *-actual/*-expected/*-diff PNGs + traces
# under test-results/ when a comparison fails.
- name: Upload visual diff artifacts
if: steps.vr.outcome == 'failure'
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: visual-regression-diffs
path: |
site/test-results/
site/playwright-report/
if-no-files-found: ignore
retention-days: 14
# Surface the advisory verdict in the job summary (the job itself stays green — §6.3).
- name: Advisory verdict
if: always()
run: |
if [ "${{ steps.vr.outcome }}" = "failure" ]; then
echo "::warning::site-visual (ADVISORY) failed — inspect the visual-regression-diffs artifact. Intentional change? Refresh baselines in this PR: npm run vr:update"
echo "## site-visual: ADVISORY FAIL — see the visual-regression-diffs artifact" >> "$GITHUB_STEP_SUMMARY"
else
echo "## site-visual: baselines match" >> "$GITHUB_STEP_SUMMARY"
fi