Skip to content

fix(ci): 构建前强制重下 sherpa 库(规避 rust-cache 不完整恢复) #54

fix(ci): 构建前强制重下 sherpa 库(规避 rust-cache 不完整恢复)

fix(ci): 构建前强制重下 sherpa 库(规避 rust-cache 不完整恢复) #54

Workflow file for this run

name: Release Tauri App
# 由 v* tag 触发:构建 Tauri 安装包并发布到 GitHub Release + 自建服务器 + OSS
# 适配说明(2026-08-21):原 Electron 发布链适配为 Tauri——
# electron-builder → cargo tauri build(nsis);更新源 latest.yml → Tauri 安装包直链
# (updater 端点未启用,TODO:启用 tauri.conf updater 后补 latest.json 同步)
# 2026-08-27 重构:build 完成后直接发布(gh release + SCP + OSS),
# 移除 artifact 中转——artifact 存储配额(500MB)无法容纳 349MB 安装包多次构建
on:
push:
tags: ['v*']
release:
types: [published]
workflow_dispatch:
permissions:
contents: write
concurrency:
group: release-tauri-${{ github.ref_name }}
cancel-in-progress: false
jobs:
lint-test:
# 项目含 Windows 专用模块(audio_route_probe/device_probe/gdi_capture 等未做 Linux cfg 隔离),
# 测试必须在 Windows runner 执行;Linux 编译会因 E0433 失败
runs-on: windows-latest
timeout-minutes: 60
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@stable
with:
targets: x86_64-pc-windows-msvc
- name: Cache cargo registry
uses: Swatinem/rust-cache@v2
with:
workspaces: app/src-tauri
# models/ 不入库(AGENTS.md 铁律),build.rs 的 bundle.resources glob 需要空目录占位
- name: Prepare models placeholder
shell: bash
run: mkdir -p app/src-tauri/models
# .cargo/config.toml 注入的是本机 Windows 预编译库绝对路径(sherpa-archive/、ort/),
# ort-sys/sherpa-onnx-sys 只要见到 ORT_LIB_LOCATION/SHERPA_ONNX_ARCHIVE_DIR 存在即跳过下载——
# CI 无法 unset env,直接移除 config 使注入消失,两库回退在线下载(CI 网络可达)
- name: Remove local cargo config (CI online download)
shell: bash
run: rm -f app/src-tauri/.cargo/config.toml
# oar-ocr 未启用 ort-sys 的 download-binaries feature(本地靠 ORT_LIB_LOCATION 链接),
# CI 必须手动提供 ONNX Runtime 库,与本地 ORT_LIB_LOCATION 同机制(CPU 包即可,测试不初始化 CUDA)
- name: Prepare ONNX Runtime for CI
shell: bash
run: |
mkdir -p app/src-tauri/ort/ci
curl -sL https://github.com/microsoft/onnxruntime/releases/download/v1.28.0/onnxruntime-win-x64-1.28.0.zip -o /tmp/ort.zip
unzip -q /tmp/ort.zip -d /tmp/ortx
cp /tmp/ortx/onnxruntime-win-x64-1.28.0/lib/onnxruntime.* app/src-tauri/ort/ci/
- name: Test
# ORT_PREFER_DYNAMIC_LINK=1:与本地一致走动态链接,规避 static MT 与项目 MD 运行时的 LNK2038 冲突
env:
ORT_LIB_LOCATION: ${{ github.workspace }}/app/src-tauri/ort/ci
ORT_PREFER_DYNAMIC_LINK: "1"
# 跳过 3 个预存基线失败(CHANGELOG 已登记,与本版无关):
# ai_client 默认 Provider 断言 / note_filter 两条黄金用例——待后续版本修复
run: |
cd app/src-tauri
# rust-cache 恢复的 target/sherpa-onnx-prebuilt 可能不完整(历史 LNK1181),强制重新下载
rm -rf target/sherpa-onnx-prebuilt
cargo test -- --skip ai_client::tests::from_settings_resolves_default_provider_when_set --skip note_filter::golden_tests::session29_live_ui_excluded_from_points --skip note_filter::tests::ocr_points_exclude_watermark_junk_and_dupes
build:
needs: lint-test
runs-on: windows-latest
# Tauri 打包 + 发布(GitHub Release + 服务器 + OSS):上限 90 分钟
timeout-minutes: 90
env:
HAS_ALIYUN_AK: ${{ secrets.ALIYUN_ACCESS_KEY_ID != '' }}
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 20
cache: 'npm'
cache-dependency-path: app/package-lock.json
- uses: dtolnay/rust-toolchain@stable
with:
targets: x86_64-pc-windows-msvc
- name: Cache cargo registry
uses: Swatinem/rust-cache@v2
with:
workspaces: app/src-tauri
# 模型资源占位:models/ 不入库(AGENTS.md 铁律),CI 构建时创建空目录
# 避免 tauri bundle 资源 glob 报错;运行时缺失模型有下载/降级路径兜底
- name: Prepare models placeholder
shell: bash
run: mkdir -p app/src-tauri/models
- name: Install frontend deps
run: cd app && npm ci
- name: Build Tauri app (NSIS)
shell: bash
# .cargo/config.toml 注入的是本机 Windows 预编译库绝对路径(sherpa-archive/、ort/),
# ort-sys/sherpa-onnx-sys 只要见到 ORT_LIB_LOCATION/SHERPA_ONNX_ARCHIVE_DIR 存在即跳过下载——
# CI 无法 unset env,直接移除 config 使注入消失,两库回退在线下载(CI 网络可达)
run: |
rm -f app/src-tauri/.cargo/config.toml
# rust-cache 恢复的 target/sherpa-onnx-prebuilt 可能不完整(历史 LNK1181),强制重新下载
rm -rf app/src-tauri/target/sherpa-onnx-prebuilt
mkdir -p app/src-tauri/ort/ci
curl -sL https://github.com/microsoft/onnxruntime/releases/download/v1.28.0/onnxruntime-win-x64-1.28.0.zip -o /tmp/ort.zip
unzip -q /tmp/ort.zip -d /tmp/ortx
cp /tmp/ortx/onnxruntime-win-x64-1.28.0/lib/onnxruntime.* app/src-tauri/ort/ci/
cd app && npx tauri build --bundles nsis
# oar-ocr 未启用 ort-sys download-binaries(本地靠 ORT_LIB_LOCATION 链接),
# CI 手动提供 ORT 库并复用同一机制;动态链接规避 LNK2038(同本地 config)
env:
ORT_LIB_LOCATION: ${{ github.workspace }}/app/src-tauri/ort/ci
ORT_PREFER_DYNAMIC_LINK: "1"
# ---------------------------------------------------------------
# 发布阶段(不再走 artifact 中转:配额 500MB 装不下 349MB 安装包多次构建)
# ---------------------------------------------------------------
- name: Collect installer and generate latest.json
id: meta
shell: bash
run: |
mkdir -p release-files
cp app/src-tauri/target/release/bundle/nsis/*.exe release-files/
FILE=$(ls release-files/*.exe | head -1 | xargs basename)
SIZE=$(stat -c%s "release-files/$FILE")
SHA256=$(sha256sum "release-files/$FILE" | awk '{print $1}')
DATE=$(date -u +%F)
printf '{"version":"%s","fileName":"%s","size":%s,"sha256":"%s","releaseDate":"%s"}\n' \
"${{ github.ref_name }}" "$FILE" "$SIZE" "$SHA256" "$DATE" > release-files/latest.json
cat release-files/latest.json
echo "file=$FILE" >> "$GITHUB_OUTPUT"
SIZE_MB=$(awk "BEGIN {printf \"%.2f\", $SIZE / 1048576}")
echo "📦 $FILE: ${SIZE_MB} MB"
if [ "$SIZE" -gt 419430400 ]; then
echo "::warning::${FILE} 超过 400MB,请检查是否误打包大文件(模型不入库)"
fi
- name: Upload installer to GitHub Release
shell: bash
env:
GH_TOKEN: ${{ github.token }}
TAG: ${{ github.ref_name }}
FILE_NAME: ${{ steps.meta.outputs.file }}
run: |
# tag 触发的 release 可能尚不存在(semantic-release 未参与时),不存在则创建
gh release view "$TAG" --json id >/dev/null 2>&1 || gh release create "$TAG" --title "$TAG" --notes "熵减 $TAG" --generate-notes
gh release upload "$TAG" "release-files/$FILE_NAME" --clobber
# ---------------------------------------------------------------
# 同步安装包至自建服务器(国内主下载源;服务器连接继承自原项目)
# appleboy/ssh-action 与 scp-action 不支持 Windows runner(MSYS 平台检测失败),
# 改用 Windows 自带 OpenSSH(ssh/scp 均在 Git Bash 可用)
# ---------------------------------------------------------------
- name: Sync installer to server
shell: bash
env:
SSH_KEY: ${{ secrets.SSH_PRIVATE_KEY }}
SERVER_HOST: ${{ secrets.SERVER_HOST }}
SERVER_USER: ${{ secrets.SERVER_USER }}
run: |
mkdir -p ~/.ssh
echo "$SSH_KEY" > ~/.ssh/deploy_key
chmod 600 ~/.ssh/deploy_key
SSH_OPTS="-i ~/.ssh/deploy_key -o StrictHostKeyChecking=no -o ConnectTimeout=30"
ssh $SSH_OPTS "$SERVER_USER@$SERVER_HOST" "mkdir -p /opt/Entropydecrease/downloads"
scp $SSH_OPTS release-files/*.exe "$SERVER_USER@$SERVER_HOST:/opt/Entropydecrease/downloads/"
# 元数据最后发布,避免 404 窗口期
scp $SSH_OPTS release-files/latest.json "$SERVER_USER@$SERVER_HOST:/opt/Entropydecrease/downloads/"
# 保留策略:仅保留最近 3 个版本的安装包,防止磁盘增长
ssh $SSH_OPTS "$SERVER_USER@$SERVER_HOST" "cd /opt/Entropydecrease/downloads && ls -t -- *.exe 2>/dev/null | tail -n +4 | while read -r f; do rm -f -- \"\$f\"; done"
rm -f ~/.ssh/deploy_key
# ---------------------------------------------------------------
# 同步至 OSS(CDN 源站;可选——未配置阿里云凭据时跳过)
# ---------------------------------------------------------------
- name: Upload to OSS (CDN origin)
if: env.HAS_ALIYUN_AK == 'true'
shell: bash
env:
AK_ID: ${{ secrets.ALIYUN_ACCESS_KEY_ID }}
AK_SECRET: ${{ secrets.ALIYUN_ACCESS_KEY_SECRET }}
OSS_ENDPOINT_IN: ${{ secrets.OSS_ENDPOINT }}
FILE_NAME: ${{ steps.meta.outputs.file }}
run: |
set -eo pipefail
OSS_ENDPOINT="${OSS_ENDPOINT_IN:-oss-cn-hangzhou.aliyuncs.com}"
# build job 为 windows runner,需下载 Windows 版 aliyun CLI
curl -sL https://aliyuncli.alicdn.com/aliyun-cli-windows-latest-amd64.zip -o /tmp/aliyun.zip
unzip -q /tmp/aliyun.zip -d /tmp/aliyun
/tmp/aliyun/aliyun.exe configure set --profile ossci --mode AK --region cn-hangzhou \
--access-key-id "$AK_ID" --access-key-secret "$AK_SECRET"
/tmp/aliyun/aliyun.exe oss cp "release-files/$FILE_NAME" \
"oss://${{ secrets.OSS_BUCKET }}/downloads/$FILE_NAME" \
--force -e "$OSS_ENDPOINT" --profile ossci
/tmp/aliyun/aliyun.exe oss cp release-files/latest.json \
"oss://${{ secrets.OSS_BUCKET }}/downloads/latest.json" \
--force -e "$OSS_ENDPOINT" --profile ossci
echo "OSS sync done"
# ---------------------------------------------------------------
# 发布结果校验:防止"空 Release"(历史事故 v0.27.0/v0.28.7)
# ---------------------------------------------------------------
- name: Verify release assets
if: startsWith(github.ref, 'refs/tags/')
shell: bash
env:
GH_TOKEN: ${{ github.token }}
GH_REPO: ${{ github.repository }}
TAG: ${{ github.ref_name }}
run: |
set -eo pipefail
names=$(gh release view "$TAG" --json assets --jq '.assets[].name')
echo "Assets of $TAG:"
echo "$names"
if ! echo "$names" | grep -qE '\.exe$'; then
echo "::error::Release $TAG 缺少 .exe 安装包资产"
exit 1
fi
echo "发布资产完整校验通过"