- iteration-2 报告 01-08(PM 拆解/后端/Flutter 评估/现实核查/UI 规范/埋点规划/证据基线/Git 规划),04、06 已由正式角色复核定稿 - mkdocs 挂「第二迭代」导航,build --strict 通过 - ADR-009 新建 patbond-pet 模块、ADR-010 照片剪出 M2、ADR-011 dev 主干/master 发布、ADR-012 北极星与 H1-H4、ADR-013 废弃 health_record_action、ADR-014 DEBT-1 随 M2、ADR-015 照护人邀请后置 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
11 KiB
08 M2 Git 与 CI 工作流规划
- 执行人:Git Workflow Master
- 日期:2026-09-07
- 范围:第二迭代(M2 宠物健康档案)开工前的三仓状态核查、分支/提交策略、CI 扩展与防泄漏规划。本报告只核查与规划,未改动任何代码、工作流或 mkdocs.yml。
1. 三仓当前状态核查(2026-09-07 实测)
| 仓库 | 分支 | 相对 origin | 工作区 | stash | 最新提交 CI 状态 |
|---|---|---|---|---|---|
| patbond-api | dev | 同步(fetch 后确认) | 干净 | 无 | success(0d81c38,CI / backend-test,run 6) |
| patbond-flutter | dev | 同步 | 干净 | 无 | success(3f8388e,CI / flutter-gates,run 11) |
| patbond-doc | main | 同步 | 干净 | 无 | success(5537f92,CI / docs-build) |
CI 状态经 Gitea commit status API 逐仓核实,非转述。
未提交内容清单:无。 第一迭代「三仓改动长期未 commit」的教训在收官阶段已彻底闭环——包括上次报告中留给用户自决的 patbond-flutter README.md 也已入库。唯一例外是本报告文件本身(写入 patbond-doc 后为未跟踪状态),按第 3 节波次规则随下一波提交。
两处非阻塞的历史遗留(可选清理,待拍板):
- patbond-api 本地
master分支(ff876bc)的上游origin/master已在远端删除(branch -vv显示「丢失」)。本地分支可删:git branch -D master(确认无独有提交后执行;ff876bc是初始 README 提交,早已被 dev 包含的话可安全删除,删前用git merge-base --is-ancestor ff876bc dev核实)。 - patbond-flutter 本地
main(030b11f)与远端origin/main均落后于 dev。dev 是事实集成分支,main 处于闲置态。M2 不动它;若未来引入「main = 可发布」语义(见 2.3),届时再统一处理。
2. M2 分支与提交策略
2.1 现状评估
第一迭代的 trunk-based 小步直推 dev(doc 直推 main)配合本地门禁运转良好:历史线性、无合并冲突、每个提交自带验收证据。但当时 CI 尚未上线,「门禁不绿不提交」全靠自觉;现在三仓 CI 已在 push 时执行同一套门禁,且三个 ci.yml 均已配置 pull_request: 触发器——PR 合入前门禁是零成本就绪的,只差用不用。
2.2 推荐方案(待拍板):trunk-based 为主 + 高风险改动走 PR
两人 + AI 辅助的协作模式下,日常改动走 PR 的评审收益低、流程开销高,不推荐全面切换。推荐分层:
- 日常改动(单波次内可完成、不动 schema、不动跨仓契约):继续小步直推 dev(doc 直推 main)。CI 在 push 后兜底,红了立即修——两人团队里一个红提交的传播面可控。
- 高风险改动强制走短命分支 + Gitea PR,合入前 CI 必须绿。触发条件(满足其一):
- 新增/变更 Flyway 迁移(M2 的宠物健康档案必然新增
V3__*.sql,首当其冲); - 跨仓契约变更(openapi.yaml 的破坏性修改);
- 依赖升级、大规模重构;
- 两人同时改同一仓库的并行期。
- 新增/变更 Flyway 迁移(M2 的宠物健康档案必然新增
- 分支命名沿用规范:
feat/<主题>、fix/<主题>(如feat/pet-health-schema),合入后即删,不留长期分叉。 - 个人分支整理历史用
git push --force-with-lease;共享分支(dev/main)依旧禁止 force push、禁止改写已推送历史。
选择理由:这是对现行 git-workflow.md 第 9 行「何时开 feature 分支」条款的最小延伸——把「破坏性风险」具体化为可判定的清单,并利用已就绪的 PR 触发器让 CI 在合入前把关,而不是引入一套全新流程。
配套(可选,待拍板):在 Gitea 仓库设置中为 dev/main 开启分支保护,勾选「合并前需状态检查通过」并选中 CI 上下文。两人团队可以不开(靠约定),开了则规则由平台强制执行,AI 辅助开发场景下多一道机械防线。
2.3 暂不引入的东西
- 不引入 Git Flow / develop-release 双轨——没有版本化发布压力,dev 单集成分支足够。
- 不引入 main 发布分支语义——等 M3 有部署目标后再议。
3. M2 提交节奏规范
3.1 波次即提交(第一迭代教训的制度化)
- 每个波次收尾时,三仓凡有改动必须 commit 并 push,push 后确认 CI 绿,才算波次闭环。 波次报告中记录各仓提交哈希与 CI 结论(沿用第一迭代收官报告的做法)。
- 波次中途允许多次小提交(鼓励),但不允许波次结束时仍有未提交改动过夜。
- AI 会话结束前,执行者对三仓各跑一次
git status,把结果写进波次报告——「工作区干净」要有出处。
3.2 提交信息:沿用现行约定,不引入新格式
git-workflow.md 已固化的「feat/fix/refactor/docs/test/chore 前缀 + 中文主题 + 正文验收证据 + ADR 引用」在第一迭代全程执行良好(近 20 个提交无一例外),M2 原样沿用,不引入英文 conventional commits 或 scope 括号语法——现行格式已具备 conventional commits 的全部实用价值(可 grep、可归类、可回溯),改格式只会割裂历史。
M2 补充一条:涉及契约的提交,正文注明对应的 openapi.yaml 版本或 doc 仓提交哈希(见 3.3)。
3.3 契约先行时的三仓提交顺序
M2 采用契约先行,顺序固定为:
- patbond-doc 先行:
docs/api/openapi.yaml的契约变更单独成提交(docs: 宠物健康档案 API 契约(M2 波次 N)),push 且 docs-build 绿。契约提交不与其他文档改动混杂,保证可独立引用与回退。 - patbond-api 跟进:实现 + 测试成一或多个提交,正文引用 doc 仓契约提交哈希,push 且 backend-test 绿。
- patbond-flutter 收尾:对接实现,正文同样引用契约哈希,push 且 flutter-gates 绿。
契约中途返工时,doc 仓允许在同波次内追加修订提交(契约未被下游消费前不算破坏性变更);一旦 api/flutter 已按某版契约合入,再改即视为破坏性修改,走 2.2 的 PR 通道。
4. CI 扩展规划
4.1 现状修正:任务假设的两问已被第一迭代末的事实回答
核查发现三仓 CI 均已上线且全绿,任务中「flutter 是否接入 CI」「doc 是否加 --strict 门禁」不再是开放问题:
- patbond-flutter CI 已上线并验证可行(run 11 success)。零外部 action 约束下 Flutter SDK 进容器的方案已在
ci.yml中落地:从 flutter-io.cn 镜像 curl 下载 Flutter 3.44.6 的 tar.xz,解压到挂载的gitea_toolcache卷(runnercontainer.options配置-v gitea_toolcache:/opt/hostedtoolcache),首跑下载约 900MB,后续 run 复用缓存秒级就绪;pub 走 pub.flutter-io.cn。门禁为 format/analyze/test 三命令,与本地一致。 - patbond-doc 的
mkdocs build --strict门禁已上线(apt 装 mkdocs,规避 PEP 668;docs-build success)。 - patbond-api CI 全绿(82 测试,约 3m18s),Testcontainers 经 docker.sock 挂载正常工作。
4.2 M2 的 CI 增量(按优先级,均为规划,实施时再改文件)
- 无必做项。 三条流水线覆盖了全部本地门禁,M2 开工不被 CI 阻塞。
- 可选——Flutter 版本升级流程注明:toolcache 以
flutter-3.44.6目录名区分版本,升级 SDK 时改 ci.yml 中FLUTTER_VERSION即自动触发新版本下载,旧目录需手动清理卷(写入 ci-runner-setup.md 的常见问题即可,M2 内低优先)。 - 可选——api CI 增加 M2 迁移的守护:
./mvnw clean test已覆盖 Flyway 迁移执行(Testcontainers 起真库跑迁移),无需新增步骤;只需坚持「已推送迁移不可变」规则。 - 明确不做:flutter
build apk冒烟(耗时大、M2 无发布需求)、覆盖率门槛(先积累基线再谈阈值)。
5. 敏感信息防泄漏(轻量方案规划,待拍板后实施)
现状:三仓 .git/hooks 均只有样例,无任何自动检查;卫生完全靠 git-workflow.md 约定 + 提交前人工核对。api 仓敏感配置已按 *.sample 模式管理(真实 application.yml 在 gitignore 中)。AI 辅助开发下,机械防线值得补上。零外部 action 约束下推荐两层,均为纯 shell + grep,无任何外部依赖:
5.1 第一层:入库的共享 pre-commit 脚本(推荐先做)
- 各仓新增
scripts/hooks/pre-commit(入库,可评审、可演进),检查git diff --cached的暂存内容:- 文件名黑名单:拦截
application.yml(非 .sample)、.env、*.pem、*.p12、*.jks、key.properties等入暂存区; - 内容模式:对暂存 diff 的新增行 grep 常见凭据特征——
BEGIN (RSA |EC )?PRIVATE KEY、password:/secret:后跟非占位值(排除changeme、your-*、<placeholder>等样例值)、长 base64/hex token 形态; - 命中即拒绝提交并打印命中行号(不打印命中内容全文,避免终端留痕)。
- 文件名黑名单:拦截
- 启用方式为一次性
git config core.hooksPath scripts/hooks(每仓每机各执行一次,写入各仓 README)。hook 可被--no-verify绕过——这是特性不是缺陷:误报时有出口,且第二层兜底。
5.2 第二层:CI 侧兜底 grep(各仓 ci.yml 加一个 step)
- checkout 后加一个纯 shell step,对整棵工作树跑同一套文件名/内容模式检查(复用 5.1 的脚本,保证两层规则同源),命中则 fail。零外部 action,新增耗时秒级。
- 与 pre-commit 的分工:hook 拦「即将提交的」,CI 拦「已经提交的」(含
--no-verify绕过和历史遗漏的新暴露)。CI 只查工作树而不扫全历史——扫历史属一次性审计,若做一次即可,不进流水线。
5.3 不推荐
- gitleaks/trufflehog 等外部工具:与零外部依赖约束冲突(需拉二进制或镜像),且对本项目的敏感面(一个 application.yml + 未来的第三方 key)而言是牛刀。
- 提交后自动改写历史清除泄漏:一旦真泄漏,正确动作是立即轮换凭据,再考虑历史清理——写入规范备忘即可。
6. 待拍板事项汇总
| # | 事项 | 推荐 | 见 |
|---|---|---|---|
| 1 | M2 分支策略:trunk-based 为主 + 高风险改动(Flyway 迁移/契约破坏性变更/依赖升级/并行期)强制短命分支 + PR | 采纳 | 2.2 |
| 2 | Gitea dev/main 分支保护 + 状态检查强制 | 可选,倾向开启 | 2.2 |
| 3 | 提交信息格式沿用现行中文约定,不切换英文 conventional commits | 沿用 | 3.2 |
| 4 | 契约先行三仓提交顺序:doc → api → flutter,契约提交独立成提交并被下游引用 | 采纳 | 3.3 |
| 5 | 防泄漏两层方案(共享 pre-commit 脚本 + CI 兜底 grep) | 采纳,M2 第一波实施 | 5 |
| 6 | patbond-api 本地孤儿 master 分支清理 |
顺手做 | 1 |
采纳后需要落实的文件改动(本报告未执行):各仓 scripts/hooks/pre-commit 与 ci.yml 的兜底 step、git-workflow.md 增补 2.2/3.1/3.3 条款、本报告挂入 mkdocs 导航。