Document registered fonts and prove the CJK path on Windows CI #399
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: CI | |
| on: | |
| pull_request: | |
| push: | |
| branches: | |
| - main | |
| permissions: | |
| contents: read | |
| jobs: | |
| zig: | |
| name: Zig Core | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - uses: mlugg/setup-zig@v2 | |
| with: | |
| version: 0.16.0 | |
| - uses: actions/setup-node@v4 | |
| with: | |
| node-version: 22 | |
| # The TypeScript core suites transpile at build/test time; without | |
| # node they skip silently, so CI must provide it. | |
| - run: npm ci --prefix packages/core | |
| - run: zig build test | |
| - run: zig build validate | |
| macos-webview: | |
| name: macOS WebView | |
| runs-on: macos-14 | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - uses: mlugg/setup-zig@v2 | |
| with: | |
| version: 0.16.0 | |
| - run: zig build test-webview-system-link | |
| - run: zig build test-webview-smoke | |
| # Signed-package seal pin: an ad-hoc signed package must pass | |
| # codesign --verify --strict (macOS runners are the only tier with | |
| # codesign; the step skips loudly anywhere else). | |
| - run: zig build test-package-signing | |
| # Shared macos-14 runners are far noisier than a dev box (the second | |
| # CI run measured a 576 ms automation-ready against the 500 ms local | |
| # ceiling), so widen the smoke budgets here instead of weakening the | |
| # local defaults. NATIVE_SDK_SMOKE_BUDGET_MS raises the first-frame latency | |
| # budget and the automation-ready ceiling together; every correctness | |
| # assertion in the smokes stays strict. | |
| - run: zig build test-gpu-dashboard-smoke | |
| env: | |
| NATIVE_SDK_SMOKE_BUDGET_MS: "1500" | |
| - run: zig build test-gpu-components-smoke | |
| env: | |
| NATIVE_SDK_SMOKE_BUDGET_MS: "1500" | |
| macos-gpu-perf: | |
| name: macOS GPU Perf | |
| runs-on: macos-14 | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - uses: mlugg/setup-zig@v2 | |
| with: | |
| version: 0.16.0 | |
| # Percentile perf check: 5 cold launches asserting p90 | |
| # first-frame latency under NATIVE_SDK_PERF_BUDGET_MS, then 5 steady-state | |
| # widget clicks asserting p90 input latency under NATIVE_SDK_PERF_INPUT_BUDGET_MS. | |
| # Its own job so a shared-runner slowdown is visible in isolation and | |
| # never blocks the correctness smokes. | |
| # Shared macos-14 runners are far noisier than a dev box (first CI run | |
| # measured a 581 ms cold-start outlier against the 300 ms default), so | |
| # widen the budgets here instead of weakening the local defaults: this | |
| # job exists to catch step-function regressions, not runner noise. | |
| - run: zig build test-gpu-dashboard-perf | |
| env: | |
| NATIVE_SDK_PERF_BUDGET_MS: "1500" | |
| NATIVE_SDK_PERF_INPUT_BUDGET_MS: "500" | |
| linux-webkitgtk: | |
| name: Linux WebKitGTK | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - uses: mlugg/setup-zig@v2 | |
| with: | |
| version: 0.16.0 | |
| - name: Install WebKitGTK dependencies | |
| run: sudo apt-get update && sudo apt-get install -y libgtk-4-dev libwebkitgtk-6.0-dev | |
| - run: zig build test-webview-system-link -Dplatform=linux | |
| # Declare-to-use, proven on real Linux executables WITH the | |
| # WebKitGTK dev package installed — the seam, not the environment: | |
| # the native-only ui-inbox binary must carry no libwebkitgtk | |
| # DT_NEEDED entry and no webkit_/jsc_ dynamic symbol even though | |
| # the headers were right there, while the webview example must | |
| # keep them. (The environment half — building native-only on a | |
| # runner with no WebKitGTK dev package at all — is the | |
| # linux-canvas-smoke job.) | |
| - run: zig build test-linux-web-layer-audit | |
| windows-webview: | |
| name: Windows WebView | |
| runs-on: windows-2022 | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - uses: mlugg/setup-zig@v2 | |
| with: | |
| version: 0.16.0 | |
| # Builds the WebView example with the system engine, compiling the | |
| # full embedded-WebView host against the vendored WebView2 SDK | |
| # header (third_party/webview2). The host refuses to fall back to | |
| # the stubbed layer, so a regression — a missing header, a broken | |
| # include path, or a conformance error in the embedded layer — is a | |
| # compile failure here, not a silent WebViewNotFound at runtime. | |
| - run: zig build test-webview-system-link -Dplatform=windows | |
| # The registered-font receipt, natively on Windows: runs the | |
| # font-registry suite — registration validation, the glyph-budget | |
| # gate, present/reference pixel parity, and the Chinese-receipt | |
| # test that registers the committed subsetted Noto Sans SC through | |
| # the app-fonts seam and proves the rendered string is real glyphs, | |
| # not tofu — on real Windows, not under emulation. The font | |
| # pipeline is platform-neutral Zig, so this lane pins that neutral | |
| # truth on a Windows host (the Linux run lives in the Zig Core | |
| # lane's `zig build test`). | |
| - run: zig build test-canvas-fonts | |
| cef-platform-tooling: | |
| name: CEF Platform Tooling | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - uses: mlugg/setup-zig@v2 | |
| with: | |
| version: 0.16.0 | |
| - uses: actions/setup-node@v4 | |
| with: | |
| node-version: 22 | |
| # The TypeScript core suites transpile at build/test time; without | |
| # node they skip silently, so CI must provide it. | |
| - run: npm ci --prefix packages/core | |
| - run: zig build test-tooling | |
| npm-package: | |
| name: npm Package | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - uses: actions/setup-node@v4 | |
| with: | |
| node-version: 24 | |
| - run: npm --prefix packages/native-sdk run version:check | |
| - run: npm --prefix packages/native-sdk run scripts:check | |
| native-examples: | |
| name: Native Examples | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - uses: mlugg/setup-zig@v2 | |
| with: | |
| version: 0.16.0 | |
| - uses: actions/setup-node@v4 | |
| with: | |
| node-version: 22 | |
| # The TypeScript examples transpile at build time; the transpiler | |
| # needs its installed dependency. | |
| - run: npm ci --prefix packages/core | |
| - name: Install GTK dependencies | |
| run: sudo apt-get update && sudo apt-get install -y libgtk-4-dev libwebkitgtk-6.0-dev | |
| - run: zig build test-examples-native | |
| # Declare-to-use, proven on real Windows executables: the | |
| # canvas-only ui-inbox cross-compiles without the embedded WebView | |
| # layer (no WebView2Loader.dll reference, no loader installed) and | |
| # the webview example keeps it. | |
| - run: zig build test-windows-web-layer-audit | |
| linux-canvas-smoke: | |
| name: Linux Canvas Smoke | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - uses: mlugg/setup-zig@v2 | |
| with: | |
| version: 0.16.0 | |
| # Deliberately NO libwebkitgtk-6.0-dev: ui-inbox declares no web | |
| # use, so its host compiles with the WebKitGTK stub seam and this | |
| # job doubles as the native-only Linux LINK test — the build can | |
| # only succeed if nothing in a native-only app needs the WebKitGTK | |
| # headers or pkg-config entry. (The seam under webkit-PRESENT | |
| # conditions is the linux-webkitgtk job's ELF cross-audit.) | |
| - name: Install GTK and Xvfb | |
| run: sudo apt-get update && sudo apt-get install -y libgtk-4-dev xvfb | |
| # The stub is the expected, configured state of every native-only | |
| # Linux app, so compiling the GTK host with the stub define must be | |
| # diagnostic-FREE, not merely successful: zig renders every clang | |
| # diagnostic of a failing translation unit as `error:` (serialized | |
| # clang diagnostics carry no severity into its error bundle), so | |
| # even an informational #pragma message in this path masquerades as | |
| # the build-killing error the moment any unrelated real error | |
| # appears in the file. `zig cc` runs clang in passthrough mode, | |
| # where warnings actually reach stderr — `zig build` only surfaces | |
| # C diagnostics on failure, which is exactly the escalation this | |
| # step pins against. The throwaway cache dir keeps the compile | |
| # cold: on a cache hit zig replays nothing, stderr included, so a | |
| # warm cache (setup-zig restores one) would hide the diagnostics | |
| # this step exists to catch. | |
| - name: WebKitGTK stub compile is diagnostic-free | |
| run: | | |
| export ZIG_GLOBAL_CACHE_DIR=$(mktemp -d) ZIG_LOCAL_CACHE_DIR=$(mktemp -d) | |
| status=0 | |
| out=$(zig cc -c src/platform/linux/gtk_host.c -DNATIVE_SDK_ALLOW_WEBKITGTK_STUB $(pkg-config --cflags gtk4) -o /tmp/gtk_host_stub.o 2>&1) || status=$? | |
| if [ "$status" -ne 0 ] || [ -n "$out" ]; then | |
| echo "the WebKitGTK stub compile must succeed with zero diagnostics (exit $status):" | |
| echo "$out" | |
| exit 1 | |
| fi | |
| # Drives the gpu_surface software path under Xvfb: snapshot ready, | |
| # gpu_backend=software, gpu_nonblank=true, automation widget-click, | |
| # a rendered screenshot, an ELF audit that the built binary carries | |
| # no WebKitGTK reference, and ZERO WebKit helper processes (canvas | |
| # apps never boot WebKit). A11y env, the widened cold-start | |
| # readiness budget (shared runners stall ~27 s before the first | |
| # runtime event), and failure forensics (dump snapshot + app log) | |
| # all live in the script. | |
| - name: Build and drive ui-inbox headless | |
| run: .github/scripts/linux-canvas-smoke.sh | |
| # Durable receipt for the GLib 2.72 fallback (the pre-2.74 | |
| # G_APPLICATION_DEFAULT_FLAGS shim in gtk_host.c): no stock image | |
| # pairs an old glib with GTK >= 4.10 (only backport distros do), | |
| # and ubuntu 22.04 ships GTK 4.6 — so a clean compile is | |
| # impossible here by design. This pins the error SET instead: | |
| # every diagnostic must match a GTK-age shape (the allowlist | |
| # script holds the shapes, why cascades are allowed, and the | |
| # positive-evidence floor) — a 2.74+ glib symbol, type, or | |
| # member used without a version-checked fallback surfaces as a | |
| # rejected diagnostic and fails this step, and so does a compile | |
| # that produced no classifiable error set at all. If this compile ever succeeds outright, the premise | |
| # changed (newer GTK in the image) and the receipt must be | |
| # re-verified rather than trusted. | |
| - name: GTK host GLib 2.72 fallback holds (error-set receipt) | |
| run: | | |
| docker run --rm -v "$PWD:/src" -v "$(dirname "$(which zig)"):/zig" ubuntu:22.04 bash -ec ' | |
| export DEBIAN_FRONTEND=noninteractive | |
| apt-get update -q >/dev/null && apt-get install -y -q libgtk-4-dev pkg-config >/dev/null | |
| export ZIG_GLOBAL_CACHE_DIR=$(mktemp -d) ZIG_LOCAL_CACHE_DIR=$(mktemp -d) | |
| status=0 | |
| out=$(/zig/zig cc -c /src/src/platform/linux/gtk_host.c -DNATIVE_SDK_ALLOW_WEBKITGTK_STUB $(pkg-config --cflags gtk4) -ferror-limit=0 -o /tmp/gtk_host_2272.o 2>&1) || status=$? | |
| if [ "$status" -eq 0 ]; then | |
| echo "unexpected clean compile on ubuntu 22.04 - this receipt assumes GTK-age errors; re-verify what it proves now" | |
| exit 1 | |
| fi | |
| echo "$out" | python3 /src/.github/scripts/glib272_error_allowlist.py | |
| ' | |
| linux-dev-smoke: | |
| name: Linux Dev Smoke (Debug scaffold) | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - uses: mlugg/setup-zig@v2 | |
| with: | |
| version: 0.16.0 | |
| - uses: actions/setup-node@v4 | |
| with: | |
| node-version: 22 | |
| # The scaffold default is the TypeScript core; its transpiler runs | |
| # under node at build time from this checkout's packages/core. | |
| - run: npm ci --prefix packages/core | |
| # No WebKitGTK dev package, same as linux-canvas-smoke: the scaffold | |
| # declares no web use, so its host compiles with the stub seam. | |
| - name: Install GTK and Xvfb | |
| run: sudo apt-get update && sudo apt-get install -y libgtk-4-dev xvfb | |
| # The Debug half of the Linux runtime story: linux-canvas-smoke runs | |
| # at the graph's release default, and Release always uses the LLVM | |
| # backend — a Debug-only x86_64 codegen fault (self-hosted backend, | |
| # the mode every fresh `native init` + `native dev` builds) stays | |
| # invisible to it. This job scaffolds the default template with the | |
| # CLI, builds it -Doptimize=Debug with automation, runs it under | |
| # Xvfb, and requires the startup scene to come up (ready=true, | |
| # gpu_nonblank=true, template widgets in the snapshot). | |
| - name: Scaffold and drive the Debug template headless | |
| run: .github/scripts/linux-dev-smoke.sh | |
| windows-canvas-smoke: | |
| name: Windows Canvas Smoke (Wine) | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 30 | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - uses: mlugg/setup-zig@v2 | |
| with: | |
| version: 0.16.0 | |
| - name: Install Wine, Xvfb, and xdotool | |
| run: sudo apt-get update && sudo apt-get install -y wine xvfb xdotool | |
| # The Windows twin of the linux-canvas-smoke stub receipt: the | |
| # WebView2 stub is the expected, configured state of every | |
| # native-only Windows app, so cross-compiling the host with the | |
| # stub define must be diagnostic-free (see that job's step comment | |
| # for why even an informational #pragma message is dangerous, and | |
| # why the compile must run against a cold cache). | |
| - name: WebView2 stub cross-compile is diagnostic-free | |
| run: | | |
| export ZIG_GLOBAL_CACHE_DIR=$(mktemp -d) ZIG_LOCAL_CACHE_DIR=$(mktemp -d) | |
| status=0 | |
| out=$(zig c++ -target x86_64-windows-gnu -std=c++17 -DNATIVE_SDK_ALLOW_WEBVIEW2_STUB -c src/platform/windows/webview2_host.cpp -o /tmp/webview2_host_stub.o 2>&1) || status=$? | |
| if [ "$status" -ne 0 ] || [ -n "$out" ]; then | |
| echo "the WebView2 stub cross-compile must succeed with zero diagnostics (exit $status):" | |
| echo "$out" | |
| exit 1 | |
| fi | |
| # Cross-compiles ui-inbox for x86_64-windows-gnu and drives the | |
| # gpu_surface software path (child HWND + WM_TIMER + SetDIBitsToDevice) | |
| # under Wine: snapshot ready, gpu_backend=software, gpu_nonblank=true, | |
| # automation widget-click, and real XTEST pointer/keyboard input. | |
| # Wineprefix init happens inline in the script (measured 21s from | |
| # scratch in an ubuntu-24.04 container, so no cache step). | |
| - name: Build and drive ui-inbox.exe under Wine | |
| run: .github/scripts/windows-canvas-smoke.sh | |
| windows-effects-smoke: | |
| name: Windows Effects Smoke (Wine) | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 30 | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - uses: mlugg/setup-zig@v2 | |
| with: | |
| version: 0.16.0 | |
| - name: Install Wine and Xvfb | |
| run: sudo apt-get update && sudo apt-get install -y wine xvfb | |
| # Cross-compiles examples/effects-probe for x86_64-windows-gnu and | |
| # proves the effect system's live Windows path under Wine: fx.spawn | |
| # launches cmd.exe, streamed lines land in the model, the worker's | |
| # PostMessageW wake shows up as effects_wake events in the trace | |
| # log (frame ticks also drain, so the log is the wake's evidence), | |
| # and fx.cancel terminates the child with the line count frozen. | |
| - name: Build and drive effects-probe.exe under Wine | |
| run: .github/scripts/windows-effects-smoke.sh | |
| frontend-examples: | |
| name: Frontend Examples | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - uses: mlugg/setup-zig@v2 | |
| with: | |
| version: 0.16.0 | |
| - run: zig build test-examples-frontends | |
| mobile-examples: | |
| name: Mobile Examples | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - uses: mlugg/setup-zig@v2 | |
| with: | |
| version: 0.16.0 | |
| - run: zig build test-examples-mobile | |
| scaffold: | |
| name: Generated App Scaffolds | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - uses: mlugg/setup-zig@v2 | |
| with: | |
| version: 0.16.0 | |
| - uses: actions/setup-node@v4 | |
| with: | |
| node-version: 22 | |
| # The default scaffold is a TypeScript core: its build runs the | |
| # @native-sdk/core transpiler from this checkout's own install. | |
| - run: npm ci --prefix packages/core | |
| - run: zig build | |
| - name: Scaffold and test the zero-config native app | |
| run: | | |
| set -euo pipefail | |
| app=".zig-cache/scaffold-native-slim" | |
| rm -rf "$app" | |
| ./zig-out/bin/native init "$app" | |
| # Slim scaffold: no build files — the CLI's generated graph drives it. | |
| test ! -f "$app/build.zig" | |
| test ! -f "$app/build.zig.zon" | |
| # The editor surface landed: package.json + tsconfig.json + the | |
| # materialized @native-sdk/core copy stock tsc resolves. | |
| test -f "$app/package.json" | |
| test -f "$app/tsconfig.json" | |
| test -f "$app/node_modules/@native-sdk/core/sdk/core.ts" | |
| # ...and none of it is build truth: every verb works without it. | |
| rm -rf "$app/node_modules" | |
| ./zig-out/bin/native test "$app" -Dplatform=null | |
| ./zig-out/bin/native check "$app" | |
| # check self-healed the editor copy back into place. | |
| test -f "$app/node_modules/@native-sdk/core/sdk/core.ts" | |
| ./zig-out/bin/native eject "$app" | |
| (cd "$app" && zig build test -Dplatform=null) | |
| - name: Scaffold and test frontend templates | |
| run: | | |
| set -euo pipefail | |
| for frontend in native next vite react svelte vue; do | |
| app=".zig-cache/scaffold-${frontend}" | |
| rm -rf "$app" | |
| ./zig-out/bin/native init "$app" --frontend "$frontend" --full | |
| (cd "$app" && zig build test -Dplatform=null && ../../zig-out/bin/native validate app.zon) | |
| # Every scaffold ships a CI workflow; parse it as real YAML. | |
| test -s "$app/.github/workflows/ci.yml" | |
| python3 -c 'import sys, yaml; yaml.safe_load(open(sys.argv[1]))' "$app/.github/workflows/ci.yml" | |
| done | |
| evals-typecheck: | |
| name: Evals Typecheck | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - uses: actions/setup-node@v4 | |
| with: | |
| node-version: 22 | |
| - uses: pnpm/action-setup@v4 | |
| with: | |
| version: 10.23.0 | |
| package_json_file: evals/package.json | |
| - run: pnpm install --frozen-lockfile | |
| working-directory: evals | |
| - run: pnpm typecheck | |
| working-directory: evals | |
| docs: | |
| name: Docs | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - uses: actions/setup-node@v4 | |
| with: | |
| node-version: 22 | |
| - uses: pnpm/action-setup@v4 | |
| with: | |
| version: 10.23.0 | |
| package_json_file: docs/package.json | |
| - run: pnpm install --frozen-lockfile | |
| working-directory: docs | |
| - run: pnpm check | |
| working-directory: docs |