Files
goauto/server/cmd/migrate/migration/init.go
T
QiuSWandClaude Opus 5 bbc5fdba05 fix(#48): replace per-migration noise with a summary, force UTF-8 console
The startup output was dominated by two upstream behaviours. Migrate
printed a bare count for every already-applied migration — a lone "1"
with no version, no explanation — through the standard logger, hence
stderr, which the launcher's `2>&1 |` renders as a red PowerShell error
block that looks like a failed migration. And the version-existence check
echoed one SELECT count(*) per version. Both replaced: a Warn-level
session for the check, and one summary line on stdout.

Console encoding needed more than [Console]::OutputEncoding: PowerShell
5.1 decodes child-process output by the console code page, so chcp 65001
goes with it.

The regression test capture was wrong twice and mutation testing caught
both. It captured only stdout while the bug wrote to stderr, and it
compared lines to "1" when the logger prefixes a timestamp, so the
assertion could never fail. It now captures the standard logger too and
matches with a pattern that allows the prefix — verified by reinstating
the bug and watching the test fail.

Not verified: the PowerShell edits, which need a Windows run.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-20 09:53:56 +08:00

80 lines
2.0 KiB
Go

package migration
import (
"fmt"
"log"
"path/filepath"
"sort"
"sync"
"gorm.io/gorm"
"gorm.io/gorm/logger"
)
var Migrate = &Migration{
version: make(map[string]func(db *gorm.DB, version string) error),
}
type Migration struct {
db *gorm.DB
version map[string]func(db *gorm.DB, version string) error
mutex sync.Mutex
}
func (e *Migration) GetDb() *gorm.DB {
return e.db
}
func (e *Migration) SetDb(db *gorm.DB) {
e.db = db
}
func (e *Migration) SetVersion(k string, f func(db *gorm.DB, version string) error) {
e.mutex.Lock()
defer e.mutex.Unlock()
e.version[k] = f
}
func (e *Migration) Migrate() {
versions := make([]string, 0)
for k := range e.version {
versions = append(versions, k)
}
if !sort.StringsAreSorted(versions) {
sort.Strings(versions)
}
var err error
var count int64
// GoAuto 改动(#48):版本存在性检查用 Warn 级会话,不回显 SQL。
// 上游每个版本都会打一条 SELECT count(*),几十个迁移就是几十行——真正
// 值得看的是下面 e.db.Debug() 执行的那些「确实要跑」的迁移。
checkDB := e.db.Session(&gorm.Session{Logger: e.db.Logger.LogMode(logger.Warn)})
applied, skipped := 0, 0
for _, v := range versions {
err = checkDB.Table("sys_migration").Where("version = ?", v).Count(&count).Error
if err != nil {
log.Fatalln(err)
}
if count > 0 {
// GoAuto 改动(#48):上游这里是 log.Println(count),每个已应用的
// 迁移打印一个裸 "1"——没有说明是什么、也没说是哪个版本。而且 log
// 写的是 stderr,启动脚本的 `2>&1 |` 会把它变成一整块红色错误,
// 看起来像迁移失败了。汇总成一行,走 stdout。
skipped++
count = 0
continue
}
err = (e.version[v])(e.db.Debug(), v)
if err != nil {
log.Fatalln(err)
}
applied++
}
fmt.Printf("迁移完成:新执行 %d 个,跳过 %d 个(已应用)\n", applied, skipped)
}
func GetFilename(s string) string {
s = filepath.Base(s)
return s[:13]
}