feat(motion): native spring integrator and GELATIN preset #116
Workflow file for this run
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 | |
| env: | |
| APP_NAME: gpuix-native | |
| MACOSX_DEPLOYMENT_TARGET: "10.13" | |
| "on": | |
| push: | |
| branches: | |
| - main | |
| tags-ignore: | |
| - "**" | |
| paths-ignore: | |
| - "**/*.md" | |
| - LICENSE | |
| - "**/*.gitignore" | |
| - docs/** | |
| pull_request: null | |
| concurrency: | |
| group: ${{ github.workflow }}-${{ github.ref }} | |
| cancel-in-progress: true | |
| jobs: | |
| build: | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| # One target per OS, on the architecture that OS is mostly used on. | |
| # Every extra target is a full gpui build, and gpui is most of the | |
| # wall clock of this workflow. Add a target back when someone asks | |
| # for it, not before: `packages/native/package.json` `napi.targets` | |
| # must list exactly the same set, or the published loader looks for | |
| # a platform package that CI never built. | |
| settings: | |
| # ── macOS (Metal) ────────────────────────────────────────── | |
| # default features include test-support (TestGpuixRenderer) | |
| - host: macos-latest | |
| target: aarch64-apple-darwin | |
| bunTarget: bun-darwin-arm64 | |
| build: bun run build --target aarch64-apple-darwin | |
| # ── Linux (Vulkan/wgpu) ──────────────────────────────────── | |
| # build:release disables test-support until wgpu image readback lands. | |
| - host: ubuntu-latest | |
| target: x86_64-unknown-linux-gnu | |
| bunTarget: bun-linux-x64 | |
| build: bun run build:release --target x86_64-unknown-linux-gnu | |
| # ── Windows (Direct3D) ───────────────────────────────────── | |
| # Test support includes TestGpuixRenderer and render_to_image. | |
| - host: windows-latest | |
| target: x86_64-pc-windows-msvc | |
| bunTarget: bun-windows-x64 | |
| build: bun run build --target x86_64-pc-windows-msvc | |
| name: build - ${{ matrix.settings.target }} | |
| runs-on: ${{ matrix.settings.host }} | |
| defaults: | |
| run: | |
| working-directory: packages/native | |
| steps: | |
| - uses: actions/checkout@v4 | |
| with: | |
| submodules: recursive | |
| - name: Setup bun | |
| uses: oven-sh/setup-bun@v2 | |
| # Reads the channel from rust-toolchain.toml, which must match zed's | |
| # pin for the gpui revision in packages/native/Cargo.toml. | |
| - name: Install Rust | |
| uses: actions-rust-lang/setup-rust-toolchain@v1 | |
| with: | |
| target: ${{ matrix.settings.target }} | |
| # this workflow caches cargo explicitly in the next step | |
| cache: false | |
| # the action defaults to RUSTFLAGS="-D warnings"; keep lint policy | |
| # in the crate instead of letting CI deny every warning | |
| rustflags: "" | |
| # gpui_apple compiles shaders with `metal`, which Xcode 26 no longer | |
| # ships by default. Without this the build fails with | |
| # "cannot execute tool 'metal' due to missing Metal Toolchain". | |
| - name: Install Metal toolchain | |
| if: contains(matrix.settings.target, 'apple-darwin') | |
| run: xcodebuild -downloadComponent MetalToolchain | |
| - name: Cache cargo | |
| uses: actions/cache@v4 | |
| with: | |
| path: | | |
| ~/.cargo/registry | |
| ~/.cargo/git | |
| packages/native/target/ | |
| key: ${{ matrix.settings.target }}-cargo-${{ hashFiles('packages/native/Cargo.lock') }} | |
| restore-keys: | | |
| ${{ matrix.settings.target }}-cargo- | |
| # Linux system deps for GPUI (Vulkan, Wayland, X11, fonts) | |
| # Based on longbridge/gpui-component and Zed's script/linux | |
| - name: Install Linux dependencies | |
| if: contains(matrix.settings.target, 'linux') | |
| working-directory: . | |
| run: | | |
| sudo apt-get update && sudo apt-get install -y \ | |
| gcc g++ clang \ | |
| libfontconfig-dev \ | |
| libwayland-dev \ | |
| libxkbcommon-x11-dev \ | |
| libx11-xcb-dev \ | |
| libssl-dev \ | |
| libzstd-dev \ | |
| libvulkan1 \ | |
| vulkan-validationlayers | |
| - name: Install dependencies | |
| working-directory: . | |
| run: bun install | |
| - name: Build native | |
| run: ${{ matrix.settings.build }} | |
| shell: bash | |
| - name: Upload artifact | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: bindings-${{ matrix.settings.target }} | |
| path: packages/native/${{ env.APP_NAME }}.*.node | |
| if-no-files-found: error | |
| - name: Build React package | |
| working-directory: packages/react | |
| shell: bash | |
| run: bun run build | |
| - name: Compile chat example | |
| working-directory: examples | |
| shell: bash | |
| env: | |
| COMPILE_OUT: example-chat-${{ matrix.settings.target }} | |
| COMPILE_TARGET: ${{ matrix.settings.bunTarget }} | |
| COMPILE_SKIP_ICONS: "1" | |
| COMPILE_SKIP_APP: "1" | |
| run: bun compile-chat.ts | |
| # A release asset is served as raw bytes, so a download loses the | |
| # executable bit and arrives with no extension: macOS and Linux users | |
| # got a file the OS refused to open. `.tar.gz` keeps the mode and names | |
| # itself. Windows already ships a `.exe`, which needs no unpacking. | |
| - name: Package chat example | |
| working-directory: examples/dist | |
| shell: bash | |
| env: | |
| NAME: example-chat-${{ matrix.settings.target }} | |
| run: | | |
| if [ -f "$NAME.exe" ]; then | |
| echo "$NAME.exe already carries an extension" | |
| exit 0 | |
| fi | |
| chmod +x "$NAME" | |
| tar -czf "$NAME.tar.gz" "$NAME" | |
| rm "$NAME" | |
| ls -l | |
| - name: Upload example artifact | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: example-chat-${{ matrix.settings.target }} | |
| path: examples/dist/example-chat-${{ matrix.settings.target }}.* | |
| if-no-files-found: error | |
| test: | |
| name: test | |
| needs: build | |
| runs-on: macos-latest | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: Setup bun | |
| uses: oven-sh/setup-bun@v2 | |
| - name: Install dependencies | |
| run: bun install | |
| - name: Download macOS arm64 artifact | |
| uses: actions/download-artifact@v4 | |
| with: | |
| name: bindings-aarch64-apple-darwin | |
| path: packages/native/ | |
| - name: Run React tests | |
| run: bun run test | |
| working-directory: packages/react | |
| - name: Build React package | |
| run: bun run build | |
| working-directory: packages/react | |
| - name: Run example tests | |
| run: bun run test | |
| working-directory: examples | |
| # Bun never typechecks. This step is what catches a broken public type, | |
| # such as `key` disappearing from every element. | |
| - name: Typecheck the example app | |
| run: bun run typecheck | |
| working-directory: example-app | |
| - name: Test CLI | |
| env: | |
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| run: bun run test | |
| working-directory: cli | |
| - name: Build CLI | |
| run: bun run build | |
| working-directory: cli | |
| test-windows: | |
| name: test-windows | |
| needs: build | |
| runs-on: windows-latest | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: Setup bun | |
| uses: oven-sh/setup-bun@v2 | |
| - name: Setup node | |
| uses: actions/setup-node@v4 | |
| with: | |
| node-version: 24 | |
| - name: Install dependencies | |
| run: bun install | |
| - name: Download Windows x64 artifact | |
| uses: actions/download-artifact@v4 | |
| with: | |
| name: bindings-x86_64-pc-windows-msvc | |
| path: packages/native/ | |
| - name: Load native binding with Bun | |
| run: bun -e "require('./packages/native'); console.log('Windows native binding OK (bun)')" | |
| - name: Load native binding with Node | |
| run: node -e "require('./packages/native'); console.log('Windows native binding OK (node)')" | |
| - name: Verify Windows test renderer | |
| shell: bash | |
| run: bun -e "const { statSync } = require('node:fs'); const { TestGpuixRenderer } = require('./packages/native'); const renderer = new TestGpuixRenderer(320, 200); renderer.applyBatch(JSON.stringify([['createElement',1,'text'],['setText',1,'Windows test renderer'],['setRoot',1]])); renderer.flush(); renderer.captureScreenshot('windows-test-renderer.png'); if (renderer.getAllText()[0] !== 'Windows test renderer' || statSync('windows-test-renderer.png').size === 0) throw new Error('TestGpuixRenderer did not render')" | |
| - name: Run React tests | |
| run: bun run test | |
| working-directory: packages/react | |
| - name: Build React package | |
| run: bun run build | |
| working-directory: packages/react | |
| - name: Run example tests | |
| run: bun run test | |
| working-directory: examples | |
| publish-cli: | |
| name: publish-cli | |
| if: github.event_name == 'push' && github.ref == 'refs/heads/main' | |
| runs-on: ubuntu-latest | |
| permissions: | |
| id-token: write | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: Setup bun | |
| uses: oven-sh/setup-bun@v2 | |
| - name: Install dependencies | |
| run: bun install | |
| - name: Test CLI | |
| env: | |
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| run: bun run test | |
| working-directory: cli | |
| - name: Publish @gpuix/cli | |
| env: | |
| SIGILLO_TOKEN: ${{ secrets.SIGILLO_TOKEN }} | |
| SIGILLO_PROJECT: ${{ vars.SIGILLO_PROJECT }} | |
| SIGILLO_ENVIRONMENT: prod | |
| run: | | |
| CURRENT_VERSION=$(node -p "require('./cli/package.json').version") | |
| if npm view "@gpuix/cli@${CURRENT_VERSION}" version 2>/dev/null; then | |
| echo "@gpuix/cli@${CURRENT_VERSION} already published, skipping" | |
| else | |
| echo "Publishing @gpuix/cli@${CURRENT_VERSION}" | |
| cd cli | |
| bunx sigillo run --command 'printf "//registry.npmjs.org/:_authToken=%s\n" "$NPM_TOKEN" > "$HOME/.npmrc" && bun publish --access public' | |
| fi | |
| publish: | |
| name: publish | |
| runs-on: ubuntu-latest | |
| needs: | |
| - build | |
| - test | |
| - test-windows | |
| permissions: | |
| contents: write | |
| id-token: write | |
| steps: | |
| - uses: actions/checkout@v4 | |
| with: | |
| submodules: recursive | |
| - name: Setup node | |
| uses: actions/setup-node@v4 | |
| with: | |
| node-version: 24 | |
| - name: Setup bun | |
| uses: oven-sh/setup-bun@v2 | |
| - name: Install browser Rust toolchain | |
| uses: actions-rust-lang/setup-rust-toolchain@v1 | |
| with: | |
| toolchain: nightly | |
| target: wasm32-unknown-unknown | |
| components: rust-src | |
| cache: false | |
| rustflags: "" | |
| - name: Install wasm-bindgen CLI | |
| run: cargo install wasm-bindgen-cli --version 0.2.127 --locked | |
| - name: Install dependencies | |
| run: bun install | |
| - name: Download native artifacts | |
| uses: actions/download-artifact@v4 | |
| with: | |
| pattern: bindings-* | |
| path: packages/native/artifacts | |
| - name: Create npm dirs and move artifacts | |
| run: | | |
| bunx @napi-rs/cli create-npm-dirs | |
| bunx @napi-rs/cli artifacts | |
| working-directory: packages/native | |
| - name: List packages | |
| run: ls -R packages/native/npm/ | |
| shell: bash | |
| # NPM_TOKEN lives in Sigillo (npm/tokens, prod). CI only stores | |
| # SIGILLO_TOKEN. Rotate the npm token in one place. | |
| - name: Publish @gpuix/native | |
| env: | |
| SIGILLO_TOKEN: ${{ secrets.SIGILLO_TOKEN }} | |
| SIGILLO_PROJECT: ${{ vars.SIGILLO_PROJECT }} | |
| SIGILLO_ENVIRONMENT: prod | |
| run: | | |
| CURRENT_VERSION=$(node -p "require('./packages/native/package.json').version") | |
| if npm view "@gpuix/native@${CURRENT_VERSION}" version 2>/dev/null; then | |
| echo "@gpuix/native@${CURRENT_VERSION} already published, skipping" | |
| else | |
| echo "Publishing @gpuix/native@${CURRENT_VERSION}" | |
| cd packages/native | |
| bunx sigillo run --command 'printf "//registry.npmjs.org/:_authToken=%s\n" "$NPM_TOKEN" > "$HOME/.npmrc" && bun publish --access public' | |
| fi | |
| - name: Build @gpuix/react | |
| run: bun run build | |
| working-directory: packages/react | |
| - name: Publish @gpuix/react | |
| env: | |
| SIGILLO_TOKEN: ${{ secrets.SIGILLO_TOKEN }} | |
| SIGILLO_PROJECT: ${{ vars.SIGILLO_PROJECT }} | |
| SIGILLO_ENVIRONMENT: prod | |
| run: | | |
| CURRENT_VERSION=$(node -p "require('./packages/react/package.json').version") | |
| if npm view "@gpuix/react@${CURRENT_VERSION}" version 2>/dev/null; then | |
| echo "@gpuix/react@${CURRENT_VERSION} already published, skipping" | |
| else | |
| echo "Publishing @gpuix/react@${CURRENT_VERSION}" | |
| cd packages/react | |
| node -e " | |
| const fs = require('fs') | |
| const pkg = JSON.parse(fs.readFileSync('package.json', 'utf8')) | |
| const native = require('../native/package.json').version | |
| pkg.dependencies['@gpuix/native'] = '^' + native | |
| fs.writeFileSync('package.json', JSON.stringify(pkg, null, 2) + '\n') | |
| " | |
| bunx sigillo run --command 'printf "//registry.npmjs.org/:_authToken=%s\n" "$NPM_TOKEN" > "$HOME/.npmrc" && bun publish --access public' | |
| fi | |
| - name: Download example artifacts | |
| if: github.event_name == 'push' && github.ref == 'refs/heads/main' | |
| uses: actions/download-artifact@v4 | |
| with: | |
| pattern: example-chat-* | |
| path: example-artifacts | |
| merge-multiple: true | |
| - name: Upload example binaries to GitHub Release | |
| if: github.event_name == 'push' && github.ref == 'refs/heads/main' | |
| env: | |
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| run: | | |
| VERSION=$(node -p "require('./packages/react/package.json').version") | |
| TAG="@gpuix/react@${VERSION}" | |
| if ! gh release view "$TAG" >/dev/null 2>&1; then | |
| echo "No GitHub release for ${TAG}, skipping example upload" | |
| exit 0 | |
| fi | |
| shopt -s nullglob | |
| files=(example-artifacts/example-chat-*) | |
| if [ ${#files[@]} -eq 0 ]; then | |
| echo "No example binaries to upload" | |
| exit 0 | |
| fi | |
| echo "Uploading example-chat binaries to ${TAG}" | |
| gh release upload "$TAG" "${files[@]}" --clobber |