migrate

package
v0.5.1 Latest Latest
Warning

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

Go to latest
Published: May 7, 2026 License: Apache-2.0 Imports: 9 Imported by: 0

Documentation

Overview

Package migrate coordinates on-disk schema migrations for AgentGuard.

Migrations are versioned transitions of persistent state (audit log, checkpoint files, rotated archives). Each migration lives under its own subpackage (pkg/migrate/vNNN_to_vMMM/), implements the Migration interface, and registers itself at init() time via Register().

There are two entry points:

  • RunStartup(ctx, env): called from main.go before the server binds. Every registered migration whose Detect() returns true runs in registration order. Any error aborts startup — we never proceed past a failed migration, because half-migrated state is worse than not upgrading.

  • RunCLI(ctx, env, args): backs the `agentguard migrate` subcommand. Supports --dry-run (log intended actions without touching disk), --id=<migration-id> (run a specific migration out of startup order, for operators who need to re-run one explicitly), and a few convenience flags documented in the subcommand help text.

The framework is deliberately stdlib-only: no external deps, no global state that survives Reset(), and every migration receives its paths and logger through the Env struct rather than reading from package-level variables. That keeps migrations testable without touching the real disk.

Index

Constants

This section is empty.

Variables

View Source
var ErrMigrationNotFound = errors.New("migration not found in registry")

ErrMigrationNotFound is returned by RunCLI when --id names a migration that is not in the registry.

Functions

func Register

func Register(m Migration)

Register adds a Migration to the registry. Typically called from an init() in the migration's subpackage. Duplicate IDs cause a panic — the registry is tiny and duplication indicates a programming error, not something to silently tolerate.

func ResetForTest

func ResetForTest()

ResetForTest clears the migration registry. Production code must never call this — migrations are immutable once registered — but tests that Register() a fake Migration need a way to tear down between runs.

func RunCLI

func RunCLI(ctx context.Context, env Env, opts CLIOptions) error

RunCLI executes the `agentguard migrate` subcommand semantics:

  • --list: print the registry and return.
  • --id=X: run only migration X (even if Detect=false — operator override).
  • default: run every migration whose Detect() is true, like RunStartup does, but honoring --dry-run.

Errors are returned rather than Fatal'd so main.go controls the exit code and the tests can drive the same code path without os.Exit.

func RunStartup

func RunStartup(ctx context.Context, env Env) error

RunStartup runs every registered migration whose Detect() returns true, in registration order. If any migration errors, startup aborts — the caller (main.go) should log the error and exit non-zero.

RunStartup is safe to call when no migrations are registered (a fresh install) or when all migrations report Detect=false (an already-upgraded install). In both cases it returns nil after logging a single summary line.

Types

type CLIOptions

type CLIOptions struct {
	DryRun          bool
	ID              string // run only this migration, skip others
	List            bool   // list registered migrations and exit
	ResetCheckpoint bool   // delete the replay checkpoint before running
	AuditLogPath    string
	CheckpointPath  string
	BackupDir       string
}

CLIOptions is the parsed form of the `agentguard migrate` subcommand flags.

type Env

type Env struct {
	// AuditLogPath is the path to the live audit.jsonl file.
	AuditLogPath string

	// CheckpointPath is the path to the .replay-checkpoint file.
	CheckpointPath string

	// BackupDir is the directory under which rollback artifacts
	// (e.g. audit.jsonl.v040-backup) are written. Empty => same dir as
	// AuditLogPath.
	BackupDir string

	// Logger is where migrations emit progress. nil => stdlib log package.
	Logger *log.Logger

	// Stdout is where CLI output is written. nil => os.Stdout. Primarily
	// used by RunCLI; migrations themselves should log via Logger.
	Stdout io.Writer
}

Env carries everything a migration may need from the host process. Paths are passed explicitly rather than via package-level globals so migrations stay testable in isolation.

type Migration

type Migration interface {
	// ID is a stable identifier used in logs, metrics, and the CLI flag.
	// Convention: "vNNN_to_vMMM", e.g. "v040_to_v041".
	ID() string

	// FromVersion is the schema version this migration accepts as input.
	// Detect() must fail if observed input is anything else.
	FromVersion() string

	// ToVersion is the schema version this migration produces.
	ToVersion() string

	// Description is a one-line human-readable summary for CLI help and log
	// output. No trailing period, no newlines.
	Description() string

	// Detect reports whether the migration should run against the current
	// on-disk state. Returns (true, nil) if Migrate() should execute,
	// (false, nil) if state is already at ToVersion (or otherwise not this
	// migration's concern), and (_, err) on read/parse failure. Read-only —
	// must not modify disk.
	Detect(ctx context.Context, env Env) (bool, error)

	// Migrate performs the transition. When dryRun is true it must log the
	// intended actions without touching disk. On error the on-disk state
	// must be left unchanged — implementations typically stage output in a
	// temp file and atomically rename on success.
	Migrate(ctx context.Context, env Env, dryRun bool) (Result, error)

	// Verify checks post-migration invariants. Called after a successful
	// Migrate() and again on startup when resuming after a crash, to ensure
	// previous output is still intact. Must be idempotent.
	Verify(ctx context.Context, env Env) error
}

Migration is the contract every on-disk migration implements. Implementations live in pkg/migrate/vNNN_to_vMMM/ and register themselves via Register().

func Registered

func Registered() []Migration

Registered returns a copy of the registry. Test-only helper; production code should call RunStartup or RunCLI instead.

type Result

type Result struct {
	MigrationID string
	From        string
	To          string
	DryRun      bool
	Stats       map[string]int64
	Notes       []string
}

Result is the summary a migration returns. Stats keys are free-form and documented per migration; common keys include "records_migrated", "bytes_written", and "backup_path" (stored as a stat for convenience although it is not a count — operators tend to look for it there).

Directories

Path Synopsis
Package v040_to_v041 adds the schema-v2 `_meta` header to a pre-existing v0.4.0 audit log.
Package v040_to_v041 adds the schema-v2 `_meta` header to a pre-existing v0.4.0 audit log.

Jump to

Keyboard shortcuts

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