feat(db): embedded goose migrations fallback (U10a first slice)
CI / go-vet (pull_request) Successful in 19s
CI / short-tests-report (pull_request) Failing after 35s
CI / backup-restore-drill (pull_request) Successful in 27s
CI / web (pull_request) Successful in 32s

- deploy/postgres (package dbassets) embeds the full goose chain;
  RunMigrations prefers the on-disk dir (dev behavior unchanged) and falls
  back to the embedded FS when the source tree is absent (single-binary
  deployments per plan U10/KTD16)
- goose SetBaseFS global state reset after use
- TestRunMigrationsEmbeddedFallback verified against a throwaway isolated
  pgvector container: nonexistent dir -> embedded chain -> version 78,
  migration gate count agrees
This commit is contained in:
2026-09-29 07:07:58 +00:00
parent 638e5b89db
commit 686dede802
3 changed files with 48 additions and 3 deletions
+16 -3
View File
@@ -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
}
+18
View File
@@ -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)
}
}