Documentation
¶
Index ¶
- Variables
- func CheckChain(names []string) error
- func ContentDigest(content string) string
- func DetectCI() (string, bool)
- func Prefix(name string) string
- func ValidatePostgresMigrations(ctx context.Context, db *sql.DB, sources ...MigrationSource) error
- type AppliedRecord
- type Discrepancy
- type DiscrepancyKind
- type Migration
- type MigrationSource
- type Postgres
- func (p *Postgres) Applied(ctx context.Context) ([]string, error)
- func (p *Postgres) AppliedRecords(ctx context.Context) (map[string]AppliedRecord, error)
- func (p *Postgres) ApplyMigrations(ctx context.Context, migrations []Migration) error
- func (p *Postgres) ApplyWithOrderingException(ctx context.Context, migrations []Migration, allowBelow []string, ...) error
- func (p *Postgres) RepairAcceptContent(ctx context.Context, m Migration, req RepairRequest) (RepairResult, error)
- func (p *Postgres) RepairAdopt(ctx context.Context, m Migration, req RepairRequest) (RepairResult, error)
- func (p *Postgres) RepairAdoptAllUnmatched(ctx context.Context, migrations []Migration, req RepairRequest) ([]RepairResult, error)
- func (p *Postgres) RepairHistory(ctx context.Context) ([]RepairRecord, error)
- func (p *Postgres) Setup(ctx context.Context) error
- func (p *Postgres) Status(ctx context.Context, migrations []Migration) (Status, error)
- func (p *Postgres) ValidateAllApplied(ctx context.Context, migrations []Migration) error
- func (p *Postgres) WithSchema(schema string, rewriteFrom ...string) *Postgres
- func (p *Postgres) WithStrictContent() *Postgres
- func (p *Postgres) WithStrictOrdering() *Postgres
- func (p *Postgres) WithWarnFunc(fn func(Discrepancy)) *Postgres
- type RepairRecord
- type RepairRequest
- type RepairResult
- type Severity
- type Status
Constants ¶
This section is empty.
Variables ¶
var ErrNothingToRepair = errors.New("migratekit: nothing to repair")
ErrNothingToRepair is returned when the ledger already matches the tree.
var ErrRepairInCI = errors.New("migratekit: repairs are operator-runtime verbs and refuse to run in CI")
ErrRepairInCI is returned when a repair verb is invoked in CI.
Functions ¶
func CheckChain ¶ added in v1.0.1
CheckChain validates a migration chain as a FILE LISTING — no database. It reports duplicate numbers, gaps and non-monotonic numbering, which is what a CI gate on the merge boundary needs. names may be in any order.
func ContentDigest ¶ added in v1.0.1
ContentDigest is the ledger's digest of a migration's bytes.
func DetectCI ¶ added in v1.0.1
DetectCI reports the name of the CI environment variable that is set, if any. An empty-string value does not count — some shells export CI="".
func Prefix ¶
Prefix extracts numeric prefix from migration filenames and normalizes it. Supports both underscore and hyphen separators. Examples:
"001_create_users.up.sql" -> "1" "1-create-users.up.sql" -> "1" "0042_add_field.up.sql" -> "42"
func ValidatePostgresMigrations ¶
ValidatePostgresMigrations validates multiple Postgres migration sources at once. Returns an error if any migrations are pending.
Types ¶
type AppliedRecord ¶ added in v1.0.1
type AppliedRecord struct {
// Key is the ledger key — Prefix(filename).
Key string
// Filename is the full migration filename that claimed Key. Empty for
// rows written before v1.5.0.
Filename string
// Digest is the sha256 of the applied migration's content. Empty for
// rows written before v1.5.0.
Digest string
}
AppliedRecord is one row of the applied-migrations ledger.
type Discrepancy ¶ added in v1.0.1
type Discrepancy struct {
Kind DiscrepancyKind
Severity Severity
// Key is the ledger key (the bare migration number).
Key string
// File is the migration file in the tree. Empty for KindLedgerOnly.
File string
// LedgerFilename is the filename the ledger recorded, if any.
LedgerFilename string
// LedgerDigest is the content digest the ledger recorded, if any.
LedgerDigest string
// FileDigest is the digest of the file in the tree, if there is one.
FileDigest string
// Blocker is the already-applied migration a KindOrderViolation sorts
// below.
Blocker string
}
Discrepancy is one disagreement between the migration files and the ledger, with everything an operator needs to resolve it.
func (Discrepancy) Headline ¶ added in v1.0.1
func (d Discrepancy) Headline() string
Headline is the one-sentence WHAT.
func (Discrepancy) OneLine ¶ added in v1.0.1
func (d Discrepancy) OneLine() string
OneLine is the whole warning in one line: what, the risk, and the verb that resolves it. This is what a log line has room for.
func (Discrepancy) String ¶ added in v1.0.1
func (d Discrepancy) String() string
String renders the full operator-facing explanation: what, why, and what to do about it, ending with the pointer at `migratekit status`.
type DiscrepancyKind ¶ added in v1.0.1
type DiscrepancyKind string
DiscrepancyKind names a class of ledger/tree disagreement.
const ( // KindNumberMismatch: the ledger says this number was applied by a // different file. Hard error — the file in the tree would never run. KindNumberMismatch DiscrepancyKind = "number_applied_by_different_file" // KindContentDrift: an applied migration's file has been edited since it // ran. Warning by default; error under WithStrictContent. KindContentDrift DiscrepancyKind = "applied_migration_edited" // KindOrderViolation: a pending migration sorts below one already // applied. Error under WithStrictOrdering. KindOrderViolation DiscrepancyKind = "pending_sorts_below_applied" // KindLedgerOnly: a ledger row with no migration file behind it. KindLedgerOnly DiscrepancyKind = "ledger_row_without_file" )
type Migration ¶
Migration is a single SQL migration
func LoadFromFS ¶
LoadFromFS loads migrations from an embedded filesystem. Reads all .up.sql files, ordered by numeric prefix (so unpadded names like 2_x and 10_x apply in numeric order), falling back to filename order for non-numeric names. Returns an error if two files normalize to the same Prefix() — tracking is prefix-keyed, so a duplicate prefix would silently skip the second file as "already applied". If dir is empty, defaults to "." (root of the filesystem).
type MigrationSource ¶
type MigrationSource struct {
App string
FS fs.FS
// Schema optionally mirrors Postgres.WithSchema for validation helpers.
// RewriteFrom carries canonical schema names to rewrite when applying via
// Postgres.WithSchema(schema, rewriteFrom...).
Schema string
RewriteFrom []string
}
MigrationSource represents a migration source with an app name and a migration filesystem (any fs.FS; embed.FS satisfies it).
type Postgres ¶
type Postgres struct {
// contains filtered or unexported fields
}
Postgres handles PostgreSQL migrations
func NewPostgres ¶
NewPostgres creates a Postgres migrator
func (*Postgres) AppliedRecords ¶ added in v1.0.1
AppliedRecords returns the applied-migrations ledger keyed by ledger key.
func (*Postgres) ApplyMigrations ¶
ApplyMigrations applies all unapplied migrations (only locks if needed). Setup() always runs first, so there is no missing-table special case.
func (*Postgres) ApplyWithOrderingException ¶ added in v1.0.1
func (p *Postgres) ApplyWithOrderingException(ctx context.Context, migrations []Migration, allowBelow []string, req RepairRequest) error
ApplyWithOrderingException applies the chain while exempting the named migrations from the strict-ordering rule — the one-shot escape for a genuine backport that must land below the high-water mark. allowBelow entries may be bare numbers or filenames. Every exemption that actually applies a migration records an audit row.
The identity checks are NOT relaxed: this exempts ordering only.
func (*Postgres) RepairAcceptContent ¶ added in v1.0.1
func (p *Postgres) RepairAcceptContent(ctx context.Context, m Migration, req RepairRequest) (RepairResult, error)
RepairAcceptContent re-stamps the recorded digest of an applied migration after a verified edit. It is the "I looked at the diff and it is cosmetic" verb: it acknowledges the content-drift warning and silences it, on the record. It refuses when the ledger names a DIFFERENT file, because that is an identity problem and `repair adopt` is the verb that says so.
func (*Postgres) RepairAdopt ¶ added in v1.0.1
func (p *Postgres) RepairAdopt(ctx context.Context, m Migration, req RepairRequest) (RepairResult, error)
RepairAdopt binds the file in the tree as the applied identity for its ledger key: filename and content digest both become this file's.
This is the verb for a ledger that is the WRONG SIDE — a restored backup, a database adopted from somewhere else, a row somebody fixed by hand. The files are right and the ledger remembers a tree that no longer exists. It is NOT the verb for a lane collision: if two files genuinely claim one number, adopting one of them silently drops the other's DDL, which is exactly the failure this package exists to prevent. Read the diff first.
func (*Postgres) RepairAdoptAllUnmatched ¶ added in v1.0.1
func (p *Postgres) RepairAdoptAllUnmatched(ctx context.Context, migrations []Migration, req RepairRequest) ([]RepairResult, error)
RepairAdoptAllUnmatched adopts EVERY ledger row whose identity disagrees with the file in the tree that carries its number. This is the restored- backup shape: one dump, one restore, and every row mismatches at once. Rows that already match, and rows with no file behind them, are left alone.
func (*Postgres) RepairHistory ¶ added in v1.0.1
func (p *Postgres) RepairHistory(ctx context.Context) ([]RepairRecord, error)
RepairHistory returns this app's repair audit trail, newest first.
func (*Postgres) Status ¶ added in v1.0.1
Status reports the ledger, the pending set, every discrepancy and the repair history for this app. It is read-only apart from ensuring the tracking tables exist, and it never fails on a discrepancy — reporting one is the whole point.
func (*Postgres) ValidateAllApplied ¶
ValidateAllApplied checks if all provided migrations have been applied. Returns an error listing any pending migrations if validation fails. This is intended for use during application startup to ensure the database schema is up-to-date before the app starts serving requests.
func (*Postgres) WithSchema ¶
WithSchema configures the schema to target for migrations.
Unqualified DDL/DML runs under:
SET LOCAL search_path = "<schema>", public
Passing one or more canonical schema names also rewrites those schema references in migration SQL before execution. This lets apps author portable hard-qualified DDL against a default schema and relocate it at runtime:
migratekit.NewPostgres(db, "app").WithSchema(cfg.Schema, "openrails")
Tracking always stays in public.migrations.
func (*Postgres) WithStrictContent ¶ added in v1.6.0
WithStrictContent turns content drift — an applied migration whose file has been edited since it ran — back into a hard error. The default is a warning (see the integrity note above); this is for consumers whose chain must be byte-reproducible and who would rather not boot than diverge.
func (*Postgres) WithStrictOrdering ¶ added in v1.0.1
WithStrictOrdering refuses to apply a pending migration that sorts below a migration already applied. Off by default; see the ordering note above.
func (*Postgres) WithWarnFunc ¶ added in v1.0.1
func (p *Postgres) WithWarnFunc(fn func(Discrepancy)) *Postgres
WithWarnFunc replaces the sink for warning-severity discrepancies. The default logs them through slog.Default() at warn level. A warning nobody sees is the failure mode this whole package exists to prevent, so the sink is never silent by default — pass func(Discrepancy){} to silence it deliberately.
type RepairRecord ¶ added in v1.0.1
type RepairRecord struct {
ID int64
App string
Schema string
Key string
Verb string
Reason string
Operator string
OSUser string
Host string
OldFilename string
OldDigest string
NewFilename string
NewDigest string
At time.Time
}
RepairRecord is one row of the repair audit trail.
func (RepairRecord) Line ¶ added in v1.0.1
func (r RepairRecord) Line() string
Line renders one audit row for a terminal.
type RepairRequest ¶ added in v1.0.1
type RepairRequest struct {
// Reason is required and recorded verbatim. "Why" is the only part of a
// repair a future reader cannot reconstruct.
Reason string
// Operator optionally names the human, alongside the OS user the audit
// row records anyway.
Operator string
// DryRun computes and returns the repair without writing anything.
DryRun bool
}
RepairRequest is the operator's authorization for a repair.
type RepairResult ¶ added in v1.0.1
type RepairResult struct {
Verb string
Key string
OldFilename string
OldDigest string
NewFilename string
NewDigest string
DryRun bool
}
RepairResult describes one ledger identity row before and after a repair.
func (RepairResult) String ¶ added in v1.0.1
func (r RepairResult) String() string
type Status ¶ added in v1.0.1
type Status struct {
App string
Schema string
// Applied is the ledger, in apply order.
Applied []AppliedRecord
// Pending names the migrations that have not run.
Pending []string
// Discrepancies is every disagreement, most severe first.
Discrepancies []Discrepancy
// Repairs is the audit trail, newest first.
Repairs []RepairRecord
}
Status is the whole picture for one app: what is applied, what is pending, what disagrees, and every repair anybody has ever run here.
Directories
¶
| Path | Synopsis |
|---|---|
|
Package chmigrate is migratekit's ClickHouse migration driver.
|
Package chmigrate is migratekit's ClickHouse migration driver. |
|
cmd
|
|
|
migratekit
command
Command migratekit is the operator's side of migration identity: it explains a boot refusal and resolves it.
|
Command migratekit is the operator's side of migration identity: it explains a boot refusal and resolves it. |
|
internal
|
|
|
coremigrate
Package coremigrate holds implementation primitives shared by migratekit's Postgres migrator (the root package) and its ClickHouse migrator (migratekit/chmigrate): the migrations-tracking table DDL and environment template substitution.
|
Package coremigrate holds implementation primitives shared by migratekit's Postgres migrator (the root package) and its ClickHouse migrator (migratekit/chmigrate): the migrations-tracking table DDL and environment template substitution. |