Help us shape the future of Go! Take the 2026 Go Developer Survey

promote

package
v1.4.15 Latest Latest
Warning

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

Go to latest
Published: Oct 19, 2026 License: MIT Imports: 24 Imported by: 0

Documentation

Overview

Package promote runs an environment promotion as an injected transaction.

Index

Constants

View Source
const AttemptFile = ".nself/state/promote-attempt.json"
View Source
const RecordFile = ".nself/state/promote.json"

RecordFile is the local promotion rollback authority.

Variables

View Source
var StepNames = []string{
	"resolve", "confirm", "verify", "preflight", "source-health", "capture",
	"build", "compare", "snapshot", "save", "apply", "migrate", "health", "record",
}

StepNames is the only accepted promotion execution order.

Functions

func AcquireRecordLock

func AcquireRecordLock(ctx context.Context, projectRoot string) (context.Context, func(), error)

AcquireRecordLock holds the deployment operation lock for the entire rollback.

func CheckDBRestoreCompletion

func CheckDBRestoreCompletion(rec *Record) error

CheckDBRestoreCompletion refuses recovery while a restore outcome is uncertain.

func ManifestHash

func ManifestHash(raw []byte) string

ManifestHash binds recovery to the exact shipped compose manifest bytes.

func MarkDBRestoreDone

func MarkDBRestoreDone(root string, rec *Record) error

MarkDBRestoreDone records the operator's explicit host verification.

func RecordApplied

func RecordApplied(st *State, res deploy.ApplyResult)

RecordApplied remembers only hosts whose artifact tree was changed.

func RestoreDatabase

func RestoreDatabase(ctx context.Context, r deploy.Remote, remotePath, tag, backup string, phase, restored *string, checkpoint func() error) error

RestoreDatabase checkpoints intent before running the remote restore.

func RollbackRecord

func RollbackRecord(ctx context.Context, projectRoot string, rec *Record, remotes map[string]deploy.Remote, remotePaths map[string]string) error

RollbackRecord re-applies every saved stack before restoring the migrated DB.

func SaveAttempt

func SaveAttempt(root string, rec Record) error

SaveAttempt persists provisional evidence without replacing promote.json.

func SaveRecord

func SaveRecord(projectRoot string, rec Record) error

SaveRecord atomically writes promote.json with private permissions.

func TargetArchitecture

func TargetArchitecture(ctx context.Context, configured string, run Runner) (string, error)

TargetArchitecture normalizes an inventory value or probes the target when absent.

func UndoApplied

func UndoApplied(ctx context.Context, st *State, remotes map[string]deploy.Remote, paths map[string]string) error

UndoApplied restores files and reapplies the previous stack, without a DB undo.

func ValidateTiers

func ValidateTiers(source, target string, sourceTier, targetTier controlplane.Tier) error

ValidateTiers rejects downward promotions and identical environments.

Types

type DeployIdentity

type DeployIdentity struct {
	StartedAt     time.Time         `json:"started_at"`
	PreDeployTar  string            `json:"pre_deploy_tar,omitempty"`
	PreDeployTars map[string]string `json:"pre_deploy_tars,omitempty"`
}

DeployIdentity records the deploy.json identity written by promotion apply.

type DigestRow

type DigestRow struct {
	Service string `json:"service"`
	Source  string `json:"source"`
	Target  string `json:"target"`
	Status  string `json:"status"`
	Detail  string `json:"detail,omitempty"`
}

DigestRow records the per-platform release identity comparison.

func CompareDigests

func CompareDigests(ctx context.Context, source []SourceImage, target []Image, targetArch string,
	tier controlplane.Tier, lookup archguard.Lookup, warn func(string)) ([]DigestRow, error)

CompareDigests proves that source and target resolve to equal platform manifests.

Purpose: reject drift and production build-context ambiguity before snapshot. Inputs: captured source identities, target image declarations, arch, tier and lookup. Outputs: deterministic comparison rows and E490 when identity is not proven. Constraints: build-context services warn below prod and fail closed on prod.

type Engine

type Engine struct {
	Steps    []Step
	Observer Observer
	Verify   func(context.Context, *State) error
	Now      func() time.Time
}

Engine executes the canonical promotion transaction.

Purpose: enforce ordering, observability, and rollback invariants. Inputs: canonical Steps, optional Observer/Verify/clock, and mutable State. Outputs: a Result plus the triggering structured error on failure. Constraints: execution is pure orchestration; all I/O lives in injected hooks.

func (Engine) Plan

func (e Engine) Plan() []StepResult

Plan returns the deterministic canonical plan without executing a step.

func (Engine) Run

func (e Engine) Run(ctx context.Context, st *State) (Result, error)

Run executes the canonical steps and compensates failures after snapshot.

type Image

type Image struct {
	Service  string
	Ref      string
	Platform string
	Build    bool
}

Image identifies one generated compose service and whether it has a build context.

func ReadComposeImages

func ReadComposeImages(files []string) ([]Image, error)

ReadComposeImages reads and merges service image declarations from compose files.

Purpose: give capture and compare one deterministic view of compose fragments. Inputs: compose files in merge order; later service declarations override earlier ones. Outputs: service/image/build rows sorted by service name. Constraints: files are read only; an empty image is retained for build-context checks.

func ResolvedArtifactImages

func ResolvedArtifactImages(ctx context.Context, local, host Runner, set deploy.ArtifactSet) ([]Image, error)

ResolvedArtifactImages resolves exactly the staged compose and environment set. Host-owned env files are read privately and removed after interpolation.

func ResolvedComposeImages

func ResolvedComposeImages(ctx context.Context, run Runner, files, envFiles []string) ([]Image, error)

ResolvedComposeImages reads Docker's merged, interpolated config model.

type ManifestIdentity

type ManifestIdentity struct {
	Hash   string `json:"hash,omitempty"`
	Absent bool   `json:"absent"`
}

ManifestIdentity authorizes a prior manifest, including a first deploy's absence.

func ReadManifestIdentity

func ReadManifestIdentity(ctx context.Context, r deploy.Remote, rp string) (ManifestIdentity, error)

Purpose: Read prior artifact identity without conflating absent and empty files. Inputs: Validated remote path. Outputs: Manifest presence and exact byte hash. Constraints: File reads only; command failures never authorize manifest absence.

type Observer

type Observer interface {
	Start(step string)
	Done(step string, d time.Duration)
	Failed(step string, err error)
	Skipped(step, reason string)
	Rollback(step string, err error)
}

Observer receives synchronous promotion lifecycle events.

type Record

type Record struct {
	SchemaVersion         int                         `json:"schema_version"`
	ID                    string                      `json:"id"`
	Source                string                      `json:"source"`
	Target                string                      `json:"target"`
	StartedAt             time.Time                   `json:"started_at"`
	CompletedAt           time.Time                   `json:"completed_at"`
	Status                string                      `json:"status"`
	SnapshotTag           string                      `json:"snapshot_tag,omitempty"`
	BackupID              string                      `json:"backup_id,omitempty"`
	BackupHost            string                      `json:"backup_host,omitempty"`
	PreDeployTar          map[string]string           `json:"pre_deploy_tar,omitempty"`
	Changed               map[string][]string         `json:"changed,omitempty"`
	Absent                map[string][]string         `json:"absent,omitempty"`
	Digests               []DigestRow                 `json:"digests,omitempty"`
	SavedManifest         SavedManifest               `json:"saved_manifest"`
	DBRestoredAt          string                      `json:"db_restored_at,omitempty"`
	MigrateStarted        bool                        `json:"migrate_started"`
	ApplyStarted          bool                        `json:"apply_started"`
	DeployIdentity        *DeployIdentity             `json:"deploy_identity,omitempty"`
	RemotePaths           map[string]string           `json:"remote_paths,omitempty"`
	AppliedManifestHash   map[string]string           `json:"applied_manifest_hash,omitempty"`
	PriorManifestIdentity map[string]ManifestIdentity `json:"prior_manifest_identity,omitempty"`
	FilesRestored         map[string]bool             `json:"files_restored,omitempty"`
	RecoveryPhase         string                      `json:"recovery_phase,omitempty"`
}

Record describes one completed promotion and everything its rollback may touch.

func LoadAttempt

func LoadAttempt(root string) (*Record, error)

LoadAttempt reads isolated attempt history, including interrupted apply.

func LoadLatestRecord

func LoadLatestRecord(projectRoot, target string) (*Record, error)

LoadLatestRecord returns a target record only when no different deploy supersedes it.

func LoadRecord

func LoadRecord(projectRoot string) (*Record, error)

LoadRecord reads promote.json; a missing record returns nil, nil.

type Result

type Result struct {
	Status      string       `json:"status"`
	Source      string       `json:"source"`
	Target      string       `json:"target"`
	Steps       []StepResult `json:"steps"`
	Digests     []DigestRow  `json:"digests,omitempty"`
	SnapshotTag string       `json:"snapshot_tag,omitempty"`
	BackupID    string       `json:"backup_id,omitempty"`
	FailedStep  string       `json:"failed_step,omitempty"`
	DryRun      bool         `json:"dry_run,omitempty"`
}

Result is the complete promotion outcome returned to human and JSON callers.

type Runner

type Runner func(context.Context, string) ([]byte, error)

Runner executes a validated command locally or through a deploy.Remote.

func CaptureSourceManifest

func CaptureSourceManifest(ctx context.Context, run Runner, root string) (Runner, []byte, error)

CaptureSourceManifest reads the source manifest and captures its image listing. Inspection is delayed until declarations from the scratch model are available.

type SavedManifest

type SavedManifest struct {
	Host         string   `json:"host"`
	ComposeFiles []string `json:"compose_files,omitempty"`
	EnvFiles     []string `json:"env_files,omitempty"`
}

SavedManifest is the target's compose and env-file manifest before apply.

type SourceImage

type SourceImage struct {
	Service  string
	Ref      string
	Platform string
	Digest   string
}

SourceImage is the per-platform identity captured from a running source.

func CaptureManifestSource

func CaptureManifestSource(ctx context.Context, run Runner, raw []byte, lookup archguard.Lookup) ([]SourceImage, error)

CaptureManifestSource inspects the captured listing using the source's resolved declarations.

func CaptureSource

func CaptureSource(ctx context.Context, run Runner, services []Image, lookup archguard.Lookup) ([]SourceImage, error)

CaptureSource reads running compose images and inspects their platform identities.

Purpose: derive release identity from what the source host actually runs. Inputs: an injected command runner, generated service declarations, optional registry lookup. Outputs: one source image identity per declared service, sorted by service. Constraints: commands contain only shell-quoted image references; no process is started here.

type State

type State struct {
	Source                string
	Target                string
	SourceTier            controlplane.Tier
	TargetTier            controlplane.Tier
	SnapshotTag           string
	BackupID              string
	BackupHost            string
	DBRestoredAt          string
	MigrateStarted        bool
	ApplyStarted          bool
	PriorManifestIdentity map[string]ManifestIdentity
	FilesRestored         map[string]bool
	RecoveryPhase         string
	RecoveryCheckpoint    func(*State) error
	Digests               []DigestRow
	PreDeployTar          map[string]string
	PreDeployChanged      map[string][]string
	PreDeployAbsent       map[string][]string
	RemotePaths           map[string]string
	AppliedManifestHash   map[string]string
	Values                map[string]any
	DryRun                bool
}

State is the mutable data shared by promotion steps.

Purpose: carry resolved promotion inputs and rollback evidence between steps. Inputs: command wiring initializes environment and tier fields; steps fill evidence. Outputs: Engine.Run copies public outcome fields into Result. Constraints: Values is opaque wiring state; this package does not interpret it.

type Step

type Step struct {
	Name string
	Run  func(context.Context, *State) error
	Undo func(context.Context, *State) error
}

Step is one promotion action and its compensating action.

func HealthStep

func HealthStep(r deploy.Remote, remotePath string) Step

HealthStep checks the target primary and is reused after rollback.

func MigrateStep

func MigrateStep(r deploy.Remote, remotePath string) Step

MigrateStep runs target migrations. Engine marks MigrateStarted first.

func SaveStep

func SaveStep(r deploy.Remote, remotePath string) Step

SaveStep reads the target manifests and stores them in State for the record.

func SnapshotStep

func SnapshotStep(r deploy.Remote, remotePath, tag string) Step

SnapshotStep creates a verified target backup and restores it on undo.

func SourceHealthStep

func SourceHealthStep(r deploy.Remote, remotePath string) Step

SourceHealthStep checks the source primary without changing it.

type StepResult

type StepResult struct {
	Name   string `json:"name"`
	Status string `json:"status"`
	Detail string `json:"detail,omitempty"`
}

StepResult is one deterministic plan or execution result row.

Jump to

Keyboard shortcuts

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