Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .release-please-manifest.json
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
{
".": "2.2.2"
".": "2.2.3"
}
33 changes: 33 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,39 @@

## [Unreleased]

## [2.2.3] - 2026-09-22

补丁版,只为把一处**随包分发缺口**送进可安装的产物:它修在 main 上,但晚于 v2.2.2 的 tag,
所以 v2.2.2 的 wheel 里仍然带着这个缺陷。

### Security

* **integrity:** wheel 此前**没把完整性自检三件套打进包**(`integrity_manifest.json`、其
`Ed25519` 签名、验签公钥),而 `config.yaml` 默认 `security.integrity_selfcheck.enforce: true`,
且"清单不存在"分支只 `logger.info("跳过自检")` 就返回 → **纯 `pip install` 的部署路径上
P0 完整性保护一条都没执行,配置却声称它在强制运行**(Docker 与便携包另外拷了源码树,
所以容器启动探测一直是绿的,把这个缺口遮住了)。现在三件随包走,且 enforce 开着却没清单
→ `RuntimeError` 拒绝启动并给三条出路;非强制模式保持原跳过语义。验收落在**产物**而非声明:
包内条目 1062 → 1065,并把 wheel 解到临时目录真跑一遍正负两向。
守卫 `tests/test_integrity_selfcheck_packaging.py` + CI 的 `Build (sdist/wheel)` 新增产物核对步骤。

### Bug Fixes

* **ci:** `release-please.yml` 的三处静默失效已修(`skip-github-pull-request: true` 而仓库从无
release PR → 每次 main push 都 `found 0 possible releases` 后成功;5 个 v4 不认的入参被整段忽略;
job 从未声明 `outputs:` → 挂在它下面的 `build-release`(sdist/wheel + SHA256SUMS)永远不跑)。
修好后它当场自动开出了下一条 release PR,故补上 `release-please-config.json` 与
`.release-please-manifest.json`,并加"什么都没发生就硬失败/写进 job 摘要"的自证。
* **version:** 版本位一致性守卫(#113 引入)补两处:漏核了**安装器内嵌**的
`scripts/installer/version.json`(`setup.nsi` 的 `File "version.json"` 取的就是它,且没有脚本
会重新生成它);另撤掉一条我自己写反的断言 —— `minimum_shell_version` 是**下界**,
强令它等于当前版本等于每次发版把上一版壳判死,改为只要求"不高于本次版本"。

### 已知未覆盖(同 v2.2.2 口径,未变)

桌面安装包链路与便携分卷仍无 workflow 覆盖;GPU 冒烟因无注册 runner 在 CI 上恒为 skipped;
锁集的全新 venv 真装复验待执行。

## [2.2.2] - 2026-09-22

<!-- 2026-09-16 那批内容原挂在「未发布」的 v2.2.2 标题下(tag 曾建后撤销);2026-09-22 正式发出,
Expand Down
2 changes: 1 addition & 1 deletion config.yaml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
version: "2.2.2"
version: "2.2.3"

server:
host: "127.0.0.1"
Expand Down
4 changes: 2 additions & 2 deletions deploy/kubernetes/deployment.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ spec:
# P0-1:subPath 挂载要求 PVC 内子目录预先存在(kubelet 不会自动创建)。
# 用主镜像(离线可用、自带 python)在可写的 data 卷上预建全部运行时目录。
- name: init-dirs
image: ghcr.io/reserendipity/tts-multimodel:2.2.2
image: ghcr.io/reserendipity/tts-multimodel:2.2.3
imagePullPolicy: IfNotPresent
command: ["python3.12", "-c",
"import os; [os.makedirs(f'/mnt/data/{d}', exist_ok=True) for d in ['data','outputs','logs','cache','lora','personas']]; print('init-dirs ok')"]
Expand All @@ -58,7 +58,7 @@ spec:
memory: "256Mi"
containers:
- name: tts
image: ghcr.io/reserendipity/tts-multimodel:2.2.2
image: ghcr.io/reserendipity/tts-multimodel:2.2.3
imagePullPolicy: IfNotPresent
ports:
- containerPort: 7869
Expand Down
2 changes: 1 addition & 1 deletion desktop/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "tts-multimodel-desktop",
"version": "2.2.2",
"version": "2.2.3",
"private": true,
"description": "TTS MultiModel 桌面应用壳",
"scripts": {
Expand Down
2 changes: 1 addition & 1 deletion desktop/src-tauri/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion desktop/src-tauri/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "tts-multimodel-desktop"
version = "2.2.2"
version = "2.2.3"
description = "TTS MultiModel 桌面应用壳"
authors = ["TTSMultiModel"]
edition = "2021"
Expand Down
2 changes: 1 addition & 1 deletion desktop/src-tauri/tauri.conf.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"$schema": "https://schema.tauri.app/config/2",
"productName": "TTSMultiModel",
"version": "2.2.2",
"version": "2.2.3",
"identifier": "com.ttsmultimodel.desktop",
"build": {
"beforeDevCommand": "",
Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[project]
name = "tts-multimodel"
version = "2.2.2"
version = "2.2.3"
description = "TTS MultiModel - Multi-engine Text-to-Speech platform with voice cloning, voice design, and LoRA fine-tuning"
readme = "README.md"
license = "Apache-2.0"
Expand Down
6 changes: 3 additions & 3 deletions scripts/installer/setup.nsi
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,15 @@ Unicode true
!include "LogicLib.nsh"

Name "TTSMultiModel 桌面版"
OutFile "TTSMultiModel-Setup-v2.2.2.exe"
OutFile "TTSMultiModel-Setup-v2.2.3.exe"
InstallDir "$LOCALAPPDATA\Programs\TTSMultiModel"
InstallDirRegKey HKCU "Software\TTSMultiModel" "InstallDir"
RequestExecutionLevel user
SetCompressor /SOLID lzma
CRCCheck on
BrandingText "TTSMultiModel"

!define APP_VERSION "2.2.2"
!define APP_VERSION "2.2.3"
!define DATA_PREFIX "TTSMultiModel-Data.7z"
!define UNINST_KEY "Software\Microsoft\Windows\CurrentVersion\Uninstall\TTSMultiModel"
!define APP_ICON "${__FILEDIR__}\..\..\desktop\src-tauri\icons\icon.ico"
Expand Down Expand Up @@ -135,7 +135,7 @@ Section "TTSMultiModel 桌面版" SEC_APP
SectionEnd

; ---------- 版本信息 ----------
VIProductVersion "2.2.2.0"
VIProductVersion "2.2.3.0"
VIAddVersionKey "ProductName" "TTSMultiModel 桌面版"
VIAddVersionKey "LegalCopyright" "Copyright (C) 2026 TTSMultiModel"
VIAddVersionKey "ProductVersion" "${APP_VERSION}"
Expand Down
26 changes: 24 additions & 2 deletions tests/test_version_consistency.py
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,11 @@ def test_no_hardcoded_old_version():
_SEMVER = re.compile(r"\d+\.\d+\.\d+")


def _ver_tuple(s: str) -> tuple[int, ...]:
"""x.y.z → 可比较的整数元组(避免字典序把 2.9 判成比 2.10 大)。"""
return tuple(int(p) for p in s.split("."))


def _site_versions() -> dict[str, str]:
"""从各版本位精确取值;取不到就抛,避免"少一个站点"被当成"一致"。"""

Expand All @@ -102,7 +107,7 @@ def grab_json(rel: str, label: str) -> str:

sites = {
"pyproject.toml": grab("pyproject.toml", r'^version\s*=\s*"([^"]+)"', "Python 包版本"),
"version.json": grab_json("version.json", "更新契约版本"),
"version.json": grab_json("version.json", "更新契约版本(唯一版本源)"),
"config.yaml": grab("config.yaml", r'^version:\s*"?([^"\n]+)"?', "前端缓存参数版本"),
"desktop/package.json": grab_json("desktop/package.json", "桌面壳 npm 版本"),
"desktop/src-tauri/tauri.conf.json": grab_json("desktop/src-tauri/tauri.conf.json", "Tauri 壳版本"),
Expand All @@ -125,6 +130,17 @@ def grab_json(rel: str, label: str) -> str:
"k8s 镜像 tag",
),
}
# 安装器**内嵌**的那份版本:`setup.nsi` 的 `File "version.json"` 取的是
# `scripts/installer/version.json`,而它是 .gitignore:436 明写的"装配中间物"
# (与 TTSMultiModel.exe 同批手工放进去,makensis 不在仓库里跑)—— 真版本源只有根
# version.json。所以不变式是**若在场则必须等于源**:干净检出里没有这个文件(CI 就没有),
# 可一旦装进安装器的那份与源不同步,装出来的壳就拿一份旧版本号做本地识别
# (assemble_installer_data.ps1:59 的注释写着"缺失会静默跳过更新")。
installer_copy = PROJECT_ROOT / "scripts" / "installer" / "version.json"
if installer_copy.exists():
sites["scripts/installer/version.json(装配中间物)"] = grab_json(
"scripts/installer/version.json", "安装器内嵌版本(壳本地识别)"
)
return sites


Expand All @@ -150,4 +166,10 @@ def test_installer_artifact_names_track_the_version_site() -> None:
assert f"TTSMultiModel-Setup-v{ver}.exe" in text, f"OutFile 还没跟到 v{ver}"
assert f'VIProductVersion "{ver}.0"' in text, f"VIProductVersion 还没跟到 {ver}.0"
data = json.loads((PROJECT_ROOT / "version.json").read_text(encoding="utf-8"))
assert data.get("minimum_shell_version") == ver, "更新契约的最低壳版本与本批版本不一致"
minimum = str(data.get("minimum_shell_version", ""))
assert _SEMVER.fullmatch(minimum), f"minimum_shell_version 不是 x.y.z 形态:{minimum!r}"
# 它是**下界**,不是"必须等于当前版本":语义是"低于它的壳不接受了"。
# 强令相等等于每次发版都把上一版壳判死(而目前代码里还没人真的读它:
# updater.rs 只在 AppVersion 结构里解析它,shell-update.json 契约里没有这个字段),
# 所以这里只钉住唯一站得住的关系:下界不得高于本次版本。
assert _ver_tuple(minimum) <= _ver_tuple(ver), f"minimum_shell_version={minimum} 高于本次版本 {ver}"
4 changes: 2 additions & 2 deletions version.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"version": "2.2.2",
"version": "2.2.3",
"release_date": "2026-09-22",
"minimum_shell_version": "2.2.2",
"changelog": "2.2.2 发布:桌面分发与便携打包链路补全 + 发布前置回归(干净环境缺 einops/addict 已修、镜像 apt 索引就绪守卫、CSRF 硬失败与 0600、IndexTTS 预热并发崩溃修复)。资产为源码包 + wheel + SHA256SUMS;不含 26 GB 便携分卷与增量包。"
"changelog": "2.2.3:修复随包分发缺口 —— wheel 此前没打进完整性自检清单三件套(清单/签名/公钥),而 enforce 默认开启,导致 pip 安装出来的环境里 P0 完整性保护一条都没执行却写着在强制运行;现在三件随包走,且 enforce 开着而清单缺失会拒绝启动。另含 2.2.2 的发布前置回归(干净环境缺 einops/addict、镜像 apt 索引就绪守卫、CSRF 硬失败与 0600、IndexTTS 预热并发崩溃修复)。资产为 wheel + sdist + SHA256SUMS;不含 26 GB 便携分卷与增量包。"
}
Loading