Files
Edu/docs/standards/git-workflow.md
SpecialX 2ba4250165
Some checks failed
CI Go / test (push) Has been cancelled
CI Proto / lint (push) Has been cancelled
CI Python / test (push) Has been cancelled
CI TypeScript / test (push) Has been cancelled
feat(p1): complete P1 foundation stage
- monorepo: pnpm workspace + go.work + pyproject.toml + commitlint/husky
- infra: docker-compose (minimal + full profiles) + init-sql + prometheus
- arch-scan: multi-language scanner skeleton (TS/Go/Python/Proto)
- shared-proto: buf v2 + classes.proto (ClassService CRUD contract)
- api-gateway: Go/Gin + JWT HS256 auth + reverse proxy + request ID
- classes: NestJS golden template (error system + observability + middleware + CRUD + tests)
- teacher-portal: Next.js + paper-feel UI design system
- CI/CD: 4 workflows (go/ts/py/proto)
- docs: migration guide + project_rules + coding-standards + git-workflow + ui-design-system + 004 + 9 module READMEs + known-issues + spec/plan migration + roadmap
2026-07-07 23:39:37 +08:00

24 KiB
Raw Blame History

Edu Git 工作流规范

版本1.0 日期2026-07-07 状态:基线发布 适用范围Edu 多语言 monorepopnpm workspace + go.work + pyproject.toml 关联文档:


目录

  1. 分支策略
  2. Conventional Commits 规范
  3. commitlint + husky 配置
  4. PR 与 Code Review
  5. 文档同步规则
  6. 多语言 monorepo 提交规则
  7. 版本与发布
  8. 紧急回滚
  9. 附录CICD 与 Edu Git 工作流差异

一、分支策略

1.1 主干开发Trunk-Based Development

本项目采用主干开发模式,所有变更最终合并至 main 分支。

核心原则

  • main 分支始终保持可发布状态
  • 短生命周期特性分支(通常 ≤ 3 天)
  • 频繁集成,每天至少一次 rebase/merge 至最新 main
  • 通过特性开关Feature Flag控制未完成功能的暴露

1.2 分支模型

gitGraph
    commit id: "init"
    commit id: "P1-foundation"
    branch feat/identity-service
    checkout feat/identity-service
    commit id: "scaffold"
    commit id: "implement-login"
    commit id: "add-tests"
    checkout main
    merge feat/identity-service tag: "v0.2.0"
    branch fix/jwt-expiry
    checkout fix/jwt-expiry
    commit id: "fix-token-refresh"
    checkout main
    merge fix/jwt-expiry tag: "v0.2.1"
    branch release/v0.3
    checkout release/v0.3
    commit id: "freeze"
    commit id: "hotfix"
    checkout main
    merge release/v0.3 tag: "v0.3.0"

1.3 分支命名规范

分支类型 前缀 示例 生命周期
主干 main main 永久
特性 feat/ feat/identity-service ≤ 3 天
修复 fix/ fix/jwt-expiry ≤ 1 天
重构 refactor/ refactor/split-data-access ≤ 5 天
性能 perf/ perf/query-optimization ≤ 3 天
文档 docs/ docs/api-specification ≤ 2 天
发布 release/v release/v0.3.0 发布周期内
热修复 hotfix/ hotfix/v0.3.1 ≤ 1 天

规则

  • 分支名使用 kebab-case
  • 一个分支只做一件事,禁止在一个分支内混合多个无关变更
  • 特性分支命名包含服务/模块名(feat/identity-service 而非 feat/login

1.4 分支保护规则

main 分支保护

  • 禁止直接 push必须通过 PR
  • 至少 1 名 Reviewer 审批通过(核心模块需 2 名)
  • 所有 CI 检查通过lint + typecheck + test + build
  • 分支必须与 main 保持最新(无冲突或已 rebase
  • 禁止 force push

release/* 分支保护

  • 禁止直接 push仅接受 cherry-pick 或特定 hotfix PR
  • 至少 2 名 Reviewer 审批
  • 发布完成后打 tag 并归档

二、Conventional Commits 规范

2.1 提交信息格式

所有提交信息必须遵循 Conventional Commits 1.0.0

<type>(<scope>): <subject>

<body>

<footer>

2.2 类型type

类型 含义 是否触发发布
feat 新功能 MINOR
fix Bug 修复 PATCH
perf 性能优化 PATCH
refactor 重构(不改变行为)
style 代码风格(格式化、空白)
test 新增/修改测试
docs 文档变更
build 构建系统或依赖变更
ci CI 配置变更
chore 杂项(不修改 src 或 test
revert 回滚某次提交

2.3 范围scope

scope 必须是服务名或包名,详见 §3.3 scope-enum

示例

  • feat(identity): 实现用户注册接口
  • fix(gateway): 修复路由匹配优先级
  • perf(teaching): 优化课表查询 N+1 问题
  • docs(contracts): 补充 identity.proto 字段说明

2.4 主题subject

规则

  • 使用中文简短描述
  • 不超过 50 个字符
  • 不以句号结尾
  • 使用祈使句("实现用户注册"而非"实现了用户注册"
  • 不包含 type/scope已在前面体现

2.5 正文body

规则

  • 解释"为什么"而非"做了什么"(代码已说明做了什么)
  • 每行不超过 72 个字符
  • 使用无序列表列出关键变更点
  • 涉及 breaking change 必须在正文开头说明

示例

feat(teaching): 作业提交支持附件上传

- 新增 Attachment 聚合根,支持多文件关联
- Outbox 事件 HomeworkSubmitted 新增 attachments 字段
- BFF 接口新增 multipart/form-data 支持

BREAKING CHANGE: HomeworkSubmitted 事件 schema 变更,
消费方需升级 proto 至 v2 才能消费新事件

2.6 脚注footer

用于关联 Issue、PR、Jira 卡片:

fix(content): 修复题库导入时重复题目标题去重逻辑

Closes #123
Refs EDU-456
Reviewed-by: @reviewer-name

三、commitlint + husky 配置

3.1 安装与初始化

# 在 monorepo 根目录
pnpm add -Dw @commitlint/cli @commitlint/config-conventional husky lint-staged

# 初始化 husky
pnpm exec husky init

3.2 commitlint 配置

创建 commitlint.config.cjs

/** @type {import('@commitlint/types').UserConfig} */
module.exports = {
  extends: ["@commitlint/config-conventional"],
  rules: {
    // type 枚举
    "type-enum": [
      2,
      "always",
      [
        "feat",
        "fix",
        "perf",
        "refactor",
        "style",
        "test",
        "docs",
        "build",
        "ci",
        "chore",
        "revert",
      ],
    ],
    // type 小写
    "type-case": [2, "always", "lower-case"],
    // type 不能为空
    "type-empty": [2, "never"],
    // scope 枚举(见 3.3
    "scope-enum": [
      2,
      "always",
      [
        // 业务微服务
        "identity",
        "org",
        "teaching",
        "content",
        "comm",
        "insight",
        // 基础设施服务
        "auth",
        "notification",
        // AI 服务
        "insight-ai",
        // 网关
        "gateway",
        // BFF
        "admin-bff",
        "teacher-bff",
        "student-bff",
        // 微前端
        "admin-shell",
        "teacher-shell",
        "student-shell",
        "parent-shell",
        // 共享包
        "contracts",
        "ui-tokens",
        "ui-components",
        "shared-ts",
        // protobuf 契约
        "proto",
        // 平台级
        "deps",
        "docs",
        "ci",
        "chore",
        "release",
      ],
    ],
    // scope 小写
    "scope-case": [2, "always", "lower-case"],
    // subject 不能为空
    "subject-empty": [2, "never"],
    // subject 不超过 50 字符
    "subject-max-length": [2, "always", 72],
    // subject 不以句号结尾
    "subject-full-stop": [2, "never", "."],
    // body 每行不超过 100 字符
    "body-max-line-length": [1, "always", 100],
    // footer 每行不超过 100 字符
    "footer-max-line-length": [1, "always", 100],
    // header 不超过 100 字符
    "header-max-length": [2, "always", 100],
  },
};

3.3 scope-enum 完整清单

分类 scope 说明
业务微服务 identity 身份与权限服务
业务微服务 org 教学组织服务
业务微服务 teaching 教学核心服务
业务微服务 content 内容分析服务
业务微服务 comm 沟通服务
业务微服务 insight 智能洞察服务
基础设施 auth 认证授权服务
基础设施 notification 通知服务
AI 服务 insight-ai AI 分析服务Python
网关 gateway API 网关Go
BFF admin-bff 管理端 BFF
BFF teacher-bff 教师端 BFF
BFF student-bff 学生/家长端 BFF
微前端 admin-shell 管理端 Shell
微前端 teacher-shell 教师端 Shell
微前端 student-shell 学生端 Shell
微前端 parent-shell 家长端 Shell
共享包 contracts protobuf 生成契约包
共享包 ui-tokens 设计令牌包
共享包 ui-components UI 组件库
共享包 shared-ts TS 共享工具包
契约 proto protobuf 定义文件
平台级 deps 依赖升级
平台级 docs 平台级文档
平台级 ci CI/CD 配置
平台级 chore 杂项
平台级 release 发布相关

3.4 husky hooks

.husky/commit-msg

#!/usr/bin/env sh
pnpm exec commitlint --edit "$1"

.husky/pre-commit

#!/usr/bin/env sh
pnpm exec lint-staged

.husky/pre-push

#!/usr/bin/env sh
# 推送前运行类型检查
pnpm -r run typecheck

3.5 lint-staged 配置

package.json(根目录):

{
  "lint-staged": {
    // TypeScript / NestJS / Next.js
    "*.{ts,tsx}": [
      "eslint --fix",
      "prettier --write"
    ],
    // Go
    "*.go": [
      "gofmt -w",
      "golangci-lint run --fix"
    ],
    // Python
    "*.py": [
      "ruff check --fix",
      "ruff format"
    ],
    // protobuf
    "*.proto": [
      "buf format --write"
    ],
    // Markdown
    "*.md": [
      "prettier --write"
    ],
    // JSON / YAML
    "*.{json,yaml,yml}": [
      "prettier --write"
    ]
  }
}

四、PR 与 Code Review

4.1 PR 流程

flowchart TD
    A[开发者创建特性分支] --> B[提交代码]
    B --> C[本地通过 lint + typecheck + test]
    C --> D[rebase 至最新 main]
    D --> E[推送至远程]
    E --> F[创建 PR]
    F --> G[CI 自动检查]
    G --> H{CI 通过?}
    H -->|否| I[修复问题]
    I --> B
    H -->|是| J[Reviewer 审查]
    J --> K{审查通过?}
    K -->|需修改| L[根据反馈修改]
    L --> B
    K -->|通过| M[Squash Merge]
    M --> N[删除特性分支]
    N --> O[CI 部署至 staging]

4.2 PR 标题

PR 标题必须符合 Conventional Commits 规范(与最终 squash merge 的 commit message 一致):

feat(identity): 实现用户注册接口

4.3 PR 模板

.github/pull_request_template.md(或 Gitea 等价路径):

## 变更说明

<!-- 简述本次变更的目的和实现方式 -->

## 变更类型

- [ ] feat: 新功能
- [ ] fix: Bug 修复
- [ ] perf: 性能优化
- [ ] refactor: 重构
- [ ] test: 测试
- [ ] docs: 文档
- [ ] build/ci: 构建/CI

## 影响范围

<!-- 列出受影响的服务/包 -->
- 服务:
- 包:
- 数据库迁移:是 / 否
- protobuf 契约变更:是 / 否
- Kafka topic 变更:是 / 否

## 测试情况

- [ ] 单元测试通过
- [ ] 集成测试通过
- [ ] 本地手动测试通过
- [ ] 新增测试覆盖新功能

## 文档同步

- [ ] 已更新服务 README如涉及服务结构变更
- [ ] 已更新架构文档(如涉及架构变更)
- [ ] 已运行 `pnpm run arch:scan` 更新 arch.db
- [ ] 已更新 known-issues.md如遇到新问题

## Breaking Change

- [ ]- [ ] 是(请在下方说明影响和迁移路径)

## 关联 Issue

Closes #

4.4 Reviewer 要求

变更类型 最少 Reviewer 备注
普通业务变更 1 默认
跨服务变更 2 涉及 ≥ 2 个服务
protobuf 契约变更 2 需包含架构组成员
数据库 schema 变更 2 需包含 DBA 或架构组
安全相关变更 2 需包含安全负责人
核心模块auth/identity 2 核心模块强制 2 人

4.5 Code Review 清单

通用检查

  • 代码是否符合 编码规范
  • 是否有明显的逻辑错误
  • 错误处理是否完整(不忽略 error/err/exception
  • 日志是否包含足够的上下文request_id、user_id 等)
  • 是否存在硬编码的密钥、token、连接字符串

架构检查

  • 是否违反限界上下文边界(跨服务直接查 DB
  • 是否违反依赖方向shared 反向依赖 services
  • protobuf 变更是否向后兼容
  • 事件 schema 变更是否向后兼容

性能检查

  • 是否有 N+1 查询
  • 是否有未加索引的查询
  • 是否有不必要的大对象拷贝
  • 是否有阻塞事件循环的同步操作Python/Node

安全检查

  • 所有入口是否经过权限校验
  • 用户输入是否经过验证
  • SQL 是否使用参数化查询
  • 是否有 SQL 注入、XSS、SSRF 风险

4.6 合并策略

默认使用 Squash Merge

  • 保留 PR 的完整变更作为一个 commit
  • commit message 使用 PR 标题
  • 删除特性分支

禁止使用 Merge Commit(除非是发布分支合并回 main

  • 避免历史中充斥 "Merge branch" 噪音
  • 保持线性历史

Rebase Merge

  • 仅用于需要保留多个有意义 commit 的特性分支
  • 需在 PR 中说明原因

五、文档同步规则

5.1 文档同步矩阵

代码变更类型 需同步的文档 同步时机
新增/删除服务 001_architecture_overview.md + 服务 README PR 内同步
新增/删除模块 服务 README + arch:scan PR 内同步
新增/删除导出函数 pnpm run arch:scan 提交前
修改函数签名 pnpm run arch:scan 提交前
修改权限点 project_rules.md + 权限文档 PR 内同步
新增/删除数据库表 架构文档 + 服务 README PR 内同步
新增/删除路由 服务 README + OpenAPI PR 内同步
修改模块间依赖 arch:scan + 架构文档 PR 内同步
新增 protobuf message proto/ README + arch:scan PR 内同步
新增 Kafka topic 架构文档 + 服务 README PR 内同步
遇到新问题/经验 known-issues.md PR 内同步

5.2 arch.db 同步规则

强制规则:任何代码变更提交前必须运行 pnpm run arch:scan 更新 arch.db。

# 提交前流程
pnpm run arch:scan          # 更新 arch.db
pnpm run arch:query -- violations  # 检查是否有违规
git add arch.db              # 将 arch.db 纳入提交
git commit -m "feat(identity): 实现用户注册接口"

违规检查

  • 长文件(> 1000 行)
  • 未校验权限的 Handler
  • 循环依赖
  • 跨限界上下文直接 DB 访问

5.3 服务 README 要求

每个服务必须包含 README.md,结构如下:

# [服务名] 服务

> 版本1.0
> 限界上下文:[上下文名]
> 技术栈:[语言 + 框架]

## 职责
[一段话描述]

## 架构
[mermaid 架构图]

## 核心流程
[mermaid 时序图]

## 目录结构
[树形结构 + 说明]

## 依赖
- 上游服务:[列表]
- 下游服务:[列表]
- 共享包:[列表]

## 约束
[业务规则、技术约束]

## 架构决策
[关键设计决策记录]

5.4 known-issues.md 格式

docs/troubleshooting/known-issues.md 采用索引式速查手册格式:

### X.X 主题分区

| 场景 | 技术/规则 |
|------|----------|
| 简述场景 | 正确做法(一句话) |

规则

  • 索引式:场景→技术/规则映射
  • 不写代码示例和错误示范
  • 同类问题在原条目补充,不重复创建
  • 在"工作经验日志"区按时间倒序追加记录

六、多语言 monorepo 提交规则

6.1 单服务单提交原则

规则:一个 commit 只涉及一个服务或一个包的变更。

原因

  • 便于回滚(按服务粒度回滚)
  • 便于追踪changelog 清晰)
  • 便于 review聚焦单一职责

例外:跨服务重构或契约变更可在同一 commit 中涉及多个服务,但需在 body 中说明。

6.2 生成代码单独提交

规则protobuf 生成的代码必须与手写代码分开提交。

# 正确流程
# 1. 修改 proto 定义
git commit -m "feat(proto): 新增 UserRegistered 事件 schema"

# 2. 生成代码
pnpm run proto:generate

# 3. 单独提交生成代码
git commit -m "build(contracts): 重新生成 proto 代码"

6.3 跨语言变更拆分

当一个功能涉及多个语言(如 TS 服务 + Go 网关 + Python AI按以下顺序拆分提交

  1. 契约先行feat(proto): ...
  2. 生成代码build(contracts): ...
  3. 后端服务feat(teaching): ...
  4. 网关层feat(gateway): ...
  5. 前端feat(teacher-shell): ...

6.4 依赖升级规则

规则

  • 依赖升级使用 build(deps): 类型
  • 必须说明升级原因(安全、功能、兼容性)
  • 安全漏洞修复必须包含 CVE 编号
  • 大版本升级需单独 PR 并完整测试

示例

build(deps): 升级 nestjs 至 10.3.0

- 修复 CVE-2024-1234 漏洞
- 升级至最新 patch 版本
- 全部测试通过

6.5 跨服务依赖更新

当一个服务的 protobuf 变更影响其他服务:

# 1. 提交 proto 变更
git commit -m "feat(proto): UserRegistered 事件新增 attachments 字段"

# 2. 生成新契约
pnpm run proto:generate
git commit -m "build(contracts): 生成 UserRegistered v2"

# 3. 更新消费方服务
git commit -m "feat(notification): 适配 UserRegistered v2 事件"

七、版本与发布

7.1 版本号体系

本项目采用双层版本号

层级 格式 说明
平台版本 v{阶段}.{迭代}.{patch} v0.3.1P3 阶段第 1 次迭代 patch 1
服务版本 {service}:{semver} identity:1.2.0

7.2 阶段版本范围

阶段 平台版本范围 说明
P1 地基 v0.1.x monorepo 初始化、CI/CD、arch.db
P2 身份 v0.2.x identity + auth + notification
P3 核心教学 v0.3.x org + teaching + content
P4 内容分析 v0.4.x insight + CQRS 读模型
P5 沟通AI v0.5.x comm + AI 增强
P6 硬化 v1.0.x 正式发布版

7.3 Docker 镜像标签

格式{registry}/edu/{service}:{tag}

tag 类型 格式 示例 用途
版本号 v{version} v0.3.1 正式发布
服务版本 {service}-{semver} identity-1.2.0 服务独立版本
Git SHA sha-{short} sha-a1b2c3d 精确追溯
最新 latest latest 开发环境
阶段 {stage}-{sha} staging-a1b2c3d 阶段环境

7.4 发布流程

flowchart TD
    A[main 分支达到发布标准] --> B[创建 release/v0.3.x 分支]
    B --> C[运行完整测试套件]
    C --> D{测试通过?}
    D -->|否| E[修复问题]
    E --> C
    D -->|是| F[更新 CHANGELOG.md]
    F --> G[打 tag v0.3.0]
    G --> H[CI 自动构建镜像]
    H --> I[部署至 staging]
    I --> J[冒烟测试]
    J --> K{冒烟通过?}
    K -->|否| L[修复并重新发布]
    L --> C
    K -->|是| M[审批发布至 production]
    M --> N[monitoring 观察指标]
    N --> O{指标正常?}
    O -->|否| P[紧急回滚]
    O -->|是| Q[发布完成]
    Q --> R[合并 release 分支回 main]

7.5 CHANGELOG 格式

CHANGELOG.mdKeep a Changelog 格式维护:

## [v0.3.0] - 2026-08-15

### Added
- 教学核心服务新增作业管理功能
- 内容服务支持题库导入
- 教师端 Shell 新增作业批改界面

### Changed
- identity 服务升级至 NestJS 10.3
- gateway 路由匹配算法优化

### Fixed
- 修复 JWT 刷新 token 过期判断错误
- 修复课表查询时区问题

### Breaking Changes
- UserRegistered 事件 schema 变更至 v2消费方需升级

7.6 服务独立版本

每个服务维护独立的 VERSION 文件,内容为 semver

# services/identity/VERSION
1.2.0

版本号升级规则

  • MAJORBreaking Changeprotobuf 不兼容变更、API 破坏性修改)
  • MINOR:新增功能,向后兼容
  • PATCHBug 修复,向后兼容

八、紧急回滚

8.1 回滚策略

场景 回滚方式 耗时
代码缺陷 git revert + 重新部署 5-10 分钟
镜像问题 kubectl rollout undo 1-2 分钟
数据库迁移问题 执行迁移 down 脚本 5-30 分钟
配置错误 回滚 ConfigMap/Secret 1-2 分钟
全站故障 回滚至上一稳定 tag 10-30 分钟

8.2 代码回滚

# 1. 确认要回滚的 commit
git log --oneline -10

# 2. 创建回滚分支
git checkout -b hotfix/v0.3.1

# 3. 回滚指定 commit
git revert <commit-sha>

# 4. 推送并创建 PR
git push origin hotfix/v0.3.1

# 5. 紧急审批合并后部署

8.3 K8s 部署回滚

# 查看部署历史
kubectl rollout history deployment/identity -n edu-prod

# 回滚至上一版本
kubectl rollout undo deployment/identity -n edu-prod

# 回滚至指定版本
kubectl rollout undo deployment/identity -n edu-prod --to-revision=3

# 监控回滚状态
kubectl rollout status deployment/identity -n edu-prod

8.4 数据库迁移回滚

规则

  • 所有迁移必须提供 updown 脚本
  • down 脚本必须在 CI 中测试
  • 回滚前必须备份生产数据
# 回滚最近一次迁移
pnpm --filter identity run migrate:down

# 回滚至指定版本
pnpm --filter identity run migrate:down -- --to <version>

8.5 回滚原则

  1. 优先保证可用性:回滚决策应在 5 分钟内做出,无需 root cause
  2. 保留现场回滚前保存日志、metrics、错误堆栈
  3. 通知相关方:回滚后立即通知运维、产品、相关开发
  4. 复盘改进:回滚后 24 小时内完成事故复盘,记录至 docs/troubleshooting/incidents/

8.6 回滚记录格式

docs/troubleshooting/incidents/YYYY-MM-DD-incident.md

# 事故记录:[简述]

> 日期YYYY-MM-DD
> 影响范围:[服务/用户]
> 持续时间:[开始-结束]
> 严重等级P0/P1/P2/P3

## 时间线
- HH:MM 告警触发
- HH:MM 确认问题
- HH:MM 决定回滚
- HH:MM 回滚完成
- HH:MM 服务恢复

## 影响分析
[受影响的功能、用户数、业务损失]

## 根本原因
[技术原因 + 流程原因]

## 回滚过程
[执行的操作]

## 改进措施
- [ ] 短期:[立即修复项]
- [ ] 中期:[流程改进项]
- [ ] 长期:[架构改进项]

九、附录CICD 与 Edu Git 工作流差异

维度 CICDNext.js 单应用) Edu微服务 monorepo
仓库结构 单一 Next.js 应用 多语言 monorepopnpm + go.work + uv
分支策略 trunk-based trunk-based沿用
提交规范 Conventional Commits Conventional Commits沿用scope 扩展至服务/包)
scope 范围 模块名(如 examshomework 服务/包名(如 identitycontracts
commitlint scope-enum 35 个模块 27 个服务/包
PR Reviewer 1 人 1-2 人(核心模块/跨服务 2 人)
合并策略 Squash Merge Squash Merge沿用
版本号 单一应用版本 双层(平台版本 + 服务独立版本)
发布粒度 整体发布 按服务独立发布
Docker 镜像 单一镜像 每服务一镜像
回滚粒度 整体回滚 按服务回滚
数据库迁移 Drizzle 单库 每服务独立库 + 独立迁移
文档同步 npm run arch:scan pnpm run arch:scan(多语言扫描)
CI 检查 lint + tsc + test lint + typecheck + test按语言分别执行
紧急回滚 git revert + 重新部署 git revert + kubectl rollout undo
事故复盘 known-issues.md incidents/ 目录独立记录

变更记录

版本 日期 变更内容
1.0 2026-07-07 基线发布,从 CICD 单应用规范迁移至微服务多语言 monorepo