chore(release): Windows 安装包以 NSIS 为主,MSI 不再主动发布

- CI Windows 构建由 --bundles msi 改为 --bundles nsis
- tauri.conf.json 默认打包目标改为仅 nsis(需要 MSI 可本地 --bundles msi 构建)
- 应用内「检查更新」优先下载 NSIS setup exe,无 exe 的历史版本自动回落 .msi
- 发布说明模板 / README 双语下载说明同步更新,CHANGELOG 记录该分发策略变更
- 测试:Rust 200(资产选择新增 NSIS 优先与 MSI 回落两例)、前端 146
This commit is contained in:
KimiSwitch Dev committed 2026-10-15 11:37:05 +08:00
1 parent da468aff13
commit f643802f82
6 files changed
+61 -25

No files matched your search

+2 -2
View File
@@ -35,7 +35,7 @@ jobs:
- platform: macos-latest - platform: macos-latest
args: --bundles app,dmg args: --bundles app,dmg
- platform: windows-latest - platform: windows-latest
args: --bundles msi args: --bundles nsis
runs-on: ${{ matrix.platform }} runs-on: ${{ matrix.platform }}
steps: steps:
@@ -89,7 +89,7 @@ jobs:
cat <<'TAIL_EOF' cat <<'TAIL_EOF'
### Downloads by platform ### Downloads by platform
- **Windows**: `.msi` installer - **Windows**: `.exe`(NSIS 安装包)——自 v0.8.3 起 Windows 以 NSIS 为主,**MSI 不再主动发布**(历史版本的 `.msi` 仍可下载)
- **macOS**: `.dmg` + `.app`(未签名,仅 Apple Silicon / M 系列芯片) - **macOS**: `.dmg` + `.app`(未签名,仅 Apple Silicon / M 系列芯片)
- **Linux**: `.deb` / `.AppImage` / `.rpm` - **Linux**: `.deb` / `.AppImage` / `.rpm`
+4
View File
@@ -6,6 +6,10 @@
--- ---
## Unreleased
- **Windows 安装包改为以 NSIS(`.exe`)为主,MSI 不再主动发布**:CI 的 Windows 构建由 `--bundles msi` 改为 `--bundles nsis`,`tauri.conf.json` 默认打包目标同步改为仅 `nsis`;应用内「检查更新」优先下载 NSIS 安装包(无 exe 的历史版本自动回落 `.msi`)。历史版本的 `.msi` 仍可下载,需要 MSI 可本地 `npx tauri build --bundles msi` 自行构建
## v0.8.3 (2026-10-15) ## v0.8.3 (2026-10-15)
配置一致性修复版(含 kimi-code CLI 2.2.0 适配核验)。 配置一致性修复版(含 kimi-code CLI 2.2.0 适配核验)。
+4 -4
View File
@@ -54,7 +54,7 @@
## 下载 ## 下载
- **Windows**: [GitHub Releases](https://github.com/billowliu2/KimiSwitch/releases/latest) → `.msi` - **Windows**: [GitHub Releases](https://github.com/billowliu2/KimiSwitch/releases/latest) → `.exe`(NSIS 安装包;**自 v0.8.3 起 Windows 以 NSIS 为主,MSI 不再主动发布**,历史版本 `.msi` 仍可下载)
- **macOS**: [GitHub Releases](https://github.com/billowliu2/KimiSwitch/releases/latest) → `.dmg`(**未签名**,仅 Apple Silicon / M 系列芯片)。安装请下载 Release 附带的 `install-macos.sh` 一键处理: - **macOS**: [GitHub Releases](https://github.com/billowliu2/KimiSwitch/releases/latest) → `.dmg`(**未签名**,仅 Apple Silicon / M 系列芯片)。安装请下载 Release 附带的 `install-macos.sh` 一键处理:
```bash ```bash
@@ -496,10 +496,10 @@ npm run tauri-build
产物位置: 产物位置:
``` ```
src-tauri/target/release/bundle/msi/Kimi Switch_<version>_x64_en-US.msi src-tauri/target/release/bundle/nsis/Kimi.Switch_<version>_x64-setup.exe
``` ```
Windows 安装包(MSI),含 WebView2 bootstrapper 自动下载。`nsis` 已禁用,目前只产 MSI。 Windows 安装包(NSIS setup exe),含 WebView2 bootstrapper 自动下载。自 v0.8.3 起 Windows **只主动发布 NSIS 安装包,MSI 不再主动发布**(如需 MSI 可本地 `npx tauri build --bundles msi` 自行构建)。
### 首次打包 ### 首次打包
@@ -565,7 +565,7 @@ A: 对 Kimi Code,`config.toml` 本身就是全量权威,直接备份即可
A: Vertex 需要 GCP project / location 凭证,当前实现留 TODO,等 GCP SDK 集成后补。 A: Vertex 需要 GCP project / location 凭证,当前实现留 TODO,等 GCP SDK 集成后补。
**Q: 支持 macOS / Linux 吗?** **Q: 支持 macOS / Linux 吗?**
A: 代码不依赖 Windows 专属 API,但 `tauri.conf.json` 的 bundle 目标目前只配了 `msi`。理论上把 `bundle.targets` 改成 `["app", "dmg"]` 等即可跨平台,但未验证。 A: 代码不依赖 Windows 专属 API,但 `tauri.conf.json` 的 bundle 目标目前只配了 `nsis`。理论上把 `bundle.targets` 改成 `["app", "dmg"]` 等即可跨平台,但未验证。
**Q: 怎么改主题 / 语言?** **Q: 怎么改主题 / 语言?**
A: 顶部齿轮 → 设置弹窗 → 主题 / 语言。保存到前端 `localStorage`(WebView2),重启后保持。 A: 顶部齿轮 → 设置弹窗 → 主题 / 语言。保存到前端 `localStorage`(WebView2),重启后保持。
+4 -4
View File
@@ -54,7 +54,7 @@
## Downloads ## Downloads
- **Windows**: [GitHub Releases](https://github.com/billowliu2/KimiSwitch/releases/latest) → `.msi` - **Windows**: [GitHub Releases](https://github.com/billowliu2/KimiSwitch/releases/latest) → `.exe` (NSIS installer; **since v0.8.3 Windows ships NSIS as the primary format and MSI is no longer actively published** — `.msi` files of past releases remain downloadable)
- **macOS**: [GitHub Releases](https://github.com/billowliu2/KimiSwitch/releases/latest) → `.dmg` (**unsigned** — first launch needs right-click → Open to bypass Gatekeeper) - **macOS**: [GitHub Releases](https://github.com/billowliu2/KimiSwitch/releases/latest) → `.dmg` (**unsigned** — first launch needs right-click → Open to bypass Gatekeeper)
- **Linux**: [GitHub Releases](https://github.com/billowliu2/KimiSwitch/releases/latest) → `.deb` / `.AppImage` / `.rpm` - **Linux**: [GitHub Releases](https://github.com/billowliu2/KimiSwitch/releases/latest) → `.deb` / `.AppImage` / `.rpm`
@@ -486,10 +486,10 @@ npm run tauri-build
Output: Output:
``` ```
src-tauri/target/release/bundle/msi/Kimi Switch_<version>_x64_en-US.msi src-tauri/target/release/bundle/nsis/Kimi.Switch_<version>_x64-setup.exe
``` ```
A Windows installer (MSI) with the WebView2 bootstrapper embedded for auto-download. `nsis` is disabled; only MSI is produced. A Windows installer (NSIS setup exe) with the WebView2 bootstrapper embedded for auto-download. Since v0.8.3 Windows **publishes only the NSIS installer; MSI is no longer actively released** (build it locally with `npx tauri build --bundles msi` if needed).
### First build ### First build
@@ -552,7 +552,7 @@ A: For Kimi Code, `config.toml` itself is the authoritative full config — back
A: Vertex requires GCP project / location credentials. The current implementation leaves a TODO pending GCP SDK integration. A: Vertex requires GCP project / location credentials. The current implementation leaves a TODO pending GCP SDK integration.
**Q: macOS / Linux support?** **Q: macOS / Linux support?**
A: The code doesn't depend on Windows-only APIs, but `tauri.conf.json` only targets `msi` for bundling. In theory, changing `bundle.targets` to `["app", "dmg"]` etc. would enable cross-platform builds, but this is unverified. A: The code doesn't depend on Windows-only APIs, but `tauri.conf.json` only targets `nsis` for bundling. In theory, changing `bundle.targets` to `["app", "dmg"]` etc. would enable cross-platform builds, but this is unverified.
**Q: How do I change the theme / language?** **Q: How do I change the theme / language?**
A: Top-right gear → Settings modal → Theme / Language. Saved to frontend `localStorage` (WebView2), persists across restarts. A: Top-right gear → Settings modal → Theme / Language. Saved to frontend `localStorage` (WebView2), persists across restarts.
+47 -14
View File
@@ -1599,7 +1599,8 @@ pub async fn download_update(
Ok(path_str) Ok(path_str)
} }
/// Open the downloaded MSI installer using the system default handler. /// Open the downloaded installer (NSIS setup exe / dmg / AppImage) using the
/// system default handler.
#[tauri::command] #[tauri::command]
pub fn open_installer(app: tauri::AppHandle, path: String) -> Result<(), String> { pub fn open_installer(app: tauri::AppHandle, path: String) -> Result<(), String> {
use tauri_plugin_opener::OpenerExt; use tauri_plugin_opener::OpenerExt;
@@ -1839,27 +1840,38 @@ fn build_kimi_web_window(app: &tauri::AppHandle, url: &tauri::Url) -> Result<(),
}); });
Ok(()) Ok(())
} }
/// Preference for Linux is AppImage (portable, no install). If the preferred /// Preference for Linux is AppImage (portable, no install). Windows prefers
/// extension is not present, returns None so the UI can fall back to /// the NSIS `-setup.exe` (MSI is no longer actively published since v0.8.3)
/// "open release page" instead of guessing a less-preferred format. /// and falls back to `.msi` for releases that predate the switch. If the
/// preferred extension is not present, returns None so the UI can fall back
/// to "open release page" instead of guessing a less-preferred format.
fn pick_asset_for_os(assets: &[serde_json::Value], os: &str) -> Option<String> { fn pick_asset_for_os(assets: &[serde_json::Value], os: &str) -> Option<String> {
let target_ext = match os { let (preferred, fallback) = match os {
"macos" => "dmg", "macos" => ("dmg", None),
"linux" => "AppImage", "linux" => ("AppImage", None),
"windows" => "msi", "windows" => ("setup.exe", Some("msi")),
_ => return None, _ => return None,
}; };
asset_url_ending_with(assets, preferred)
.or_else(|| fallback.and_then(|ext| asset_url_ending_with(assets, ext)))
.map(str::to_string)
}
/// Download URL of the first release asset whose name ends with `ext`.
fn asset_url_ending_with<'a>(
assets: &'a [serde_json::Value],
ext: &str,
) -> Option<&'a str> {
assets assets
.iter() .iter()
.find(|a| { .find(|a| {
a.get("name") a.get("name")
.and_then(|n| n.as_str()) .and_then(|n| n.as_str())
.map(|n| n.ends_with(target_ext)) .map(|n| n.ends_with(ext))
.unwrap_or(false) .unwrap_or(false)
}) })
.and_then(|a| a.get("browser_download_url")) .and_then(|a| a.get("browser_download_url"))
.and_then(|v| v.as_str()) .and_then(|v| v.as_str())
.map(|s| s.to_string())
} }
/// Pick the GitHub release asset for the current OS (runtime target). /// Pick the GitHub release asset for the current OS (runtime target).
@@ -1872,7 +1884,10 @@ fn update_temp_filename() -> String {
let ext = match std::env::consts::OS { let ext = match std::env::consts::OS {
"macos" => "dmg", "macos" => "dmg",
"linux" => "AppImage", "linux" => "AppImage",
"windows" => "msi", // The preferred Windows installer is the NSIS setup exe; the fallback
// (.msi, pre-v0.8.3-releases) keeps its own extension via the same
// suffix match, so "exe" covers the actively published format.
"windows" => "exe",
_ => "bin", _ => "bin",
}; };
format!("KimiSwitch_update.{ext}") format!("KimiSwitch_update.{ext}")
@@ -2160,10 +2175,28 @@ mod asset_picker_tests {
} }
#[test] #[test]
fn windows_picks_msi() { fn windows_prefers_nsis_setup_exe_over_msi() {
let assets = assets(&["KimiSwitch_0.7.0_x64_en-US.msi", "KimiSwitch_0.7.0_aarch64.dmg", "KimiSwitch_0.7.0_amd64.AppImage"]); let assets = assets(&[
"Kimi.Switch_0.8.3_x64_en-US.msi",
"Kimi.Switch_0.8.3_x64-setup.exe",
"Kimi.Switch_0.8.3_aarch64.dmg",
]);
let url = pick_asset_for_os(&assets, "windows"); let url = pick_asset_for_os(&assets, "windows");
assert_eq!(url.as_deref(), Some("https://example.com/KimiSwitch_0.7.0_x64_en-US.msi")); assert_eq!(
url.as_deref(),
Some("https://example.com/Kimi.Switch_0.8.3_x64-setup.exe")
);
}
#[test]
fn windows_falls_back_to_msi_when_no_setup_exe() {
// Pre-v0.8.3 releases (and older Gitea releases) ship only the .msi.
let assets = assets(&["Kimi.Switch_0.8.2_x64_en-US.msi"]);
let url = pick_asset_for_os(&assets, "windows");
assert_eq!(
url.as_deref(),
Some("https://example.com/Kimi.Switch_0.8.2_x64_en-US.msi")
);
} }
#[test] #[test]
-1
View File
@@ -27,7 +27,6 @@
"bundle": { "bundle": {
"active": true, "active": true,
"targets": [ "targets": [
"msi",
"nsis" "nsis"
], ],
"icon": [ "icon": [