test: enforce chinese schema comments
This commit is contained in:
@@ -11,7 +11,7 @@
|
|||||||
- `internal/storage/mysql/`:连接、事务与显式迁移,不向 SDK 暴露。
|
- `internal/storage/mysql/`:连接、事务与显式迁移,不向 SDK 暴露。
|
||||||
- `sdk/go/`:独立 Go module;对外 DTO 与服务端模型分别维护。
|
- `sdk/go/`:独立 Go module;对外 DTO 与服务端模型分别维护。
|
||||||
|
|
||||||
模型使用普通 Go struct 与 `db` 标签,模型与持久化字段提供中文注释,SQL 表和字段同步维护中文 COMMENT。SQL 是可审查的版本化迁移。目前未引入 ORM,也没有自动同步表结构。
|
模型使用普通 Go struct 与 `db` 标签,模型与持久化字段提供中文注释,SQL 表和字段同步维护中文 COMMENT。`TestFreshInstallBaselineHasChineseModelComments` 会在测试门禁中逐表、逐字段检查当前基线,防止新增持久化字段漏写说明。SQL 是可审查的版本化迁移。目前未引入 ORM,也没有自动同步表结构。
|
||||||
|
|
||||||
## 2. 存储约定
|
## 2. 存储约定
|
||||||
|
|
||||||
|
|||||||
@@ -9,6 +9,7 @@
|
|||||||
| 本地发布门禁统一入口 | 2026-09-20;`make release-local-check` | PASS;服务端、SDK、独立示例竞态测试、vet、build、当前协议门禁、146个 Markdown 本地链接和 SDK 独立依赖检查均通过;命令明确不替代真实 MySQL 集成与目标生产验收 |
|
| 本地发布门禁统一入口 | 2026-09-20;`make release-local-check` | PASS;服务端、SDK、独立示例竞态测试、vet、build、当前协议门禁、146个 Markdown 本地链接和 SDK 独立依赖检查均通过;命令明确不替代真实 MySQL 集成与目标生产验收 |
|
||||||
| 就绪探针排空门控 | `go test -race ./internal/transport/httpserver ./cmd/orbit`;`TestReadinessEntersDrainBeforeShutdown` | PASS;SIGTERM 关闭路径先将 `/health/ready` 置为 503,再进入限定优雅关闭窗口;响应不泄露内部错误 |
|
| 就绪探针排空门控 | `go test -race ./internal/transport/httpserver ./cmd/orbit`;`TestReadinessEntersDrainBeforeShutdown` | PASS;SIGTERM 关闭路径先将 `/health/ready` 置为 503,再进入限定优雅关闭窗口;响应不泄露内部错误 |
|
||||||
| 健康探针响应契约 | 2026-09-20;`go test ./internal/transport/httpserver && go test -race ./internal/transport/httpserver && make docs-check` | PASS;`/health/live` 与 `/health/ready` 返回 `Cache-Control: no-store`、`X-Content-Type-Options: nosniff`;未就绪和排空状态返回 `Retry-After: 1`,并由 HTTP 契约测试覆盖 |
|
| 健康探针响应契约 | 2026-09-20;`go test ./internal/transport/httpserver && go test -race ./internal/transport/httpserver && make docs-check` | PASS;`/health/live` 与 `/health/ready` 返回 `Cache-Control: no-store`、`X-Content-Type-Options: nosniff`;未就绪和排空状态返回 `Retry-After: 1`,并由 HTTP 契约测试覆盖 |
|
||||||
|
| 数据模型中文注释门禁 | 2026-09-20;`go test ./internal/storage/mysql -run 'Test(FreshInstallBaselineHasChineseModelComments|FreshInstallBaselineContainsNoReferenceDDL|MigrationsAfterForeignKeyRemovalDoNotReintroduceReferences|PostRemovalMigrationGuard)$'` | PASS;当前无外键基线逐表、逐持久化字段检查中文 `COMMENT`,并继续阻止后续迁移重新引入引用约束 |
|
||||||
| 服务端单元与竞态、vet、构建 | Docker `golang:1.27.1`,仓库声明版本;`GOWORK=off go test -race ./... && go vet ./... && go build ./...` | PASS |
|
| 服务端单元与竞态、vet、构建 | Docker `golang:1.27.1`,仓库声明版本;`GOWORK=off go test -race ./... && go vet ./... && go build ./...` | PASS |
|
||||||
| 后台运行参数边界 | `internal/config.TestRuntimeDefaultsAndBoundedOverrides`;默认值与五个 `ORBIT_*` 覆盖项 | PASS;循环间隔限定100ms–1m,批量限定1–100,排空超时限定1s–5m,服务启动日志记录生效值 |
|
| 后台运行参数边界 | `internal/config.TestRuntimeDefaultsAndBoundedOverrides`;默认值与五个 `ORBIT_*` 覆盖项 | PASS;循环间隔限定100ms–1m,批量限定1–100,排空超时限定1s–5m,服务启动日志记录生效值 |
|
||||||
| 生效运行参数指标 | `internal/observability.TestRuntimeObservationDoesNotExposeErrors`;固定指标目录 | PASS;workflow/schedule/execution_recovery 间隔、批量上限和排空超时以固定基数指标导出;排空状态同步为固定 gauge,不进入业务或租户标签 |
|
| 生效运行参数指标 | `internal/observability.TestRuntimeObservationDoesNotExposeErrors`;固定指标目录 | PASS;workflow/schedule/execution_recovery 间隔、批量上限和排空超时以固定基数指标导出;排空状态同步为固定 gauge,不进入业务或租户标签 |
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import (
|
|||||||
"regexp"
|
"regexp"
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
"unicode"
|
||||||
)
|
)
|
||||||
|
|
||||||
// 已应用的历史文件不改写;移除迁移之后的DDL不能再引入数据库引用约束。
|
// 已应用的历史文件不改写;移除迁移之后的DDL不能再引入数据库引用约束。
|
||||||
@@ -52,6 +53,63 @@ func TestFreshInstallBaselineContainsNoReferenceDDL(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 当前基线是持久化模型的可执行说明:表和每个字段都必须保留中文注释,
|
||||||
|
// 防止后续新增模型只写类型、不写职责、单位和可空语义。
|
||||||
|
func TestFreshInstallBaselineHasChineseModelComments(t *testing.T) {
|
||||||
|
inTable := false
|
||||||
|
tableName := ""
|
||||||
|
columns := 0
|
||||||
|
for lineNumber, line := range strings.Split(freshInstallBaseline, "\n") {
|
||||||
|
trimmed := strings.TrimSpace(line)
|
||||||
|
if strings.HasPrefix(trimmed, "CREATE TABLE `") {
|
||||||
|
if inTable {
|
||||||
|
t.Fatalf("line %d starts a table before %s was closed", lineNumber+1, tableName)
|
||||||
|
}
|
||||||
|
start := strings.Index(trimmed, "`") + 1
|
||||||
|
end := strings.Index(trimmed[start:], "`")
|
||||||
|
if start <= 0 || end < 0 {
|
||||||
|
t.Fatalf("line %d has malformed table declaration: %s", lineNumber+1, trimmed)
|
||||||
|
}
|
||||||
|
tableName = trimmed[start : start+end]
|
||||||
|
inTable = true
|
||||||
|
columns = 0
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if !inTable {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if strings.HasPrefix(trimmed, "`") {
|
||||||
|
columns++
|
||||||
|
comment := strings.Index(line, " COMMENT '")
|
||||||
|
if comment < 0 || !hasChineseComment(line[comment:]) {
|
||||||
|
t.Fatalf("table %s column on line %d must have a Chinese COMMENT", tableName, lineNumber+1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if strings.HasPrefix(trimmed, ") ENGINE=") {
|
||||||
|
if columns == 0 {
|
||||||
|
t.Fatalf("table %s has no columns", tableName)
|
||||||
|
}
|
||||||
|
if !strings.Contains(line, " COMMENT='") || !hasChineseComment(line) {
|
||||||
|
t.Fatalf("table %s must have a Chinese table COMMENT", tableName)
|
||||||
|
}
|
||||||
|
inTable = false
|
||||||
|
tableName = ""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if inTable {
|
||||||
|
t.Fatalf("table %s is not closed", tableName)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func hasChineseComment(s string) bool {
|
||||||
|
for _, r := range s {
|
||||||
|
if unicode.Is(unicode.Han, r) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
func TestPostRemovalMigrationGuard(t *testing.T) {
|
func TestPostRemovalMigrationGuard(t *testing.T) {
|
||||||
if err := validateNoReferenceDDL(9, []string{"ALTER TABLE pulse_tasks ADD CONSTRAINT fk FOREIGN KEY (queue_id) REFERENCES pulse_queues(id)"}); err == nil {
|
if err := validateNoReferenceDDL(9, []string{"ALTER TABLE pulse_tasks ADD CONSTRAINT fk FOREIGN KEY (queue_id) REFERENCES pulse_queues(id)"}); err == nil {
|
||||||
t.Fatal("post-removal migration accepted foreign-key DDL")
|
t.Fatal("post-removal migration accepted foreign-key DDL")
|
||||||
|
|||||||
Reference in New Issue
Block a user