deployurls

package
v0.8.5 Latest Latest
Warning

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

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

Documentation

Overview

Package deployurls keeps an immutable hostname for each recent successful deploy: a retained service that runs that attempt's pinned image and sleeps when idle, so a past deployment can be opened without rolling back.

Index

Constants

View Source
const (
	// EnvKeep is how many recent successful deploys per app keep a URL; 0 turns the feature off.
	EnvKeep = "APP_DEPLOY_URL_KEEP"
	// EnvIdleMinutes is how long a retained deploy runs without traffic before it sleeps.
	EnvIdleMinutes = "APP_DEPLOY_URL_IDLE_MINUTES"
	// EnvInterval is how often the syncer looks for new deploys.
	EnvInterval = "APP_DEPLOY_URL_INTERVAL"
)

Environment variables that tune deploy URLs.

View Source
const (
	DefaultKeep        = 3
	DefaultIdleMinutes = 5
	DefaultInterval    = time.Minute
)

Defaults for the variables above.

View Source
const DefaultMaxUnready = 3

DefaultMaxUnready matches the few restarts the crash backoff allows before it plateaus.

View Source
const EnvMaxUnready = "APP_DEPLOY_URL_MAX_UNREADY"

EnvMaxUnready is how many readiness failures in a row a retained deploy service may have before it is suspended instead of retried.

Variables

This section is empty.

Functions

func Clone

Clone is the retained service for w: the app's config restored to that attempt, running the pinned image, with no volumes, host ports, hooks or automatic rollback, so an old deploy cannot touch live data or fight the app.

func Key

func Key(a store.DeployAttempt) string

Key is the short, DNS-safe identity of an attempt: the commit when it has one, else its id.

func MaxUnreadyFromEnv

func MaxUnreadyFromEnv(getenv func(string) string) int

MaxUnreadyFromEnv reads EnvMaxUnready, falling back to the default.

func ServiceName

func ServiceName(app, key string) string

ServiceName is the retained service for app and key; it doubles as the host label.

Types

type Config

type Config struct {
	Keep        int
	IdleMinutes int
	Interval    time.Duration
}

Config is the environment-driven tuning.

func ConfigFromEnv

func ConfigFromEnv(getenv func(string) string) Config

ConfigFromEnv reads the Env* variables, using defaults for anything missing or malformed.

func FromProcessEnv

func FromProcessEnv() Config

FromProcessEnv is ConfigFromEnv over the process environment.

func (Config) Enabled

func (c Config) Enabled() bool

Enabled reports whether any URLs are kept.

type Guard

type Guard struct {
	Store GuardStore
	Max   int
	// contains filtered or unexported fields
}

Guard bounds the retries of retained deploy services and lets them resolve their app's secrets. It outlives the per-pass controllers.

func (*Guard) IsRetained

func (g *Guard) IsRetained(ctx context.Context, service string) bool

IsRetained reports whether service is a retained deploy service.

func (*Guard) NoteReady

func (g *Guard) NoteReady(service string)

NoteReady forgets service's failure count.

func (*Guard) NoteUnready

func (g *Guard) NoteUnready(ctx context.Context, service string) (retained, stopped bool, err error)

NoteUnready records a readiness failure of service. For a retained deploy service that reaches Max it suspends the service (containers are torn down by the normal suspend path) and reports stopped. Other services are untouched.

type GuardStore

type GuardStore interface {
	DeployURLApp(ctx context.Context, serviceName string) (string, bool, error)
	UpdateServiceSuspended(ctx context.Context, name string, suspended bool) error
}

GuardStore is what Guard needs; *store.DB satisfies it.

type ParentSecrets

type ParentSecrets struct {
	Inner SecretReader
	Apps  interface {
		DeployURLApp(ctx context.Context, serviceName string) (string, bool, error)
	}
}

ParentSecrets resolves a retained deploy service's secrets under its app's name, so the clone sees the same secret env without a stored copy of the values.

func (ParentSecrets) Exists

func (p ParentSecrets) Exists(ctx context.Context, service, key string) (bool, error)

Exists implements SecretReader.

func (ParentSecrets) Resolve

func (p ParentSecrets) Resolve(ctx context.Context, service, key string) (string, error)

Resolve implements SecretReader.

type SecretReader

type SecretReader interface {
	Exists(ctx context.Context, serviceName, envKey string) (bool, error)
	Resolve(ctx context.Context, serviceName, envKey string) (string, error)
}

SecretReader is the secrets surface the application controller uses.

type Store

type Store interface {
	ListDesiredServices(ctx context.Context) ([]store.DesiredService, error)
	SaveDesiredService(ctx context.Context, svc store.DesiredService) error
	ListDeployAttempts(ctx context.Context, serviceName string) ([]store.DeployAttempt, error)
	ListRollbackPins(ctx context.Context, serviceName string) ([]store.RollbackPin, error)
	SetAppSleepIdle(ctx context.Context, serviceName string, minutes int, now time.Time) error
	SetAppSleepHold(ctx context.Context, serviceName string, hold bool, now time.Time) error
	ListDeployURLs(ctx context.Context, appName string) ([]store.DeployURL, error)
	SaveDeployURL(ctx context.Context, u store.DeployURL) error
	DeleteDeployURL(ctx context.Context, serviceName string) error
}

Store is what the syncer needs; *store.DB satisfies it.

type Syncer

type Syncer struct {
	Store  Store
	Config Config
	// HostFor returns the hostname for a retained service, or "" when none can be formed.
	HostFor func(ctx context.Context, serviceName string) string
	// Remove deletes a retained service and tears its containers down.
	Remove func(ctx context.Context, serviceName string) error
	// Nudge asks the reconcilers to run now.
	Nudge  func()
	Now    func() time.Time
	Logger *slog.Logger
	// contains filtered or unexported fields
}

Syncer reconciles retained deploy services against each app's recent deploys.

func (*Syncer) Run

func (s *Syncer) Run(ctx context.Context) error

Run syncs every Config.Interval until ctx ends.

func (*Syncer) Sync

func (s *Syncer) Sync(ctx context.Context) error

Sync runs one pass. A failure on one app is logged and does not stop the rest.

type Wanted

type Wanted struct {
	Attempt     store.DeployAttempt
	Key         string
	ServiceName string
	Pin         *store.RollbackPin
	Ref         string
	// Live is true while the attempt is what the app runs now: the app's own URL serves it.
	Live bool
}

Wanted is one deploy attempt that should have a URL.

func Plan

func Plan(app store.DesiredService, attempts []store.DeployAttempt, pins []store.RollbackPin, keep int) []Wanted

Plan picks the newest keep successful attempts whose content can still be redeployed (a registry digest or a rollback pin). Two attempts of the same commit share one URL, the newest. Image GC is untouched: it only frees what no pin or running service holds.

Jump to

Keyboard shortcuts

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