refactor: consolidate Core 2.0 and restore cross-platform behavior (#1019)
* refactor: split Linux egui host from shared backend * fix: keep CI contracts portable across runners * fix(ci): preserve CRLF while removing qwen dependency * fix(ci): regenerate target lockfile and install ripgrep * fix(ci): gate desktop-only selection voice module * ci: limit native build parallelism on cross-platform runners * fix(host): expose blocking task seam to coordinator * fix(settings): avoid macOS default hotkey collision * docs: record cross-platform CI evidence * ci: expose Linux validation package artifact * ci: grant reusable Linux package permissions * refactor: remove legacy coordinator dictation facade * ci: skip unsupported MSI prerelease builds * ci: install minisign only for signed Linux releases * fix: keep test-only coordinator session helper * refactor: move style preview diagnostics into core * fix: import shared preferences type from core * refactor: centralize enabled vocabulary projection * ci: install ripgrep for Linux package gates * test: make source contract line-ending agnostic * fix: keep Linux desktop entry standards compliant * docs: expose core style diagnostics contract * ci: resolve Linux package version in app directory * refactor: centralize ASR vocabulary priority * fix: use shared vocabulary note constant * refactor: keep vocabulary priority inside core * test: retain starting-stop queue coverage * ci: scope Linux updater URL to the current repository * docs: close implementation and artifact evidence * docs: record final CI artifact evidence * fix(android): align updater plugin versions * fix(android): pin updater crate exactly * refactor(core): remove unused type anchor * docs: record final artifact runs * fix(remote-input): preserve beta status fields * fix(tauri): finish beta host merge * fix(asr): pass scoped operation to native qwen adapter * fix(macos): bundle mlx metallib as a resource * test(remote-input): update status wire contract * feat: share Less Computer voice flow with Linux * refactor(core): centralize host-independent runtime policy * refactor(core): complete 2.0 backend consolidation * fix(ci): prepare Sherpa after cache restore * fix(macos): route native model paths through Core store * fix(macos): use ModelStore catalog API * fix(ci): serialize macOS native test build * test(ci): preserve macOS cargo diagnostics * fix(macos): release input source lock before await * test(core): replace legacy hotkey injection gate * test(core): move Codex sandbox contract into Core * fix(core): close final runtime policy gaps * fix(windows): terminate coding agent process trees * fix(core): complete local model migration * fix(credentials): align Core LLM model account * fix(core): restore 1.x parity across shared backend * fix(android): complete shared backend stubs * fix: close cross-platform migration review gaps * fix: complete migration lifecycles and platform compatibility * docs: define desktop 2.0 acceptance and Linux handoff * fix: close desktop parity and session lifecycle gaps * fix: finish voice lifecycle and desktop feedback parity * fix: close desktop cancellation and feedback race gaps * fix: honor proxy settings and reject stale session effects * fix: dispatch native cleanup on host runtimes and order events * fix: keep optional recording effects best effort * fix: close desktop agent model and QA lifecycle gaps * fix: preserve desktop raw voice and QA turn ownership * fix: finalize desktop dictation and QA feedback
This commit is contained in:
1 parent
fc9824eecc
commit
fc38edd1a3
342 files changed
+118293
-55619
No files matched your search
+94
-36
@@ -3,7 +3,7 @@ name: CI
|
||||
# 多平台跨语言质量门禁。release-tauri.yml 是发版流水线(仅打包构建),这里负责
|
||||
# 在合并前快速验证两件事:
|
||||
# 1. 全部前端/契约测试与 vite bundle 通过(捕获行为、合同及跨 locale 类型 drift)
|
||||
# 2. Rust 后端在 macOS / Windows / Linux 都能 cargo check 过(捕获 cfg 漏分支 / 平台 API 误用)
|
||||
# 2. Tauri 后端在 macOS / Windows、移动端在 Android 编译;Linux 只编译共享 core 与 egui host。
|
||||
# 跑 build-mac.sh / windows-package-msvc.ps1 / Tauri bundle 太重;只跑轻量 cargo check + vite build。
|
||||
|
||||
on:
|
||||
@@ -12,6 +12,12 @@ on:
|
||||
pull_request:
|
||||
branches: [main, beta]
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
upload_linux_validation_artifact:
|
||||
description: Build and upload the Linux egui validation packages (never a release)
|
||||
required: false
|
||||
default: false
|
||||
type: boolean
|
||||
|
||||
# 同一 PR 快速重复推送时取消旧运行;workflow_dispatch 用 run_id 隔离。
|
||||
concurrency:
|
||||
@@ -107,7 +113,7 @@ jobs:
|
||||
run: node scripts/ci-disable-macos-qwen3.mjs
|
||||
|
||||
- name: Check Tauri backend (Android target)
|
||||
run: cargo check --manifest-path src-tauri/Cargo.toml --target aarch64-linux-android
|
||||
run: cargo check --locked --manifest-path src-tauri/Cargo.toml --target aarch64-linux-android
|
||||
|
||||
- name: Initialize generated Android project
|
||||
run: npm run tauri -- android init --ci
|
||||
@@ -121,7 +127,7 @@ jobs:
|
||||
WRY_ANDROID_PACKAGE: com.openless.app
|
||||
run: |
|
||||
mkdir -p "$WRY_ANDROID_KOTLIN_FILES_OUT_DIR"
|
||||
cargo check --manifest-path src-tauri/Cargo.toml --target x86_64-linux-android
|
||||
cargo check --locked --manifest-path src-tauri/Cargo.toml --target x86_64-linux-android
|
||||
|
||||
- name: Copy Android production and test scaffolding
|
||||
run: node scripts/copy-android-scaffolding.mjs
|
||||
@@ -165,6 +171,71 @@ jobs:
|
||||
-x :app:rustBuildX86_64Debug
|
||||
--no-daemon
|
||||
|
||||
linux-core-contract:
|
||||
name: Linux core and egui host
|
||||
runs-on: ubuntu-22.04
|
||||
defaults:
|
||||
run:
|
||||
working-directory: openless-all/app
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: false
|
||||
|
||||
- uses: dtolnay/rust-toolchain@stable
|
||||
with:
|
||||
components: clippy
|
||||
|
||||
- uses: swatinem/rust-cache@v2
|
||||
with:
|
||||
workspaces: 'openless-all/app -> target'
|
||||
|
||||
- name: Install Linux native dependencies without WebKitGTK
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y \
|
||||
build-essential \
|
||||
libasound2-dev \
|
||||
libdbus-1-dev \
|
||||
libssl-dev \
|
||||
libwayland-dev \
|
||||
libx11-dev \
|
||||
libxkbcommon-dev \
|
||||
ripgrep \
|
||||
pkg-config
|
||||
|
||||
- name: Test and lint shared backend
|
||||
run: |
|
||||
cargo test --locked -p openless-core
|
||||
cargo clippy --locked -p openless-core --all-targets -- -D warnings
|
||||
|
||||
- name: Test Linux host and UI contract
|
||||
run: |
|
||||
cargo test --locked -p openless-linux-egui --all-targets
|
||||
cargo check --locked -p openless-linux-egui --all-targets
|
||||
|
||||
- name: Verify dependency direction, compatibility baseline, and secret surfaces
|
||||
shell: pwsh
|
||||
run: |
|
||||
./scripts/check-core-deps.ps1
|
||||
./scripts/check-core-deps.ps1 openless-linux-egui
|
||||
./scripts/check-command-event-baseline.ps1
|
||||
./scripts/check-core-secret-surface.ps1
|
||||
./scripts/check-core-test-isolation.ps1
|
||||
./scripts/check-core-runtime-seam.ps1
|
||||
./scripts/check-linux-public-surface.ps1
|
||||
|
||||
linux-egui-validation-artifact:
|
||||
name: Linux egui validation artifact
|
||||
if: github.event_name == 'workflow_dispatch' && inputs.upload_linux_validation_artifact
|
||||
needs: linux-core-contract
|
||||
permissions:
|
||||
contents: write
|
||||
uses: ./.github/workflows/release-linux-egui.yml
|
||||
with:
|
||||
release_tag: ''
|
||||
secrets: inherit
|
||||
|
||||
cross-platform:
|
||||
name: ${{ matrix.label }} checks
|
||||
strategy:
|
||||
@@ -178,23 +249,21 @@ jobs:
|
||||
- os: windows-latest
|
||||
label: Windows
|
||||
preflight: true
|
||||
- os: ubuntu-latest
|
||||
label: Linux
|
||||
preflight: false
|
||||
runs-on: ${{ matrix.os }}
|
||||
env:
|
||||
# 新增 shared Core 后,macOS 首次编译同时构建 MLX C++ 依赖和完整
|
||||
# Tauri test binary;限制并发避免 arm64 runner 在峰值内存处被系统终止。
|
||||
CARGO_BUILD_JOBS: 2
|
||||
CARGO_PROFILE_TEST_DEBUG: 0
|
||||
CMAKE_BUILD_PARALLEL_LEVEL: 2
|
||||
defaults:
|
||||
run:
|
||||
working-directory: openless-all/app
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
# 只在 macOS 初始化 MLX 子模块;Linux 的 C 后端单独初始化 qwen-asr。
|
||||
# 只在 macOS 初始化 MLX 子模块;Windows 不解析该依赖。
|
||||
submodules: ${{ matrix.os == 'macos-latest' && 'recursive' || 'false' }}
|
||||
|
||||
- name: Initialize Linux C ASR submodule
|
||||
if: runner.os == 'Linux'
|
||||
shell: bash
|
||||
run: git submodule update --init src-tauri/vendor/qwen-asr
|
||||
- name: Disable macOS-only Qwen3 MLX dependency
|
||||
if: runner.os != 'macOS'
|
||||
run: node scripts/ci-disable-macos-qwen3.mjs
|
||||
@@ -214,21 +283,10 @@ jobs:
|
||||
with:
|
||||
workspaces: 'openless-all/app/src-tauri -> target'
|
||||
|
||||
- name: Install Linux check dependencies
|
||||
if: runner.os == 'Linux'
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y \
|
||||
build-essential \
|
||||
curl \
|
||||
file \
|
||||
libasound2-dev \
|
||||
libayatana-appindicator3-dev \
|
||||
librsvg2-dev \
|
||||
libssl-dev \
|
||||
libwebkit2gtk-4.1-dev \
|
||||
libxdo-dev \
|
||||
wget
|
||||
- name: Prepare Windows Sherpa static libraries
|
||||
if: runner.os == 'Windows'
|
||||
shell: pwsh
|
||||
run: ./scripts/prepare-windows-sherpa.ps1
|
||||
|
||||
- name: Install frontend dependencies
|
||||
run: npm ci
|
||||
@@ -242,7 +300,7 @@ jobs:
|
||||
if: matrix.preflight
|
||||
shell: pwsh
|
||||
run: |
|
||||
foreach ($script in @("./scripts/windows-preflight.ps1", "./scripts/windows-build-gnu.ps1", "./scripts/windows-runtime-smoke.ps1")) {
|
||||
foreach ($script in @("./scripts/windows-preflight.ps1", "./scripts/windows-build-gnu.ps1", "./scripts/windows-runtime-smoke.ps1", "./scripts/prepare-windows-sherpa.ps1")) {
|
||||
$errors = $null
|
||||
[System.Management.Automation.PSParser]::Tokenize((Get-Content -Raw $script), [ref]$errors) | Out-Null
|
||||
if ($errors) {
|
||||
@@ -271,27 +329,27 @@ jobs:
|
||||
if: runner.os == 'macOS'
|
||||
env:
|
||||
OPENLESS_CODEX_TEST_EXE: codex
|
||||
run: cargo test --manifest-path src-tauri/Cargo.toml --lib coding_agent::codex::live::hardening_actually_narrows_the_writable_roots -- --ignored --nocapture --test-threads=1
|
||||
run: cargo test --locked -p openless-core hardening_actually_narrows_the_writable_roots -- --ignored --nocapture --test-threads=1
|
||||
|
||||
- name: Check Tauri backend (cargo check)
|
||||
run: cargo check --manifest-path src-tauri/Cargo.toml
|
||||
run: cargo check --locked --manifest-path src-tauri/Cargo.toml
|
||||
|
||||
- name: Run Rust backend unit tests
|
||||
if: runner.os != 'Windows'
|
||||
run: cargo test --manifest-path src-tauri/Cargo.toml --lib
|
||||
run: cargo test --locked --manifest-path src-tauri/Cargo.toml --lib
|
||||
|
||||
- name: Compile Rust backend unit tests (Windows)
|
||||
# Windows runner 能链接 lib test binary,但干净镜像缺少可选 native runtime
|
||||
# DLL entrypoint 时,进程会在 test harness 启动前退出。这里保留 cfg/link
|
||||
# 覆盖;Rust-only 后端单测由下一步实际执行。
|
||||
# 覆盖;共享 Core 的公开 compatibility contract 由下一步实际执行。
|
||||
if: runner.os == 'Windows'
|
||||
run: cargo test --manifest-path src-tauri/Cargo.toml --lib --no-run
|
||||
run: cargo test --locked --manifest-path src-tauri/Cargo.toml --lib --no-run
|
||||
|
||||
- name: Run Rust-only backend unit tests (Windows)
|
||||
# 只把纯 Rust 后端模块编进独立 test crate,不链接完整 Tauri app lib。
|
||||
# 这样 Windows CI 能实际执行 coordinator/hotkey/recorder/insertion 逻辑单测。
|
||||
# 独立 test crate 不链接完整 Tauri app lib,只验证公开 Core contract。
|
||||
# Windows 专属 Tauri 测试在此 runner 只做上一步的 cfg/link 编译覆盖。
|
||||
if: runner.os == 'Windows'
|
||||
run: cargo test --manifest-path src-tauri/backend-tests/Cargo.toml
|
||||
run: cargo test --locked --manifest-path src-tauri/backend-tests/Cargo.toml
|
||||
|
||||
- name: Check Tauri backend with Rust 1.88 MSRV
|
||||
run: cargo +1.88.0 check --locked --manifest-path src-tauri/Cargo.toml
|
||||
|
||||
@@ -0,0 +1,261 @@
|
||||
name: Release Linux egui
|
||||
|
||||
# This workflow deliberately has no automatic tag trigger until real Ubuntu
|
||||
# audio, focus/input, install, upgrade, and rollback evidence is recorded. It is
|
||||
# already reusable by a release orchestrator: pass release_tag to upload verified packages.
|
||||
on:
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
release_tag:
|
||||
description: Existing GitHub release tag to receive Linux assets; blank only uploads Actions artifacts
|
||||
required: false
|
||||
type: string
|
||||
workflow_call:
|
||||
inputs:
|
||||
release_tag:
|
||||
required: false
|
||||
type: string
|
||||
secrets:
|
||||
LINUX_EGUI_MINISIGN_SECRET_KEY:
|
||||
required: false
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
|
||||
jobs:
|
||||
build-linux-egui:
|
||||
runs-on: ubuntu-22.04
|
||||
env:
|
||||
RELEASE_TAG: ${{ inputs.release_tag }}
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: false
|
||||
|
||||
- name: Install native build and packaging dependencies
|
||||
run: |
|
||||
sudo add-apt-repository -y universe || true
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y \
|
||||
appstream \
|
||||
build-essential \
|
||||
cmake \
|
||||
desktop-file-utils \
|
||||
extra-cmake-modules \
|
||||
fcitx5-modules-dev \
|
||||
file \
|
||||
fuse \
|
||||
libasound2-dev \
|
||||
libdbus-1-dev \
|
||||
libfcitx5config-dev \
|
||||
libfcitx5core-dev \
|
||||
libfcitx5utils-dev \
|
||||
libopenblas-dev \
|
||||
libssl-dev \
|
||||
libwayland-dev \
|
||||
libx11-dev \
|
||||
libxkbcommon-dev \
|
||||
patchelf \
|
||||
pkg-config \
|
||||
ripgrep \
|
||||
rpm \
|
||||
ruby-dev \
|
||||
wget
|
||||
sudo gem install --no-document fpm -v 1.16.0
|
||||
|
||||
- name: Install appimagetool
|
||||
env:
|
||||
APPIMAGETOOL_SHA256: b90f4a8b18967545fda78a445b27680a1642f1ef9488ced28b65398f2be7add2
|
||||
run: |
|
||||
wget -q https://github.com/AppImage/AppImageKit/releases/download/continuous/appimagetool-x86_64.AppImage \
|
||||
-O /tmp/appimagetool
|
||||
echo "$APPIMAGETOOL_SHA256 /tmp/appimagetool" | sha256sum --check --strict
|
||||
chmod +x /tmp/appimagetool
|
||||
sudo install -m 0755 /tmp/appimagetool /usr/local/bin/appimagetool
|
||||
file /usr/local/bin/appimagetool | grep -q ELF
|
||||
|
||||
- uses: dtolnay/rust-toolchain@stable
|
||||
with:
|
||||
components: clippy
|
||||
|
||||
- name: Cache Cargo
|
||||
uses: swatinem/rust-cache@v2
|
||||
with:
|
||||
workspaces: 'openless-all/app -> target'
|
||||
|
||||
- name: Build fcitx5 plugin
|
||||
working-directory: openless-all/scripts/linux-fcitx5-plugin
|
||||
run: |
|
||||
cmake -S . -B build -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=/usr
|
||||
cmake --build build --parallel
|
||||
ctest --test-dir build --output-on-failure
|
||||
test -s build/libopenless.so
|
||||
test -s build/openless.conf
|
||||
|
||||
- name: Checkout pinned Qwen ASR runtime source
|
||||
run: git submodule update --init --depth 1 -- openless-all/app/src-tauri/vendor/qwen-asr
|
||||
|
||||
- name: Build portable Qwen ASR runtime
|
||||
working-directory: openless-all/app/src-tauri/vendor/qwen-asr
|
||||
run: |
|
||||
make blas CFLAGS_BASE="-Wall -Wextra -O3 -ffast-math -mtune=generic"
|
||||
test -x qwen_asr
|
||||
./qwen_asr --help >/dev/null 2>&1
|
||||
|
||||
- name: Verify framework-independent Linux contract
|
||||
working-directory: openless-all/app
|
||||
shell: pwsh
|
||||
run: |
|
||||
cargo test --locked -p openless-core
|
||||
cargo clippy --locked -p openless-core --all-targets -- -D warnings
|
||||
cargo test --locked -p openless-linux-egui --all-targets
|
||||
cargo check --locked -p openless-linux-egui --all-targets
|
||||
./scripts/check-core-deps.ps1
|
||||
./scripts/check-core-deps.ps1 openless-linux-egui
|
||||
./scripts/check-core-secret-surface.ps1
|
||||
./scripts/check-core-test-isolation.ps1
|
||||
./scripts/check-core-runtime-seam.ps1
|
||||
./scripts/check-linux-public-surface.ps1
|
||||
|
||||
- name: Validate release target and UI gate
|
||||
shell: bash
|
||||
env:
|
||||
GH_TOKEN: ${{ github.token }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
if [ -z "${RELEASE_TAG:-}" ]; then
|
||||
exit 0
|
||||
fi
|
||||
case "$RELEASE_TAG" in
|
||||
v*-tauri) ;;
|
||||
*)
|
||||
echo "::error::release_tag must name an existing v*-tauri release"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
if grep -q 'openless-linux-egui host stub' openless-all/app/linux-egui/src/main.rs; then
|
||||
echo "::error::The egui UI stub cannot be uploaded as a release asset"
|
||||
exit 1
|
||||
fi
|
||||
gh release view "$RELEASE_TAG" --repo "$GITHUB_REPOSITORY" >/dev/null
|
||||
|
||||
- name: Validate Linux desktop metadata
|
||||
run: |
|
||||
desktop-file-validate openless-all/app/linux-egui/packaging/openless.desktop
|
||||
appstreamcli validate --no-net openless-all/app/linux-egui/packaging/top.openless.OpenLess.metainfo.xml
|
||||
|
||||
- name: Build Linux egui host
|
||||
working-directory: openless-all/app
|
||||
run: cargo build --locked --release -p openless-linux-egui
|
||||
|
||||
- name: Resolve package version
|
||||
id: version
|
||||
shell: bash
|
||||
working-directory: openless-all/app
|
||||
run: |
|
||||
if [ -n "${RELEASE_TAG:-}" ]; then
|
||||
VERSION=${RELEASE_TAG#v}
|
||||
VERSION=${VERSION%-tauri}
|
||||
else
|
||||
VERSION=$(sed -n 's/^version = "\([^"]*\)"/\1/p' src-tauri/Cargo.toml | head -1)
|
||||
fi
|
||||
test -n "$VERSION"
|
||||
echo "version=$VERSION" >> "$GITHUB_OUTPUT"
|
||||
|
||||
- name: Package deb, rpm, and AppImage without Tauri
|
||||
working-directory: openless-all/app
|
||||
env:
|
||||
OPENLESS_LINUX_VERSION: ${{ steps.version.outputs.version }}
|
||||
OPENLESS_LINUX_ARCH: x86_64
|
||||
APPIMAGE_EXTRACT_AND_RUN: '1'
|
||||
run: bash scripts/package-linux-egui.sh
|
||||
|
||||
- name: Verify package contents and ELF dependencies
|
||||
working-directory: openless-all/app
|
||||
run: |
|
||||
OUTPUT=target/linux-egui-packages
|
||||
test "$(find "$OUTPUT" -maxdepth 1 -name '*.deb' | wc -l)" -eq 1
|
||||
test "$(find "$OUTPUT" -maxdepth 1 -name '*.rpm' | wc -l)" -eq 1
|
||||
test "$(find "$OUTPUT" -maxdepth 1 -name '*.AppImage' | wc -l)" -eq 1
|
||||
! ldd target/release/openless-linux-egui | grep -q 'not found'
|
||||
! ldd target/release/openless-linux-egui | grep -Eqi 'webkit|wry|tauri'
|
||||
! ldd src-tauri/vendor/qwen-asr/qwen_asr | grep -q 'not found'
|
||||
dpkg-deb -c "$OUTPUT"/*.deb | grep -q 'usr/bin/openless'
|
||||
dpkg-deb -c "$OUTPUT"/*.deb | grep -q 'fcitx5/libopenless.so'
|
||||
dpkg-deb -c "$OUTPUT"/*.deb | grep -q 'usr/lib/openless/resources/qwen-asr/qwen_asr'
|
||||
rpm -qlp "$OUTPUT"/*.rpm | grep -q '/usr/bin/openless'
|
||||
rpm -qlp "$OUTPUT"/*.rpm | grep -q '/usr/lib64/fcitx5/libopenless.so'
|
||||
rpm -qlp "$OUTPUT"/*.rpm | grep -q '/usr/lib/openless/resources/qwen-asr/qwen_asr'
|
||||
"$OUTPUT"/*.AppImage --appimage-extract >/dev/null
|
||||
test -x squashfs-root/usr/bin/openless
|
||||
test -s squashfs-root/usr/lib/openless/resources/linux-fcitx5-plugin/libopenless.so
|
||||
test -x squashfs-root/usr/lib/openless/resources/qwen-asr/qwen_asr
|
||||
! ldd squashfs-root/usr/lib/openless/resources/qwen-asr/qwen_asr | grep -q 'not found'
|
||||
squashfs-root/usr/lib/openless/resources/qwen-asr/qwen_asr --help >/dev/null 2>&1
|
||||
rm -rf squashfs-root
|
||||
|
||||
- name: Sign AppImage and write independent updater manifest
|
||||
working-directory: openless-all/app
|
||||
env:
|
||||
MINISIGN_SECRET: ${{ secrets.LINUX_EGUI_MINISIGN_SECRET_KEY }}
|
||||
VERSION: ${{ steps.version.outputs.version }}
|
||||
run: |
|
||||
OUTPUT=target/linux-egui-packages
|
||||
APPIMAGE=$(find "$OUTPUT" -maxdepth 1 -name '*.AppImage' -print -quit)
|
||||
if [ -n "${RELEASE_TAG:-}" ] && [ -z "${MINISIGN_SECRET:-}" ]; then
|
||||
echo "::error::LINUX_EGUI_MINISIGN_SECRET_KEY is required for release upload"
|
||||
exit 1
|
||||
fi
|
||||
if [ -n "${MINISIGN_SECRET:-}" ]; then
|
||||
if ! command -v minisign >/dev/null 2>&1; then
|
||||
cargo install --locked --version 0.9.1 minisign
|
||||
fi
|
||||
printf '%s' "$MINISIGN_SECRET" > "$RUNNER_TEMP/linux-egui.minisign.key"
|
||||
minisign -S -s "$RUNNER_TEMP/linux-egui.minisign.key" -m "$APPIMAGE" -x "$APPIMAGE.minisig"
|
||||
fi
|
||||
SHA256=$(sha256sum "$APPIMAGE" | cut -d' ' -f1)
|
||||
ASSET=$(basename "$APPIMAGE")
|
||||
RELEASE_REPOSITORY="${GITHUB_REPOSITORY:-Open-Less/openless}"
|
||||
SIGNATURE=null
|
||||
if [ -f "$APPIMAGE.minisig" ]; then
|
||||
SIGNATURE=$(base64 -w0 "$APPIMAGE.minisig" | jq -R .)
|
||||
fi
|
||||
jq -n \
|
||||
--arg version "$VERSION" \
|
||||
--arg url "https://github.com/$RELEASE_REPOSITORY/releases/download/${RELEASE_TAG:-manual}/$ASSET" \
|
||||
--arg sha256 "$SHA256" \
|
||||
--argjson signature "$SIGNATURE" \
|
||||
'{schemaVersion:1, host:"linux-egui", arch:"x86_64", version:$version, url:$url, sha256:$sha256, minisign:$signature}' \
|
||||
> "$OUTPUT/latest-linux-egui-x86_64.json"
|
||||
|
||||
- name: Verify Linux updater manifest matches the artifact
|
||||
working-directory: openless-all/app
|
||||
run: |
|
||||
set -euo pipefail
|
||||
OUTPUT=target/linux-egui-packages
|
||||
APPIMAGE=$(find "$OUTPUT" -maxdepth 1 -name '*.AppImage' -print -quit)
|
||||
MANIFEST="$OUTPUT/latest-linux-egui-x86_64.json"
|
||||
test -s "$APPIMAGE"
|
||||
test -s "$MANIFEST"
|
||||
SHA256=$(sha256sum "$APPIMAGE" | cut -d' ' -f1)
|
||||
RELEASE_REPOSITORY="${GITHUB_REPOSITORY:-Open-Less/openless}"
|
||||
jq -e \
|
||||
--arg sha256 "$SHA256" \
|
||||
--arg repository "$RELEASE_REPOSITORY" \
|
||||
'.schemaVersion == 1 and .host == "linux-egui" and .arch == "x86_64" and .sha256 == $sha256 and (.url | startswith("https://github.com/" + $repository + "/releases/download/"))' \
|
||||
"$MANIFEST" >/dev/null
|
||||
|
||||
- name: Upload Linux egui workflow artifacts
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: openless-linux-egui-x86_64
|
||||
path: openless-all/app/target/linux-egui-packages/*
|
||||
if-no-files-found: error
|
||||
|
||||
- name: Upload Linux egui assets to existing release
|
||||
if: inputs.release_tag != ''
|
||||
uses: softprops/action-gh-release@v2
|
||||
with:
|
||||
tag_name: ${{ inputs.release_tag }}
|
||||
files: openless-all/app/target/linux-egui-packages/*
|
||||
fail_on_unmatched_files: true
|
||||
@@ -5,7 +5,8 @@ name: Release Tauri (cross-platform)
|
||||
# - 手动 dispatch(用于测试构建,不发版)
|
||||
#
|
||||
# 输出:
|
||||
# macOS arm64/x64 .dmg + Windows x64 .msi/.exe + Linux x64 .deb/.rpm/.AppImage,自动作为 GitHub Release 资产上传。
|
||||
# macOS arm64/x64 .dmg + Windows x64 .msi/.exe,自动作为 GitHub Release 资产上传。
|
||||
# Linux egui 由 release-linux-egui.yml 独立构建;本工作流不编译 Linux/Tauri。
|
||||
#
|
||||
# macOS 分发:
|
||||
# - 配好 APPLE_CERTIFICATE / APPLE_CERTIFICATE_PASSWORD / APPLE_ID /
|
||||
@@ -46,10 +47,6 @@ jobs:
|
||||
rust-target: x86_64-pc-windows-msvc
|
||||
updater-target: windows
|
||||
updater-arch: x86_64
|
||||
- platform: ubuntu-22.04
|
||||
rust-target: x86_64-unknown-linux-gnu
|
||||
updater-target: linux
|
||||
updater-arch: x86_64
|
||||
runs-on: ${{ matrix.platform }}
|
||||
env:
|
||||
TAURI_SIGNING_PRIVATE_KEY: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY }}
|
||||
@@ -65,14 +62,9 @@ jobs:
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
# MLX 子模块只在 macOS 发布构建需要;Linux 的 C 后端单独初始化 qwen-asr。
|
||||
# MLX 子模块只在 macOS 发布构建需要。
|
||||
submodules: ${{ startsWith(matrix.platform, 'macos') && 'recursive' || 'false' }}
|
||||
|
||||
- name: Initialize Linux C ASR submodule
|
||||
if: matrix.platform == 'ubuntu-22.04'
|
||||
shell: bash
|
||||
run: git submodule update --init openless-all/app/src-tauri/vendor/qwen-asr
|
||||
|
||||
- name: Disable macOS-only Qwen3 MLX dependency
|
||||
if: ${{ !startsWith(matrix.platform, 'macos') }}
|
||||
run: node openless-all/app/scripts/ci-disable-macos-qwen3.mjs
|
||||
@@ -92,25 +84,11 @@ jobs:
|
||||
with:
|
||||
workspaces: 'openless-all/app/src-tauri -> target'
|
||||
|
||||
- name: Install Linux bundle deps
|
||||
if: matrix.platform == 'ubuntu-22.04'
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y \
|
||||
build-essential \
|
||||
curl \
|
||||
file \
|
||||
libasound2-dev \
|
||||
libayatana-appindicator3-dev \
|
||||
libfuse2 \
|
||||
librsvg2-dev \
|
||||
libssl-dev \
|
||||
libwebkit2gtk-4.1-dev \
|
||||
libxdo-dev \
|
||||
patchelf \
|
||||
rpm \
|
||||
squashfs-tools \
|
||||
wget
|
||||
- name: Prepare Windows Sherpa static libraries
|
||||
if: matrix.platform == 'windows-latest'
|
||||
working-directory: 'openless-all/app'
|
||||
shell: pwsh
|
||||
run: ./scripts/prepare-windows-sherpa.ps1
|
||||
|
||||
- name: Install npm deps
|
||||
working-directory: 'openless-all/app'
|
||||
@@ -263,6 +241,16 @@ jobs:
|
||||
TAURI_SIGNING_PRIVATE_KEY_PASSWORD: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY_PASSWORD }}
|
||||
run: |
|
||||
set +e
|
||||
# WiX/MSI only accepts a numeric prerelease identifier. Manual
|
||||
# validation runs use the repository's Beta version even though the
|
||||
# ref is a branch (and therefore OPENLESS_RELEASE_CHANNEL=stable),
|
||||
# so detect the version explicitly instead of relying on the tag.
|
||||
app_version=$(node -p "require('./src-tauri/tauri.conf.json').version")
|
||||
msi_supported=1
|
||||
if [[ "$app_version" =~ -[^0-9] ]]; then
|
||||
msi_supported=0
|
||||
echo "[info] Skipping MSI bundle for non-numeric prerelease version $app_version."
|
||||
fi
|
||||
# 拆两轮跑:Tauri 的签名 / updater artifact 阶段是 post-bundle 钩子,
|
||||
# 任意 bundler 失败会让 *所有* bundle 的 .sig 跳过。MSI 必踩 ICE80,
|
||||
# 所以单一 `tauri build` 永远拿不到 NSIS 的 .exe.sig。
|
||||
@@ -273,9 +261,9 @@ jobs:
|
||||
if [ -n "${TAURI_SIGNING_PRIVATE_KEY:-}" ]; then
|
||||
npm run tauri -- build --bundles nsis --config '{"bundle":{"createUpdaterArtifacts":true}}'
|
||||
nsis_exit=$?
|
||||
if [ "${OPENLESS_RELEASE_CHANNEL:-stable}" = "beta" ]; then
|
||||
if [ "${OPENLESS_RELEASE_CHANNEL:-stable}" = "beta" ] || [ "$msi_supported" -eq 0 ]; then
|
||||
echo "OPENLESS_SKIP_WINDOWS_MSI=1" >> "$GITHUB_ENV"
|
||||
echo "[info] Skipping MSI bundle for beta release channel."
|
||||
echo "[info] Skipping MSI bundle for unsupported prerelease/channel."
|
||||
msi_exit=0
|
||||
else
|
||||
echo "OPENLESS_SKIP_WINDOWS_MSI=0" >> "$GITHUB_ENV"
|
||||
@@ -285,9 +273,9 @@ jobs:
|
||||
else
|
||||
npm run tauri -- build --bundles nsis
|
||||
nsis_exit=$?
|
||||
if [ "${OPENLESS_RELEASE_CHANNEL:-stable}" = "beta" ]; then
|
||||
if [ "${OPENLESS_RELEASE_CHANNEL:-stable}" = "beta" ] || [ "$msi_supported" -eq 0 ]; then
|
||||
echo "OPENLESS_SKIP_WINDOWS_MSI=1" >> "$GITHUB_ENV"
|
||||
echo "[info] Skipping MSI bundle for beta release channel."
|
||||
echo "[info] Skipping MSI bundle for unsupported prerelease/channel."
|
||||
msi_exit=0
|
||||
else
|
||||
echo "OPENLESS_SKIP_WINDOWS_MSI=0" >> "$GITHUB_ENV"
|
||||
@@ -379,149 +367,6 @@ jobs:
|
||||
throw "MSI installer smoke failed with exit $LASTEXITCODE"
|
||||
}
|
||||
|
||||
# ── Linux:先编译 fcitx5 插件,再产 deb / rpm / AppImage ──
|
||||
- name: Build fcitx5 plugin
|
||||
if: matrix.platform == 'ubuntu-22.04'
|
||||
shell: bash
|
||||
working-directory: 'openless-all/scripts/linux-fcitx5-plugin'
|
||||
run: |
|
||||
# v1.3.4-3 之后 Ubuntu 22.04 universe 把 fcitx5-dev 这个 meta 包移除了
|
||||
# (v1.3.4-4/-5/-6 在此步连挂三次,错误 "Unable to locate package fcitx5-dev")。
|
||||
# v1.3.4-6 加的 apt-cache search 诊断显示,22.04 jammy 实际只剩拆分后的
|
||||
# libfcitx5{core,utils,config}-dev / fcitx5-modules-dev 等子包,
|
||||
# 但 fcitx5-dev 这个 umbrella 包确认已不在源里。
|
||||
#
|
||||
# CMakeLists.txt 实际只需要:
|
||||
# find_package(Fcitx5Core) → libfcitx5core-dev
|
||||
# find_package(Fcitx5Utils) → libfcitx5utils-dev
|
||||
# find_package(Fcitx5Module) → fcitx5-modules-dev
|
||||
# 另外 fcitx5 自己的 CMake config 文件依赖 KDE ECM。
|
||||
# 保留 add-apt-repository universe + 本步骤内 apt-get update 作为通用防御。
|
||||
sudo add-apt-repository -y universe || true
|
||||
sudo apt-get update
|
||||
if ! sudo apt-get install -y \
|
||||
cmake \
|
||||
extra-cmake-modules \
|
||||
libfcitx5core-dev \
|
||||
libfcitx5utils-dev \
|
||||
libfcitx5config-dev \
|
||||
fcitx5-modules-dev; then
|
||||
echo "::error::fcitx5 dev packages install failed. Diagnostics ↓"
|
||||
echo "--- apt-cache search fcitx5 ---"
|
||||
apt-cache search fcitx5 || true
|
||||
echo "--- /etc/os-release ---"
|
||||
cat /etc/os-release || true
|
||||
echo "--- /etc/apt/sources.list.d ---"
|
||||
ls -la /etc/apt/sources.list.d/ || true
|
||||
exit 1
|
||||
fi
|
||||
mkdir -p build && cd build
|
||||
# 显式 CMAKE_INSTALL_PREFIX=/usr:fcitx5 在 Ubuntu 上的运行时插件搜索
|
||||
# 路径是 /usr/lib/<arch>/fcitx5/,默认 prefix=/usr/local 会让 .deb 把
|
||||
# 插件安到 /usr/local/lib/fcitx5/,fcitx5 永远找不到。
|
||||
# 历史上 v1.3.4-3 也是这条 bug 路径,只是 cmake -LA 那行先挂掉,没人意识到。
|
||||
cmake .. -DCMAKE_INSTALL_PREFIX=/usr 2>&1 | tee cmake-configure.log
|
||||
make
|
||||
# v1.3.4-7 暴露:fcitx5 5.0.14 把 FCITX_INSTALL_* 设为普通变量而非 CACHE,
|
||||
# `cmake -LA` 抓不到 → grep 退码 1 → set -e -o pipefail 整步退出。
|
||||
# 改从 configure 阶段 message(STATUS ...) 的输出抓(CMakeLists.txt 已经打印)。
|
||||
FCITX_ADDON_DIR=$(grep "FCITX_INSTALL_ADDONDIR:" cmake-configure.log \
|
||||
| tail -1 | sed -E 's/^[^:]*: ([^ ]+).*/\1/')
|
||||
FCITX_PKGDATA_DIR=$(grep "FCITX_INSTALL_PKGDATADIR:" cmake-configure.log \
|
||||
| tail -1 | sed -E 's/^[^:]*: ([^ ]+).*/\1/')
|
||||
if [ -z "$FCITX_ADDON_DIR" ] || [ -z "$FCITX_PKGDATA_DIR" ]; then
|
||||
echo "::error::Failed to extract FCITX_INSTALL_* paths from cmake configure log"
|
||||
echo "--- cmake-configure.log (last 50 lines) ---"
|
||||
tail -50 cmake-configure.log
|
||||
exit 1
|
||||
fi
|
||||
echo "Detected: addon=$FCITX_ADDON_DIR pkgdata=$FCITX_PKGDATA_DIR"
|
||||
echo "FCITX_ADDON_DIR=$FCITX_ADDON_DIR" >> "$GITHUB_ENV"
|
||||
echo "FCITX_ADDON_CONF_DIR=${FCITX_PKGDATA_DIR}/addon" >> "$GITHUB_ENV"
|
||||
# 对 RPM 目标映射路径:Debian multiarch(如 /usr/lib/x86_64-linux-gnu)
|
||||
# -> /usr/lib64(RPM 标准)。conf 路径跨发行版一致。
|
||||
RPM_ADDON_DIR=$(echo "$FCITX_ADDON_DIR" \
|
||||
| sed 's|/usr/lib/[^/]*/fcitx5|/usr/lib64/fcitx5|;s|/usr/lib/x86_64-linux-gnu/fcitx5|/usr/lib64/fcitx5|')
|
||||
echo "FCITX_RPM_ADDON_DIR=$RPM_ADDON_DIR" >> "$GITHUB_ENV"
|
||||
# 把插件 .so + .conf 复制到 src-tauri/linux-fcitx5-plugin/ 下面,
|
||||
# 供 tauri deb/rpm bundler 的 files 配置使用。
|
||||
mkdir -p "$GITHUB_WORKSPACE/openless-all/app/src-tauri/linux-fcitx5-plugin"
|
||||
cp libopenless.so "$GITHUB_WORKSPACE/openless-all/app/src-tauri/linux-fcitx5-plugin/"
|
||||
cp openless.conf "$GITHUB_WORKSPACE/openless-all/app/src-tauri/linux-fcitx5-plugin/"
|
||||
test -s "$GITHUB_WORKSPACE/openless-all/app/src-tauri/linux-fcitx5-plugin/libopenless.so"
|
||||
test -s "$GITHUB_WORKSPACE/openless-all/app/src-tauri/linux-fcitx5-plugin/openless.conf"
|
||||
|
||||
- name: Build (Linux)
|
||||
if: matrix.platform == 'ubuntu-22.04'
|
||||
shell: bash
|
||||
working-directory: 'openless-all/app'
|
||||
env:
|
||||
TAURI_SIGNING_PRIVATE_KEY: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY }}
|
||||
TAURI_SIGNING_PRIVATE_KEY_PASSWORD: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY_PASSWORD }}
|
||||
run: |
|
||||
# deb/rpm:通过 files 映射把插件安装到系统 fcitx5 路径。
|
||||
# AppImage:通过 bundle.resources 把 .so 打进包内,运行时由
|
||||
# ensure_plugin_installed() 自动安装到 ~/.local/ 下。
|
||||
# 插件 .so + .conf 由上一步 Build fcitx5 plugin 生成并复制到
|
||||
# src-tauri/linux-fcitx5-plugin/ 下。
|
||||
test -s src-tauri/linux-fcitx5-plugin/libopenless.so
|
||||
test -s src-tauri/linux-fcitx5-plugin/openless.conf
|
||||
cat > /tmp/tauri-linux-config.json << CONFIG_EOF
|
||||
{
|
||||
"bundle": {
|
||||
"resources": [
|
||||
"linux-fcitx5-plugin/libopenless.so",
|
||||
"linux-fcitx5-plugin/openless.conf"
|
||||
],
|
||||
"linux": {
|
||||
"deb": {
|
||||
"depends": ["fcitx5", "fcitx5-module-dbus", "libdbus-1-3"],
|
||||
"files": {
|
||||
"${FCITX_ADDON_DIR}/libopenless.so": "linux-fcitx5-plugin/libopenless.so",
|
||||
"${FCITX_ADDON_CONF_DIR}/openless.conf": "linux-fcitx5-plugin/openless.conf"
|
||||
}
|
||||
},
|
||||
"rpm": {
|
||||
"depends": ["fcitx5", "fcitx5-module-dbus"],
|
||||
"files": {
|
||||
"${FCITX_RPM_ADDON_DIR}/libopenless.so": "linux-fcitx5-plugin/libopenless.so",
|
||||
"${FCITX_ADDON_CONF_DIR}/openless.conf": "linux-fcitx5-plugin/openless.conf"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
CONFIG_EOF
|
||||
if [ -n "${TAURI_SIGNING_PRIVATE_KEY:-}" ]; then
|
||||
jq '.bundle.createUpdaterArtifacts = true' /tmp/tauri-linux-config.json > /tmp/tauri-linux-config-signed.json
|
||||
CONFIG_FILE=/tmp/tauri-linux-config-signed.json
|
||||
else
|
||||
CONFIG_FILE=/tmp/tauri-linux-config.json
|
||||
fi
|
||||
npm run tauri -- build --bundles deb,rpm,appimage --config "$CONFIG_FILE"
|
||||
|
||||
APPIMAGE_PATH=$(find src-tauri/target/release/bundle/appimage -maxdepth 1 -name '*.AppImage' -print -quit)
|
||||
if [ -z "$APPIMAGE_PATH" ]; then
|
||||
echo "::error::AppImage bundle was not produced"
|
||||
exit 1
|
||||
fi
|
||||
# Type-2 AppImage has an ELF launcher before the embedded SquashFS.
|
||||
# Resolve the filesystem offset before asking unsquashfs to inspect it.
|
||||
APPIMAGE_OFFSET=$("$APPIMAGE_PATH" --appimage-offset)
|
||||
if ! [[ "$APPIMAGE_OFFSET" =~ ^[0-9]+$ ]]; then
|
||||
echo "::error::Could not resolve the AppImage SquashFS offset"
|
||||
exit 1
|
||||
fi
|
||||
APPIMAGE_CONTENTS=$(unsquashfs -offset "$APPIMAGE_OFFSET" -l "$APPIMAGE_PATH")
|
||||
if ! grep -Eq '(^|/)usr/lib/OpenLess/linux-fcitx5-plugin/libopenless\.so$' <<< "$APPIMAGE_CONTENTS"; then
|
||||
echo "::error::AppImage is missing usr/lib/OpenLess/linux-fcitx5-plugin/libopenless.so"
|
||||
exit 1
|
||||
fi
|
||||
if ! grep -Eq '(^|/)usr/lib/OpenLess/linux-fcitx5-plugin/openless\.conf$' <<< "$APPIMAGE_CONTENTS"; then
|
||||
echo "::error::AppImage is missing usr/lib/OpenLess/linux-fcitx5-plugin/openless.conf"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
- name: Disambiguate macOS updater bundle filename
|
||||
if: startsWith(matrix.platform, 'macos') && env.TAURI_SIGNING_PRIVATE_KEY != ''
|
||||
shell: bash
|
||||
@@ -557,7 +402,7 @@ jobs:
|
||||
- name: List artifacts (debug)
|
||||
shell: bash
|
||||
working-directory: 'openless-all/app/src-tauri/target/release/bundle'
|
||||
run: ls -la macos/ dmg/ nsis/ msi/ deb/ rpm/ appimage/ 2>/dev/null || true
|
||||
run: ls -la macos/ dmg/ nsis/ msi/ 2>/dev/null || true
|
||||
|
||||
# 防御性步骤:剥掉 macOS 产物上任何残留扩展属性 / quarantine。
|
||||
# 理论上 GitHub Actions 输出的 .app/.dmg 不会带 com.apple.quarantine
|
||||
@@ -618,43 +463,11 @@ jobs:
|
||||
openless-all/app/src-tauri/target/release/bundle/latest-windows-x86_64*.json
|
||||
if-no-files-found: error
|
||||
|
||||
- name: Upload fcitx5 plugin artifact (standalone)
|
||||
if: matrix.platform == 'ubuntu-22.04'
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: openless-fcitx5-plugin-linux-x64
|
||||
path: |
|
||||
${{ github.workspace }}/openless-all/scripts/linux-fcitx5-plugin/build/libopenless.so
|
||||
${{ github.workspace }}/openless-all/scripts/linux-fcitx5-plugin/build/openless.conf
|
||||
if-no-files-found: error
|
||||
|
||||
- name: Upload Linux artifacts
|
||||
if: matrix.platform == 'ubuntu-22.04'
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: openless-linux-x64
|
||||
path: |
|
||||
openless-all/app/src-tauri/target/release/bundle/deb/*.deb
|
||||
openless-all/app/src-tauri/target/release/bundle/rpm/*.rpm
|
||||
openless-all/app/src-tauri/target/release/bundle/appimage/*.AppImage
|
||||
if-no-files-found: error
|
||||
|
||||
- name: Upload Linux updater artifacts
|
||||
if: matrix.platform == 'ubuntu-22.04' && env.TAURI_SIGNING_PRIVATE_KEY != ''
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: openless-linux-x64-updater
|
||||
path: |
|
||||
openless-all/app/src-tauri/target/release/bundle/appimage/*.AppImage.sig
|
||||
openless-all/app/src-tauri/target/release/bundle/latest-linux-x86_64*.json
|
||||
if-no-files-found: error
|
||||
|
||||
# ── tag 推送时,同步上传到 GitHub Release ──
|
||||
# 只有 leader job (darwin/aarch64) 把 release body 写到文件,其余 matrix job
|
||||
# 的 body_path 留空,softprops/action-gh-release@v2 在 body 为空时会保留
|
||||
# existing release body 不动,避免每个 matrix job 都 append 一遍同样的 prelude
|
||||
# 导致 release notes 重复 N 次 (v1.3.4-tauri 出现 4 次的 root cause:
|
||||
# 4 个 matrix job × append_body=true × 共享同一份 body)。
|
||||
# 导致 release notes 重复 N 次。
|
||||
- name: Prepare release body prelude
|
||||
if: matrix.updater-target == 'darwin' && matrix.updater-arch == 'aarch64' && startsWith(github.ref, 'refs/tags/v') && endsWith(github.ref, '-tauri')
|
||||
shell: bash
|
||||
@@ -699,8 +512,7 @@ jobs:
|
||||
# "prelude + generated notes",re-run 同一 tag 时也保持 idempotent
|
||||
# (append_body=true 会让 re-run 把上轮 body 拼到前面、再次复制)。
|
||||
body_path: ${{ env.OPENLESS_RELEASE_BODY_PATH }}
|
||||
# generate_release_notes 也只在 leader 跑:避免 4 个 matrix jobs
|
||||
# 产生 4 份相同的 What's Changed 段。
|
||||
# generate_release_notes 也只在 leader 跑,避免 matrix jobs 重复生成。
|
||||
generate_release_notes: ${{ matrix.updater-target == 'darwin' && matrix.updater-arch == 'aarch64' }}
|
||||
files: |
|
||||
openless-all/app/src-tauri/target/release/bundle/dmg/*.dmg
|
||||
@@ -710,14 +522,7 @@ jobs:
|
||||
openless-all/app/src-tauri/target/release/bundle/nsis/*.exe.sig
|
||||
openless-all/app/src-tauri/target/release/bundle/msi/*.msi
|
||||
openless-all/app/src-tauri/target/release/bundle/msi/*.msi.sig
|
||||
openless-all/app/src-tauri/target/release/bundle/deb/*.deb
|
||||
openless-all/app/src-tauri/target/release/bundle/rpm/*.rpm
|
||||
openless-all/app/src-tauri/target/release/bundle/appimage/*.AppImage
|
||||
openless-all/app/src-tauri/target/release/bundle/appimage/*.AppImage.sig
|
||||
openless-all/app/src-tauri/target/release/bundle/latest-*.json
|
||||
# fcitx5 插件独立下载:供 AppImage 用户或手动安装
|
||||
openless-all/scripts/linux-fcitx5-plugin/build/libopenless.so
|
||||
openless-all/scripts/linux-fcitx5-plugin/build/openless.conf
|
||||
|
||||
# ── 正式版发布后,自动更新 Homebrew cask ──
|
||||
# 为什么放进这条流水线,而不是单独的 `release: published` 工作流:softprops 用默认
|
||||
|
||||
Reference in new issue
Block a user