From b10ae9da5f7719ff28dfc700a40be6911bb72e08 Mon Sep 17 00:00:00 2001 From: baiqing Date: Thu, 7 May 2026 21:20:57 +0800 Subject: [PATCH] feat(release): split updater manifest by channel from tag suffix MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 让 release pipeline 根据 tag 名后缀区分 Beta / 正式版渠道,是 opt-in beta 机制的服务端基础。客户端读取的 endpoint 在 PR-B-2 接入。 约定: - `v-tauri` = 正式版渠道(stable) - `v-beta-tauri` = Beta 渠道(beta) release-tauri.yml 改动: - 在 jobs.build 顶层加 OPENLESS_RELEASE_CHANNEL job-env,由 endsWith(github.ref_name, '-beta-tauri') 决定;workflow_dispatch 与 非 tag 触发回退为 stable,不改变现有 dispatch 行为。 - Write updater manifest step 把 OPENLESS_RELEASE_CHANNEL 透传给脚本。 - Upload-artifact 的 manifest path 改为 `latest-{tgt}-{arch}*.json` glob, 让 stable 和 beta 两种文件名(或 mirror 变体)都能被收集,避免 if-no-files-found 在 beta release 时挂掉。 - Create release 的 prerelease 改为 `${{ env.OPENLESS_RELEASE_CHANNEL == 'beta' }}`:beta tag 自动标 GitHub prerelease(UI 折叠 + 默认不算 latest),stable 保持不变。 write-updater-manifest.mjs 改动: - 读取 OPENLESS_RELEASE_CHANNEL(默认 stable);非 stable / beta 时 fail-fast,避免拼错 env 静默走错路径。 - beta 渠道时 manifest 文件名加 `-beta` 后缀: latest-{tgt}-{arch}-beta.json latest-{tgt}-{arch}-beta-mirror.json 正式版用户的 endpoint 永远指向不带后缀的旧文件名,不会被 beta release 覆盖。 向后兼容: - 现有 v1.2.23-tauri 等 stable release 行为完全不变(文件名、prerelease=false 沿用旧逻辑)。 - workflow_dispatch 不打 tag 时也照常构建 + 不上传 release。 发版后 checklist(PR-B-2 文档段会写进 CLAUDE.md): - 推 v-beta-tauri tag → GitHub Release 应标 prerelease 且只含 latest-*-beta.json - 推 v-tauri tag → 正式 release 且只含 latest-*.json(不带后缀) --- .github/workflows/release-tauri.yml | 24 +++++++++++++------ .../app/scripts/write-updater-manifest.mjs | 11 +++++++-- 2 files changed, 26 insertions(+), 9 deletions(-) diff --git a/.github/workflows/release-tauri.yml b/.github/workflows/release-tauri.yml index c5f57892..00138246 100644 --- a/.github/workflows/release-tauri.yml +++ b/.github/workflows/release-tauri.yml @@ -24,6 +24,14 @@ jobs: build: permissions: contents: write + # 渠道由 tag 后缀决定: + # v-beta-tauri → beta 渠道(GitHub Release 标 prerelease, + # manifest 文件名带 -beta 后缀,正式版用户的 endpoint 拿不到) + # v-tauri → stable 渠道(正式版,文件名沿用旧约定,向后兼容) + # workflow_dispatch / 非 tag 触发时 github.ref_name 不是 tag 字符串, + # endsWith 返回 false,回退为 stable,不改变现有 dispatch 行为。 + env: + OPENLESS_RELEASE_CHANNEL: ${{ endsWith(github.ref_name, '-beta-tauri') && 'beta' || 'stable' }} strategy: fail-fast: false matrix: @@ -370,6 +378,8 @@ jobs: OPENLESS_UPDATE_ARCH: ${{ matrix.updater-arch }} OPENLESS_UPDATE_REPO: appergb/openless 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 }} run: node scripts/write-updater-manifest.mjs # ── 收集产物 ── @@ -413,8 +423,7 @@ jobs: path: | openless-all/app/src-tauri/target/release/bundle/macos/*.app.tar.gz openless-all/app/src-tauri/target/release/bundle/macos/*.app.tar.gz.sig - openless-all/app/src-tauri/target/release/bundle/latest-darwin-${{ matrix.updater-arch }}.json - openless-all/app/src-tauri/target/release/bundle/latest-darwin-${{ matrix.updater-arch }}-mirror.json + openless-all/app/src-tauri/target/release/bundle/latest-darwin-${{ matrix.updater-arch }}*.json if-no-files-found: error - name: Upload Windows artifacts @@ -435,8 +444,7 @@ jobs: path: | openless-all/app/src-tauri/target/release/bundle/nsis/*.exe.sig openless-all/app/src-tauri/target/release/bundle/msi/*.msi.sig - openless-all/app/src-tauri/target/release/bundle/latest-windows-x86_64.json - openless-all/app/src-tauri/target/release/bundle/latest-windows-x86_64-mirror.json + openless-all/app/src-tauri/target/release/bundle/latest-windows-x86_64*.json if-no-files-found: error - name: Upload Linux artifacts @@ -457,8 +465,7 @@ jobs: name: openless-linux-x64-updater path: | openless-all/app/src-tauri/target/release/bundle/appimage/*.AppImage.sig - openless-all/app/src-tauri/target/release/bundle/latest-linux-x86_64.json - openless-all/app/src-tauri/target/release/bundle/latest-linux-x86_64-mirror.json + openless-all/app/src-tauri/target/release/bundle/latest-linux-x86_64*.json if-no-files-found: error # ── tag 推送时,同步上传到 GitHub Release ── @@ -469,7 +476,10 @@ jobs: tag_name: ${{ github.ref_name }} name: 'OpenLess ${{ github.ref_name }}' draft: false - prerelease: false + # beta 渠道的 release 必须标 prerelease=true:GitHub UI 会折叠它, + # 普通用户看不到;同时只上传 latest-*-beta.json,正式版用户的 + # endpoint(latest-*.json)永远不会被覆盖,保证 Beta 不溢出正式版。 + prerelease: ${{ env.OPENLESS_RELEASE_CHANNEL == 'beta' }} # Matrix jobs all upload assets to the same release. Generate notes once # so macOS, Windows, and Linux jobs do not duplicate the release body. generate_release_notes: ${{ matrix.updater-target == 'darwin' && matrix.updater-arch == 'aarch64' }} diff --git a/openless-all/app/scripts/write-updater-manifest.mjs b/openless-all/app/scripts/write-updater-manifest.mjs index eb0e7762..171cd35a 100755 --- a/openless-all/app/scripts/write-updater-manifest.mjs +++ b/openless-all/app/scripts/write-updater-manifest.mjs @@ -8,6 +8,13 @@ const target = process.env.OPENLESS_UPDATE_TARGET; const arch = process.env.OPENLESS_UPDATE_ARCH; const repo = process.env.OPENLESS_UPDATE_REPO || 'appergb/openless'; const mirrorBaseUrl = process.env.OPENLESS_UPDATE_MIRROR_BASE_URL || 'https://fastgit.cc/https://github.com'; +// 渠道决定 manifest 文件名后缀:stable → 旧文件名(向后兼容);beta → 加 -beta 后缀, +// 让 stable 用户的 endpoint 永远拿不到 beta 包。空 / 未设置 = stable。 +const rawChannel = (process.env.OPENLESS_RELEASE_CHANNEL || 'stable').toLowerCase(); +if (rawChannel !== 'stable' && rawChannel !== 'beta') { + throw new Error(`Invalid OPENLESS_RELEASE_CHANNEL: "${rawChannel}" (expected "stable" or "beta")`); +} +const channelSuffix = rawChannel === 'beta' ? '-beta' : ''; if (!target || !arch) { throw new Error('OPENLESS_UPDATE_TARGET and OPENLESS_UPDATE_ARCH are required'); @@ -55,8 +62,8 @@ if (!existsSync(signaturePath)) { } const assetName = basename(artifact); -const manifestName = `latest-${target}-${arch}.json`; -const mirrorManifestName = `latest-${target}-${arch}-mirror.json`; +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}`; const manifest = {