合并 internal → main: 退款/提现/激活/CI 全面优化 #4

Open
shanshanzhong147 wants to merge 76 commits from internal into main
7 changed files with 422 additions and 0 deletions
Showing only changes of commit cfc9cf790b - Show all commits
+24
View File
@@ -0,0 +1,24 @@
# Code owners — 自动 request review
#
# 仓库私有 + 当前 plan 不支持 branch protection(详见 doc/development-workflow-zh.md
# 「平台层约束的现状」一节),CODEOWNERS 在此用作"自动 request review + 显性责任划分"
# 而非强制门禁。
#
# 任何 PR 默认 request 给 @shanshanzhong147 (owner) review。若后续引入团队
# handle(例如 @TawCorp/backend),把对应 path 改成 team handle 即可。
# 全部路径 — owner 默认 reviewer
* @shanshanzhong147
# 部署/CI/Docker — 改这些要再确认一次(涉及生产部署链路)
/.github/ @shanshanzhong147
/Dockerfile @shanshanzhong147
/docker-compose.*.yml @shanshanzhong147
/scripts/ @shanshanzhong147
/Makefile @shanshanzhong147
# 流程文档自身 — 改这里就是改流程
/CONTRIBUTING.md @shanshanzhong147
/CONTRIBUTING_ZH.md @shanshanzhong147
/doc/development-workflow-zh.md @shanshanzhong147
/.github/CODEOWNERS @shanshanzhong147
+51
View File
@@ -0,0 +1,51 @@
<!--
完整流程见 doc/development-workflow-zh.md
-->
## 关联 Issue
Closes HIF-XXX
<!-- 如关联多个:Closes HIF-XXX, Closes HIF-YYY -->
## 改动摘要
<!-- 1-3 句话说清楚做了什么、为什么 -->
## 改动细节
<!-- 按文件/模块逐条列;引用代码用 `file.go:行号` 格式 -->
-
-
## 测试计划
- [ ] `go build ./...` 通过
- [ ] `go vet ./...` 通过
- [ ] `go test -race ./... -count=1` 通过
- [ ] golangci-lint 通过
- [ ] 新增/修改的逻辑有对应单测覆盖
- [ ] (如涉及 DB 变更)migration up/down 双向验证
- [ ] (如涉及 APIcurl / Postman 验证命令贴在下面
<!-- 贴 curl 或测试输出 -->
```
```
## 风险 / 回滚
<!-- 这次改动失败时怎么回滚;是否影响线上数据;是否需要 feature flag -->
-
## Reviewer 自检清单
- [ ] PR 标题符合 commitlint 规范(`修复/新功能/重构/文档/配置(#<num>): ...`
- [ ] 分支命名 `fix/<num>-…` / `feat/<num>-…` / `chore/…`
- [ ] 目标分支 = `internal`
- [ ] 改动 scope 与 Issue 描述一致,无 scope creep
- [ ] **无无关代码改动**(架构师红线)
- [ ] 无密钥/凭证泄露
- [ ] CI 全绿
- [ ] 测试工程师已验收(如涉及业务逻辑)
+64
View File
@@ -0,0 +1,64 @@
name: CI
on:
pull_request:
branches:
- internal
- main
workflow_dispatch:
permissions:
contents: read
concurrency:
group: ci-${{ github.ref }}
cancel-in-progress: true
jobs:
build-and-test:
name: Build, vet, test
runs-on: ubuntu-latest
timeout-minutes: 20
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Setup Go
uses: actions/setup-go@v5
with:
go-version-file: go.mod
cache: true
- name: Download modules
run: go mod download
- name: Build
run: go build ./...
- name: Vet
run: go vet ./...
- name: Test
run: go test -race -count=1 ./...
lint:
name: golangci-lint
runs-on: ubuntu-latest
timeout-minutes: 10
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Setup Go
uses: actions/setup-go@v5
with:
go-version-file: go.mod
cache: true
- name: golangci-lint
uses: golangci/golangci-lint-action@v6
with:
version: latest
args: --timeout=5m
+2
View File
@@ -1,5 +1,7 @@
# Pull Request Submission Guidelines
> **TawCorp internal contributors**: read [`doc/development-workflow-zh.md`](doc/development-workflow-zh.md) first. It documents the canonical end-to-end flow (Multica issue → branch → PR → CI → review → squash merge via GitHub UI → Deploy Staging → QA), agent role boundaries, branch / commit conventions, and the soft-constraint model used in place of branch protection. The guidelines below apply to all contributors (internal and external) as the baseline.
To ensure the quality of the codebase and maintainability of the project, please follow these guidelines before submitting a Pull Request (PR):
## 1. PR Title and Description
+2
View File
@@ -1,5 +1,7 @@
# Pull Request 提交须知
> **TawCorp 内部协作者**:请先阅读 [`doc/development-workflow-zh.md`](doc/development-workflow-zh.md)。该文档定义了从 Multica issue 到 PR 合并到 Deploy Staging 到 QA 验收的端到端流程,以及 agent 角色边界、分支/commit 约定、和不依赖 GitHub branch protection 的软约束模型。下面的通用指南仍然适用,但内部协作以 `doc/development-workflow-zh.md` 为准。
为了确保代码库的质量和项目的可维护性,在提交 Pull Request(PR)之前,请务必遵循以下准则:
## 1. PR 标题和描述
+254
View File
@@ -0,0 +1,254 @@
# 开发流程(迁移到 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 自动跑
→ 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 上有对应 issueHIF-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,通知可以部署(虽然 Deploy Staging 已自动跑,但运维需要确认部署状态)。
**禁止做的事**
- ❌ 在本地 squash 再 `git push``internal` / `main`
- ❌ Rebase merge / Create a merge commit(保持 linear history
- ❌ Force push 到 `internal` / `main`
- ❌ Bypass CICI 红时不要 merge
- ❌ 自己 approve 自己的 PR
- ❌ 未经测试工程师验收的分支合并(架构师红线)
### 2.7 Deploy Staging 自动触发
合并到 `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 + Deploy Staging 通过 + 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 自己分支 | 合 PRpush `internal` / `main`;改 CODEOWNERS;自己 approve 自己 PR |
| 架构师(Squad Leader | reviewapproveGitHub 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 APIHTTP 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`
+25
View File
@@ -16,3 +16,28 @@ commit-msg:
commands:
commitlint:
run: npx --no -- commitlint --edit $1
# Soft constraint: the GitHub plan tier blocks branch protection on this
# private repo (HTTP 403). Catch direct pushes to internal / main here so the
# normal flow stays "open a PR + GitHub UI Squash and merge".
# See doc/development-workflow-zh.md § 5 for the full soft-constraint model.
#
# Emergency bypass: `git push --no-verify`. The reason must be logged in the
# corresponding Multica issue per the development workflow doc.
pre-push:
commands:
block-direct-push-to-protected:
run: |
set -e
while read local_ref local_sha remote_ref remote_sha; do
case "$remote_ref" in
refs/heads/internal|refs/heads/main)
echo "❌ Direct push to ${remote_ref##refs/heads/} is forbidden." >&2
echo " Open a PR and use GitHub UI 'Squash and merge' instead." >&2
echo " See doc/development-workflow-zh.md § 2." >&2
echo " Emergency bypass: git push --no-verify (must be logged in Multica)." >&2
exit 1
;;
esac
done