# 发布策略

此运行手册描述了我们如何避免用户在 **OAuth** （包括 **Gmail**）时在 **过时的桌面安装程序** 上完成流程，而规范流程是 **最新** 版本。

## 分发

* **GitHub Releases** 是 [tinyhumansai/openhuman](https://github.com/tinyhumansai/openhuman/releases) 桌面构建的主要来源。
* 这个 **Tauri 更新器** 端点（参见 `scripts/prepareTauriConfig.js` 以及发布工作流）应将用户引导到当前发布产物。
* **退役旧的稳定产物：** 当放弃某个发布分支时，请移除或隐藏 **GitHub Releases**上的过时安装程序资源，更新 **网站 / CDN** 下载链接至 **releases/latest** （或当前版本），刷新 **更新器清单** （例如 Gist / `latest.json`），以免将用户指向已弃用的构建，并抽查旧的直链是否被 **重定向、404 或 410** 到适当位置。验证：尝试文档或书签中的已知旧资源 URL，确认它们不再提供主要安装路径。

## OAuth 的最低应用版本

生产环境网页构建会在 **最低受支持的应用 semver 版本** 于 **构建时** 嵌入其中，这样 OAuth 深度链接就无法在已弃用的二进制文件上完成。每个安装包都携带其生成时设定的最低版本门槛；若要让从不升级的用户提高门槛，则需要他们安装一个 **新的** 发布版本（或通过应用内更新）。可选的未来工作：通过一个 **运行时** API 强制执行动态变化的最低版本，而捆绑值仅作为后备。

| 变量                                   | 用途                                                                                      |
| ------------------------------------ | --------------------------------------------------------------------------------------- |
| `VITE_MINIMUM_SUPPORTED_APP_VERSION` | 例如 `0.51.0` - 桌面应用必须 **≥** 此版本才能完成 `openhuman://oauth/success`.                         |
| `VITE_LATEST_APP_DOWNLOAD_URL`       | 可选；默认为 `https://github.com/tinyhumansai/openhuman/releases/latest`。当门槛阻止 OAuth 时会打开该地址。 |

将这些配置为 **GitHub Actions 变量**。它们必须同时存在于 **两个** 独立的 **`pnpm build`** 步骤和 **`tauri-apps/tauri-action`** 步骤的 env 中，位于 `.github/workflows/build-desktop.yml` （由 `release-production.yml` / `release-staging.yml`）和 `build-windows.yml` 调用的可复用矩阵），这样已发布安装程序中嵌入的 Vite 打包内容才会包含该门槛。将 `VITE_MINIMUM_SUPPORTED_APP_VERSION` **未设置** 留给本地开发（门槛禁用）。

实现： `app/src/utils/oauthAppVersionGate.ts`, `app/src/utils/desktopDeepLinkListener.ts`.

## Gmail / Google Cloud OAuth

* **重定向 URI** 在 Google Cloud Console 中必须与 **当前** 后端 + 隧道回调路径匹配。
* 桌面协议（`openhuman://`）是稳定的； **已安装的二进制文件** 在 `VITE_MINIMUM_SUPPORTED_APP_VERSION` 设置时必须满足最低版本。

## 发布检查清单（避免回归）

1. 提升 `app/package.json` 和 `app/src-tauri/tauri.conf.json` （以及根目录 `Cargo.toml` / core）中的版本，遵循现有版本工作流。
2. 当停止支持旧版本安装时，将 **`VITE_MINIMUM_SUPPORTED_APP_VERSION`** 设置为新的最低门槛 **之前** 或 **配合** ，针对该发布版本（仓库 Actions 变量 + 上述两个工作流步骤）。
3. 从面向用户的界面中移除、重定向或退役较旧的稳定安装程序和过时的 **更新器** 条目（GitHub Release 资源、网站、CDN、更新源）。确认默认安装 / 更新流程无法访问已弃用的产物。
4. 冒烟测试 **Gmail 连接** 在全新安装上从 **releases/latest**.
5. 完成 [手动冒烟检查清单](https://github.com/tinyhumansai/openhuman/blob/main/docs/RELEASE-MANUAL-SMOKE.md)，然后在打标签之前将已完成的签署块（逐字保留，所有已勾选项保持勾选）粘贴到发布 PR 描述中。

## 工作流：staging 与 production

两个一等公民 GitHub Actions 工作流，每个环境一个。根据意图选择，而不是切换一个标志。

| 工作流                                                                                                                      | 分支     | 升级                                  | 推送的标签           | 并发组                  | 使用场景                                 |
| ------------------------------------------------------------------------------------------------------------------------ | ------ | ----------------------------------- | --------------- | -------------------- | ------------------------------------ |
| [`release-staging.yml`](https://github.com/tinyhumansai/openhuman/blob/main/.github/workflows/release-staging.yml)       | `main` | `补丁` 仅                              | `v<版本>-staging` | `release-staging`    | 为 QA 生成一个 staging 构建。运行频繁；语义版本变动较小。  |
| [`release-production.yml`](https://github.com/tinyhumansai/openhuman/blob/main/.github/workflows/release-production.yml) | `main` | `补丁` / `次要` / `主要` （仅在 `main_head`) | `v<版本>`         | `release-production` | 将已验证的 staging 标签提升到生产，或从 `main` HEAD |

修复。 [`.github/workflows/build-desktop.yml`](https://github.com/tinyhumansai/openhuman/blob/main/.github/workflows/build-desktop.yml) 两个流程共用的矩阵构建 / 签名 / Sentry-DIF / 产物上传流水线位于 `中，作为一个` workflow\_call

### 可复用工作流。上述两个顶层工作流负责引用解析、版本提升、打标签以及发布 / 清理；真正的构建是共享的。

1. 运行 **生成 staging 构建** 通过 `发布（Staging）` 来自 `main`.
2. workflow\_dispatch `补丁` 于 `main`该工作流会提升 `，提交`chore(staging): vX.Y.Z `，推送分支，并在该提交处创建一个不可变的` vX.Y.Z-staging
3. 标签。 **构建矩阵从该** 标签 `main` 运行（而不是 main HEAD），因此即使
4. 已继续前进，重跑也会重新构建字节级完全相同的内容。 `main` 失败时会自动删除 staging 标签； `上的提升提交会保留，因此下一次生成会从`.

vX.Y.(Z+1) `staging` 没有单独的 `main`分支，staging 生成和生产提升都位于`。两者仅通过标签后缀（` -staging

### ）以及创建该标签的工作流来区分。

1. 运行 **提升到生产（默认流程）** 通过 `发布（Staging）` 配合 `Release Production` release\_source = staging\_tag
2. （默认值）。 `将` staging\_tag `留空以提升最新的`v\*-staging `，或传入一个明确的标签（例如`v1.2.4-staging
3. 该工作流会去掉 `。两者仅通过标签后缀（`，在相同提交上创建 `v<版本>` ，并从该标签运行生产构建矩阵。 **不再额外进行版本提升**，产物复用 staging 已验证的内容。

### 从 `main` HEAD

1. 运行 **提升到生产（默认流程）** 通过 `发布（Staging）` 配合 `修复：release_source = main_head` 以及所需的 `release_type` (`补丁` / `次要` / `主要`).
2. 工作流会运行旧的提升并打标签路径：在 `main`上提升，提交 `chore(release): vX.Y.Z`，推送，打标签 `vX.Y.Z`，构建。
3. 仅当某个仅生产环境的修复需要跳过 staging 直接发布时使用此方式。

### 标签策略与回滚

* **命名。** Staging 标签使用 SemVer 预发布后缀 `。两者仅通过标签后缀（` (`，或传入一个明确的标签（例如`），因此它们的排序 *之前* 与对应的生产标签相匹配。提升到生产时会原样去掉后缀；捆绑安装程序中嵌入的版本在这两个标签之间是相同的。
* **冲突。** 如果目标标签已在本地或 `origin`上存在，两个工作流都会立即失败。通过删除过时标签（仅限组织维护者）或继续提升版本来解决。
* **回滚（生产）。** 构建矩阵失败会触发 `cleanup-failed-release`，它会删除草稿 GitHub Release 和 `v<版本>` 标签。其来源的 staging 标签不会受影响，修复后可以重新提升。
* **回滚（staging）。** 失败的 staging 构建会删除 `v<版本>-staging` 标签。 `main` 上的提升提交会保留；下一次 staging 生成会从新的补丁号继续，而不是重复使用它（我们接受补丁号中出现一个小小的“空档”，也不愿与并发合并竞态）。
* **谁可以删除标签。** 与 `main`相同的写权限。工作流驱动的清理删除通过 `actions/github-script` 使用工作流令牌执行（GitHub App 令牌仅用于 `prepare-build` 中的提升提交 + 标签推送）；手动删除（`git push --delete origin <tag>`）需要相当的维护者权限。


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://tinyhumans.gitbook.io/openhuman/zh/kai-fa/release-policy.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
