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 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 # 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 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 # 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