# 开发流程（迁移到 GitHub 后）

> 适用：`github.com/TawCorp/hifast-server`（canonical 仓库）及配套的 Multica agent 工作区。
> 历史背景：本仓库于 2026-06-03 从 `git.kxsw.us/HI-VPN/hi-server` 迁移到 GitHub。**`git.kxsw.us` 已废弃**，所有新开发只走本仓库。

---

## 0. TL;DR

```
Multica issue → 分支 fix/<num>-中文简述 → 推 github → 开 PR → CI 绿 → 架构师 approve
            → GitHub UI Squash and merge 进 internal → 测试环境部署 (deploy-staging.yml) 自动跑
            → QA 在 staging 验收 → Multica issue → done

发版时：架构师把 internal squash 进 main → 对外正式版本
```

不要在 GitHub UI 之外 squash 后直接 push `internal` / `main`。不要往 `git.kxsw.us` 推。

---

## 1. 分支模型

| 分支 | 角色 | 写入方式 |
|---|---|---|
| `main` | 对外正式版本（生产） | **只**由架构师 squash merge `internal` → `main` |
| `internal` | 日常开发主干，staging 触发分支 | **只**由架构师在 GitHub UI 上 Squash and merge PR |
| `fix/<num>-…` | bug 修复分支 | 工程师自己开自己删（PR 合并后 GitHub 自动删） |
| `feat/<num>-…` | 新功能分支 | 同上 |
| `chore/…` `refactor/…` `hotfix/…` | 杂项 / 重构 / 紧急修复 | 同上 |

**分支命名约定**（严格遵守，便于 CI / CODEOWNERS / 历史追溯）：

| 前缀 | 用途 | 示例 |
|---|---|---|
| `fix/<num>-` | 关联 Multica issue 编号的 bug 修复 | `fix/143-邀请权益单测flake` |
| `feat/<num>-` | 关联 Multica issue 编号的新功能 | `feat/77-套餐列表促销信息` |
| `chore/` | 配置 / 文档 / 工具链（无关联 issue 可不带编号） | `chore/dev-workflow-docs` |
| `hotfix/<num>-` | 生产紧急修复 | `hotfix/151-payment-callback-503` |
| `refactor/<num>-` | 重构（行为不变） | `refactor/138-promo-eligibility` |

**单分支存活上限：3 天**（架构师 CLAUDE.md 约定）。超时未合并的分支由架构师在 issue 上 ping 持有者收尾或重切。

---

## 2. 标准 PR 生命周期

### 2.1 立项

- Multica 上有对应 issue（HIF-XXX）。
- issue 已 assigned，状态 `todo` 或 `in_progress`。

### 2.2 写代码

```bash
# 在 worktree 里
git fetch origin
git checkout -B fix/<num>-中文简述 origin/internal

# 编码 + 写测试
# lefthook pre-commit 会自动跑 fmt / imports / lint / vet / test
git commit -m "修复(#<num>): 一句话说清楚做了什么"

# 推到 github（不再推 git.kxsw.us）
git push origin fix/<num>-中文简述
```

**commit message**（commitlint 强制）：

```
<类型>(#<num>): <一句话描述，<= 72 字符>

<可选正文，说明 why>
```

类型只有这五个：**`修复` / `新功能` / `重构` / `文档` / `配置`**。其它一律不允许。

### 2.3 开 PR

```bash
gh pr create --base internal --title '修复(#<num>): ...' --body-file <path>
```

或 GitHub UI 开。PR 模板（`.github/PULL_REQUEST_TEMPLATE.md`）会自动填入，按指引补内容。

**PR 标题必须等于 squash 后的合入 commit 标题**（用 `<类型>(#<num>): ...` 形式）。

### 2.4 CI 自动跑

`.github/workflows/ci.yml` 在 PR 上触发：

| Job | 执行 |
|---|---|
| `build-and-test` | `go build ./...` + `go vet ./...` + `go test -race -count=1 ./...` |
| `lint` | `golangci-lint run` |

红 → 工程师本地复现 + 修，反复直到全绿。

### 2.5 Code review

- `CODEOWNERS` 自动 request review。
- 架构师（或被指派的 reviewer）逐 hunk 看，特别关注：
  - scope 与 issue 一致性（无 scope creep——架构师红线之一）
  - 错误处理 / SQL 注入 / N+1
  - 测试覆盖关键边界
  - 是否引入了无关的代码改动（架构师红线："发现成员修改了无关代码 → 立即打回重做"）
- review 通过即在 PR 上点 Approve。

### 2.6 Merge to `internal`

- **必须用 GitHub UI 的 "Squash and merge"**。
- squash 后 commit message 由架构师编辑确认：保持 `<类型>(#<num>): ...` 形式 + 必要正文。
- 合并按钮按下后 PR 自动 close，分支由 GitHub 自动删（"Automatically delete head branches" 应开启）。
- 架构师在 Multica issue 上 `@运维工程师` 附 commit hash，通知可以部署（虽然测试环境部署 workflow 已自动跑，但运维需要确认部署状态）。

**禁止做的事**：
- ❌ 在本地 squash 再 `git push` 到 `internal` / `main`
- ❌ Rebase merge / Create a merge commit（保持 linear history）
- ❌ Force push 到 `internal` / `main`
- ❌ Bypass CI（CI 红时不要 merge）
- ❌ 自己 approve 自己的 PR
- ❌ 未经测试工程师验收的分支合并（架构师红线）

### 2.7 测试环境部署自动触发 (`.github/workflows/deploy-staging.yml`)

合并到 `internal` 后，`.github/workflows/deploy-staging.yml` 自动触发：

1. `go test ./...`（已被 CI 保证过，理论上不会再红）
2. Build Docker image `registry.kxsw.us/vpn-server:<sha>` + `:staging`
3. scp `docker-compose.cloud.yml` 到 staging host
4. ssh 重启 `ppanel-server` 服务
5. healthcheck + Telegram 通知

部署失败 → Telegram 告警 → 运维介入回滚。Deploy 不阻塞下一个 PR，但**修复 deploy 是当前 deploy 失败者的责任**。

### 2.8 QA 验收

- 测试工程师在 staging（`tapi.hifast.biz` / 配套前端）按 issue 描述的 acceptance criteria 验收。
- 验收通过 → Multica issue 推 `done`。
- 任何一项失败 → 单独开子 issue 指派对应工程师，**不要**回退 PR / revert（除非生产数据安全风险）。

### 2.9 发版到 `main`（对外正式版本）

由架构师在合适的时机（feature 集齐、staging 跑稳一段时间后）执行：

```bash
gh pr create --base main --head internal --title '发版: <版本号>'
```

走和普通 PR 一样的流程（CI 绿 + review + Squash and merge）。`main` 的 push 也可以触发后续生产部署 workflow（如未来增加 `deploy-production.yml`）。

---

## 3. Multica issue 状态映射

| Multica 状态 | 对应阶段 |
|---|---|
| `backlog` | 还没排期 |
| `todo` | 已排期，待 assigned agent 开始 |
| `in_progress` | 分支已开始写，未 push |
| `in_review` | PR 已开，等 review / CI / merge |
| `done` | PR merged + 测试环境部署通过 + QA 验收通过 |

**三个条件没全满足就不要标 done**——否则验收链路看不到真问题。

Issue metadata 建议字段（与现有 agent CLAUDE.md 推荐一致）：

| 字段 | 内容 |
|---|---|
| `pr_url` | https://github.com/TawCorp/hifast-server/pull/XX |
| `merge_commit` | merge 后的 squash commit SHA |
| `deploy_url` | `tapi.hifast.biz` 或对应前端域名 |
| `pipeline_status` | `coding` / `pr_open` / `merged` / `deployed` / `qa_passed` |
| `waiting_on` | 当前阻塞点（如 `qa_e2e_access` / `architect_review`） |

---

## 4. Agent 边界

| Agent | 可以做 | 不可以做 |
|---|---|---|
| 后端 / 前端 / 运维工程师 | push 自己的 fix/feat 分支；开 PR；回评 issue；本地 squash 自己分支 | 合 PR；push `internal` / `main`；改 CODEOWNERS；自己 approve 自己 PR |
| 架构师（Squad Leader） | review；approve；GitHub UI squash merge；在 issue 上拆解需求 + 分派子任务；维护 doc/ 和 CLAUDE.md | 在本地 merge 后 push `internal`（绕过 CI gate）；直接编写业务逻辑或 UI 代码 |
| 测试工程师 | 在 staging 验收；回评 issue；开子 issue 报 bug | 改 prod 代码；改 CI workflow；自己合 PR |
| 仓库 owner（人类） | 任何越界操作 + 流程治理决策（如 branch protection 升级） | — |

任何越界都需要在 issue 上声明 + 走另一个 PR。

---

## 5. 平台层约束的现状（重要）

> 私有仓库 + 当前 GitHub plan 不支持 branch protection / rulesets API（HTTP 403）。

这意味着 "禁止直接 push internal" / "require CI pass" / "require approval" 这些**在 GitHub 平台层面没法硬强制**。当前依赖三层软约束：

1. **客户端层**：`lefthook.yml` 的 `pre-push` 钩子会在尝试直接 push `internal` / `main` 时报错。绕过去要明确加 `--no-verify`，会留 git trailers。
2. **流程层**：本文档 + `CODEOWNERS` 自动 request review + 架构师作为单一合并执行人。
3. **审计层**：所有 merge 都对应 Multica issue，事后任何"非 PR 路径上去的 commit"都能在 git log + Multica 对照查出来。

如果未来组织规模扩大、人类协作者增多，建议升级 GitHub Team（$4/user/月）拿到 branch protection 平台保障。**目前规模下软约束足够。**

---

## 6. 常见场景

### Hotfix（生产紧急修复）

走和 fix 同样的流程，只是分支前缀 `hotfix/`，PR 标题前加 `[HOTFIX]`。架构师可酌情把 review 等待时间压缩到 30 分钟以内。Hotfix 通常直接合 `internal` 后立即由架构师再开 `internal → main` 的 PR 一起发版。

### Revert

- 在 GitHub UI 上找到要 revert 的 PR，点 "Revert"。
- GitHub 会生成 revert PR，按正常流程过 review + merge。
- Revert PR 标题用 `修复(#<原 issue 编号>): revert <原 PR 标题>`。

### 文档 / 配置改动

走 `chore/` 分支。CI 一样跑（保险），review 可走 fast-track。

### 跨多个 issue 的大改动

- 优先拆成多个独立 PR，每个 PR 对应一个 issue。
- 如果实在拆不开，PR title 用 `<类型>(#XXX/#YYY/#ZZZ): ...`，PR body 里 `Closes` 三个。

---

## 7. FAQ

**Q: 为什么不允许在本地 squash 再推 internal？**
A: 绕过 GitHub PR review 流程 + CI gate + 审计记录。即使你确定改动 100% 正确，也走 PR——这是文化约束，避免架构师红线被逐渐侵蚀。

**Q: CI 跑得慢，PR 一直 yellow，可以先 merge 吗？**
A: 不可以。CI 通常 5 分钟内出结果；如果超过 15 分钟仍 pending，检查是否有 stuck job，必要时 re-run。

**Q: 如果架构师不在，怎么办？**
A: 备份 reviewer = 仓库 owner（@shanshanzhong147）。CODEOWNERS 已经把 owner 列为兜底 reviewer。

**Q: lefthook pre-push 不让我 push internal，但我确实需要紧急修一行小字？**
A: 没有"紧急修一行小字"这种例外。开 hotfix 分支 + 开 PR + 走 fast-track review。

**Q: Multica issue 状态没流转到 done，是不是要手动推？**
A: 不要直接推。先确认 PR merged + deploy 绿 + QA 通过三个条件全满足。任一项没满足就维持 `in_review` 并加评论说卡在哪。

**Q: 我能不能用 Rebase / Merge commit 模式合 PR？**
A: 不行。必须用 Squash and merge。`internal` 必须保持 linear history（一个 PR = 一个 commit），方便回滚和审计。

---

## 8. 紧急联系

- Deploy 红 / staging 挂：运维工程师（Multica agent `071d94d9-38bb-43cc-8c58-29e3b52d7bd4`）
- 流程问题 / branch protection 决策：仓库 owner @shanshanzhong147
- 架构 / API 设计：架构师（Multica agent `0de10589-f101-49ef-8dfa-0e9e992fe27c`）
