fix(web): CI-owned wasm artifacts + e2e harness fixes #95

Merged
funman300 merged 3 commits from fix/web-ci-reproducible-and-e2e into master 2026-06-23 17:01:04 +00:00
Owner

Fixes the web build after the migration. Three commits.

1. Reproducible-ish wasm build (9c473d6)

build_wasm.sh now remaps the machine-specific source prefixes (cargo registry → /cargo, rustup std → /rustup, repo → /build) via CARGO_ENCODED_RUSTFLAGS, re-stating the getrandom_backend cfg (env rustflags replace .cargo/config.toml's). This removes embedded /home/<user>/... paths from the artifacts — good hygiene regardless of the gate.

2. E2e harness fixes (5b2b234)

The e2e suite ran for the first time once #94 fixed the webServer timeout: 14 passed, 4 failed — both pre-existing latent bugs:

  • __FERROUS_DEBUG__.serialize is not a function — game.js's /play-classic bridge was missing serialize() (play.html's had it; they drifted). Added it.
  • page.clock.tick is not a function — sinon name; Playwright's Clock API is page.clock.runFor(). Fixed all 6 calls.

3. CI owns wasm artifacts (2328643) — replaces the #93 freshness gate

The rebuild-and-diff gate could never pass: the Bevy wasm isn't byte-reproducible across machines. Confirmed exhaustively — identical rustc 1.95.0 / LLVM 22.1.2, identical flags / Cargo.lock / remapped paths still produced a 248 KB-different artifact in CI, while same-machine rebuilds (even from different paths) are bit-identical. The remaining variable is the build host itself (a dependency build script reading the host env). Pinning tool versions and remapping paths is necessary but not sufficient.

So CI becomes the single source of truth: the new web-wasm-rebuild workflow rebuilds pkg/ on every master change to a wasm-feeding crate and commits it back. The deployed artifacts can't silently rot, and contributors never hand-run build_wasm.sh. The pkg/ commit isn't in the rebuild workflow's trigger paths (no loop) but is in docker-build's, so the fresh wasm deploys. The false-failing web-wasm-freshness workflow is removed.

After merge

web-wasm-rebuild fires (build_wasm.sh changed), regenerates pkg/ in the CI environment, and commits it — superseding the local-machine bytes here. web-e2e then runs against the fresh wasm and should be 18/18.

🤖 Generated with Claude Code

Fixes the web build after the migration. Three commits. ## 1. Reproducible-ish wasm build (`9c473d6`) `build_wasm.sh` now remaps the machine-specific source prefixes (cargo registry → `/cargo`, rustup std → `/rustup`, repo → `/build`) via `CARGO_ENCODED_RUSTFLAGS`, re-stating the `getrandom_backend` cfg (env rustflags *replace* `.cargo/config.toml`'s). This removes embedded `/home/<user>/...` paths from the artifacts — good hygiene regardless of the gate. ## 2. E2e harness fixes (`5b2b234`) The e2e suite ran for the first time once #94 fixed the webServer timeout: 14 passed, 4 failed — both pre-existing latent bugs: - **`__FERROUS_DEBUG__.serialize is not a function`** — game.js's `/play-classic` bridge was missing `serialize()` (play.html's had it; they drifted). Added it. - **`page.clock.tick is not a function`** — sinon name; Playwright's Clock API is `page.clock.runFor()`. Fixed all 6 calls. ## 3. CI owns wasm artifacts (`2328643`) — replaces the #93 freshness gate The rebuild-and-diff gate could never pass: **the Bevy wasm isn't byte-reproducible across machines.** Confirmed exhaustively — identical rustc 1.95.0 / **LLVM 22.1.2**, identical flags / `Cargo.lock` / remapped paths still produced a **248 KB-different** artifact in CI, while same-machine rebuilds (even from different paths) are bit-identical. The remaining variable is the build host itself (a dependency build script reading the host env). Pinning tool versions and remapping paths is necessary but not sufficient. So **CI becomes the single source of truth**: the new `web-wasm-rebuild` workflow rebuilds `pkg/` on every master change to a wasm-feeding crate and commits it back. The deployed artifacts can't silently rot, and contributors never hand-run `build_wasm.sh`. The `pkg/` commit isn't in the rebuild workflow's trigger paths (no loop) but is in `docker-build`'s, so the fresh wasm deploys. The false-failing `web-wasm-freshness` workflow is removed. ## After merge `web-wasm-rebuild` fires (build_wasm.sh changed), regenerates `pkg/` in the CI environment, and commits it — superseding the local-machine bytes here. `web-e2e` then runs against the fresh wasm and should be 18/18. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
funman300 added 2 commits 2026-06-23 16:35:32 +00:00
The web-wasm-freshness gate (#93) false-failed because the Bevy wasm build
baked in machine-specific absolute source paths — the cargo registry
(/home/<user>/.cargo/registry/...), the rustup std sources (~/.rustup/...),
and this checkout — so CI's rebuild (under /workspace, /root) never matched the
committed bytes even with identical pinned tool versions.

build_wasm.sh now exports CARGO_ENCODED_RUSTFLAGS with three --remap-path-prefix
rules (cargo home -> /cargo, rustup home -> /rustup, repo -> /build) so the
embedded paths are identical on any machine. It re-states the
getrandom_backend cfg because a *_RUSTFLAGS env var replaces (not merges with)
.cargo/config.toml's target rustflags.

Regenerated all four artifacts with the remap applied — verified zero
machine-specific paths remain (only canonical /cargo + /rustup prefixes), which
is the precondition for the gate's byte-for-byte rebuild-and-diff to match
across machines.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
fix(web-e2e): expose serialize() on classic bridge; use real clock API
Web WASM Freshness / freshness (pull_request) Failing after 7m8s
5b2b234c54
Two latent test bugs surfaced once the e2e suite actually ran (it had been
red on the webServer startup timeout, so these never executed): 14 passed,
4 failed.

- game.js `__FERROUS_DEBUG__` was missing `serialize()` — play.html's bridge
  has it but the /play-classic bridge (which the resume/move-history tests
  use) drifted. Added it (the wasm SolitaireGame already exposes serialize()).
- game_behaviors.spec.js called `page.clock.tick()`, which is the sinon name;
  Playwright's Clock API method is `page.clock.runFor()`. Replaced all 6 calls.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
funman300 added 1 commit 2026-06-23 17:00:13 +00:00
The rebuild-and-diff freshness gate (#93) could never pass: the Bevy wasm
artifacts aren't byte-reproducible across machines. Confirmed conclusively —
identical rustc 1.95.0 / LLVM 22.1.2, identical flags, Cargo.lock and remapped
source paths still yield host-dependent output (CI's build was 248 KB smaller
than a local one), while same-machine rebuilds are bit-identical. Path
remapping (kept in build_wasm.sh) is necessary but not sufficient.

Make CI the single source of truth instead: `web-wasm-rebuild` rebuilds pkg/ on
every master change to a wasm-feeding crate and commits it back. The deployed
artifacts can't silently rot and contributors no longer hand-run build_wasm.sh.
The pkg/ commit isn't in this workflow's trigger paths (no loop) but is in
docker-build's, so the refreshed wasm deploys.

Removes the false-failing web-wasm-freshness workflow.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
funman300 changed title from fix(web): reproducible wasm builds + e2e harness fixes to fix(web): CI-owned wasm artifacts + e2e harness fixes 2026-06-23 17:00:33 +00:00
funman300 merged commit fc45b6d261 into master 2026-06-23 17:01:04 +00:00
Sign in to join this conversation.
No Reviewers
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: funman300/Ferrous-Solitaire#95