migrate

package
v0.10.0-rc9 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jun 1, 2026 License: MIT Imports: 13 Imported by: 0

Documentation

Overview

Package migrate implements the ncps schema-migration runtime: state detection, dbmate→goose adoption, fresh-install via Ent's Schema.Create, and the goose hand-off for incremental migrations. Per design D6 (Option E) of the migrate-to-ent-and-atlas change.

Index

Constants

This section is empty.

Variables

View Source
var (
	ErrOptionsDBNil           = errors.New("migrate: Options.DB is nil")
	ErrOptionsMigrationsFSNil = errors.New("migrate: Options.MigrationsFS is nil")
)

ErrOptionsDBNil / ErrOptionsMigrationsFSNil signal misuse of the migrate.Options struct.

View Source
var (
	// ErrUnknownState is returned when adopt encounters an unrecognised
	// State value. Distinct from database.ErrUnknownDialect, which is for
	// database.Type values.
	ErrUnknownState = errors.New("migrate: unknown state")

	// ErrCorruptState is returned when probe detects ncps application
	// tables but no schema_migrations tracking table. This should never
	// happen during normal operation and requires manual intervention.
	ErrCorruptState = errors.New(
		"migrate: ncps application tables exist but schema_migrations does not — refusing to adopt",
	)
)

Sentinel errors for state detection. Unrecognised database.Type values are reported via the package-level database.ErrUnknownDialect sentinel (see pkg/database) so callers match a single value regardless of which layer produced the error.

View Source
var ErrDownNotSupported = errors.New(
	"migrate: down migrations are not supported — use the expand-contract recipe " +
		"and the four-step NOT NULL promotion procedure documented in CLAUDE.md",
)

ErrDownNotSupported is returned by Down to signal callers that ncps uses a forward-only migration policy (design D10: expand-contract + four-step NOT NULL recipe).

View Source
var ErrImpossibleState = errors.New("migrate: impossible adoption state — manual intervention required")

ErrImpossibleState is returned when MySQL adoption finds a configuration that cannot arise from any happy-path operation (state S6 in design D6: both `schema_migrations` and `schema_migrations_dbmate_backup` exist, with `schema_migrations` still in dbmate shape). Indicates manual intervention or corruption.

Functions

func Down

func Down(_ context.Context, _ Options) error

Down is the explicit "we don't support down migrations" entry point. CLI callers wire this to `ncps migrate down` and let the error message guide operators to the expand-contract recipe.

func Up

func Up(ctx context.Context, opts Options) error

Up runs the full `ncps migrate up` flow: probe state, run any needed adoption / fresh-install work, then hand off to goose for incremental migrations.

Returns nil on success. The caller logs progress; this function is quiet by design so a future programmatic caller (tests, fsck) can surface results without parsing log lines.

Types

type Options

type Options struct {
	// DB is the database connection. The caller owns its lifecycle.
	DB *sql.DB

	// Dialect identifies which SQL dialect DB speaks.
	Dialect database.Type

	// MigrationsFS is the dialect-specific sub-FS — i.e. the result of
	// `fs.Sub(migrations.FS, "<dialect>")`. The caller is responsible
	// for the sub-FS lookup so this package does not import the
	// migrations package directly.
	MigrationsFS fs.FS
}

Options bundles the inputs to Up / DryRun. Constructed by the caller (typically the CLI) so this package stays free of urfave/cli imports.

type Plan

type Plan struct {
	// State is the detected adoption state.
	State State

	// AdoptionAction is a human-readable description of what the
	// adoption step would do (or "no adoption needed").
	AdoptionAction string

	// PendingVersions is the list of migration version stamps that
	// goose would apply after adoption (empty for fresh-install and
	// adopted-but-current states).
	PendingVersions []int64

	// AppliedCount is the number of versions already recorded in
	// schema_migrations at probe time (0 for empty / dbmate states).
	AppliedCount int
}

Plan is the result of DryRun: what Up *would* do without actually touching the database.

func DryRun

func DryRun(ctx context.Context, opts Options) (Plan, error)

DryRun returns the Plan that Up would execute without touching the database. Side-effect free except for read-only catalog probes.

type State

type State int

State describes what `ncps migrate up` finds when it probes the database. Each state has a dedicated handler in this package.

const (
	// StateUnknown is the zero value and should never be observed in
	// practice. Treated as an error case.
	StateUnknown State = iota

	// StateEmpty: the database has no `schema_migrations` table and no
	// ncps application tables. Fresh install — `Schema.Create` produces
	// the full schema in one shot.
	StateEmpty

	// StateDbmate: `schema_migrations` exists with dbmate's column
	// layout (`version VARCHAR(...)` PRIMARY KEY, no `is_applied`
	// column). One of the prior ncps versions migrated this database
	// with dbmate; we now adopt the tracking table to goose's shape and
	// hand off to goose to apply the bridge.
	StateDbmate

	// StateAdopted: `schema_migrations` has goose's column layout
	// (`id, version_id, is_applied, tstamp`). The normal incremental
	// path — hand straight to goose.
	StateAdopted

	// StateMySQLS4 (MySQL-only mid-adoption recovery): the rename step
	// of MySQL adoption completed but the new schema_migrations was not
	// yet created. `schema_migrations_dbmate_backup` exists,
	// `schema_migrations` does not. Recovery: re-run from the CREATE
	// step.
	StateMySQLS4

	// StateMySQLS5 (MySQL-only mid-adoption recovery): the new
	// schema_migrations was created (and possibly populated) but the
	// backup was not yet dropped. Both `schema_migrations` (goose
	// shape) and `schema_migrations_dbmate_backup` exist. Recovery:
	// verify row-count parity, drop backup (or re-INSERT then drop on
	// mismatch).
	StateMySQLS5

	// StateImpossibleS6 (MySQL-only diagnostic): both tables exist but
	// `schema_migrations` still has dbmate shape. Per design D6 this
	// state is unreachable through any happy-path; we abort with an
	// operator-readable diagnostic.
	StateImpossibleS6
)

func Detect

func Detect(ctx context.Context, db *sql.DB, d database.Type) (State, error)

Detect probes the database and returns the adoption state. It uses the dialect-appropriate catalog query for table-and-column existence; no DDL is issued.

func (State) String

func (s State) String() string

String returns a human-readable name (for logging / dry-run output).

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL