Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 3 additions & 37 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,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 }}
Expand Down Expand Up @@ -71,7 +69,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 && pnpm run core:stage"},"plugins":{"updater":{"active":false}}}'
cargo tauri build -c "$TAURI_CONFIG_OVERRIDE" --bundles deb
env:
NODE_ENV: production
Expand All @@ -80,37 +80,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}"
37 changes: 34 additions & 3 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -525,9 +525,40 @@ 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

# 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).
# 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).
- name: Upload non-macOS installers to release
if: needs.prepare-build.outputs.release_enabled == 'true' && matrix.settings.platform
!= 'macos-latest'
Expand Down
64 changes: 43 additions & 21 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -56,8 +49,9 @@ jobs:
name: coverage-report
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
Expand All @@ -70,6 +64,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
Expand All @@ -86,6 +112,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
Expand All @@ -102,12 +129,7 @@ jobs:
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: 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
- name: Stage sidecar for Tauri shell tests
Expand Down
24 changes: 8 additions & 16 deletions .github/workflows/typecheck.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down
6 changes: 3 additions & 3 deletions app/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand All @@ -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",
Expand All @@ -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",
Expand All @@ -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",
Expand Down
9 changes: 9 additions & 0 deletions app/src/AppRoutes.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,15 @@ const AppRoutes = () => {
}
/>

<Route
path="/notifications"
element={
<ProtectedRoute requireAuth={true}>
<Notifications />
</ProtectedRoute>
}
/>

<Route
path="/settings/*"
element={
Expand Down
20 changes: 10 additions & 10 deletions app/test/e2e/specs/linux-cef-deb-runtime.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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';

Expand Down Expand Up @@ -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):/);
Expand Down Expand Up @@ -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 () => {
Expand Down
Loading
Loading