Documentation
¶
Overview ¶
Package upgrade replaces a bare-binary Instance's binary with a newer release without stopping it (ADR 0033, ADR 0034): it verifies the archive, unpacks the new binary next to the old one, runs the new binary's `migrate` while the old one still serves, and only then swaps the file atomically, keeping the old one as `.old`.
Index ¶
Constants ¶
This section is empty.
Variables ¶
var ( // ErrNeedsConfirmation: the release has Upgrade notes and --yes was not given. ErrNeedsConfirmation = errors.New("the release has Upgrade notes: read them above and rerun with --yes") // ErrDowngrade: the requested release is older than the running one. ErrDowngrade = errors.New("refusing to downgrade") )
Errors a caller maps to an exit code or a message.
Functions ¶
func ArchiveName ¶
ArchiveName is the release archive for a version (no leading "v") and platform, as the release build names it.
func DetectContainer ¶
func DetectContainer() string
DetectContainer says "docker" inside a container and "helm" on Kubernetes, "" otherwise.
Types ¶
type Boundaries ¶
type Boundaries struct {
State MajorFloor `json:"state"`
Majors []MajorFloor `json:"majors"`
}
Boundaries is what `sphericon migrate --status --json` prints and the walk reads: the database's schema state and the binary's table of Majors, oldest first, where the Floor of entry N+1 is the last release of Major N (internal/db.Majors).
type GitHub ¶
type GitHub struct {
// contains filtered or unexported fields
}
GitHub reads the public GitHub Releases of the project. It is a Source for `upgrade`, and its LatestRelease is the one question "is there a newer release" that the Release check (ADR 0032) and `upgrade --check` share.
func NewGitHub ¶
NewGitHub points at api.github.com. It honours HTTP_PROXY, HTTPS_PROXY and NO_PROXY.
func NewGitHubAt ¶
NewGitHubAt points at another API root (a test server, GitHub Enterprise); "" is api.github.com.
func (*GitHub) Fetch ¶
Fetch downloads the archive and checksums.txt of a release into a temporary directory.
func (*GitHub) LatestRelease ¶
LatestRelease is the newest stable release (GitHub's `latest`: no prerelease, no draft), without the leading "v".
type MajorFloor ¶
MajorFloor is one Major and the oldest release that runs on its schema.
type Options ¶
type Options struct {
Source Source
Target string // path of the installed binary
Current string // running version, "v0.1.0" or "0.1.0"
Version string // pinned release; empty = the newest the Source has
Platform Platform // zero = this OS and architecture
Yes bool // go past Upgrade notes
Out io.Writer
// Service is the systemd unit the restart hint names; "" = "sphericon".
Service string
// Container names the command to use instead when running inside a container or on
// Kubernetes ("docker" or "helm"), "" on a bare host; nil = detect from the environment.
Container func() string
// Run executes a binary, writing its stdout to stdout; nil = os/exec with the
// process environment and stderr passed through.
Run func(ctx context.Context, bin string, args []string, stdout io.Writer) error
// PostSwap runs after the swap; nil = print the restart command. A later `--restart`
// replaces it with one that restarts the systemd service.
PostSwap func(ctx context.Context, r Result) error
// contains filtered or unexported fields
}
Options is one Upgrade step.
type Platform ¶
type Platform struct{ OS, Arch string }
Platform is the OS and architecture a release archive is built for.
type Release ¶
type Release struct {
Version string // without the leading "v"
ArchiveName string
ArchivePath string
ChecksumsPath string
// Cleanup removes what the source staged; nil when nothing was (a directory source).
Cleanup func()
}
Release is one release's archive and checksums.txt, staged on local disk.
type Result ¶
type Result struct {
Changed bool // false when the Instance already runs the release
Version string // installed release, without the leading "v"
Binary string // the installed path
Old string // the previous binary, kept next to it
}
Result is what a step left on disk.
func Walk ¶
Walk upgrades to the target (Options.Version, or the newest the Source has), going first to the last release of each Major the database has yet to cross, every step a full Step. Inside one Major that is a single step.
The table of Majors lives in the release being installed, not in the running binary, so the walk stages the target, asks it (`migrate --status --json`, which also reads the database) and then installs the Floor of every Major above the database's, oldest first. It needs nothing beyond the target's own archive, so it works offline. That same staged binary carries the changelog of every release up to itself, so the walk prints the Upgrade notes of every release it will install, and waits for --yes, before the first migration or swap; the target is then installed from the staged copy rather than fetched again.
With a directory Source every archive of the walk is checked before the first step, and a missing one refuses the whole Upgrade.
type Source ¶
type Source interface {
// Versions lists the releases it can supply for the platform (without the leading "v").
Versions(ctx context.Context, p Platform) ([]string, error)
// Fetch stages one release (version without the leading "v") for the platform.
Fetch(ctx context.Context, version string, p Platform) (Release, error)
}
Source is where releases come from: a directory of downloaded files, or GitHub Releases. The Major walk asks it for versions and fetches one per step.
type Systemd ¶
Systemd is `upgrade --restart`: it runs the new binary's `migrate` as a transient unit with the service's own User and EnvironmentFile (so the Self-hoster installs no second unit file, ADR 0034), and restarts the service once the binary is swapped.