Documentation
¶
Overview ¶
Package migrations embeds the SQL migration files for the kagent database schema and provides the runner that applies them at startup.
Index ¶
Constants ¶
This section is empty.
Variables ¶
var FS embed.FS
Functions ¶
func RunUp ¶
RunUp applies all pending migrations for each source, in slice order.
All PreChecks run first, before any source is applied, so a failed precheck aborts the run before touching the database. Each source is then applied with the same per-track safety behavior: it tolerates a database ahead of this binary (compatibility mode), refuses a dirty-and-ahead database, and rolls itself back if its own Up fails. If a later source fails, previously-applied sources are rolled back to their pre-run versions in reverse order.
ctx is honored at source boundaries and during schema setup and prechecks. golang-migrate's apply is not context-aware, so an in-flight migration is not cancellable.
func VerifyMigrated ¶
VerifyMigrated checks, without applying or reverting anything, that every source's migrations have been applied to the database. It is the boot-time guard for the SKIP_MIGRATIONS deployment mode, where migrations run out-of-band (a pipeline or pre-upgrade hook) and the server must refuse to serve a wrong-shaped schema. It issues only SELECTs — never golang-migrate, which creates the tracking table on open — so it is safe on a connection whose role has no DDL privileges.
Per source: a missing tracking table or a version behind this binary's embedded max is an error; a dirty tracking table is an error; a database ahead of the binary is tolerated (compatibility mode), matching RunUp.
func WithMigrator ¶
func WithMigrator(ctx context.Context, url string, src Source, fn func(*migrate.Migrate) error) error
WithMigrator opens a migrator for src against url, runs fn against it, and closes it. The migrator carries the same schema handling, tracking-table configuration, and advisory-lock identity as the orchestrator's own runs, so out-of-band tooling (the `kagent db migrate` CLI) built on this serializes correctly against a concurrently booting server and cannot drift from the startup path. fn's migration operations (Up/Down/Steps/Migrate/Force) each take golang-migrate's per-(database, schema) advisory lock; Version reads do not.
Types ¶
type Source ¶
type Source struct {
// Name labels the source in logs and errors (e.g. "core", "vector").
Name string
// Schema is the Postgres schema the track lives in. Empty means the
// connection's default schema (resolved via search_path / current_schema),
// which is what the built-in tracks use. A non-empty value scopes the
// tracking table and migration objects to that schema: the orchestrator
// creates it (CREATE SCHEMA IF NOT EXISTS) and sets search_path on the
// connection. Schema is treated as an untrusted identifier and validated.
//
// When Schema is empty (the built-in tracks), the DSN is left untouched:
// the connection keeps the server's default search_path ("$user", public), so
// migration objects and the tracking table land in public exactly as before
// this orchestrator existed. The schema handling below applies only when
// Schema is set.
//
// When Schema is set, search_path is pinned to it alone (pg_catalog is always
// implicitly searched, so built-in types and functions still resolve). public
// is NOT on the path, which keeps a schema-scoped track strictly isolated. A
// migration that needs a shared extension installed in public (e.g. the
// pgvector "vector" type) must therefore either install/relocate the extension
// into this schema or schema-qualify the reference; it cannot rely on public.
//
// Do not register two sources whose schemas resolve to the same value with the
// same TrackingTable — e.g. one source with Schema == "" and another naming the
// connection's current_schema() explicitly. They would share one tracking-table
// row and one advisory lock and corrupt each other's state. The collision unit
// is (resolved schema, TrackingTable). validateSources catches collisions on the
// literal Schema; RunUp additionally resolves "" to current_schema() and rejects
// collisions that only appear after resolution.
Schema string
// TrackingTable is the golang-migrate bookkeeping table for this track.
TrackingTable string
// FS holds the embedded migration files.
FS fs.FS
// Dir is the subdirectory within FS that holds this track's files.
Dir string
// PreCheck, if set, runs before any source is applied. A non-nil error
// aborts the whole run before any migration executes (fail-fast).
PreCheck func(url string) error
}
Source describes one migration track for the orchestrator to apply. Downstream consumers register their own Sources alongside the built-in ones rather than owning a runner, so track ordering and failure handling stay centralized.
func BuiltinSources ¶
BuiltinSources returns the built-in source set: the core track always, and the vector track when vectorEnabled. app.Start prepends these to any downstream-registered extra sources before calling RunUp, so the built-in tracks always run first and downstream consumers only supply their own extras (never assembling this slice themselves). A caller that invokes RunUp directly (e.g. a migration CLI) composes the list the same way: BuiltinSources first, then extras.