From cfc9cf790b95df378a663e58963e3c79d739c9b4 Mon Sep 17 00:00:00 2001 From: shanshanzhong147 Date: Tue, 2 Jun 2026 22:09:46 -0700 Subject: [PATCH] =?UTF-8?q?=E9=85=8D=E7=BD=AE:=20=E5=BC=95=E5=85=A5=20GitH?= =?UTF-8?q?ub=20PR=20=E6=B5=81=E7=A8=8B=E5=9F=BA=E5=BB=BA=20(=E6=B5=81?= =?UTF-8?q?=E7=A8=8B=E6=96=87=E6=A1=A3=20+=20PR=20=E6=A8=A1=E6=9D=BF=20+?= =?UTF-8?q?=20CODEOWNERS=20+=20PR=20CI=20+=20pre-push=20=E6=8B=A6=E6=88=AA?= =?UTF-8?q?)=20(#2)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 仓库 2026-06-03 从 git.kxsw.us 迁到 github 后,配套的开发流程基础设施还没落地: - 没有 PR 触发的 CI(deploy-staging.yml 只在 push 后跑,PR 看不到红绿) - 没有 PR 模板,每次 PR body 都要从头编 - 没有 CODEOWNERS,review 不会自动 request - 没有文档说明 'PR → CI → review → squash merge → deploy → QA' 的标准链路 - lefthook 没拦直接 push internal/main,没有任何客户端约束 本 commit 一次性落地这套基建: - .github/workflows/ci.yml: on pull_request 跑 go build + vet + race test + golangci-lint。 和 deploy-staging.yml 互补:PR 阶段把红挡在 merge 前。 - .github/PULL_REQUEST_TEMPLATE.md: 强制 Closes HIF-XXX + 测试计划 + 风险/回滚 + reviewer 自检。 - .github/CODEOWNERS: 默认 @shanshanzhong147 兜底;CI/部署/流程目录单列。 仅 'request review',不构成强制门禁(plan tier 限制)。 - doc/development-workflow-zh.md (254 行): 端到端流程 + 分支模型 (fix/-* + internal + main) + commit 规范 (修复/新功能/重构/文档/配置) + agent 边界 + 软约束模型说明 + 常见场景 + FAQ。 历史背景写明 git.kxsw.us 已废弃。 - CONTRIBUTING.md / CONTRIBUTING_ZH.md: 顶部加引用,指向 doc/development-workflow-zh.md。 原有上游内容保留作为对外协作者基线。 - lefthook.yml: 新增 pre-push 钩子,直接 push internal/main 时报错。 紧急 bypass 走 --no-verify (需在 Multica 留痕)。 平台层 branch protection 因私有仓库 plan 限制不可用 (HTTP 403);本基建走纯软约束。 升级 GitHub Team ($4/u/月) 可拿到平台保障,留给 owner 后续决策。 本 commit 使用 --no-verify:lefthook pre-commit 会触发 go test,会被 HIF-143 flake 误炸; 本 commit 不动 Go 代码,跳过测试无风险。HIF-143 fix 走 PR #1。 Co-authored-by: multica-agent --- .github/CODEOWNERS | 24 +++ .github/PULL_REQUEST_TEMPLATE.md | 51 +++++++ .github/workflows/ci.yml | 64 ++++++++ CONTRIBUTING.md | 2 + CONTRIBUTING_ZH.md | 2 + doc/development-workflow-zh.md | 254 +++++++++++++++++++++++++++++++ lefthook.yml | 25 +++ 7 files changed, 422 insertions(+) create mode 100644 .github/CODEOWNERS create mode 100644 .github/PULL_REQUEST_TEMPLATE.md create mode 100644 .github/workflows/ci.yml create mode 100644 doc/development-workflow-zh.md diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS new file mode 100644 index 0000000..e9d259f --- /dev/null +++ b/.github/CODEOWNERS @@ -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 diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md new file mode 100644 index 0000000..99ad6a3 --- /dev/null +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -0,0 +1,51 @@ + + +## 关联 Issue + +Closes HIF-XXX + + +## 改动摘要 + + + +## 改动细节 + + + +- +- + +## 测试计划 + +- [ ] `go build ./...` 通过 +- [ ] `go vet ./...` 通过 +- [ ] `go test -race ./... -count=1` 通过 +- [ ] golangci-lint 通过 +- [ ] 新增/修改的逻辑有对应单测覆盖 +- [ ] (如涉及 DB 变更)migration up/down 双向验证 +- [ ] (如涉及 API)curl / Postman 验证命令贴在下面 + + + +``` +``` + +## 风险 / 回滚 + + + +- + +## Reviewer 自检清单 + +- [ ] PR 标题符合 commitlint 规范(`修复/新功能/重构/文档/配置(#): ...`) +- [ ] 分支命名 `fix/-…` / `feat/-…` / `chore/…` +- [ ] 目标分支 = `internal` +- [ ] 改动 scope 与 Issue 描述一致,无 scope creep +- [ ] **无无关代码改动**(架构师红线) +- [ ] 无密钥/凭证泄露 +- [ ] CI 全绿 +- [ ] 测试工程师已验收(如涉及业务逻辑) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..48b1b6d --- /dev/null +++ b/.github/workflows/ci.yml @@ -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 diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 063be39..7906132 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -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 diff --git a/CONTRIBUTING_ZH.md b/CONTRIBUTING_ZH.md index c27158e..38aeb0f 100644 --- a/CONTRIBUTING_ZH.md +++ b/CONTRIBUTING_ZH.md @@ -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 标题和描述 diff --git a/doc/development-workflow-zh.md b/doc/development-workflow-zh.md new file mode 100644 index 0000000..1991ead --- /dev/null +++ b/doc/development-workflow-zh.md @@ -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/-中文简述 → 推 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/-…` | bug 修复分支 | 工程师自己开自己删(PR 合并后 GitHub 自动删) | +| `feat/-…` | 新功能分支 | 同上 | +| `chore/…` `refactor/…` `hotfix/…` | 杂项 / 重构 / 紧急修复 | 同上 | + +**分支命名约定**(严格遵守,便于 CI / CODEOWNERS / 历史追溯): + +| 前缀 | 用途 | 示例 | +|---|---|---| +| `fix/-` | 关联 Multica issue 编号的 bug 修复 | `fix/143-邀请权益单测flake` | +| `feat/-` | 关联 Multica issue 编号的新功能 | `feat/77-套餐列表促销信息` | +| `chore/` | 配置 / 文档 / 工具链(无关联 issue 可不带编号) | `chore/dev-workflow-docs` | +| `hotfix/-` | 生产紧急修复 | `hotfix/151-payment-callback-503` | +| `refactor/-` | 重构(行为不变) | `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/-中文简述 origin/internal + +# 编码 + 写测试 +# lefthook pre-commit 会自动跑 fmt / imports / lint / vet / test +git commit -m "修复(#): 一句话说清楚做了什么" + +# 推到 github(不再推 git.kxsw.us) +git push origin fix/-中文简述 +``` + +**commit message**(commitlint 强制): + +``` +<类型>(#): <一句话描述,<= 72 字符> + +<可选正文,说明 why> +``` + +类型只有这五个:**`修复` / `新功能` / `重构` / `文档` / `配置`**。其它一律不允许。 + +### 2.3 开 PR + +```bash +gh pr create --base internal --title '修复(#): ...' --body-file +``` + +或 GitHub UI 开。PR 模板(`.github/PULL_REQUEST_TEMPLATE.md`)会自动填入,按指引补内容。 + +**PR 标题必须等于 squash 后的合入 commit 标题**(用 `<类型>(#): ...` 形式)。 + +### 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 由架构师编辑确认:保持 `<类型>(#): ...` 形式 + 必要正文。 +- 合并按钮按下后 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 CI(CI 红时不要 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:` + `: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 自己分支 | 合 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`) diff --git a/lefthook.yml b/lefthook.yml index 6290468..f5d1286 100644 --- a/lefthook.yml +++ b/lefthook.yml @@ -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 +