From ad6b2f97c5225d33da52c258ea992e104990475a Mon Sep 17 00:00:00 2001 From: Steven Enamakel Date: Fri, 24 Apr 2026 10:38:53 -0700 Subject: [PATCH 1/4] ci: parallelize rust tests, drop duplicated work from build/test MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Split `rust-tests` into `rust-core-tests` + `rust-tauri-tests` so they run in parallel (separate Swatinem cache keys; CEF cache only on the Tauri job). Clippy removed — `typecheck.yml` already runs it. - Drop Sentry debug-symbol upload from `build.yml`; release workflows already upload symbols, and `build.yml` strips debug info anyway. Also removes the now-unused `actions: read` permission. - Skip `tsc` inside `cargo tauri build` on `build.yml` by overriding `beforeBuildCommand` via `TAURI_CONFIG_OVERRIDE`. Typechecking stays in `typecheck.yml`; `package.json` is unchanged so local + release builds keep running `tsc`. --- .github/workflows/build.yml | 40 +++----------------------------- .github/workflows/test.yml | 46 ++++++++++++++++++++++++++++--------- 2 files changed, 38 insertions(+), 48 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 2fecb51b0e1..28936063aae 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -8,8 +8,6 @@ on: permissions: contents: read pull-requests: read - # Required for Sentry to associate commits with releases - actions: read concurrency: group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.head_ref || github.ref }} @@ -80,7 +78,9 @@ jobs: - name: Build Tauri app (CEF default) working-directory: app run: | - TAURI_CONFIG_OVERRIDE='{"plugins":{"updater":{"active":false}}}' + # Skip tsc in beforeBuildCommand — typechecking runs in the dedicated + # `typecheck` workflow, so doing it again here is duplicated CI time. + TAURI_CONFIG_OVERRIDE='{"build":{"beforeBuildCommand":"npx vite build && npm run core:stage"},"plugins":{"updater":{"active":false}}}' cargo tauri build -c "$TAURI_CONFIG_OVERRIDE" --bundles deb env: NODE_ENV: production @@ -89,37 +89,3 @@ jobs: CARGO_PROFILE_RELEASE_LTO: "false" CARGO_PROFILE_RELEASE_STRIP: "true" CARGO_PROFILE_RELEASE_DEBUG: "false" - - - name: Upload Rust debug symbols to Sentry - if: github.event_name == 'push' && github.ref == 'refs/heads/main' - env: - SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }} - SENTRY_ORG: ${{ vars.SENTRY_ORG }} - SENTRY_PROJECT: ${{ vars.SENTRY_PROJECT }} - run: | - # Install sentry-cli if not available (container runs as root, no sudo needed) - if ! command -v sentry-cli &> /dev/null; then - curl -sSL https://github.com/getsentry/sentry-cli/releases/download/2.34.2/sentry-cli-Linux-x86_64 -o /tmp/sentry-cli - chmod +x /tmp/sentry-cli - mv /tmp/sentry-cli /usr/local/bin/sentry-cli - fi - - # Create Sentry release and upload debug symbols - VERSION=$(grep -m1 '^version\s*=' app/src-tauri/Cargo.toml | sed 's/version\s*=\s*"\([^"]*\)"/\1/') - RELEASE="openhuman@${VERSION}" - - echo "Creating Sentry release: ${RELEASE}" - sentry-cli releases new "${RELEASE}" || true - # Use --ignore-missing because fetch-depth: 1 means shallow clone - sentry-cli releases set-commits --auto --ignore-missing "${RELEASE}" || true - - echo "Uploading debug symbols..." - # Debug symbols are indexed by debug-ID, not release-scoped, so no --release flag - sentry-cli upload-dif \ - --org "$SENTRY_ORG" \ - --project "$SENTRY_PROJECT" \ - --log-level=warning \ - app/src-tauri/target/release/deps/ - - sentry-cli releases finalize "${RELEASE}" - echo "Sentry symbol upload complete for ${RELEASE}" diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 0a917627ef2..ffd2afde1e8 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -66,8 +66,8 @@ jobs: path: coverage retention-days: 7 - rust-tests: - name: Rust Tests + Quality + rust-core-tests: + name: Rust Core Tests + Quality runs-on: ubuntu-22.04 container: image: ghcr.io/tinyhumansai/openhuman_ci:rust-1.93.0 @@ -80,6 +80,38 @@ jobs: # individual compilation units across branches. RUSTC_WRAPPER: sccache SCCACHE_GHA_ENABLED: "true" + steps: + - name: Checkout code + uses: actions/checkout@v4 + with: + fetch-depth: 1 + submodules: recursive + + - name: Cache Rust build artifacts + uses: Swatinem/rust-cache@v2 + with: + workspaces: . -> target + cache-on-failure: true + key: core + + - name: Install system dependencies (cmake, ALSA, X11) + run: apt-get update && apt-get install -y --no-install-recommends cmake libasound2-dev libxdo-dev libxtst-dev libx11-dev libevdev-dev && rm -rf /var/lib/apt/lists/* + + - name: Install sccache + uses: mozilla-actions/sccache-action@v0.0.9 + + - name: Test core crate (openhuman) + run: cargo test -p openhuman + + rust-tauri-tests: + name: Rust Tauri Shell Tests + runs-on: ubuntu-22.04 + container: + image: ghcr.io/tinyhumansai/openhuman_ci:rust-1.93.0 + env: + CARGO_INCREMENTAL: "0" + RUSTC_WRAPPER: sccache + SCCACHE_GHA_ENABLED: "true" steps: - name: Checkout code uses: actions/checkout@v4 @@ -97,6 +129,7 @@ jobs: . -> target app/src-tauri -> target cache-on-failure: true + key: tauri # CEF is the default runtime, so `cargo test --manifest-path app/src-tauri/Cargo.toml` # links the Chromium dylib via cef-dll-sys. Cache the download to avoid @@ -115,15 +148,6 @@ jobs: - name: Install sccache uses: mozilla-actions/sccache-action@v0.0.9 - - name: Check formatting (cargo fmt) - run: cargo fmt --all -- --check - - - name: Run clippy (core crate) - run: cargo clippy -p openhuman - - - name: Test core crate (openhuman) - run: cargo test -p openhuman - - name: Build sidecar core binary run: cargo build --profile ci --target x86_64-unknown-linux-gnu --bin openhuman-core From a8321bb155a7658d4bb82b4b2d69a68276e5da6d Mon Sep 17 00:00:00 2001 From: Steven Enamakel Date: Fri, 24 Apr 2026 10:41:18 -0700 Subject: [PATCH 2/4] chore(deps,ci): add missing command-palette deps, upload Rust symbols on release MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Add `@radix-ui/react-dialog`, `cmdk`, `@testing-library/user-event` — imported by `src/components/commands/*` but never actually installed, so `tsc` in the pre-push hook fails on a clean checkout. - Wire `scripts/upload_sentry_symbols.sh` into `release.yml` after the Tauri build. Release builds now upload Rust debug symbols (core sidecar + Tauri shell) to Sentry so production stack traces symbolicate. Gated on `release_enabled` and `SENTRY_AUTH_TOKEN`. --- .github/workflows/release.yml | 30 ++++++++++++++++++++++++++++++ app/package.json | 6 +++--- yarn.lock | 4 ++-- 3 files changed, 35 insertions(+), 5 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index a59b24011e1..31d2000dec0 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -562,6 +562,36 @@ jobs: # on macos-arm64 runners, causing OOM at node's ~2GB auto default. NODE_OPTIONS="--max-old-space-size=8192" cargo tauri build -c "$TAURI_CONFIG_OVERRIDE" $MATRIX_ARGS + # Upload Rust debug info to Sentry so backend + Tauri-shell stack traces + # symbolicate in production. The frontend source maps are handled by + # sentry-vite-plugin in the build step above; this is the Rust half. + # Keyed by debug-ID, so it's safe to run per-matrix-target without + # collisions — Sentry merges artifacts across platforms. + - name: Upload Rust debug symbols to Sentry + if: needs.prepare-build.outputs.release_enabled == 'true' && env.SENTRY_AUTH_TOKEN != '' + shell: bash + env: + SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }} + SENTRY_ORG: ${{ vars.SENTRY_ORG }} + SENTRY_PROJECT: ${{ vars.SENTRY_PROJECT }} + VERSION: ${{ needs.prepare-build.outputs.version }} + MATRIX_TARGET: ${{ matrix.settings.target }} + run: | + set -euo pipefail + # Core crate deps (sidecar symbols) + Tauri shell deps (app binary + # symbols) both live under the per-target release dir. upload-dif + # scans recursively. + for deps_dir in \ + "target/${MATRIX_TARGET}/release/deps" \ + "app/src-tauri/target/${MATRIX_TARGET}/release/deps"; do + if [ -d "$deps_dir" ]; then + echo "==> Uploading symbols from $deps_dir" + bash scripts/upload_sentry_symbols.sh "$VERSION" "$deps_dir" + else + echo "==> Skipping $deps_dir (not present)" + fi + done + # tauri-action previously uploaded non-macOS installer assets directly # to the release. Replicate that for Linux + Windows here (macOS goes # through the re-sign + notarize path below and uploads separately). diff --git a/app/package.json b/app/package.json index 645baff3521..22d6dd33375 100644 --- a/app/package.json +++ b/app/package.json @@ -56,7 +56,7 @@ "dependencies": { "@noble/hashes": "^2.0.1", "@noble/secp256k1": "^3.0.0", - "@radix-ui/react-dialog": "^1", + "@radix-ui/react-dialog": "^1.1.15", "@reduxjs/toolkit": "^2.11.2", "@scure/bip32": "^2.0.1", "@scure/bip39": "^2.0.1", @@ -67,7 +67,7 @@ "@tauri-apps/plugin-os": "^2.3.2", "@types/three": "^0.183.1", "buffer": "^6.0.3", - "cmdk": "^1", + "cmdk": "^1.1.1", "debug": "^4.4.3", "lottie-react": "^2.4.1", "os-browserify": "^0.3.0", @@ -86,6 +86,7 @@ }, "devDependencies": { "@eslint/js": "^9.39.2", + "@sentry/vite-plugin": "^2.22.6", "@tailwindcss/forms": "^0.5.11", "@tailwindcss/typography": "^0.5.19", "@tauri-apps/cli": "2.10.0", @@ -101,7 +102,6 @@ "@types/redux-logger": "^3.0.13", "@typescript-eslint/eslint-plugin": "^8.54.0", "@typescript-eslint/parser": "^8.54.0", - "@sentry/vite-plugin": "^2.22.6", "@vitejs/plugin-react": "^4.6.0", "@vitest/coverage-v8": "^4.0.18", "@wdio/appium-service": "^9.24.0", diff --git a/yarn.lock b/yarn.lock index 9b0ecdfff1e..825beb9d146 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1205,7 +1205,7 @@ resolved "https://registry.yarnpkg.com/@radix-ui/react-context/-/react-context-1.1.2.tgz#61628ef269a433382c364f6f1e3788a6dc213a36" integrity sha512-jCi/QKUM2r1Ju5a3J64TH2A5SpKAgh0LpknyqdQ4m6DCV0xJ2HG1xARRwNGPQfi1SLdLWZ1OJz6F4OMBBNiGJA== -"@radix-ui/react-dialog@^1", "@radix-ui/react-dialog@^1.1.6": +"@radix-ui/react-dialog@^1.1.15", "@radix-ui/react-dialog@^1.1.6": version "1.1.15" resolved "https://registry.yarnpkg.com/@radix-ui/react-dialog/-/react-dialog-1.1.15.tgz#1de3d7a7e9a17a9874d29c07f5940a18a119b632" integrity sha512-TCglVRtzlffRNxRMEyR36DGBLJpeusFcgMVD9PZEzAKnUs1lKCgX5u9BmC2Yg+LL9MgZDugFFs1Vl+Jp4t/PGw== @@ -3273,7 +3273,7 @@ clone@^1.0.2: resolved "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz" integrity sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg== -cmdk@^1: +cmdk@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/cmdk/-/cmdk-1.1.1.tgz#b8524272699ccaa37aaf07f36850b376bf3d58e5" integrity sha512-Vsv7kFaXm+ptHDMZ7izaRsP70GgrW9NBNGswt9OZaVBLlE0SNpDq8eu/VGXyF9r7M0azK3Wy7OlYXsuyYLFzHg== From 6c2cb8ea2ef86aebee4780207beb0f499458055b Mon Sep 17 00:00:00 2001 From: Steven Enamakel Date: Fri, 24 Apr 2026 10:58:30 -0700 Subject: [PATCH 3/4] chore: post-merge lint fix, regen pnpm lockfile Upstream merged the pnpm migration (#886) and the CEF deb runtime spec (#893). After resolving conflicts: - Drop unused `waitForText` import and escape-`/` in the runtime spec so eslint passes on the hook's default rules. - Re-run `pnpm install` to refresh the root lockfile with the command-palette deps already declared in `app/package.json`. --- .../e2e/specs/linux-cef-deb-runtime.spec.ts | 20 +++++++++---------- pnpm-lock.yaml | 4 ++-- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/app/test/e2e/specs/linux-cef-deb-runtime.spec.ts b/app/test/e2e/specs/linux-cef-deb-runtime.spec.ts index 90090d789d0..4853670099c 100644 --- a/app/test/e2e/specs/linux-cef-deb-runtime.spec.ts +++ b/app/test/e2e/specs/linux-cef-deb-runtime.spec.ts @@ -18,7 +18,7 @@ */ import { waitForApp, waitForAppReady } from '../helpers/app-helpers'; import { callOpenhumanRpc } from '../helpers/core-rpc'; -import { dumpAccessibilityTree, textExists, waitForText } from '../helpers/element-helpers'; +import { dumpAccessibilityTree, textExists } from '../helpers/element-helpers'; import { supportsExecuteScript } from '../helpers/platform'; import { startMockServer, stopMockServer } from '../mock-server'; @@ -100,7 +100,7 @@ describe('Linux CEF deb package runtime (UI → Tauri → sidecar)', () => { stepLog('core_rpc_url returned', { url }); // Validate URL format: http://host:port/rpc - expect(url).toMatch(/^http:\/\/[^\/]+:\d+\/rpc$/); + expect(url).toMatch(/^http:\/\/[^/]+:\d+\/rpc$/); // Should be localhost or 127.0.0.1 expect(url).toMatch(/http:\/\/(127\.0\.0\.1|localhost):/); @@ -158,14 +158,14 @@ describe('Linux CEF deb package runtime (UI → Tauri → sidecar)', () => { } } -// At least one method should succeed - const anySuccess = Object.values(results).some(v => v); - if (!anySuccess) { - throw new Error( - `Expected at least one health check to pass. Results: ${JSON.stringify(results)}` - ); - } - expect(anySuccess).toBe(true); + // At least one method should succeed + const anySuccess = Object.values(results).some(v => v); + if (!anySuccess) { + throw new Error( + `Expected at least one health check to pass. Results: ${JSON.stringify(results)}` + ); + } + expect(anySuccess).toBe(true); }); it('sidecar binary was found and spawned (not self-subcommand fallback)', async () => { diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index a5f612fc906..40a28b4e182 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -28,7 +28,7 @@ importers: specifier: ^3.0.0 version: 3.1.0 '@radix-ui/react-dialog': - specifier: ^1 + specifier: ^1.1.15 version: 1.1.15(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5) '@reduxjs/toolkit': specifier: ^2.11.2 @@ -61,7 +61,7 @@ importers: specifier: ^6.0.3 version: 6.0.3 cmdk: - specifier: ^1 + specifier: ^1.1.1 version: 1.1.1(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5) debug: specifier: ^4.4.3 From e277362144b4d67cb4fbb17c864ff39436969801 Mon Sep 17 00:00:00 2001 From: Steven Enamakel Date: Fri, 24 Apr 2026 11:03:09 -0700 Subject: [PATCH 4/4] chore: migrate CI workflows from yarn to pnpm - Updated GitHub Actions workflows for testing and type checking to use pnpm instead of yarn. - Removed caching steps related to yarn and adjusted dependency installation commands accordingly. - Ensured compatibility with Node.js 24.x and streamlined the setup process for pnpm. --- .github/workflows/test.yml | 19 ++++++------------- .github/workflows/typecheck.yml | 24 ++++++++---------------- 2 files changed, 14 insertions(+), 29 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 73db4e5c7b9..b292206c325 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -28,25 +28,18 @@ jobs: uses: actions/checkout@v4 with: fetch-depth: 1 + - name: Setup pnpm + uses: pnpm/action-setup@v4 + with: + cache: true - name: Setup Node.js 24.x uses: actions/setup-node@v4 with: node-version: 24.x - cache: yarn - - name: Cache node modules - id: yarn-cache - uses: actions/cache@v4 - with: - path: node_modules - key: ${{ runner.os }}-test-${{ hashFiles('**/yarn.lock') }} - restore-keys: | - ${{ runner.os }}-test- - ${{ runner.os }}-build- - name: Install dependencies - if: steps.yarn-cache.outputs.cache-hit != 'true' - run: yarn install --frozen-lockfile + run: pnpm install --frozen-lockfile - name: Run tests with coverage - run: yarn test:coverage + run: pnpm test:coverage env: NODE_ENV: test - name: Upload coverage reports diff --git a/.github/workflows/typecheck.yml b/.github/workflows/typecheck.yml index c0179ad4c7c..eced03f8f7d 100644 --- a/.github/workflows/typecheck.yml +++ b/.github/workflows/typecheck.yml @@ -20,34 +20,26 @@ jobs: uses: actions/checkout@v4 with: fetch-depth: 1 + - name: Setup pnpm + uses: pnpm/action-setup@v4 + with: + cache: true - name: Setup Node.js 24.x uses: actions/setup-node@v4 with: node-version: 24.x - cache: yarn - - name: Cache node modules - id: yarn-cache - uses: actions/cache@v4 - with: - path: node_modules - key: ${{ runner.os }}-typecheck-${{ hashFiles('**/yarn.lock') }} - restore-keys: | - ${{ runner.os }}-typecheck- - ${{ runner.os }}-test- - ${{ runner.os }}-build- - name: Install dependencies - if: steps.yarn-cache.outputs.cache-hit != 'true' - run: yarn install --frozen-lockfile + run: pnpm install --frozen-lockfile - name: Type check TypeScript files - run: yarn workspace openhuman-app compile + run: pnpm --filter openhuman-app compile env: NODE_ENV: test - name: Check Prettier formatting - run: yarn workspace openhuman-app format:check + run: pnpm --filter openhuman-app format:check env: NODE_ENV: test - name: Run ESLint - run: yarn workspace openhuman-app lint + run: pnpm --filter openhuman-app lint env: NODE_ENV: test rust-quality: