Migrate E2E coverage to Playwright (#2610)

This commit is contained in:
Steven Enamakel
2026-05-25 23:38:34 -07:00
committed by GitHub
parent 0a9f7a0e99
commit e7e7e8a951
122 changed files with 11968 additions and 328 deletions
+2 -2
View File
@@ -57,8 +57,8 @@ jobs:
cache: 'pnpm'
- name: Install dependencies
run: pnpm install --frozen-lockfile
run: bash scripts/ci-cancel-aware.sh pnpm install --frozen-lockfile
# Hard gate: mobile Tauri host compiles for Android.
- name: cargo check -- mobile host (aarch64-linux-android)
run: cargo check --manifest-path app/src-tauri-mobile/Cargo.toml --target aarch64-linux-android
run: bash scripts/ci-cancel-aware.sh cargo check --manifest-path app/src-tauri-mobile/Cargo.toml --target aarch64-linux-android
+5 -5
View File
@@ -238,9 +238,9 @@ jobs:
!= 'true') || (matrix.settings.platform != 'windows-latest' && steps.tauri-cli-cache-unix.outputs.cache-hit
!= 'true')
shell: bash
run: cargo install --locked --path app/src-tauri/vendor/tauri-cef/crates/tauri-cli
run: bash scripts/ci-cancel-aware.sh cargo install --locked --path app/src-tauri/vendor/tauri-cef/crates/tauri-cli
- name: Install dependencies
run: pnpm install --frozen-lockfile
run: bash scripts/ci-cancel-aware.sh pnpm install --frozen-lockfile
- name: Validate signing prerequisites
# The minisign pubkey is baked into the static tauri.conf.json, not
@@ -349,7 +349,7 @@ jobs:
if [ -z "${OPENHUMAN_CORE_SENTRY_DSN}" ]; then
echo "::warning::vars.OPENHUMAN_CORE_SENTRY_DSN (or legacy vars.OPENHUMAN_SENTRY_DSN) is empty — the standalone CLI artifact will ship without crash reporting."
fi
cargo build \
bash scripts/ci-cancel-aware.sh cargo build \
--manifest-path "$CORE_MANIFEST" \
--target "$MATRIX_TARGET" \
--bin "$CORE_BIN_NAME"
@@ -440,7 +440,7 @@ jobs:
# macOS / Windows take the original single-call path.
if [ "${RUNNER_OS}" = "Linux" ]; then
echo "[appimage-fix] linux split build: compile first to fetch CEF"
NODE_OPTIONS="--max-old-space-size=8192" cargo tauri build --no-bundle $PROFILE_FLAG -c "$TAURI_CONFIG_OVERRIDE" $MATRIX_ARGS
NODE_OPTIONS="--max-old-space-size=8192" bash ../scripts/ci-cancel-aware.sh cargo tauri build --no-bundle $PROFILE_FLAG -c "$TAURI_CONFIG_OVERRIDE" $MATRIX_ARGS
CEF_LIB_DIR="$(find "$HOME/.cache/tauri-cef" -name libcef.so -printf '%h\n' 2>/dev/null | head -1)"
if [ -z "$CEF_LIB_DIR" ]; then
echo "::error::libcef.so not found under ~/.cache/tauri-cef after --no-bundle compile; cannot satisfy lib4bin ldd resolution." >&2
@@ -449,7 +449,7 @@ jobs:
echo "[appimage-fix] prepending CEF lib dir to LD_LIBRARY_PATH: $CEF_LIB_DIR"
export LD_LIBRARY_PATH="$CEF_LIB_DIR${LD_LIBRARY_PATH:+:$LD_LIBRARY_PATH}"
fi
NODE_OPTIONS="--max-old-space-size=8192" cargo tauri build $PROFILE_FLAG -c "$TAURI_CONFIG_OVERRIDE" $MATRIX_ARGS
NODE_OPTIONS="--max-old-space-size=8192" bash ../scripts/ci-cancel-aware.sh cargo tauri build $PROFILE_FLAG -c "$TAURI_CONFIG_OVERRIDE" $MATRIX_ARGS
# Diagnostic for the recurring quick-sharun "is missing libraries!
# Aborting..." error on the AppImage bundler — the upstream script
+3 -3
View File
@@ -65,11 +65,11 @@ jobs:
- name: Install vendored tauri-cli (cef-aware bundler)
if: steps.tauri-cli-cache.outputs.cache-hit != 'true'
shell: bash
run: cargo install --locked --path app/src-tauri/vendor/tauri-cef/crates/tauri-cli
run: bash scripts/ci-cancel-aware.sh cargo install --locked --path app/src-tauri/vendor/tauri-cef/crates/tauri-cli
- name: Enable Corepack
run: corepack enable
- name: Install dependencies
run: pnpm install --frozen-lockfile
run: bash scripts/ci-cancel-aware.sh pnpm install --frozen-lockfile
# vite build runs via tauri.conf.json's beforeBuildCommand during the
# "Build Tauri app" step below — no separate frontend build needed.
@@ -103,7 +103,7 @@ jobs:
VITE_LATEST_APP_DOWNLOAD_URL: ${{ vars.VITE_LATEST_APP_DOWNLOAD_URL }}
TAURI_CONFIG_OVERRIDE: ${{ steps.config-overrides.outputs.json }}
run: |
NODE_OPTIONS="--max-old-space-size=8192" cargo tauri build -c "$TAURI_CONFIG_OVERRIDE" --target x86_64-pc-windows-msvc
NODE_OPTIONS="--max-old-space-size=8192" bash ../scripts/ci-cancel-aware.sh cargo tauri build -c "$TAURI_CONFIG_OVERRIDE" --target x86_64-pc-windows-msvc
- name: Upload MSI artifact
uses: actions/upload-artifact@v5
with:
+2 -2
View File
@@ -58,7 +58,7 @@ jobs:
restore-keys: |
pnpm-store-${{ runner.os }}-
- name: Install dependencies
run: pnpm install --frozen-lockfile
run: bash scripts/ci-cancel-aware.sh pnpm install --frozen-lockfile
# Core is linked into the Tauri binary as a path dep — no separate
# sidecar build / stage step needed.
- name: Build Tauri app (CEF default)
@@ -67,7 +67,7 @@ jobs:
# 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"},"plugins":{"updater":{"active":false}}}'
cargo tauri build -c "$TAURI_CONFIG_OVERRIDE" --bundles deb
bash ../scripts/ci-cancel-aware.sh cargo tauri build -c "$TAURI_CONFIG_OVERRIDE" --bundles deb
env:
NODE_ENV: production
# CI builds should point at staging, not production.
+76
View File
@@ -0,0 +1,76 @@
---
name: E2E Playwright
on:
workflow_dispatch: {}
permissions:
contents: read
packages: read
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
e2e-playwright:
name: E2E (Playwright / web lane)
runs-on: ubuntu-22.04
container:
image: ghcr.io/tinyhumansai/openhuman_ci:latest
timeout-minutes: 90
steps:
- name: Checkout code
uses: actions/checkout@v5
with:
fetch-depth: 1
persist-credentials: false
submodules: recursive
- 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: Cache Rust build artifacts
uses: Swatinem/rust-cache@v2
with:
workspaces: |
. -> target
app/src-tauri -> target
cache-on-failure: true
key: e2e-playwright-linux
- name: Install JS dependencies
run: bash scripts/ci-cancel-aware.sh pnpm install --frozen-lockfile
- name: Ensure .env exists for E2E build
run: |
touch .env
touch app/.env
- name: Build Playwright web E2E bundle + standalone core
run: bash scripts/ci-cancel-aware.sh pnpm --filter openhuman-app test:e2e:web:build
- name: Install Playwright Chromium headless shell
run: bash scripts/ci-cancel-aware.sh pnpm --filter openhuman-app exec playwright install chromium-headless-shell
- name: Run Playwright web E2E suite
env:
OPENHUMAN_WORKSPACE: ${{ runner.temp }}/openhuman-playwright-workspace
run: |
mkdir -p "$OPENHUMAN_WORKSPACE"
bash scripts/ci-cancel-aware.sh bash app/scripts/e2e-web-session.sh
- name: Upload Playwright E2E failure artifacts
if: failure()
uses: actions/upload-artifact@v5
with:
name: e2e-playwright-failure-logs-${{ github.run_id }}
path: |
${{ runner.temp }}/openhuman-playwright-workspace/**
retention-days: 7
if-no-files-found: ignore
+41 -51
View File
@@ -2,7 +2,7 @@
# Reusable E2E workflow — single source of truth for the desktop E2E recipe.
#
# Callers:
# - `.github/workflows/e2e.yml` — PR/push, Linux-only smoke (blocking).
# - `.github/workflows/e2e.yml` — PR/push, all-OS mega-flow gate.
# - `.github/workflows/release-staging.yml` — pretest gate, all 3 OS, full suite.
# - `.github/workflows/release-production.yml` — pretest gate, all 3 OS, full suite.
#
@@ -50,8 +50,8 @@ on:
full:
description:
When true, run the entire spec suite via `e2e-run-session.sh` (no
spec arg). When false, run the smoke spec + mega-flow (mega-flow
non-blocking). Releases set this to true; PR runs leave it false.
spec arg). When false, run the desktop full-flow lane only
(`mega-flow.spec.ts`). Releases set this to true.
type: boolean
default: false
@@ -60,7 +60,7 @@ permissions:
packages: read
jobs:
# Smoke/mega-flow gate for PR/push (full=false). The full-suite path lives in
# Mega-flow gate for PR/push (full=false). The full-suite path lives in
# `e2e-linux-full` below, which fans out across 4 parallel shards via
# `e2e-run-all-flows.sh --suite=<list>`. Splitting the two prevents the
# smoke job from paying matrix overhead for a 2-spec run.
@@ -118,7 +118,7 @@ jobs:
key: appium3-chromium-${{ runner.os }}-v1
- name: Install JS dependencies
run: pnpm install --frozen-lockfile
run: bash scripts/ci-cancel-aware.sh pnpm install --frozen-lockfile
- name: Ensure .env exists for E2E build
run: |
@@ -128,29 +128,20 @@ jobs:
- name: Install Appium and chromium driver
run: |
if ! command -v appium >/dev/null 2>&1; then
npm install -g appium@3
bash scripts/ci-cancel-aware.sh npm install -g appium@3
fi
# `appium driver list --installed` can miss cached installs on some
# Appium builds; install idempotently and ignore "already installed".
appium driver install --source=npm appium-chromium-driver >/dev/null 2>&1 || true
bash scripts/ci-cancel-aware.sh appium driver install --source=npm appium-chromium-driver >/dev/null 2>&1 || true
- name: Build E2E app
run: pnpm --filter openhuman-app test:e2e:build
run: bash scripts/ci-cancel-aware.sh pnpm --filter openhuman-app test:e2e:build
- name: Run E2E (smoke)
if: ${{ !inputs.full }}
run: |
xvfb-run -a --server-args="-screen 0 1280x960x24" \
bash app/scripts/e2e-run-session.sh test/e2e/specs/smoke.spec.ts smoke
# Mega-flow exercises the OAuth-success-deep-link and Composio
# trigger-lifecycle paths. Hard-fails on regressions — if the
# deep-link → custom-event propagation race resurfaces, fix it
# at the source rather than re-adding `continue-on-error`.
- name: Run E2E (mega-flow)
if: ${{ !inputs.full }}
run: |
xvfb-run -a --server-args="-screen 0 1280x960x24" \
bash scripts/ci-cancel-aware.sh \
xvfb-run -a --server-args="-screen 0 1280x960x24" \
bash app/scripts/e2e-run-session.sh test/e2e/specs/mega-flow.spec.ts mega-flow
- name: Upload E2E failure artifacts
@@ -228,7 +219,7 @@ jobs:
cef-x86_64-unknown-linux-gnu-v2-
- name: Install JS dependencies
run: pnpm install --frozen-lockfile
run: bash scripts/ci-cancel-aware.sh pnpm install --frozen-lockfile
- name: Ensure .env exists for E2E build
run: |
@@ -236,7 +227,7 @@ jobs:
touch app/.env
- name: Build E2E app
run: pnpm --filter openhuman-app test:e2e:build
run: bash scripts/ci-cancel-aware.sh pnpm --filter openhuman-app test:e2e:build
- name: Package build artifact
run: |
@@ -304,14 +295,14 @@ jobs:
key: appium3-chromium-${{ runner.os }}-v1
- name: Install JS dependencies (for test harness only)
run: pnpm install --frozen-lockfile
run: bash scripts/ci-cancel-aware.sh pnpm install --frozen-lockfile
- name: Install Appium and chromium driver
run: |
if ! command -v appium >/dev/null 2>&1; then
npm install -g appium@3
bash scripts/ci-cancel-aware.sh npm install -g appium@3
fi
appium driver install --source=npm appium-chromium-driver >/dev/null 2>&1 || true
bash scripts/ci-cancel-aware.sh appium driver install --source=npm appium-chromium-driver >/dev/null 2>&1 || true
- name: Download build artifact
uses: actions/download-artifact@v5
@@ -342,7 +333,8 @@ jobs:
if [[ "${E2E_BAIL_ON_FAILURE:-}" == "1" ]]; then
BAIL_FLAG="--bail"
fi
xvfb-run -a --server-args="-screen 0 1280x960x24" \
bash scripts/ci-cancel-aware.sh \
xvfb-run -a --server-args="-screen 0 1280x960x24" \
bash app/scripts/e2e-run-all-flows.sh --skip-preflight \
--suite=${{ matrix.shard.suites }} $BAIL_FLAG
@@ -409,7 +401,7 @@ jobs:
key: rust-e2e-linux
- name: Install JS dependencies
run: pnpm install --frozen-lockfile
run: bash scripts/ci-cancel-aware.sh pnpm install --frozen-lockfile
- name: Ensure .env exists for tests
run: |
@@ -417,7 +409,7 @@ jobs:
touch app/.env
- name: Run Rust E2E suite (tests/*_e2e.rs vs mock backend)
run: pnpm test:rust:e2e
run: bash scripts/ci-cancel-aware.sh pnpm test:rust:e2e
# No artifact uploads here either — same release-workflow reuse
# concern as the Tauri job above. Mock-backend log lives at
@@ -486,7 +478,7 @@ jobs:
key: appium3-chromium-${{ runner.os }}-v1
- name: Install JS dependencies
run: pnpm install --frozen-lockfile
run: bash scripts/ci-cancel-aware.sh pnpm install --frozen-lockfile
- name: Ensure .env exists for E2E build
run: |
@@ -496,14 +488,14 @@ jobs:
- name: Install Appium and chromium driver
run: |
if ! command -v appium >/dev/null 2>&1; then
npm install -g appium@3
bash scripts/ci-cancel-aware.sh npm install -g appium@3
fi
# `appium driver list --installed` can miss cached installs on some
# Appium builds; install idempotently and ignore "already installed".
appium driver install --source=npm appium-chromium-driver >/dev/null 2>&1 || true
bash scripts/ci-cancel-aware.sh appium driver install --source=npm appium-chromium-driver >/dev/null 2>&1 || true
- name: Build E2E app
run: pnpm --filter openhuman-app test:e2e:build
run: bash scripts/ci-cancel-aware.sh pnpm --filter openhuman-app test:e2e:build
# macOS rejects dynamic-framework loads from unsigned bundles — adhoc
# signing satisfies the loader without a real developer-ID cert.
@@ -514,10 +506,9 @@ jobs:
codesign --verify --deep --verbose=2 \
app/src-tauri/target/debug/bundle/macos/OpenHuman.app
- name: Run E2E (smoke + mega-flow)
- name: Run E2E (mega-flow)
run: |
bash app/scripts/e2e-run-session.sh test/e2e/specs/smoke.spec.ts smoke
bash app/scripts/e2e-run-session.sh test/e2e/specs/mega-flow.spec.ts mega-flow
bash scripts/ci-cancel-aware.sh bash app/scripts/e2e-run-session.sh test/e2e/specs/mega-flow.spec.ts mega-flow
# Artifact uploads intentionally omitted — see e2e-linux for the
# reusable-workflow-is-also-used-by-releases rationale.
@@ -574,7 +565,7 @@ jobs:
key: appium3-chromium-${{ runner.os }}-v1
- name: Install JS dependencies
run: pnpm install --frozen-lockfile
run: bash scripts/ci-cancel-aware.sh pnpm install --frozen-lockfile
- name: Ensure .env exists for E2E build
shell: bash
@@ -586,20 +577,19 @@ jobs:
shell: bash
run: |
if ! command -v appium >/dev/null 2>&1; then
npm install -g appium@3
bash scripts/ci-cancel-aware.sh npm install -g appium@3
fi
# `appium driver list --installed` can miss cached installs on some
# Appium builds; install idempotently and ignore "already installed".
appium driver install --source=npm appium-chromium-driver >/dev/null 2>&1 || true
bash scripts/ci-cancel-aware.sh appium driver install --source=npm appium-chromium-driver >/dev/null 2>&1 || true
- name: Build E2E app
run: pnpm --filter openhuman-app test:e2e:build
run: bash scripts/ci-cancel-aware.sh pnpm --filter openhuman-app test:e2e:build
- name: Run E2E (smoke + mega-flow)
- name: Run E2E (mega-flow)
shell: bash
run: |
bash app/scripts/e2e-run-session.sh test/e2e/specs/smoke.spec.ts smoke
bash app/scripts/e2e-run-session.sh test/e2e/specs/mega-flow.spec.ts mega-flow
bash scripts/ci-cancel-aware.sh bash app/scripts/e2e-run-session.sh test/e2e/specs/mega-flow.spec.ts mega-flow
# Artifact uploads intentionally omitted — see e2e-linux for the
# reusable-workflow-is-also-used-by-releases rationale.
@@ -680,7 +670,7 @@ jobs:
key: appium3-chromium-${{ runner.os }}-v1
- name: Install JS dependencies
run: pnpm install --frozen-lockfile
run: bash scripts/ci-cancel-aware.sh pnpm install --frozen-lockfile
- name: Ensure .env exists for E2E build
run: |
@@ -690,9 +680,9 @@ jobs:
- name: Install Appium and chromium driver
run: |
if ! command -v appium >/dev/null 2>&1; then
npm install -g appium@3
bash scripts/ci-cancel-aware.sh npm install -g appium@3
fi
appium driver install --source=npm appium-chromium-driver >/dev/null 2>&1 || true
bash scripts/ci-cancel-aware.sh appium driver install --source=npm appium-chromium-driver >/dev/null 2>&1 || true
# Binary cache — see Linux full job for the rationale. Mac caches the
# entire .app bundle (self-contained including frontend assets + CEF
@@ -707,7 +697,7 @@ jobs:
- name: Build E2E app
if: steps.e2e-binary-cache.outputs.cache-hit != 'true'
run: pnpm --filter openhuman-app test:e2e:build
run: bash scripts/ci-cancel-aware.sh pnpm --filter openhuman-app test:e2e:build
# Adhoc-sign runs unconditionally — codesign is idempotent and a
# restored .app bundle from cache also needs to be (re-)signed for
@@ -727,7 +717,7 @@ jobs:
if [[ "${E2E_BAIL_ON_FAILURE:-}" == "1" ]]; then
BAIL_FLAG="--bail"
fi
bash app/scripts/e2e-run-all-flows.sh --skip-preflight \
bash scripts/ci-cancel-aware.sh bash app/scripts/e2e-run-all-flows.sh --skip-preflight \
--suite=${{ matrix.shard.suites }} $BAIL_FLAG
- name: Upload E2E failure artifacts
@@ -822,7 +812,7 @@ jobs:
key: appium3-chromium-${{ runner.os }}-v1
- name: Install JS dependencies
run: pnpm install --frozen-lockfile
run: bash scripts/ci-cancel-aware.sh pnpm install --frozen-lockfile
- name: Ensure .env exists for E2E build
shell: bash
@@ -834,9 +824,9 @@ jobs:
shell: bash
run: |
if ! command -v appium >/dev/null 2>&1; then
npm install -g appium@3
bash scripts/ci-cancel-aware.sh npm install -g appium@3
fi
appium driver install --source=npm appium-chromium-driver >/dev/null 2>&1 || true
bash scripts/ci-cancel-aware.sh appium driver install --source=npm appium-chromium-driver >/dev/null 2>&1 || true
# Binary cache — see Linux full job for rationale. Windows is built
# with --debug --no-bundle so the .exe + frontend dist are what the
@@ -856,7 +846,7 @@ jobs:
# hit (see Linux full job for the rationale).
- name: Build E2E app
if: steps.e2e-binary-cache.outputs.cache-hit != 'true' || steps.cef-cache.outputs.cache-hit != 'true'
run: pnpm --filter openhuman-app test:e2e:build
run: bash scripts/ci-cancel-aware.sh pnpm --filter openhuman-app test:e2e:build
- name: Run E2E shard (${{ matrix.shard.name }} — suites=${{ matrix.shard.suites }})
shell: bash
@@ -871,7 +861,7 @@ jobs:
if [[ "${E2E_BAIL_ON_FAILURE:-}" == "1" ]]; then
BAIL_FLAG="--bail"
fi
bash app/scripts/e2e-run-all-flows.sh --skip-preflight \
bash scripts/ci-cancel-aware.sh bash app/scripts/e2e-run-all-flows.sh --skip-preflight \
--suite=${{ matrix.shard.suites }} $BAIL_FLAG
- name: Upload E2E failure artifacts
+8 -25
View File
@@ -1,33 +1,16 @@
---
# PR/push E2E gate.
#
# Calls the reusable `e2e-reusable.yml` with Linux only (smoke + mega-flow).
# macOS / Windows E2E only runs at release time — see release-staging.yml
# and release-production.yml `pretest` jobs which call the same reusable
# workflow with `run_macos`, `run_windows`, and `full` all true.
#
# `workflow_dispatch` lets an operator opt in to a full-suite all-OS run
# without cutting a release tag.
# Desktop full-flow lane (mega-flow) across Linux, macOS, and Windows.
# The browser-hosted Playwright suite lives in its own standalone workflow so
# it can be run on demand without gating every push / PR.
name: E2E
on:
push:
branches: [main]
pull_request:
workflow_dispatch:
inputs:
run_macos:
description: Also run the macOS E2E job.
type: boolean
default: false
run_windows:
description: Also run the Windows E2E job.
type: boolean
default: false
full:
description: Run the entire spec suite (slow; ~30+ min per OS).
type: boolean
default: false
workflow_dispatch: {}
permissions:
contents: read
@@ -39,10 +22,10 @@ concurrency:
cancel-in-progress: true
jobs:
e2e:
e2e-desktop:
uses: ./.github/workflows/e2e-reusable.yml
with:
run_linux: true
run_macos: ${{ github.event_name == 'workflow_dispatch' && inputs.run_macos }}
run_windows: ${{ github.event_name == 'workflow_dispatch' && inputs.run_windows }}
full: ${{ github.event_name == 'workflow_dispatch' && inputs.full }}
run_macos: true
run_windows: true
full: false
+5 -5
View File
@@ -66,27 +66,27 @@ jobs:
cache: 'pnpm'
- name: Install dependencies
run: pnpm install --frozen-lockfile
run: bash scripts/ci-cancel-aware.sh pnpm install --frozen-lockfile
# Hard gate: mobile Tauri host compiles for iOS. No more soft-gate
# `continue-on-error` — the mobile crate uses stock Tauri without CEF
# so cef-dll-sys is not in the dependency graph.
- name: cargo check -- mobile host (aarch64-apple-ios)
run: cargo check --manifest-path app/src-tauri-mobile/Cargo.toml --target aarch64-apple-ios
run: bash scripts/ci-cancel-aware.sh cargo check --manifest-path app/src-tauri-mobile/Cargo.toml --target aarch64-apple-ios
# Hard gate: PTT plugin (host-target check; Swift sources are built
# lazily by swift-rs during the iOS-target check above).
- name: cargo check -- tauri-plugin-ptt
run: cargo check --manifest-path packages/tauri-plugin-ptt/Cargo.toml
run: bash scripts/ci-cancel-aware.sh cargo check --manifest-path packages/tauri-plugin-ptt/Cargo.toml
# Hard gate: TypeScript compile.
- name: pnpm compile
run: pnpm --dir app compile
run: bash scripts/ci-cancel-aware.sh pnpm --dir app compile
# Hard gate: iOS-relevant Vitest suites.
- name: pnpm test (iOS suites)
run: >
pnpm --dir app test --
bash scripts/ci-cancel-aware.sh pnpm --dir app test --
src/services/transport
src/lib/tunnel
src/pages/ios
+1 -1
View File
@@ -76,7 +76,7 @@ jobs:
OPENHUMAN_BUILD_SHA: ${{ github.sha }}
OPENHUMAN_APP_ENV: production
run: |
cargo build --release --bin openhuman-core
bash scripts/ci-cancel-aware.sh cargo build --release --bin openhuman-core
VERSION="${{ github.event.release.tag_name }}"
bash scripts/release/package-cli-tarball.sh \
target/release/openhuman-core \
+40 -41
View File
@@ -28,16 +28,23 @@ on:
default: patch
type: choice
options: [patch, minor, major]
skip_e2e:
skip_pretests:
description:
Skip the entire pretest phase (unit/rust plus E2E) and continue
directly to create-release + build matrix. Use only when the
required pretest signal is already known (e.g. promoting a
staging tag whose pretests already ran green) and you need to
unblock a production cut.
Skip the unit/rust pretest phase and continue directly to the build
matrix. Release workflows no longer run E2E. Use only when the
required pretest signal is already known and you need to unblock a
production cut.
required: false
type: boolean
default: false
create_release:
description:
Create and publish the GitHub Release and attach release assets. When
false, run the production build matrix without creating or publishing
a GitHub Release.
required: false
type: boolean
default: true
permissions:
contents: write
packages: write
@@ -52,9 +59,8 @@ concurrency:
# prepare-build
# │
# ├─── pretest-tests (reusable test-reusable.yml — unit + rust)
# ├─── pretest-e2e (reusable e2e-reusable.yml — all 3 OS, full)
# │
# ├─── create-release
# ├─── create-release (optional no-op when `create_release=false`)
# │ │
# │ ┌────┴───────────────┬────────────────┐
# │ │ │ │
@@ -309,8 +315,7 @@ jobs:
echo "base_url=$BASE_URL" >> "$GITHUB_OUTPUT"
# =========================================================================
# Phase 1b: Pretest gate — run the full test + E2E suite across every
# target OS exactly once on the build ref before we spin up the release
# Phase 1b: Pretest gate — run unit + rust on the build ref before we spin up the release
# draft or any signed-build matrix. Pretest failures abort the workflow
# before `create-release` runs, so a busted commit never produces a
# half-finished GH Release that has to be cleaned up.
@@ -318,42 +323,35 @@ jobs:
pretest-tests:
name: Pretest — unit + rust
needs: [prepare-build]
if: ${{ !inputs.skip_e2e }}
if: ${{ !inputs.skip_pretests }}
uses: ./.github/workflows/test-reusable.yml
with:
ref: ${{ needs.prepare-build.outputs.build_ref }}
pretest-e2e:
name: Pretest — E2E (all OS, full suite)
needs: [prepare-build]
if: ${{ !inputs.skip_e2e }}
uses: ./.github/workflows/e2e-reusable.yml
with:
ref: ${{ needs.prepare-build.outputs.build_ref }}
run_linux: true
run_macos: true
run_windows: true
full: true
# =========================================================================
# Phase 2: Create draft GitHub release
# =========================================================================
create-release:
name: Create GitHub release
name: Prepare GitHub release
runs-on: ubuntu-latest
environment: Production
needs: [prepare-build, pretest-tests, pretest-e2e]
needs: [prepare-build, pretest-tests]
if: >-
always()
&& needs.prepare-build.result == 'success'
&& (needs.pretest-tests.result == 'success'
|| (inputs.skip_e2e && needs.pretest-tests.result == 'skipped'))
&& (needs.pretest-e2e.result == 'success'
|| (inputs.skip_e2e && needs.pretest-e2e.result == 'skipped'))
|| (inputs.skip_pretests && needs.pretest-tests.result == 'skipped'))
outputs:
release_id: ${{ steps.create.outputs.release_id }}
upload_url: ${{ steps.create.outputs.upload_url }}
release_id: ${{ steps.create.outputs.release_id || steps.noop.outputs.release_id }}
upload_url: ${{ steps.create.outputs.upload_url || steps.noop.outputs.upload_url }}
steps:
- name: Skip release creation
if: ${{ !inputs.create_release }}
id: noop
run: |
echo "release_id=" >> "$GITHUB_OUTPUT"
echo "upload_url=" >> "$GITHUB_OUTPUT"
- name: Create draft release with generated notes
if: ${{ inputs.create_release }}
id: create
uses: actions/github-script@v8
with:
@@ -390,7 +388,7 @@ jobs:
build-desktop:
name: Build desktop matrix
needs: [prepare-build, create-release]
# `always()` is load-bearing: when `skip_e2e=true` the pretest jobs are
# `always()` is load-bearing: when `skip_pretests=true` the pretest job is
# `skipped`, and GitHub propagates that skipped status transitively to any
# downstream job lacking an explicit status function — even though we only
# `needs` create-release here, the build would otherwise be skipped along
@@ -412,10 +410,10 @@ jobs:
telegram_bot_username: openhumanaibot
# with_macos_signing defaults to true — left implicit; production
# always notarizes. See build-desktop.yml inputs.
with_release_upload: true
with_release_upload: ${{ inputs.create_release }}
release_id: ${{ needs.create-release.outputs.release_id }}
build_sidecar: false
skip_pretests: ${{ inputs.skip_e2e }}
skip_pretests: ${{ inputs.skip_pretests }}
# =========================================================================
# Phase 3b: Build & push Docker image (runs parallel with build-desktop).
@@ -514,7 +512,7 @@ jobs:
build-cli-linux:
name: "CLI: ${{ matrix.target }}"
needs: [prepare-build, create-release]
if: always() && needs.create-release.result == 'success'
if: ${{ inputs.create_release && always() && needs.create-release.result == 'success' }}
environment: Production
runs-on: ${{ matrix.runner }}
strategy:
@@ -561,7 +559,7 @@ jobs:
# baked elsewhere — see prepare-build.outputs.short_sha comment.
OPENHUMAN_BUILD_SHA: ${{ needs.prepare-build.outputs.short_sha }}
OPENHUMAN_APP_ENV: production
run: cargo build --release --bin openhuman-core
run: bash scripts/ci-cancel-aware.sh cargo build --release --bin openhuman-core
- name: Package and upload tarball to release
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
@@ -583,7 +581,7 @@ jobs:
publish-updater-manifest:
name: Publish updater manifest (latest.json)
needs: [prepare-build, create-release, build-desktop]
if: always() && needs.build-desktop.result == 'success'
if: ${{ inputs.create_release && always() && needs.build-desktop.result == 'success' }}
runs-on: ubuntu-latest
environment: Production
steps:
@@ -616,6 +614,8 @@ jobs:
- build-docker
- publish-updater-manifest
if: >-
inputs.create_release
&&
always()
&& needs.build-desktop.result == 'success'
&& needs.build-cli-linux.result == 'success'
@@ -716,7 +716,7 @@ jobs:
runs-on: ubuntu-latest
environment: Production
needs: [prepare-build, publish-release]
if: always() && needs.publish-release.result == 'success'
if: ${{ inputs.create_release && always() && needs.publish-release.result == 'success' }}
env:
REGISTRY: ghcr.io
IMAGE_NAME: tinyhumansai/openhuman-core
@@ -752,7 +752,7 @@ jobs:
runs-on: ubuntu-latest
environment: Production
needs: [prepare-build, publish-release]
if: always() && needs.publish-release.result == 'success'
if: ${{ inputs.create_release && always() && needs.publish-release.result == 'success' }}
env:
SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }}
SENTRY_URL: ${{ vars.SENTRY_URL }}
@@ -792,7 +792,6 @@ jobs:
needs:
- prepare-build
- pretest-tests
- pretest-e2e
- create-release
- build-desktop
- build-cli-linux
@@ -812,7 +811,7 @@ jobs:
&& (
(needs.create-release.result != 'success'
&& (needs.pretest-tests.result == 'failure' || needs.pretest-tests.result == 'cancelled'
|| needs.pretest-e2e.result == 'failure' || needs.pretest-e2e.result == 'cancelled'))
))
|| (needs.create-release.result == 'success'
&& (needs.build-desktop.result == 'failure' || needs.build-desktop.result == 'cancelled'
|| needs.build-cli-linux.result == 'failure' || needs.build-cli-linux.result == 'cancelled'
@@ -823,7 +822,7 @@ jobs:
- name: Delete GitHub release
# Skip on the pretest-failure cleanup path: create-release didn't run,
# so there's no draft release to delete (only an orphaned tag).
if: needs.create-release.result == 'success'
if: ${{ inputs.create_release && needs.create-release.result == 'success' }}
uses: actions/github-script@v8
with:
script: |
+17 -38
View File
@@ -3,12 +3,12 @@ name: Release Staging
on:
workflow_dispatch:
inputs:
skip_e2e:
skip_pretests:
description:
Skip the entire pretest phase (unit/rust plus E2E) and continue
directly to the desktop/docker staging build. Use only when the
required pretest signal is already known and you need to unblock a
staging cut.
Skip the unit/rust pretest phase and continue directly to the
desktop/docker staging build. Release workflows no longer run E2E.
Use only when the required pretest signal is already known and you
need to unblock a staging cut.
required: false
type: boolean
default: false
@@ -26,9 +26,8 @@ concurrency:
# prepare-build
# │
# ├── pretest-tests (reusable test-reusable.yml — unit + rust;
# │ optional when `skip_e2e` is true)
# ├── pretest-e2e (reusable e2e-reusable.yml — all 3 OS, full suite;
# │ optional when `skip_e2e` is true)
# │ optional when `skip_pretests` is true)
# ├── pretest-tests (reusable test-reusable.yml — unit + rust)
# │
# ├── build-desktop (delegated to .github/workflows/build-desktop.yml)
# ├── build-docker (build only — no GHCR push on staging)
@@ -37,10 +36,8 @@ concurrency:
# │
# cleanup-failed-staging (on failure)
#
# The pretest jobs are a hard gate — `build-desktop` and `build-docker`
# only start once unit/rust/E2E have all passed across every target. This
# guarantees we never produce a staging tag whose installers were built
# against unproven code.
# The pretest job is a hard gate — `build-desktop` and `build-docker`
# only start once unit/rust have passed, unless explicitly skipped.
#
# The actual desktop build / Sentry / artifact-upload pipeline lives in
# `.github/workflows/build-desktop.yml` and is shared with
@@ -189,42 +186,27 @@ jobs:
echo "base_url=https://staging-api.tinyhumans.ai/" >> "$GITHUB_OUTPUT"
# =========================================================================
# Phase 1b: Pretest gate — run the full test + E2E suite across every
# target OS exactly once on the staging commit before any build job
# Phase 1b: Pretest gate — run unit + rust once on the staging commit before any build job
# spins up. A failure here aborts the matrix (and `cleanup-failed-staging`
# deletes the tag) without burning four signed Tauri builds first.
# =========================================================================
pretest-tests:
name: Pretest — unit + rust
needs: [prepare-build]
if: ${{ !inputs.skip_e2e }}
if: ${{ !inputs.skip_pretests }}
uses: ./.github/workflows/test-reusable.yml
with:
ref: ${{ needs.prepare-build.outputs.build_ref }}
pretest-e2e:
name: Pretest — E2E (all OS, full suite)
needs: [prepare-build]
if: ${{ !inputs.skip_e2e }}
uses: ./.github/workflows/e2e-reusable.yml
with:
ref: ${{ needs.prepare-build.outputs.build_ref }}
run_linux: true
run_macos: true
run_windows: true
full: true
# =========================================================================
# Phase 2: Build desktop artifacts (delegated to reusable workflow)
# =========================================================================
build-desktop:
name: Build desktop matrix
needs: [prepare-build, pretest-tests, pretest-e2e]
needs: [prepare-build, pretest-tests]
if: >-
always()
&& (needs.pretest-tests.result == 'success'
|| (inputs.skip_e2e && needs.pretest-tests.result == 'skipped'))
&& (needs.pretest-e2e.result == 'success'
|| (inputs.skip_e2e && needs.pretest-e2e.result == 'skipped'))
|| (inputs.skip_pretests && needs.pretest-tests.result == 'skipped'))
uses: ./.github/workflows/build-desktop.yml
secrets: inherit
with:
@@ -254,7 +236,7 @@ jobs:
# real consumer. Set `build_sidecar: true` to re-enable a per-platform
# CLI Actions artifact + its Sentry DIF upload for QA spot-checks.
build_sidecar: false
skip_pretests: ${{ inputs.skip_e2e }}
skip_pretests: ${{ inputs.skip_pretests }}
# =========================================================================
# Phase 2b: Build the openhuman-core Docker image without pushing.
@@ -267,13 +249,11 @@ jobs:
# =========================================================================
build-docker:
name: "Docker: build (no push)"
needs: [prepare-build, pretest-tests, pretest-e2e]
needs: [prepare-build, pretest-tests]
if: >-
always()
&& (needs.pretest-tests.result == 'success'
|| (inputs.skip_e2e && needs.pretest-tests.result == 'skipped'))
&& (needs.pretest-e2e.result == 'success'
|| (inputs.skip_e2e && needs.pretest-e2e.result == 'skipped'))
|| (inputs.skip_pretests && needs.pretest-tests.result == 'skipped'))
runs-on: ubuntu-latest
environment: Production
steps:
@@ -354,12 +334,11 @@ jobs:
name: Remove staging tag if build failed
runs-on: ubuntu-latest
environment: Production
needs: [prepare-build, pretest-tests, pretest-e2e, build-desktop, build-docker]
needs: [prepare-build, pretest-tests, build-desktop, build-docker]
if: >-
always()
&& needs.prepare-build.result == 'success'
&& (needs.pretest-tests.result == 'failure' || needs.pretest-tests.result == 'cancelled'
|| needs.pretest-e2e.result == 'failure' || needs.pretest-e2e.result == 'cancelled'
|| needs.build-desktop.result == 'failure' || needs.build-desktop.result == 'cancelled'
|| needs.build-docker.result == 'failure' || needs.build-docker.result == 'cancelled')
steps:
+7 -7
View File
@@ -57,9 +57,9 @@ jobs:
restore-keys: |
pnpm-store-${{ runner.os }}-
- name: Install dependencies
run: pnpm install --frozen-lockfile
run: bash scripts/ci-cancel-aware.sh pnpm install --frozen-lockfile
- name: Verify i18n coverage (missing / extra / drifted / en.ts ↔ chunks)
run: pnpm i18n:check
run: bash scripts/ci-cancel-aware.sh pnpm i18n:check
unit-tests:
if: inputs.run_unit
@@ -81,9 +81,9 @@ jobs:
restore-keys: |
pnpm-store-${{ runner.os }}-
- name: Install dependencies
run: pnpm install --frozen-lockfile
run: bash scripts/ci-cancel-aware.sh pnpm install --frozen-lockfile
- name: Run tests with coverage
run: pnpm test:coverage
run: bash scripts/ci-cancel-aware.sh pnpm test:coverage
env:
NODE_ENV: test
- name: Upload coverage reports
@@ -122,7 +122,7 @@ jobs:
- name: Install sccache
uses: mozilla-actions/sccache-action@v0.0.9
- name: Test core crate (openhuman)
run: cargo test -p openhuman
run: bash scripts/ci-cancel-aware.sh cargo test -p openhuman
rust-core-tests-windows:
if: inputs.run_rust_core
@@ -153,7 +153,7 @@ jobs:
# Runs the full security::secrets suite including all #[cfg(windows)]
# tests: self-repair ACL path (OPENHUMAN-TAURI-GN), domain-qualified
# icacls username, is_permission_error, repair_windows_acl.
run: cargo test -p openhuman -- security::secrets --nocapture
run: bash scripts/ci-cancel-aware.sh cargo test -p openhuman -- security::secrets --nocapture
rust-tauri-tests:
if: inputs.run_rust_tauri
@@ -192,4 +192,4 @@ jobs:
- name: Install sccache
uses: mozilla-actions/sccache-action@v0.0.9
- name: Test Tauri shell (OpenHuman)
run: cargo test --manifest-path app/src-tauri/Cargo.toml
run: bash scripts/ci-cancel-aware.sh cargo test --manifest-path app/src-tauri/Cargo.toml