diff --git a/crates/df-im-gateway/src/commander.rs b/crates/df-im-gateway/src/commander.rs index 6f95dc1..5543293 100644 --- a/crates/df-im-gateway/src/commander.rs +++ b/crates/df-im-gateway/src/commander.rs @@ -85,6 +85,7 @@ async fn connect_once( kind: HelloKind::Commander, channel_id: channel_id.to_string(), token: token.to_string(), + proto: 1, }; sink.send(Message::Text(serde_json::to_string(&hello)?)).await?; diff --git a/scripts/publish-release.ps1 b/scripts/publish-release.ps1 index 72ec688..9d84957 100644 --- a/scripts/publish-release.ps1 +++ b/scripts/publish-release.ps1 @@ -62,13 +62,15 @@ if (-not $SkipBuild) { Write-Host "[3/6] 跳过构建(-SkipBuild),复用已有产物" } -# 定位产物:裸 exe / .nsis.zip / .sig +# 定位产物:Tauri v2 = setup.exe + .exe.sig(更新包即安装器本身);v1 遗留 = .nsis.zip + .nsis.zip.sig $setupExe = Get-ChildItem "$nsisDir\devflow_${version}_x64-setup.exe" -ErrorAction SilentlyContinue | Select-Object -First 1 +$sigFile = Get-ChildItem "$nsisDir\devflow_${version}_x64-setup.exe.sig","$nsisDir\devflow_${version}_x64-setup.nsis.zip.sig" -ErrorAction SilentlyContinue | Select-Object -First 1 $zipFile = Get-ChildItem "$nsisDir\devflow_${version}_x64-setup.nsis.zip" -ErrorAction SilentlyContinue | Select-Object -First 1 -$sigFile = Get-ChildItem "$nsisDir\devflow_${version}_x64-setup.nsis.zip.sig" -ErrorAction SilentlyContinue | Select-Object -First 1 -if (-not $zipFile) { Write-Host "[失败] 未找到 .nsis.zip 产物(确认 createUpdaterArtifacts=true)"; exit 1 } -if (-not $sigFile) { Write-Host "[失败] 未找到 .sig 签名文件"; exit 1 } -Write-Host " 产物: $($zipFile.Name) ($([math]::Round($zipFile.Length/1MB,1))MB)" +if (-not $sigFile) { Write-Host "[失败] 未找到 .sig 签名文件(确认 createUpdaterArtifacts=true 且 TAURI_SIGNING_PRIVATE_KEY 就位)"; exit 1 } +# 与 .sig 配对的更新产物:v2 签名(.exe.sig)配 setup.exe;v1 签名(.nsis.zip.sig)配 .nsis.zip +$artifact = if ($sigFile.Name.EndsWith('.exe.sig')) { $setupExe } else { $zipFile } +if (-not $artifact) { Write-Host "[失败] 未找到与 $($sigFile.Name) 配对的更新产物"; exit 1 } +Write-Host " 产物: $($artifact.Name) ($([math]::Round($artifact.Length/1MB,1))MB)" # ── 4. 生成 latest.json ── Write-Host "[4/6] 生成 latest.json..." @@ -79,7 +81,7 @@ if (-not $Notes) { if (-not $Notes) { $Notes = "DevFlow v$version" } } $pubDate = (Get-Date).ToUniversalTime().ToString("yyyy-MM-ddTHH:mm:ssZ") -$sha256 = (Get-FileHash $zipFile.FullName -Algorithm SHA256).Hash.ToLower() +$sha256 = (Get-FileHash $artifact.FullName -Algorithm SHA256).Hash.ToLower() $latestJson = [ordered]@{ version = $version notes = $Notes @@ -87,7 +89,7 @@ $latestJson = [ordered]@{ platforms = [ordered]@{ "windows-x86_64" = [ordered]@{ signature = $sig - url = "$baseUrl/devflow_${version}_x64-setup.nsis.zip" + url = "$baseUrl/$($artifact.Name)" } } } | ConvertTo-Json -Depth 5 @@ -102,8 +104,8 @@ $env:MSYS_NO_PATHCONV = "1" ssh-proxy exec -n $site -c "mkdir -p $remoteDir" if ($LASTEXITCODE -ne 0) { Write-Host "[失败] 创建远程目录"; exit 1 } -$uploads = @($latestPath, $zipFile.FullName, $sigFile.FullName) -if ($setupExe) { $uploads += $setupExe.FullName } +$uploads = @($latestPath, $sigFile.FullName, $artifact.FullName) +if ($setupExe -and $setupExe.FullName -ne $artifact.FullName) { $uploads += $setupExe.FullName } foreach ($f in $uploads) { $name = Split-Path $f -Leaf Write-Host " 上传 $name ..." diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index 1406ac6..4b79f0f 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "devflow" -version = "0.1.1" +version = "0.1.2" description = "DevFlow Desktop App" authors = [""] edition = "2021" diff --git a/src-tauri/src/commands/update.rs b/src-tauri/src/commands/update.rs index 3628cb1..f13c9a9 100644 --- a/src-tauri/src/commands/update.rs +++ b/src-tauri/src/commands/update.rs @@ -64,10 +64,30 @@ const DEFAULT_INTERVAL_MINUTES: u32 = 15; /// 走 Tauri updater 的 `check()`:拉取 `tauri.conf.json` plugins.updater.endpoints /// 配置的 latest.json,内建 ed25519 签名校验(公钥在 pubkey)。无更新返回 `has_update=false`。 /// 网络失败/解析失败返回 Err(前端据此提示,不谎报「已是最新」)。 +/// 构建 updater:支持用环境变量覆盖端点(仅供本地演练,生产不设即走 tauri.conf 配置)。 +/// +/// `DEVFLOW_UPDATER_ENDPOINT=http://127.0.0.1:8765/latest.json` 时改用该端点—— +/// 用于在**不发布线上**的前提下跑通「检查→下载→校验→安装」全链(线上端点未发布时无法演练)。 +fn build_updater(app: &AppHandle) -> Result { + let builder = app.updater_builder(); + let override_url = std::env::var("DEVFLOW_UPDATER_ENDPOINT").unwrap_or_default(); + if override_url.trim().is_empty() { + return builder.build().map_err(err_str); + } + let url = tauri::Url::parse(override_url.trim()) + .map_err(|e| format!("DEVFLOW_UPDATER_ENDPOINT 非法({override_url}): {e}"))?; + tracing::warn!(endpoint = %override_url, "[update] 更新端点被环境变量覆盖(本地演练模式)"); + builder + .endpoints(vec![url]) + .map_err(err_str)? + .build() + .map_err(err_str) +} + #[tauri::command] pub async fn app_check_update(app: AppHandle) -> Result { let current_version = env!("CARGO_PKG_VERSION").to_string(); - let updater = app.updater().map_err(err_str)?; + let updater = build_updater(&app)?; match updater.check().await { Ok(Some(update)) => Ok(UpdateCheckResult { has_update: true, @@ -202,7 +222,7 @@ pub struct UpdateProgress { pub async fn app_download_install_update(app: AppHandle) -> Result<(), String> { use tauri::Emitter; - let updater = app.updater().map_err(err_str)?; + let updater = build_updater(&app)?; let update = updater .check() .await diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json index a29d5fc..119800f 100644 --- a/src-tauri/tauri.conf.json +++ b/src-tauri/tauri.conf.json @@ -1,6 +1,6 @@ { "productName": "devflow", - "version": "0.1.1", + "version": "0.1.2", "identifier": "top.1216.devflow", "build": { "beforeDevCommand": "bun dev",