setup

package
v2.1.0 Latest Latest
Warning

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

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

README

package setup

Abstract bulk setup plans: ordered, fail-closed, idempotent steps for deploy Jobs (migrate, permissions, bootstrap, verify, …).

No dependency on Frame Service, Cloud Run, or HTTP — only context and logging via util.Log.

Type Role
Step Name() + Run(ctx)
Func Function-backed step
Registry Register + Run / RunAll
Selection / Select Pure argv/env → which steps to run

Full documentation: docs/SETUP_JOB.md.

reg := setup.NewRegistry()
reg.RegisterFunc(setup.NameMigrate, migrate)
reg.RegisterFunc(setup.NameVerify, verify)

sel := setup.Select(os.Args[1:], false, os.Getenv("FRAME_SETUP_TASKS"))
if sel.Active {
    return reg.Run(ctx, sel.Names...)
}

Documentation

Overview

Package setup defines an abstract, Frame-agnostic model for one-shot setup work: schema migrations, permission publishing, root/bot bootstrap, health probes, and any other bulk steps a deploy job must run before traffic.

Design goals:

  • Steps implement a tiny interface (Name + Run) — no Service, HTTP, or Cloud Run types in the contract.
  • A Registry holds steps and executes them in bulk (all, or a named subset) fail-closed and in order.
  • Selection (which process is a setup job, which step names) is pure config/argv parsing — callers wire env/CLI however they like.

Frame integrates via thin adapters (frame.WithSetupStep, Service.Setup) so applications can also use this package outside Frame if needed.

Index

Constants

View Source
const (
	// NameMigrate is the conventional name for schema migrations.
	NameMigrate = "migrate"

	// NamePermissions is the conventional name for publishing a service
	// permission manifest (e.g. to tenancy).
	NamePermissions = "permissions"

	// NameBootstrap is the conventional name for root/bot/seed work that
	// must run once after migrate and before traffic.
	NameBootstrap = "bootstrap"

	// NameVerify is the conventional name for post-setup checks
	// (connectivity, required rows, tuple presence, etc.).
	NameVerify = "verify"
)

Well-known step names. Applications may register any other stable names (e.g. "bootstrap", "verify", "seed"). Conventions only — the registry does not special-case these strings.

View Source
const Command = "setup"

Command is the conventional argv[0] that marks a process as a setup job (e.g. Cloud Run Job args: ["setup", "migrate", "permissions"]).

Variables

View Source
var ErrEmptyPlan = errors.New("setup: no steps requested and none registered")

ErrEmptyPlan is returned when Run has nothing to execute.

View Source
var ErrUnknownStep = errors.New("unknown setup step")

ErrUnknownStep is returned when Run is asked for a name that was never registered.

Functions

This section is empty.

Types

type Func

type Func struct {
	StepName string
	Fn       func(ctx context.Context) error
}

Func is a Step backed by a function. Use when you do not need a custom type.

setup.Func{StepName: setup.NameMigrate, Fn: migrateFn}

func (Func) Name

func (f Func) Name() string

Name implements Step.

func (Func) Run

func (f Func) Run(ctx context.Context) error

Run implements Step.

type Registry

type Registry struct {
	// contains filtered or unexported fields
}

Registry holds named setup steps and executes them in bulk.

Registration order is preserved. Registering the same Name again replaces the previous Step but keeps its position in the order.

Registry is safe for concurrent Register / Names; Run should be called from a single goroutine (typical for a Job main).

func NewRegistry

func NewRegistry() *Registry

NewRegistry returns an empty step registry.

func (*Registry) Get

func (r *Registry) Get(name string) (Step, bool)

Get returns a registered step by name.

func (*Registry) Len

func (r *Registry) Len() int

Len returns how many steps are registered.

func (*Registry) Names

func (r *Registry) Names() []string

Names returns registered step names in registration order.

func (*Registry) Register

func (r *Registry) Register(step Step)

Register adds or replaces a step. Empty names and nil steps are ignored.

func (*Registry) RegisterFunc

func (r *Registry) RegisterFunc(name string, fn func(ctx context.Context) error)

RegisterFunc is sugar for Register(Func{StepName: name, Fn: fn}).

func (*Registry) Run

func (r *Registry) Run(ctx context.Context, names ...string) error

Run executes steps fail-closed, in the order of names.

  • If names is non-empty, those names run in the given order.
  • If names is empty, every registered step runs in registration order.

Each step is logged at Info on start/success. The first error aborts the plan and is wrapped with the step name.

func (*Registry) RunAll

func (r *Registry) RunAll(ctx context.Context) error

RunAll is Run with no name filter (every registered step, registration order).

type Selection

type Selection struct {
	// Active is true when this process is a setup job (not a long-running server).
	Active bool

	// Names is the ordered step list to run. Empty with Active true means
	// “run every registered step” (Registry.Run treats empty as all).
	Names []string
}

Selection describes whether this process should run setup (and which steps). It is pure data — no I/O — so tests and CLIs can build it without a Registry.

sel := setup.Select(os.Args[1:], doSetupFlag, setupTasksCSV)
if sel.Active {
    return registry.Run(ctx, sel.Names...)
}

func Select

func Select(args []string, doSetup bool, tasksCSV string) Selection

Select builds a Selection from process argv and optional flags.

Precedence for names when Active:

  1. argv after Command: `setup migrate permissions` → [migrate, permissions]
  2. else tasksCSV (comma-separated), if non-empty
  3. else empty (run all registered)

Active is true when:

  • argv[0] == Command ("setup"), or
  • doSetup is true, or
  • tasksCSV is non-empty

Legacy bare `migrate` as argv[0] does NOT activate setup mode — callers keep separate DoDatabaseMigrate paths for backwards compatibility.

func SelectFromOS

func SelectFromOS(doSetup bool, tasksCSV string) Selection

SelectFromOS is Select(os.Args[1:], doSetup, tasksCSV).

type Step

type Step interface {
	Name() string
	Run(ctx context.Context) error
}

Step is one idempotent unit of work in a setup plan.

Contracts:

  • Name is stable and unique within a Registry (case-sensitive).
  • Run is fail-closed: a non-nil error aborts the plan.
  • Run must be safe to re-execute after success (no-op or upsert).

Jump to

Keyboard shortcuts

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