mirror of
https://github.com/tinyhumansai/openhuman.git
synced 2026-07-29 14:02:19 +00:00
feat(build): make CEF the default webview runtime across builds, tests, and releases (#641)
- Flip `app/src-tauri/Cargo.toml` `default = ["cef"]` (wry is now opt-in via `--no-default-features --features wry`). `cef-dll-sys` auto-downloads the Chromium runtime per-target at compile time. - Update dev scripts: `dev:app` now uses CEF + keychain safe-storage setup; `dev:cef` aliased to it; new `dev:wry` for opt-out; `macos:build:*` and `tauri:build:ui` switched to `cargo tauri` so the CEF-aware bundler runs. - Replace `tauri-apps/tauri-action@v0.6.2` / `yarn tauri build` with `cargo tauri build` in `build.yml`, `build-windows.yml`, and `release.yml`. The upstream `@tauri-apps/cli` binary does not bundle CEF framework files into the produced installer — only the fork at `vendor/tauri-cef` does, so workflows must use the fork's CLI or the shipped apps fail to launch. - Bake the CEF-aware `cargo-tauri` into `ghcr.io/tinyhumansai/openhuman_ci` by compiling it from the submodule during Docker image build, plus CEF runtime libs (libnss3, libgbm1, libxshmfence1, …). Skips the per-run cargo-install in the container-based `build.yml`. - Cache CEF downloads per-OS in matrix jobs (~400MB/platform) and cache the compiled `cargo-tauri` binary on raw GH runners (build-windows, release). - Explicit `gh release upload` step for Linux + Windows installers since the tauri-action upload path was removed; macOS keeps its existing re-sign + notarize + re-upload flow.
This commit is contained in:
+29
-2
@@ -2,7 +2,10 @@ FROM ubuntu:22.04
|
||||
|
||||
ENV DEBIAN_FRONTEND=noninteractive
|
||||
|
||||
# System deps for Tauri + mold linker + clang + E2E testing (xvfb, dbus, webkit2gtk-driver)
|
||||
# System deps for Tauri + mold linker + clang + E2E testing (xvfb, dbus, webkit2gtk-driver).
|
||||
# CEF (bundled Chromium) runtime libs: libnss3, libnspr4, libgbm1, libxshmfence1,
|
||||
# libxkbcommon0, libatk-bridge2.0-0 — required to link/run the CEF shared lib that
|
||||
# cef-dll-sys downloads at build time (CEF is the default runtime now).
|
||||
RUN apt-get update && apt-get install -y --no-install-recommends \
|
||||
build-essential \
|
||||
cmake \
|
||||
@@ -23,6 +26,17 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
|
||||
at-spi2-core \
|
||||
dbus-x11 \
|
||||
webkit2gtk-driver \
|
||||
libnss3 \
|
||||
libnspr4 \
|
||||
libgbm1 \
|
||||
libxshmfence1 \
|
||||
libxkbcommon0 \
|
||||
libatk-bridge2.0-0 \
|
||||
libxcomposite1 \
|
||||
libxdamage1 \
|
||||
libxrandr2 \
|
||||
libcups2 \
|
||||
libpangocairo-1.0-0 \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
# Rust 1.93.0 with minimal profile + fmt/clippy
|
||||
@@ -56,9 +70,22 @@ RUN curl -fsSL https://github.com/mozilla/sccache/releases/download/v0.10.0/scca
|
||||
# tauri-driver (WebDriver server for Tauri E2E tests)
|
||||
RUN cargo install tauri-driver --version 2.0.5
|
||||
|
||||
# Vendored CEF-aware tauri-cli. The upstream @tauri-apps/cli binary does not
|
||||
# bundle CEF framework files into installers — only the fork at
|
||||
# app/src-tauri/vendor/tauri-cef (a submodule) does. We compile it here so
|
||||
# release/build workflows can invoke `cargo tauri build` directly without
|
||||
# paying the ~5 min compile cost every run.
|
||||
#
|
||||
# Submodule must be checked out before `docker build` (see docker-ci-image.yml
|
||||
# `submodules: recursive`). Source is discarded after install — only the
|
||||
# `cargo-tauri` binary in $CARGO_HOME/bin is kept.
|
||||
COPY app/src-tauri/vendor/tauri-cef /opt/tauri-cef
|
||||
RUN cargo install --locked --path /opt/tauri-cef/crates/tauri-cli \
|
||||
&& rm -rf /opt/tauri-cef /usr/local/cargo/registry/cache /usr/local/cargo/registry/src
|
||||
|
||||
# E2E entrypoint (starts Xvfb + dbus for headless webkit2gtk testing)
|
||||
COPY e2e/docker-entrypoint.sh /docker-entrypoint.sh
|
||||
RUN chmod +x /docker-entrypoint.sh
|
||||
|
||||
# Verify installs
|
||||
RUN rustc --version && cargo --version && node --version && yarn --version && mold --version && sccache --version && which tauri-driver
|
||||
RUN rustc --version && cargo --version && node --version && yarn --version && mold --version && sccache --version && which tauri-driver && cargo tauri --version
|
||||
|
||||
@@ -23,7 +23,7 @@ jobs:
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 1
|
||||
submodules: true
|
||||
submodules: recursive
|
||||
|
||||
- name: Setup Node.js 24.x
|
||||
uses: actions/setup-node@v4
|
||||
@@ -53,6 +53,28 @@ jobs:
|
||||
restore-keys: |
|
||||
Windows-cargo-registry-
|
||||
|
||||
# CEF runtime auto-downloads via cef-dll-sys / vendored tauri-cli. Cache
|
||||
# it so we don't re-fetch ~400MB every run.
|
||||
- name: Cache CEF binary distribution
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: ~/AppData/Local/tauri-cef
|
||||
key: cef-windows-${{ hashFiles('app/src-tauri/Cargo.toml') }}
|
||||
restore-keys: |
|
||||
cef-windows-
|
||||
|
||||
- name: Cache vendored tauri-cli binary
|
||||
id: tauri-cli-cache
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: ~/.cargo/bin/cargo-tauri.exe
|
||||
key: vendored-tauri-cli-windows-${{ hashFiles('app/src-tauri/vendor/tauri-cef/crates/tauri-cli/Cargo.toml') }}
|
||||
|
||||
- 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
|
||||
|
||||
- name: Install dependencies
|
||||
run: yarn install --frozen-lockfile
|
||||
|
||||
@@ -126,18 +148,17 @@ jobs:
|
||||
const config = prepareTauriConfig();
|
||||
core.setOutput('json', JSON.stringify(config));
|
||||
|
||||
- name: Build Tauri app
|
||||
uses: tauri-apps/tauri-action@v0.6.2
|
||||
- name: Build Tauri app (CEF default, vendored CLI)
|
||||
id: tauri-build
|
||||
shell: bash
|
||||
working-directory: app
|
||||
env:
|
||||
BASE_URL: ${{ vars.BASE_URL }}
|
||||
VITE_MINIMUM_SUPPORTED_APP_VERSION: ${{ vars.VITE_MINIMUM_SUPPORTED_APP_VERSION }}
|
||||
VITE_LATEST_APP_DOWNLOAD_URL: ${{ vars.VITE_LATEST_APP_DOWNLOAD_URL }}
|
||||
with:
|
||||
projectPath: app
|
||||
args: -c ${{ steps.config-overrides.outputs.json }} --target x86_64-pc-windows-msvc
|
||||
includeDebug: false
|
||||
includeRelease: true
|
||||
TAURI_CONFIG_OVERRIDE: ${{ steps.config-overrides.outputs.json }}
|
||||
run: |
|
||||
cargo tauri build -c "$TAURI_CONFIG_OVERRIDE" --target x86_64-pc-windows-msvc
|
||||
|
||||
- name: Upload MSI artifact
|
||||
uses: actions/upload-artifact@v4
|
||||
|
||||
@@ -24,7 +24,7 @@ jobs:
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 1
|
||||
submodules: true
|
||||
submodules: recursive
|
||||
|
||||
- name: Cache Rust build artifacts
|
||||
uses: Swatinem/rust-cache@v2
|
||||
@@ -34,6 +34,22 @@ jobs:
|
||||
app/src-tauri -> target
|
||||
cache-on-failure: true
|
||||
|
||||
# CEF (Chromium Embedded Framework) runtime is downloaded on-demand by
|
||||
# cef-dll-sys + the vendored tauri-cli. Cache it across builds — the
|
||||
# payload is ~400MB per platform and fetching every run is painful.
|
||||
- name: Cache CEF binary distribution
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: ~/.cache/tauri-cef
|
||||
key: cef-ubuntu-22.04-${{ hashFiles('app/src-tauri/Cargo.toml') }}
|
||||
restore-keys: |
|
||||
cef-ubuntu-22.04-
|
||||
|
||||
# Note: the vendored CEF-aware tauri-cli is pre-installed in the
|
||||
# ghcr.io/tinyhumansai/openhuman_ci image (see .github/Dockerfile),
|
||||
# so `cargo tauri build` below resolves to the fork without any
|
||||
# per-run compile step.
|
||||
|
||||
- name: Cache node modules
|
||||
id: yarn-cache
|
||||
uses: actions/cache@v4
|
||||
@@ -59,11 +75,11 @@ jobs:
|
||||
cp target/x86_64-unknown-linux-gnu/ci/openhuman-core app/src-tauri/binaries/openhuman-core-x86_64-unknown-linux-gnu
|
||||
chmod +x app/src-tauri/binaries/openhuman-core-x86_64-unknown-linux-gnu
|
||||
|
||||
- name: Build Tauri app
|
||||
- name: Build Tauri app (CEF default)
|
||||
working-directory: app
|
||||
run: |
|
||||
TAURI_CONFIG_OVERRIDE='{"plugins":{"updater":{"active":false}}}'
|
||||
yarn tauri build -c "$TAURI_CONFIG_OVERRIDE" --bundles deb
|
||||
cargo tauri build -c "$TAURI_CONFIG_OVERRIDE" --bundles deb
|
||||
env:
|
||||
NODE_ENV: production
|
||||
CARGO_PROFILE_RELEASE_OPT_LEVEL: "1"
|
||||
|
||||
@@ -7,6 +7,7 @@ on:
|
||||
- ".github/Dockerfile"
|
||||
- ".github/workflows/docker-ci-image.yml"
|
||||
- "e2e/docker-entrypoint.sh"
|
||||
- ".gitmodules"
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
@@ -21,6 +22,9 @@ jobs:
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
# vendored tauri-cef fork is compiled into the image
|
||||
submodules: recursive
|
||||
|
||||
- name: Log in to GHCR
|
||||
uses: docker/login-action@v3
|
||||
|
||||
@@ -272,7 +272,7 @@ jobs:
|
||||
with:
|
||||
ref: ${{ needs.prepare-build.outputs.build_ref }}
|
||||
fetch-depth: 1
|
||||
submodules: true
|
||||
submodules: recursive
|
||||
|
||||
- name: Configure staging app environment
|
||||
if: inputs.build_target == 'staging'
|
||||
@@ -323,6 +323,55 @@ jobs:
|
||||
restore-keys: |
|
||||
${{ runner.os }}-cargo-registry-
|
||||
|
||||
# CEF is now the default runtime — cef-dll-sys + vendored tauri-cli
|
||||
# auto-download the ~400MB Chromium distribution on first build. Cache
|
||||
# it per-OS across runs. Default path is `dirs::cache_dir()/tauri-cef`
|
||||
# (macOS: ~/Library/Caches; Linux: ~/.cache; Windows: %LOCALAPPDATA%).
|
||||
- name: Cache CEF binary distribution (unix)
|
||||
if: matrix.settings.platform != 'windows-latest'
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: |
|
||||
~/Library/Caches/tauri-cef
|
||||
~/.cache/tauri-cef
|
||||
key: cef-${{ matrix.settings.target }}-${{ hashFiles('app/src-tauri/Cargo.toml') }}
|
||||
restore-keys: |
|
||||
cef-${{ matrix.settings.target }}-
|
||||
|
||||
- name: Cache CEF binary distribution (windows)
|
||||
if: matrix.settings.platform == 'windows-latest'
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: ~/AppData/Local/tauri-cef
|
||||
key: cef-${{ matrix.settings.target }}-${{ hashFiles('app/src-tauri/Cargo.toml') }}
|
||||
restore-keys: |
|
||||
cef-${{ matrix.settings.target }}-
|
||||
|
||||
# Upstream @tauri-apps/cli (used by tauri-action) doesn't bundle CEF
|
||||
# framework files into the produced installer. Only the fork at
|
||||
# vendor/tauri-cef does. Build and install that CLI so `cargo tauri
|
||||
# build` invokes the cef-aware bundler.
|
||||
- name: Cache vendored tauri-cli binary (unix)
|
||||
if: matrix.settings.platform != 'windows-latest'
|
||||
id: tauri-cli-cache-unix
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: ~/.cargo/bin/cargo-tauri
|
||||
key: vendored-tauri-cli-${{ runner.os }}-${{ hashFiles('app/src-tauri/vendor/tauri-cef/crates/tauri-cli/Cargo.toml') }}
|
||||
|
||||
- name: Cache vendored tauri-cli binary (windows)
|
||||
if: matrix.settings.platform == 'windows-latest'
|
||||
id: tauri-cli-cache-windows
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: ~/.cargo/bin/cargo-tauri.exe
|
||||
key: vendored-tauri-cli-${{ runner.os }}-${{ hashFiles('app/src-tauri/vendor/tauri-cef/crates/tauri-cli/Cargo.toml') }}
|
||||
|
||||
- name: Install vendored tauri-cli (cef-aware bundler)
|
||||
if: (matrix.settings.platform == 'windows-latest' && steps.tauri-cli-cache-windows.outputs.cache-hit != '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
|
||||
|
||||
- name: Install dependencies
|
||||
run: yarn install --frozen-lockfile
|
||||
|
||||
@@ -455,16 +504,16 @@ jobs:
|
||||
CORE_TARGET_DIR: ${{ steps.core-paths.outputs.core_target_dir }}
|
||||
CORE_BIN_NAME: ${{ steps.core-paths.outputs.core_bin_name }}
|
||||
|
||||
- name: Build, package and upload to release
|
||||
if: needs.prepare-build.outputs.release_enabled == 'true'
|
||||
uses: tauri-apps/tauri-action@v0.6.2
|
||||
# CEF is the default runtime — we build via the vendored tauri-cli so
|
||||
# the bundler copies Chromium Embedded Framework files into the .app /
|
||||
# .deb / .AppImage / .msi / NSIS setup. macOS signing is intentionally
|
||||
# skipped here and handled by the dedicated re-sign + notarize step
|
||||
# below (hardened runtime + entitlements are required for notarization).
|
||||
- name: Build and package Tauri app (CEF, vendored CLI)
|
||||
id: tauri-build
|
||||
shell: bash
|
||||
working-directory: app
|
||||
env:
|
||||
# NOTE: APPLE_CERTIFICATE, APPLE_SIGNING_IDENTITY, APPLE_ID, etc. are
|
||||
# intentionally omitted so tauri-action builds WITHOUT signing.
|
||||
# Signing + notarization are handled in a dedicated step afterwards
|
||||
# where we sign everything with hardened runtime + entitlements
|
||||
# (required by Apple notarization).
|
||||
BASE_URL: ${{ needs.prepare-build.outputs.base_url }}
|
||||
OPENHUMAN_APP_ENV: ${{ inputs.build_target == 'staging' && 'staging' || 'production' }}
|
||||
VITE_OPENHUMAN_APP_ENV: ${{ inputs.build_target == 'staging' && 'staging' || 'production' }}
|
||||
@@ -473,36 +522,51 @@ jobs:
|
||||
TAURI_SIGNING_PRIVATE_KEY_PASSWORD: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY_PASSWORD || secrets.UPDATER_PRIVATE_KEY_PASSWORD }}
|
||||
TAURI_SIGNING_PRIVATE_KEY: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY || secrets.UPDATER_PRIVATE_KEY }}
|
||||
WITH_UPDATER: "true"
|
||||
# Must match standalone "Build frontend" so tauri-action's beforeBuildCommand embeds the gate.
|
||||
VITE_MINIMUM_SUPPORTED_APP_VERSION: ${{ vars.VITE_MINIMUM_SUPPORTED_APP_VERSION }}
|
||||
VITE_LATEST_APP_DOWNLOAD_URL: ${{ vars.VITE_LATEST_APP_DOWNLOAD_URL }}
|
||||
with:
|
||||
projectPath: app
|
||||
args: -c ${{ steps.config-overrides.outputs.json }} ${{ matrix.settings.args }}
|
||||
includeDebug: false
|
||||
includeRelease: true
|
||||
releaseId: ${{ needs.create-release.outputs.release_id }}
|
||||
owner: tinyhumansai
|
||||
repo: openhuman
|
||||
TAURI_CONFIG_OVERRIDE: ${{ steps.config-overrides.outputs.json }}
|
||||
MATRIX_ARGS: ${{ matrix.settings.args }}
|
||||
run: |
|
||||
cargo tauri build -c "$TAURI_CONFIG_OVERRIDE" $MATRIX_ARGS
|
||||
|
||||
- name: Build and package staging artifacts
|
||||
if: needs.prepare-build.outputs.release_enabled != 'true'
|
||||
# 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'
|
||||
shell: bash
|
||||
env:
|
||||
BASE_URL: ${{ needs.prepare-build.outputs.base_url }}
|
||||
OPENHUMAN_APP_ENV: staging
|
||||
VITE_OPENHUMAN_APP_ENV: staging
|
||||
VITE_BACKEND_URL: ${{ needs.prepare-build.outputs.base_url }}
|
||||
MACOSX_DEPLOYMENT_TARGET: ${{ matrix.settings.platform == 'macos-latest' && '10.15' || '' }}
|
||||
TAURI_SIGNING_PRIVATE_KEY_PASSWORD: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY_PASSWORD || secrets.UPDATER_PRIVATE_KEY_PASSWORD }}
|
||||
TAURI_SIGNING_PRIVATE_KEY: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY || secrets.UPDATER_PRIVATE_KEY }}
|
||||
WITH_UPDATER: "true"
|
||||
VITE_MINIMUM_SUPPORTED_APP_VERSION: ${{ vars.VITE_MINIMUM_SUPPORTED_APP_VERSION }}
|
||||
VITE_LATEST_APP_DOWNLOAD_URL: ${{ vars.VITE_LATEST_APP_DOWNLOAD_URL }}
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
TAG: ${{ needs.prepare-build.outputs.tag }}
|
||||
MATRIX_TARGET: ${{ matrix.settings.target }}
|
||||
run: |
|
||||
yarn --cwd app tauri build \
|
||||
-c '${{ steps.config-overrides.outputs.json }}' \
|
||||
${{ matrix.settings.args }}
|
||||
set -euo pipefail
|
||||
shopt -s nullglob
|
||||
BUNDLE_ROOTS=(
|
||||
"app/src-tauri/target/${MATRIX_TARGET}/release/bundle"
|
||||
"target/${MATRIX_TARGET}/release/bundle"
|
||||
)
|
||||
UPLOAD=()
|
||||
for root in "${BUNDLE_ROOTS[@]}"; do
|
||||
[ -d "$root" ] || continue
|
||||
for f in \
|
||||
"$root"/deb/*.deb \
|
||||
"$root"/appimage/*.AppImage \
|
||||
"$root"/appimage/*.AppImage.sig \
|
||||
"$root"/msi/*.msi \
|
||||
"$root"/msi/*.msi.sig \
|
||||
"$root"/nsis/*-setup.exe \
|
||||
"$root"/nsis/*-setup.exe.sig; do
|
||||
[ -e "$f" ] && UPLOAD+=("$f")
|
||||
done
|
||||
done
|
||||
if [ ${#UPLOAD[@]} -eq 0 ]; then
|
||||
echo "No installer artifacts found for ${MATRIX_TARGET}"
|
||||
exit 1
|
||||
fi
|
||||
echo "Uploading:"
|
||||
printf ' %s\n' "${UPLOAD[@]}"
|
||||
gh release upload "$TAG" "${UPLOAD[@]}" --repo tinyhumansai/openhuman --clobber
|
||||
|
||||
- name: Locate macOS .app bundle
|
||||
if: matrix.settings.platform == 'macos-latest'
|
||||
|
||||
@@ -76,9 +76,9 @@ jobs:
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 1
|
||||
# Required for app/src-tauri/vendor/tauri-cef, which the
|
||||
# [patch.crates-io] block in app/src-tauri/Cargo.toml resolves
|
||||
# every tauri-* crate through (even without --features cef).
|
||||
# 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
|
||||
@@ -89,6 +89,17 @@ jobs:
|
||||
app/src-tauri -> target
|
||||
cache-on-failure: true
|
||||
|
||||
# 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@v4
|
||||
with:
|
||||
path: ~/.cache/tauri-cef
|
||||
key: cef-ubuntu-22.04-${{ hashFiles('app/src-tauri/Cargo.toml') }}
|
||||
restore-keys: |
|
||||
cef-ubuntu-22.04-
|
||||
|
||||
- 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/*
|
||||
|
||||
|
||||
Reference in New Issue
Block a user