From 58a0ad9e6250dfa15fc0ef41b1c030b1d25489ca Mon Sep 17 00:00:00 2001 From: TRIP <1933142963@qq.com> Date: Fri, 8 May 2026 09:04:14 +0800 Subject: [PATCH] fix(release): use tagged URL in beta manifest, not releases/latest (#344) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 修复 v1.2.24-1-beta-tauri release verification 时发现的 latent bug: Beta manifest 里 url 字段指向 https://github.com/.../releases/latest/download/, 但 releases/latest 永远是最新非-prerelease(即 Stable),Beta 用户按这个 url auto-update 会拉到 Stable 包: - macOS Beta: 文件名 OpenLess_aarch64.app.tar.gz 跟 Stable 重名 → 下载 Stable 包, 装上的是 1.2.23 但 manifest 声称 1.2.24-1,version drift - Windows/Linux Beta: 文件名带版本号 OpenLess_1.2.24-1_x64-setup.exe / .AppImage, releases/latest 路径下没这个文件 → 直接 404 Stable 渠道沿用 releases/latest 是对的(latest = Stable)。 修法:write-updater-manifest.mjs 多读一个 OPENLESS_RELEASE_TAG env,beta 时 url 拼成 releases/download//(指定具体 tag,不被 prerelease 折叠 影响);stable 不变。脚本对 beta 缺 tag 做 fail-fast。 release-tauri.yml 在 manifest step 多注入 OPENLESS_RELEASE_TAG: ${{ github.ref_name }}。 为什么不重发 v1.2.24-1:当前走 Path A 手动下载式 opt-in,前端调 fetch_latest_beta_release 拿 GitHub release 页 html_url,用户跳浏览器手动选包, 不消费 manifest.url。所以 v1.2.24-1 已发布的 manifest 里 url 错也是 dormant。 下一轮 Beta tag(v1.2.24-2-beta-tauri 或 stable cut 后再做 Beta)会用修复后 的脚本产出正确 URL。 本地 smoke test: - channel=beta + 缺 OPENLESS_RELEASE_TAG → fail-fast 抛 "is required" - channel=beta + 有 tag → env 检查通过,进入 artifact 解析 - channel=stable + 不传 tag → 维持原行为 - python yaml.safe_load() 解析 release-tauri.yml 通过 Co-authored-by: baiqing --- .github/workflows/release-tauri.yml | 5 +++++ .../app/scripts/write-updater-manifest.mjs | 17 +++++++++++++++-- 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/.github/workflows/release-tauri.yml b/.github/workflows/release-tauri.yml index 875ccd97..043da8d3 100644 --- a/.github/workflows/release-tauri.yml +++ b/.github/workflows/release-tauri.yml @@ -379,6 +379,11 @@ jobs: OPENLESS_UPDATE_MIRROR_BASE_URL: https://fastgit.cc/https://github.com # beta 渠道时输出 latest-{tgt}-{arch}-beta.json,stable 沿用旧文件名。 OPENLESS_RELEASE_CHANNEL: ${{ env.OPENLESS_RELEASE_CHANNEL }} + # Beta 渠道里脚本要把 manifest.url 写成 releases/download//... + # 而不是 releases/latest(后者永远 = Stable,Beta 用户按 url 下载会拉到错文件)。 + # workflow_dispatch 时 github.ref_name 不是 tag——但那种情况下 channel=stable, + # 脚本不会读这个字段,安全。 + OPENLESS_RELEASE_TAG: ${{ github.ref_name }} run: node scripts/write-updater-manifest.mjs # ── 收集产物 ── diff --git a/openless-all/app/scripts/write-updater-manifest.mjs b/openless-all/app/scripts/write-updater-manifest.mjs index 171cd35a..0803fbb1 100755 --- a/openless-all/app/scripts/write-updater-manifest.mjs +++ b/openless-all/app/scripts/write-updater-manifest.mjs @@ -15,6 +15,14 @@ if (rawChannel !== 'stable' && rawChannel !== 'beta') { throw new Error(`Invalid OPENLESS_RELEASE_CHANNEL: "${rawChannel}" (expected "stable" or "beta")`); } const channelSuffix = rawChannel === 'beta' ? '-beta' : ''; +// Beta 渠道里 manifest.url 必须指向具体 tag 路径,不能用 releases/latest——后者 +// 永远是最新非-prerelease(即 Stable),Beta 用户按 url 下载会拉到 Stable 包, +// 文件名碰巧重名时下载错版本,文件名带版本号时直接 404。 +// Stable 渠道沿用 releases/latest,没问题。 +const releaseTag = process.env.OPENLESS_RELEASE_TAG || ''; +if (rawChannel === 'beta' && !releaseTag) { + throw new Error('OPENLESS_RELEASE_TAG is required when OPENLESS_RELEASE_CHANNEL=beta'); +} if (!target || !arch) { throw new Error('OPENLESS_UPDATE_TARGET and OPENLESS_UPDATE_ARCH are required'); @@ -64,8 +72,13 @@ if (!existsSync(signaturePath)) { const assetName = basename(artifact); const manifestName = `latest-${target}-${arch}${channelSuffix}.json`; const mirrorManifestName = `latest-${target}-${arch}${channelSuffix}-mirror.json`; -const githubAssetUrl = `https://github.com/${repo}/releases/latest/download/${assetName}`; -const mirrorAssetUrl = `${mirrorBaseUrl.replace(/\/$/, '')}/${repo}/releases/latest/download/${assetName}`; +// Stable: releases/latest/download/(GitHub 自动重定向到最新非-prerelease) +// Beta: releases/download//(指定具体 tag,不被 prerelease 折叠影响) +const downloadPath = rawChannel === 'beta' + ? `releases/download/${releaseTag}/${assetName}` + : `releases/latest/download/${assetName}`; +const githubAssetUrl = `https://github.com/${repo}/${downloadPath}`; +const mirrorAssetUrl = `${mirrorBaseUrl.replace(/\/$/, '')}/${repo}/${downloadPath}`; const manifest = { version: packageJson.version, pub_date: new Date().toISOString(),