Repository navigation
245 lines (235 loc) · 12.9 KB
/
Copy pathrelease.yml
File metadata and controls
245 lines (235 loc) · 12.9 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
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/
# sherpa-onnx-sys 自带的在线下载在 CI 上不稳定(曾出现解压残缺导致 LNK1181),
# 改用官方 SHERPA_ONNX_ARCHIVE_DIR 机制(与本地 config 一致):curl 预下载 tar 包,
# build script 从 archive 解压,绕开其内嵌下载逻辑
- name: Prepare sherpa-onnx archive for CI
shell: bash
run: |
mkdir -p app/src-tauri/sherpa-archive
curl -sL "https://github.com/k2-fsa/sherpa-onnx/releases/download/v1.13.5/sherpa-onnx-v1.13.5-win-x64-shared-MT-Release-lib.tar.bz2" \
-o app/src-tauri/sherpa-archive/sherpa-onnx-v1.13.5-win-x64-shared-MT-Release-lib.tar.bz2
- name: Test
# ORT_PREFER_DYNAMIC_LINK=1:与本地一致走动态链接,规避 static MT 与项目 MD 运行时的 LNK2038 冲突
shell: bash
env:
ORT_LIB_LOCATION: ${{ github.workspace }}/app/src-tauri/ort/ci
ORT_PREFER_DYNAMIC_LINK: "1"
SHERPA_ONNX_ARCHIVE_DIR: ${{ github.workspace }}/app/src-tauri/sherpa-archive
# 跳过 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
# sherpa-onnx-sys 自带的在线下载在 CI 上不稳定(曾出现解压残缺导致 LNK1181),
# 改用官方 SHERPA_ONNX_ARCHIVE_DIR 机制(与本地 config 一致):curl 预下载 tar 包
- name: Prepare sherpa-onnx archive for CI
shell: bash
run: |
mkdir -p app/src-tauri/sherpa-archive
curl -sL "https://github.com/k2-fsa/sherpa-onnx/releases/download/v1.13.5/sherpa-onnx-v1.13.5-win-x64-shared-MT-Release-lib.tar.bz2" \
-o app/src-tauri/sherpa-archive/sherpa-onnx-v1.13.5-win-x64-shared-MT-Release-lib.tar.bz2
- 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 使注入消失,改由下方 env 显式注入 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"
SHERPA_ONNX_ARCHIVE_DIR: ${{ github.workspace }}/app/src-tauri/sherpa-archive
# ---------------------------------------------------------------
# 发布阶段(不再走 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 源站;可选——未配置阿里云凭据时跳过)
# ---------------------------------------------------------------
# OSS 凭据可能过期/被禁用(历史 UserDisable),不阻断发布链
# 构建+GitHub Release+服务器同步已完成,OSS 仅为 CDN 源站加速
- name: Upload to OSS (CDN origin)
if: env.HAS_ALIYUN_AK == 'true'
continue-on-error: 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 "发布资产完整校验通过"