90 lines
4.1 KiB
Markdown
90 lines
4.1 KiB
Markdown
# migrate
|
|
|
|
`go.auvem.com/corestack/migrate` sets the house configuration for
|
|
[Goose's Provider API](https://pressly.github.io/goose/documentation/provider/).
|
|
It returns `*goose.Provider` directly: Goose owns execution, version tracking,
|
|
status, and errors. There is no lifecycle dependency or background work.
|
|
|
|
Consumers must create migration files with Goose's
|
|
[`create` command](https://pressly.github.io/goose/documentation/cli-commands/#create).
|
|
For timestamp-to-sequential reconciliation before deployment, use its
|
|
[`fix` command](https://pressly.github.io/goose/documentation/cli-commands/#fix)
|
|
as described in [hybrid versioning](https://github.com/pressly/goose#hybrid-versioning).
|
|
These commands edit source files before embedding; `fix` does not update database
|
|
history. Never renumber migrations already applied to shared databases.
|
|
|
|
Embed migrations in the application's binary and run them before serving traffic:
|
|
|
|
```go
|
|
package app
|
|
|
|
import (
|
|
"context"
|
|
"database/sql"
|
|
"embed"
|
|
"log/slog"
|
|
|
|
"github.com/pressly/goose/v3"
|
|
"go.auvem.com/corestack/migrate"
|
|
)
|
|
|
|
//go:embed migrations/*.sql
|
|
var migrations embed.FS
|
|
|
|
func migrateDatabase(ctx context.Context, db *sql.DB, logger *slog.Logger) error {
|
|
provider, err := migrate.New(db, goose.DialectPostgres, migrations, "migrations", logger)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
_, err = provider.Up(ctx)
|
|
return err
|
|
}
|
|
```
|
|
|
|
The caller opens and closes `db`, selects a matching database driver and dialect,
|
|
supplies a nonnil logger, and controls the operation context/deadline. Construction
|
|
is offline; SQL is parsed lazily by Goose. `Provider.Close` also closes `db`, so do
|
|
not defer it when sharing the pool with the application. Use `"."` for SQL files
|
|
at the embedded root. Files in the selected directory are discovered directly,
|
|
without recursively searching subdirectories.
|
|
|
|
Preserve Goose's creator/fix filenames and ship the complete migration history.
|
|
The pinned Goose SQL-only provider relies on lexical filename order matching
|
|
numeric version order. Timestamp versions and gaps are supported; never derive
|
|
versions from file counts. For operations, errors, and SQL annotations, use the
|
|
[Provider API](https://pkg.go.dev/github.com/pressly/goose/v3#Provider) and
|
|
[SQL migration docs](https://pressly.github.io/goose/documentation/annotations/).
|
|
|
|
For Go functions, use Goose's
|
|
[provider-local registration](https://pressly.github.io/goose/documentation/provider/#withgomigrations):
|
|
pass fresh `goose.NewGoMigration` values as the trailing arguments to `migrate.New`.
|
|
The creator's default Go template instead calls `goose.AddMigrationContext` from
|
|
`init`; replace that registration with provider-local construction. Global
|
|
registration is disabled to keep each provider's migration set isolated and avoid
|
|
import side effects. If `fix` renames Go migrations, update their explicit
|
|
registration versions to match. Versions must be unique across SQL and Go files.
|
|
|
|
Postgres providers automatically use Goose's default session advisory locker.
|
|
Concurrent startup calls from separate providers/processes serialize migration
|
|
execution and recheck applied versions under the lock. The default lock ID
|
|
serializes Goose migrations throughout the same database, including different
|
|
schemas. Use a direct connection or a session-pooling proxy: transaction pooling
|
|
cannot preserve session locks.
|
|
`RunDB` Go migrations need spare pool connections while the locked session is
|
|
held; avoid a one-connection pool for them.
|
|
|
|
Other dialects have no cross-provider/process lock configured by this package.
|
|
Serialize migration runs externally, for example with a single deployment job.
|
|
SQLite tests validate the SQL convention, not concurrent daemon startup safety.
|
|
|
|
Run the integration suite against an existing Postgres database with schema
|
|
creation privileges:
|
|
|
|
```sh
|
|
MIGRATE_POSTGRES_DSN='postgres://user:password@localhost/testdb?sslmode=disable' go test -race ./migrate
|
|
```
|
|
|
|
Tests create and clean only random schemas they own. Without a DSN, Postgres
|
|
tests skip locally; in CI a missing DSN fails, and the CI job supplies a Postgres
|
|
service. SQLite tests always run in process using temporary databases.
|