The preview JPEGs (~2.4 MiB, already compressed so gzip passed them straight through) leave the wasm data segment: a platform-free asset registry in op-editor-core tracks per-route Absent/Pending/Ready/Failed with single-flight and install-once semantics, the browser half fetches over ArrayBuffer XHR with managed-mode headers and a slot-wrapped callback so no synchronous failure can strand a route in Pending, and paint sites fall back to the existing placeholder when bytes are not (yet) there. Native keeps include_bytes verbatim. The staging script copies the asset dirs into pkg/assets/ — under /pkg/ because the hub frontend owns /assets/ — and the gate, CI workflow, and web image all run it and assert the layout. Bundle: 7.13 → 5.10 MiB gzip, so the tripwire returns to 6 MiB (85% occupancy); the sdk bundle keeps its own 8 MiB pending a real measurement. Also closes the final review test gaps: the owner-session fixture now returns a must-use lane guard (a dropped receiver made the saturated lane read as Disconnected, not Full) and seeds the daemon's baseline document so the hash check exercises the real path, and the closed write barrier has a direct multi-page active-page regression test.
161 lines
7.6 KiB
YAML
161 lines
7.6 KiB
YAML
name: WASM bundle build (#56 — real canvaskit deployable)
|
|
|
|
# Builds the REAL production web bundle (the `canvaskit` cargo feature, not the
|
|
# `web` compile stub), size-gates it, and uploads it as a reproducible
|
|
# deployable artifact. This is the CI counterpart of the local
|
|
# `tools/check-wasm-bundle.sh` developer gate.
|
|
#
|
|
# Why a NEW file instead of un-deferring the block in `rust-release.yml`
|
|
# / `rust-multiplatform.yml`: those deferred blocks describe the RETIRED
|
|
# from-scratch skia pipeline (`--features skia`, `vendor/skia-safe-op`,
|
|
# `crates/wasm-libc-shim`, brew-emscripten + EMSDK + the `.wasm.a` → `.a`
|
|
# symlink hack). That whole path was retired 2026-06-17 (see the workspace
|
|
# `Cargo.toml` note + `tools/check-wasm-bundle.sh` lines 57-59): the editor now
|
|
# renders through the official CanvasKit skia WASM, so the Rust bundle is pure
|
|
# logic and needs NO EMSDK / skia-safe / libc shim. Un-deferring the stale
|
|
# blocks would mean rewriting them top to bottom; a clean new job that mirrors
|
|
# the CURRENT local script is the honest option.
|
|
#
|
|
# Authoritative recipe mirrored from `tools/check-wasm-bundle.sh`:
|
|
# prerequisites: cargo, wasm-bindgen, wasm-opt, node, gzip (NO EMSDK)
|
|
# 1. cargo build -p op-host-web --target wasm32-unknown-unknown \
|
|
# --no-default-features --features canvaskit --release
|
|
# 2. wasm-bindgen --target web --out-dir crates/op-host-web/pkg <target.wasm>
|
|
# 3. assert 0 env.* imports (LinkError guard)
|
|
# 4. wasm-opt -Oz with the rustc-emitted WebAssembly feature flags, then
|
|
# gzip size <= ceiling (default 6291456 bytes = 6 MiB, overridable via
|
|
# STEP1B_SHELL_WASM_GZIP_LIMIT_BYTES)
|
|
# The job calls the script directly rather than duplicating that logic — the
|
|
# script already runs non-interactively (`set -euo pipefail`, exit 0/1/2) and
|
|
# is the single source of truth for the gate.
|
|
|
|
on:
|
|
pull_request:
|
|
paths:
|
|
- 'Cargo.toml'
|
|
- 'Cargo.lock'
|
|
- 'crates/**'
|
|
- 'deny.toml'
|
|
- 'tools/check-wasm-bundle.sh'
|
|
- '.github/workflows/wasm-bundle-build.yml'
|
|
push:
|
|
branches: ['**']
|
|
paths:
|
|
- 'Cargo.toml'
|
|
- 'Cargo.lock'
|
|
- 'crates/**'
|
|
- 'tools/check-wasm-bundle.sh'
|
|
- '.github/workflows/wasm-bundle-build.yml'
|
|
# Allow on-demand runs so a release can produce the artifact without a code
|
|
# change (e.g. to re-bundle against an updated toolchain).
|
|
workflow_dispatch:
|
|
|
|
jobs:
|
|
build-canvaskit-bundle:
|
|
name: build + size-gate canvaskit web bundle
|
|
runs-on: ubuntu-latest
|
|
steps:
|
|
- uses: actions/checkout@v4
|
|
with:
|
|
submodules: recursive
|
|
|
|
- uses: dtolnay/rust-toolchain@stable
|
|
with:
|
|
toolchain: '1.94'
|
|
targets: wasm32-unknown-unknown
|
|
|
|
- uses: Swatinem/rust-cache@v2
|
|
with:
|
|
shared-key: wasm-bundle-build
|
|
|
|
# The CanvasKit bundle is pure Rust + web_sys + serde — no skia-safe, no
|
|
# emscripten, no system GL libs. So the toolchain footprint is just the
|
|
# wasm-bindgen CLI + wasm-opt (binaryen) + node, exactly the prerequisites
|
|
# `tools/check-wasm-bundle.sh` asserts via its `need` checks.
|
|
- name: Install wasm-bindgen-cli (pinned to the locked version)
|
|
run: |
|
|
# Pin the CLI to the same version as the `wasm-bindgen` crate in
|
|
# Cargo.lock so the generated JS glue matches the linked runtime —
|
|
# a version skew between the two is the classic `wasm-bindgen`
|
|
# "schema version mismatch" panic at mount time. Read the locked
|
|
# version straight out of Cargo.lock (the `[[package]]` block whose
|
|
# name is exactly `wasm-bindgen`).
|
|
version="$(cargo metadata --format-version 1 --locked --no-deps >/dev/null 2>&1; \
|
|
awk '/^name = "wasm-bindgen"$/{found=1; next} found && /^version = /{gsub(/[" ]/,"",$3); print $3; exit}' Cargo.lock)"
|
|
if [ -z "$version" ]; then
|
|
echo "::error::could not resolve wasm-bindgen version from Cargo.lock"
|
|
exit 1
|
|
fi
|
|
echo "Installing wasm-bindgen-cli $version"
|
|
cargo install wasm-bindgen-cli --version "$version" --locked
|
|
|
|
- name: Install binaryen (pinned modern release) + headless server runtime deps
|
|
run: |
|
|
sudo apt-get update
|
|
sudo apt-get install -y \
|
|
pkg-config \
|
|
libfreetype-dev \
|
|
libfontconfig1-dev \
|
|
fonts-noto-cjk
|
|
# Ubuntu's apt `binaryen` is v108 (2022) — far too old for rustc
|
|
# 1.94's wasm feature set (memory.copy/fill from bulk-memory-opt),
|
|
# so `wasm-opt` rejects the bundle with "all used features should be
|
|
# allowed". Pin a modern release matching the local dev toolchain.
|
|
BINARYEN_VERSION=version_123
|
|
curl -fsSL \
|
|
"https://github.com/WebAssembly/binaryen/releases/download/${BINARYEN_VERSION}/binaryen-${BINARYEN_VERSION}-x86_64-linux.tar.gz" \
|
|
| tar -xz
|
|
echo "${GITHUB_WORKSPACE}/binaryen-${BINARYEN_VERSION}/bin" >> "$GITHUB_PATH"
|
|
"${GITHUB_WORKSPACE}/binaryen-${BINARYEN_VERSION}/bin/wasm-opt" --version
|
|
|
|
- name: Verify node + gzip + Chrome are present (script prerequisites)
|
|
run: |
|
|
node --version
|
|
gzip --version | head -n1
|
|
google-chrome --version || chromium --version || chromium-browser --version
|
|
|
|
# Single source of truth: run the local gate script verbatim. It performs
|
|
# cargo build (canvaskit) -> wasm-bindgen --target web -> 0-env-import
|
|
# assert -> wasm-opt -Oz with rustc's WebAssembly feature flags -> gzip
|
|
# size <= ceiling, and exits non-zero on any breach, which fails the job.
|
|
# The ceiling default (6 MiB gzip) lives in the script; override here only
|
|
# if a release intentionally re-baselines.
|
|
- name: Build + size-gate the canvaskit bundle
|
|
run: bash tools/check-wasm-bundle.sh
|
|
|
|
- name: Browser smoke the canvaskit bundle + daemon
|
|
run: OPENPENCIL_SKIP_WASM_BUILD=1 bash tools/check-web-browser-smoke.sh
|
|
|
|
# Assemble the deployable layout the daemon's `web_static.rs` expects: the
|
|
# wasm-bindgen `pkg/` output PLUS the vendored CanvasKit artifact under a
|
|
# `canvaskit/` subdir, all inside a single `web-bundle/` directory. This
|
|
# mirrors the `<exe_dir>/web-bundle` + `web-bundle/canvaskit` resolution
|
|
# order in `crates/op-host-services/src/web_static.rs`.
|
|
#
|
|
# `pkg/` also carries `assets/` — the preview JPEGs the wasm bundle no
|
|
# longer embeds and the browser fetches from `/pkg/assets/…` (staged by
|
|
# `tools/stage-web-assets.sh`, which the gate script above runs). The
|
|
# assertion below is what stops a bundle shipping without them.
|
|
- name: Assemble deployable web-bundle/
|
|
run: |
|
|
set -euo pipefail
|
|
rm -rf web-bundle
|
|
mkdir -p web-bundle
|
|
cp -R crates/op-host-web/pkg/. web-bundle/
|
|
cp -R crates/op-host-web/assets/canvaskit web-bundle/canvaskit
|
|
test -d web-bundle/assets/prompt_center_previews \
|
|
|| { echo "::error::web-bundle is missing assets/prompt_center_previews"; exit 1; }
|
|
echo "web-bundle contents:"
|
|
find web-bundle -maxdepth 2 -type f | sort
|
|
echo "staged runtime assets: $(find web-bundle/assets -type f | wc -l) files"
|
|
|
|
- name: Upload deployable web-bundle artifact
|
|
uses: actions/upload-artifact@v4
|
|
with:
|
|
name: op-web-bundle
|
|
path: web-bundle
|
|
if-no-files-found: error
|
|
# The bundle is deterministic from the inputs; keep it briefly so a
|
|
# release / Docker build can pull it without rebuilding.
|
|
retention-days: 14
|