docs: introduce Beta/Stable two-channel branching workflow (#327)

把分支模型从「dev/main」改造为「Beta/正式版」双渠道,渠道语义直接由分支名承载:

- `beta` — Beta 渠道(开发版),默认分支、集成缓冲区,所有 PR 一律打到这里。
  Beta 包不推送给普通用户,只面向主动加入 Beta 渠道的用户。
- `main` — 正式版渠道(Stable),始终可发布。仅由维护者在双端冒烟测试通过后从
  beta 合入;普通用户默认拿到的就是这条线。

文档与 CI 改动:
- README.md / README.zh.md:把「Contributing workflow / 贡献流程」章节
  改写为 Beta/正式版双渠道,含分支流向 ASCII 图、6 条核心规则,
  以及「Beta 不溢出正式版」的隔离要求。
- CLAUDE.md:把 `### Branch & contribution workflow` 改名为
  `### Branch & release-channel workflow`,明确「分支名=渠道名」。
- ci.yml:触发分支从 [main, dev] 改为 [main, beta]。

仓库侧已同步:
- 远端 dev 分支已重命名为 beta(git push origin dev:beta + 删除旧 dev)
- GitHub 仓库默认分支已切到 beta
- release-tauri.yml 用 v*-tauri tag 触发,跟分支无关,发版机制不受影响

Beta 包的 opt-in 分发机制(per-channel updater endpoint + 设置页开关)
将在独立 PR 中接入。在它落地之前,所有 v*-tauri tag 都按正式版对待,
不要从 beta 分支直接打 tag。

Co-authored-by: baiqing <lbx12309@icloud.com>
This commit is contained in:
TRIPandbaiqing authored and GitHub committed 2026-05-07 21:55:31 +08:00
1 parent 0b8c7b4529
commit 2fe5f2e0d4
4 files changed
+86 -2

No files matched your search

+2 -2
View File
@@ -8,9 +8,9 @@ name: CI
on: on:
push: push:
branches: [main, dev] branches: [main, beta]
pull_request: pull_request:
branches: [main, dev] branches: [main, beta]
jobs: jobs:
cross-platform: cross-platform:
+22
View File
@@ -105,6 +105,28 @@ Push a `v*-tauri` tag → `.github/workflows/release-tauri.yml` builds macOS arm
When bumping versions, update **both** `version` fields: `openless-all/app/package.json` and `openless-all/app/src-tauri/tauri.conf.json` (and `Cargo.toml`). When bumping versions, update **both** `version` fields: `openless-all/app/package.json` and `openless-all/app/src-tauri/tauri.conf.json` (and `Cargo.toml`).
### Branch & release-channel workflow
Two-channel branching. **Branch name = release channel.**
- **`beta`** — **Beta channel** (开发版). Default branch, integration buffer. **All PRs target `beta`** (never `main`). Beta builds may exist but are not pushed to general users — only opt-in users on the Beta channel see them.
- **`main`** — **Stable channel** (正式版). Always-releasable. Updated only by `beta → main` merges performed by maintainers after a two-platform smoke build. Release tags `v<version>-tauri` are pushed on `main` and trigger `release-tauri.yml` (tag-driven; unaffected by branch renames).
Per-PR contract:
- Run the change locally on your target platform before opening the PR (build green + manual verification of the affected feature).
- `pr-agent.yml` runs one AI review pass per PR — treat it as advisory, do not iterate on it.
- Keep AI rework rounds tight (1–2). If a fix resists, escalate to a human or restart with fresh context.
- `ci.yml` runs on push/PR for both `main` and `beta`; no extra wiring needed when adding new branches off `beta`.
For maintainers:
- Merge `beta → main` only after the two-platform (macOS + Windows) smoke build passes. **Beta work must not leak to Stable** — that gate exists for a reason.
- Tag `v<version>-tauri` **on `main`**, not on `beta`. The release workflow keys off the tag, but tagging on `main` keeps the release commit linear with the always-releasable line.
- Avoid direct pushes to `main` outside the `beta → main` merge — it bypasses the smoke-test gate.
Channel distribution (in progress): per-channel updater endpoints + a Settings toggle for "join Beta channel" are tracked as a separate change. Until that lands, every release reaches every user; treat all `v*-tauri` tags as Stable-grade for now and avoid tagging anything from `beta` directly.
## Repo conventions ## Repo conventions
- **Comments, log messages, user-facing strings, and most docs are in Simplified Chinese.** UI strings additionally route through `react-i18next` (`src/i18n/{zh-CN,en}.ts`) so we ship English alongside; `zh-CN.ts` is source of truth. - **Comments, log messages, user-facing strings, and most docs are in Simplified Chinese.** UI strings additionally route through `react-i18next` (`src/i18n/{zh-CN,en}.ts`) so we ship English alongside; `zh-CN.ts` is source of truth.
+31
View File
@@ -208,6 +208,37 @@ Logs: `~/Library/Logs/OpenLess/openless.log` (macOS) / `%LOCALAPPDATA%\OpenLess\
**Windows build** — see [`openless-all/README.md`](openless-all/README.md) for MSVC vs GNU/MinGW routes. **Windows build** — see [`openless-all/README.md`](openless-all/README.md) for MSVC vs GNU/MinGW routes.
## Contributing workflow
OpenLess uses a two-channel branching model.
- **`beta`** — the **Beta channel**. Default branch and integration buffer; all in-progress development lands here. Beta builds may exist but are **not pushed to regular users** — they only reach people who explicitly opt into the Beta channel.
- **`main`** — the **Stable channel (正式版)**. Always-releasable. The build everyone gets by default.
```text
your fork / topic branch
│ (test locally on your target platform first)
▼
PR → beta ← AI review (one pass, advisory only)
│ ← maintainer lightweight glance (scope, cross-module impact)
▼
merged into beta
│ (periodically, after a two-platform smoke build)
▼
merged into main → tag `v<version>-tauri` → release CI → Stable users
```
Rules of thumb:
- **Open PRs against `beta`, never against `main`.** GitHub already defaults the base branch to `beta` for new PRs.
- **Verify the change on your target platform before opening the PR** — build green is necessary, manual verification is required.
- **AI review runs once per PR and is advisory.** Don't loop on it. Apply your judgment.
- **Keep AI rework rounds tight (1–2).** If a fix resists, ask a human or restart with fresh context — multi-round AI back-and-forth tends to do more harm than good here.
- **Beta work must not leak to Stable.** `main` only receives merges from `beta`, performed by maintainers after a successful two-platform smoke build. No direct pushes to `main`.
- **Stable releases are cut from `main`** by pushing a `v<version>-tauri` tag — see the maintainer release checklist below.
Beta release distribution (opt-in, not yet wired): Beta builds are intended for users who consciously join the Beta channel; the in-app updater currently treats every release as Stable, and a follow-up change will introduce per-channel updater endpoints + a Settings toggle.
## Credentials ## Credentials
Credentials live in the OS credential vault (service = `com.openless.app`): macOS Keychain, Windows Credential Manager, or Linux keyring. A legacy plaintext JSON file is read only as a migration source and removed after a successful vault write: Credentials live in the OS credential vault (service = `com.openless.app`): macOS Keychain, Windows Credential Manager, or Linux keyring. A legacy plaintext JSON file is read only as a migration source and removed after a successful vault write:
+31
View File
@@ -211,6 +211,37 @@ npm run build
**Windows 构建** — MSVC 和 GNU/MinGW 两种路线详见 [`openless-all/README.md`](openless-all/README.md)。 **Windows 构建** — MSVC 和 GNU/MinGW 两种路线详见 [`openless-all/README.md`](openless-all/README.md)。
## 贡献流程
OpenLess 采用 **Beta / 正式版** 双渠道分支模型。
- **`beta`** —— **Beta 渠道(开发版)**。默认分支,也是日常集成缓冲区;所有进行中的开发都先落到这里。Beta 渠道可以直接出包,但**不会推送给普通用户**——只有主动切换到 Beta 渠道的用户才会拿到 Beta 包。
- **`main`** —— **正式版渠道(Stable)**。始终保持可发布状态,普通用户默认拿到的就是这条线上的版本。
```text
你的 fork / topic 分支
│ (先在目标平台本地自测通过)
▼
PR → beta ← AI Review(一次性,仅供参考)
│ ← 维护者轻量过一眼(范围、跨模块影响)
▼
合入 beta
│ (定期或里程碑节点,跑双端冒烟测试)
▼
合入 main → 打 tag `v<版本>-tauri` → Release CI → 推给正式版用户
```
核心规则:
- **PR 一律打到 `beta`,不要直接打到 `main`。** GitHub 上新建 PR 的 base 已默认是 `beta`。
- **开 PR 前先在目标平台跑通功能** —— build 绿是底线,必须做人工验证。
- **AI Review 每个 PR 只跑一轮,结果仅供参考。** 不要围绕它反复改,最终判断权在贡献者和维护者手里。
- **AI 改 Review 意见控制在 1–2 轮。** 卡住了直接换人工或重开对话上下文,避免多轮 AI 越改越乱。
- **Beta 不能溢出到正式版。** `main` 只接收来自 `beta` 的合并,由维护者在双端冒烟测试通过后执行;任何人不要直接 push `main`。
- **正式版 Release 从 `main` 切出**,通过推送 `v<版本>-tauri` tag 触发,详见下方"维护者:发布检查"。
Beta 包的分发(opt-in,尚未接入):Beta 包面向主动加入 Beta 渠道的用户;当前 App 内 updater 把所有 release 都当作正式版处理,后续会在设置页加入"加入 Beta 渠道"开关,并把 updater endpoint 按渠道拆开。
## 凭据 ## 凭据
凭据保存在系统凭据库(service = `com.openless.app`):macOS Keychain、Windows Credential Manager 或 Linux keyring。旧版明文 JSON 只作为迁移来源读取,成功写入系统凭据库后会被删除: 凭据保存在系统凭据库(service = `com.openless.app`):macOS Keychain、Windows Credential Manager 或 Linux keyring。旧版明文 JSON 只作为迁移来源读取,成功写入系统凭据库后会被删除: