douyin-release-gate / verify (push) Failing after 3m10s
- 迁移 037(幂等):补删 browser_env.image_version、audit_event 镜像列、browser_image 表
- 恢复 034 为引入时原版(撤销 6cd4cdc 的原地修改)
- 新增 migrations immutable 单测:迁移文件引入后不得改内容,要改就新增版本号
- web: 指纹种子字段中文化 + 指纹参数 400 错误映射为具体中文提示
70 lines
2.4 KiB
Go
70 lines
2.4 KiB
Go
package environment
|
||
|
||
import (
|
||
"os"
|
||
"os/exec"
|
||
"path/filepath"
|
||
"strings"
|
||
"testing"
|
||
)
|
||
|
||
// 迁移文件一旦按版本号记录进 schema_migration 就不会再执行。
|
||
// 内容修正是用版本号不变的方式提交的话,已 applied 的库永远拿不到修正,
|
||
// 造成不同库 schema 漂移(034 曾因此漏删 browser_env.image_version,
|
||
// 触发 "environment persistence operation failed")。
|
||
// 本测试锁死规则:迁移文件内容自引入起不可变更;要改就新增版本号。
|
||
func TestMigrationFilesAreImmutableAfterIntroduction(t *testing.T) {
|
||
// 迁移文件相对本包的路径 → 仓库根相对路径(git show 需要仓库根路径)。
|
||
repoPath := map[string]string{
|
||
"migrations/*.sql": "internal/environment",
|
||
"../creator/migrations/*.sql": "internal/creator",
|
||
"../account/migrations/*.sql": "internal/account",
|
||
}
|
||
for pattern, repoDir := range repoPath {
|
||
entries, err := filepath.Glob(pattern)
|
||
if err != nil {
|
||
t.Fatalf("list migrations for %s: %v", pattern, err)
|
||
}
|
||
for _, file := range entries {
|
||
// repoDir 已是仓库根相对包目录,glob 出的文件按 basename 拼回。<pkg>/migrations/<name>.sql
|
||
file, repoFile := file, repoDir+"/migrations/"+filepath.Base(file)
|
||
t.Run(file, func(t *testing.T) {
|
||
introduced := gitOutput(t, "log", "--format=%H", "--diff-filter=A", "--", repoFile)
|
||
if introduced == "" {
|
||
t.Skipf("no introducing commit found for %s", repoFile)
|
||
}
|
||
firstCommit := strings.SplitN(introduced, "\n", 2)[0]
|
||
original := gitOutput(t, "show", firstCommit+":"+repoFile)
|
||
current, err := os.ReadFile(file)
|
||
if err != nil {
|
||
t.Fatalf("read %s: %v", file, err)
|
||
}
|
||
if original != string(current) {
|
||
t.Errorf("migration %s was modified after introduction in %s; migrations are immutable — add a new versioned migration instead", repoFile, firstCommit)
|
||
}
|
||
})
|
||
}
|
||
}
|
||
}
|
||
|
||
func gitOutput(t *testing.T, args ...string) string {
|
||
t.Helper()
|
||
cmd := exec.Command("git", args...)
|
||
cmd.Dir = repoRoot(t)
|
||
out, err := cmd.Output()
|
||
if err != nil {
|
||
t.Skipf("git %s unavailable: %v", args[0], err)
|
||
}
|
||
return string(out)
|
||
}
|
||
|
||
// repoRoot 定位 git 仓库根,保证 glob 出的包相对路径都能转成仓库根相对路径。
|
||
func repoRoot(t *testing.T) string {
|
||
t.Helper()
|
||
out, err := exec.Command("git", "rev-parse", "--show-toplevel").Output()
|
||
if err != nil {
|
||
t.Skipf("git repository unavailable: %v", err)
|
||
}
|
||
return strings.TrimSpace(string(out))
|
||
}
|