Merge pull request 'U10a 首切片:goose 迁移内嵌回退(单文件部署去 cwd 依赖第一步)' (#9) from feature/u10a-embedded-migrations-2026-09-29 into dev
This commit was merged in pull request #9.
This commit is contained in:
@@ -0,0 +1,14 @@
|
||||
// Package dbassets 内嵌数据库迁移链(U10a:单文件应用无源码目录时回退使用)。
|
||||
// 磁盘目录存在时仍优先磁盘(开发态行为不变);磁盘与嵌入的一致性由
|
||||
// 迁移门禁测试(ExpectedMigrationCount)约束。
|
||||
package dbassets
|
||||
|
||||
import "embed"
|
||||
|
||||
// MigrationsFS 内嵌 deploy/postgres/goose 迁移链。
|
||||
//
|
||||
//go:embed all:goose
|
||||
var MigrationsFS embed.FS
|
||||
|
||||
// MigrationsDir 是嵌入 FS 内的迁移子目录名(goose SetBaseFS 的根)。
|
||||
const MigrationsDir = "goose"
|
||||
+16
-3
@@ -9,6 +9,7 @@ import (
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
"chat-agent-system/deploy/postgres"
|
||||
"github.com/jackc/pgx/v5/pgxpool"
|
||||
"github.com/jackc/pgx/v5/stdlib"
|
||||
"github.com/pressly/goose/v3"
|
||||
@@ -25,8 +26,9 @@ func RunMigrations(ctx context.Context, pool *pgxpool.Pool, migrationsDir string
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
useDisk := true
|
||||
if _, err := os.Stat(absDir); err != nil {
|
||||
return fmt.Errorf("db migrate: directory %s: %w", absDir, err)
|
||||
useDisk = false
|
||||
}
|
||||
|
||||
db := stdlib.OpenDB(*pool.Config().ConnConfig)
|
||||
@@ -37,8 +39,19 @@ func RunMigrations(ctx context.Context, pool *pgxpool.Pool, migrationsDir string
|
||||
}
|
||||
goose.SetTableName(schemaTable)
|
||||
|
||||
if err := goose.UpContext(ctx, db, absDir); err != nil {
|
||||
return fmt.Errorf("db migrate up: %w", err)
|
||||
if useDisk {
|
||||
if err := goose.UpContext(ctx, db, absDir); err != nil {
|
||||
return fmt.Errorf("db migrate up: %w", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// U10a:源码目录不存在(单文件部署)时回退内嵌迁移链。
|
||||
// goose SetBaseFS 是全局状态;用后复位,避免污染后续磁盘调用。
|
||||
goose.SetBaseFS(dbassets.MigrationsFS)
|
||||
defer goose.SetBaseFS(nil)
|
||||
if err := goose.UpContext(ctx, db, dbassets.MigrationsDir); err != nil {
|
||||
return fmt.Errorf("db migrate up (embedded): %w", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -278,3 +278,21 @@ func rewriteDatabaseName(dsn, name string) string {
|
||||
}
|
||||
return dsn
|
||||
}
|
||||
|
||||
func TestRunMigrationsEmbeddedFallback(t *testing.T) {
|
||||
dsn := os.Getenv("TEST_DATABASE_URL")
|
||||
if dsn == "" {
|
||||
t.Skip("TEST_DATABASE_URL not set; embedded fallback needs PG")
|
||||
}
|
||||
ctx := context.Background()
|
||||
pool, err := pgxpool.New(ctx, dsn)
|
||||
if err != nil {
|
||||
t.Fatalf("connect: %v", err)
|
||||
}
|
||||
defer pool.Close()
|
||||
|
||||
// 不存在的磁盘目录必须触发内嵌回退并成功走完迁移链(幂等)。
|
||||
if err := RunMigrations(ctx, pool, filepath.Join(t.TempDir(), "no-such-dir")); err != nil {
|
||||
t.Fatalf("embedded fallback migrations: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user