--- name: Test on: push: branches: [main] pull_request: workflow_dispatch: inputs: run_macos_e2e: description: Run macOS E2E tests (Appium Mac2) required: false default: 'false' type: choice options: ['false', 'true'] permissions: contents: read pull-requests: read concurrency: group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.head_ref || github.ref }} cancel-in-progress: true jobs: unit-tests: name: Frontend Unit Tests runs-on: ubuntu-22.04 container: image: ghcr.io/tinyhumansai/openhuman_ci:rust-1.93.0 steps: - name: Checkout code uses: actions/checkout@v5 with: fetch-depth: 1 - name: Cache pnpm store uses: actions/cache@v5 with: path: ~/.local/share/pnpm/store key: pnpm-store-${{ runner.os }}-${{ hashFiles('pnpm-lock.yaml') }} restore-keys: | pnpm-store-${{ runner.os }}- - name: Install dependencies run: pnpm install --frozen-lockfile - name: Run tests with coverage run: pnpm test:coverage env: NODE_ENV: test - name: Upload coverage reports if: always() uses: actions/upload-artifact@v5 with: name: coverage-report path: coverage retention-days: 7 rust-core-tests: name: Rust Core Tests + Quality runs-on: ubuntu-22.04 # Healthy runtime on this image is ~6 minutes. Cap at 20 so the rare # `LLM_PERMITS` cross-runtime-semaphore deadlock surfaces logs instead # of wedging the runner for the GitHub-Actions default 6h ceiling. timeout-minutes: 20 container: image: ghcr.io/tinyhumansai/openhuman_ci:rust-1.93.0 env: # Incremental compilation is pointless on fresh CI runners and just wastes # disk and IO. Swatinem/rust-cache already handles cross-run warmup. CARGO_INCREMENTAL: '0' # Route rustc through sccache, backed by the GitHub Actions cache. This # layers on top of Swatinem/rust-cache (which caches target/) by caching # individual compilation units across branches. RUSTC_WRAPPER: sccache SCCACHE_GHA_ENABLED: 'true' steps: - name: Checkout code uses: actions/checkout@v5 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 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@v5 with: fetch-depth: 1 # Required for app/src-tauri/vendor/tauri-cef — the fork supplies # tauri-runtime-cef (compiled into the default build) and the # cef-aware tauri-cli + tauri-bundler used by release workflows. submodules: recursive - name: Cache Rust build artifacts uses: Swatinem/rust-cache@v2 with: workspaces: | . -> 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 # re-fetching ~400MB every PR run. - name: Cache CEF binary distribution uses: actions/cache@v5 with: path: ~/.cache/tauri-cef key: cef-ubuntu-22.04-${{ hashFiles('app/src-tauri/Cargo.toml') }} restore-keys: | cef-ubuntu-22.04- - name: Install sccache uses: mozilla-actions/sccache-action@v0.0.9 # Core is linked into the Tauri binary as a path dep, so the shell's # cargo test pulls it in automatically — no separate sidecar build. - name: Test Tauri shell (OpenHuman) run: cargo test --manifest-path app/src-tauri/Cargo.toml # E2E note: OpenHuman's default desktop runtime is CEF. Linux tauri-driver # talks to WebKitWebDriver / webkit2gtk and cannot drive the CEF-backed # WebView, so Linux CEF E2E remains commented out until a CEF-compatible # driver or replacement harness exists. Use macOS/Appium for local or manual # desktop E2E runs. # e2e-linux: # name: E2E (Linux / tauri-driver) # runs-on: ubuntu-22.04 # timeout-minutes: 60 # steps: # - name: Checkout code # uses: actions/checkout@v5 # with: # fetch-depth: 1 # submodules: recursive # - name: Setup Node.js 24.x # uses: actions/setup-node@v5 # with: # node-version: 24.x # cache: "pnpm" # - name: Install Rust (rust-toolchain.toml) # uses: dtolnay/rust-toolchain@1.93.0 # - name: Install system dependencies # run: | # sudo apt-get update # sudo apt-get install -y \ # libgtk-3-dev libwebkit2gtk-4.1-dev libappindicator3-dev \ # librsvg2-dev patchelf \ # xvfb at-spi2-core dbus-x11 \ # webkit2gtk-driver \ # libasound2-dev libxdo-dev libxtst-dev libx11-dev libevdev-dev # - name: Cargo.lock fingerprint (deps only) # id: cargo-lock-fingerprint # shell: bash # run: | # echo "hash=$(tail -n +8 Cargo.lock | openssl dgst -sha256 | awk '{print $2}')" >> "$GITHUB_OUTPUT" # - name: Cache Cargo registry and build # uses: actions/cache@v5 # with: # path: | # ~/.cargo/registry # ~/.cargo/git # target # key: ${{ runner.os }}-e2e-cargo-${{ steps.cargo-lock-fingerprint.outputs.hash }} # restore-keys: | # ${{ runner.os }}-e2e-cargo- # - name: Install tauri-driver # run: cargo install tauri-driver --version 2.0.5 # - name: Install JS dependencies # run: pnpm install --frozen-lockfile # - name: Ensure .env exists for E2E build # run: | # touch .env # touch app/.env # - name: Build E2E app # run: pnpm --filter openhuman-app test:e2e:build # # Core is linked in-process through the Tauri host; no extra binary # # staging step is required before launching the app. # - name: Run E2E tests under Xvfb # run: | # export DISPLAY=:99 # Xvfb :99 -screen 0 1280x1024x24 & # sleep 2 # # dbus session is required by webkit2gtk # eval "$(dbus-launch --sh-syntax)" # # Ensure XDG dirs exist for deep-link URL scheme registration on Linux # mkdir -p ~/.local/share/applications # export RUST_BACKTRACE=1 # cd app # # Core specs for the old WebKit-compatible Linux harness # FAILED=0 # for spec in \ # test/e2e/specs/login-flow.spec.ts \ # test/e2e/specs/smoke.spec.ts \ # test/e2e/specs/navigation.spec.ts \ # test/e2e/specs/telegram-flow.spec.ts; do # SPEC_NAME=$(basename "$spec" .spec.ts) # echo "=== Running $SPEC_NAME ===" # bash scripts/e2e-run-spec.sh "$spec" "$SPEC_NAME" || { # echo "FAILED: $SPEC_NAME" # cat /tmp/tauri-driver-e2e-${SPEC_NAME}.log 2>/dev/null || true # FAILED=1 # } # done # # Extended specs (auth, billing, gmail, notion, payments) were skipped # # on the old Linux harness because webkit2gtk text matching differences # # caused Settings page navigation timeouts. Full suite runs through # # macOS/Appium locally or in a manually dispatched workflow when enabled. # if [ "$FAILED" -eq 1 ]; then # echo "Core E2E specs failed" # exit 1 # fi # echo "Core E2E specs passed" # e2e-macos: # name: E2E (macOS / Appium) # if: github.event_name == 'workflow_dispatch' && github.event.inputs.run_macos_e2e == 'true' # runs-on: macos-latest # timeout-minutes: 90 # steps: # - name: Checkout code # uses: actions/checkout@v5 # with: # fetch-depth: 1 # submodules: recursive # - name: Setup Node.js 24.x # uses: actions/setup-node@v5 # with: # node-version: 24.x # cache: "pnpm" # - name: Install Rust (rust-toolchain.toml) # uses: dtolnay/rust-toolchain@1.93.0 # - name: Install dependencies # run: pnpm install --frozen-lockfile # - name: Ensure .env exists for E2E build # run: | # touch .env # touch app/.env # - name: Install Appium and mac2 driver # run: | # npm install -g appium # appium driver install mac2 # - name: Build E2E app bundle # run: pnpm --filter openhuman-app test:e2e:build # - name: Run all E2E flows # run: pnpm --filter openhuman-app test:e2e:all:flows