selfupdate

package
v0.8.64 Latest Latest
Warning

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

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

Documentation

Overview

Package selfupdate powers `dejima update`. Dejima installs two ways, so it updates two ways (the "dual-mode" epic):

  • source mode — a dev/server box with the repo checked out, installed via `make install`. Updating means `git pull` + rebuild + reinstall.
  • release mode — a client that installed a tagged binary (install.sh / a release asset). Updating means fetching the latest release binary and replacing the running one.

The mode is inferred from the build version: a real semver release (stamped via -ldflags at `make release`) means release mode; "dev"/a git-describe string means a source checkout.

This file is the *read-only* foundation: detect the mode and report whether a newer release exists. The mutating steps (git pull/rebuild; download/replace/ restart) are layered on top deliberately, behind their own review.

Index

Constants

This section is empty.

Variables

View Source
var ErrReleaseApplyUnsupported = errors.New("automatic apply for release installs isn't supported yet")

ErrReleaseApplyUnsupported marks the not-yet-built release download path, so the command can print manual steps instead of failing opaquely.

View Source
var TokenFallback func() string

githubToken returns a GitHub token from the environment, if any, used to lift the release-check off the unauthenticated 60/hr rate limit (→ 5000/hr). TokenFallback, when set, supplies a GitHub token for the release-check API calls if neither GITHUB_TOKEN nor GH_TOKEN is set — so a daemon (or client) that already has a connected GitHub identity authenticates its update checks (5000/hr) instead of sharing the anonymous 60/hr-per-IP limit. Wired at startup to the connected identity; kept as a hook so selfupdate needn't import the identity store (and stays usable with no token at all).

Functions

func ApplyReleaseSelf

func ApplyReleaseSelf(ctx context.Context, ver string, out io.Writer) error

ApplyReleaseSelf updates the *running* executable to ver: it downloads the matching release, verifies it, and atomically replaces this binary in place. The install dir must be writable (the Windows client lives under LOCALAPPDATA; a root-owned /usr/local/bin needs elevation — caller surfaces that error).

func ApplySource

func ApplySource(ctx context.Context, dir string, execute bool, out io.Writer, run Runner) error

ApplySource updates a source install. It preflights (a clean dejima checkout that can fast-forward), then either prints the plan (execute=false, the default) or runs it. It never force-merges or discards local work: a dirty or diverged tree is a hard stop, not something to paper over.

func AssetName

func AssetName(ver, goos, goarch string) string

AssetName returns the release archive name for a platform, matching the names produced by `make release-binaries` (see .github/workflows/release.yml): dejima_<ver>_<os>_<arch>.tar.gz, or .zip on Windows.

func FetchBinary

func FetchBinary(ctx context.Context, ver, goos, goarch, binName, destPath string) error

FetchBinary downloads the release asset for (ver, goos, goarch), verifies it against the release's SHA256SUMS, and extracts the binary named binName (e.g. "dejima", "dejima.exe", "dejimad") to destPath (0755).

func FindCheckout

func FindCheckout(start string) (string, error)

FindCheckout walks up from start looking for the dejima source tree (a go.mod declaring this module). Returns an error with guidance if none is found.

func LatestRelease

func LatestRelease(ctx context.Context) (string, error)

LatestRelease returns the tag of the newest published (non-prerelease) release.

func PrepareSource

func PrepareSource(ctx context.Context, dir string, out io.Writer, run Runner) error

PrepareSource runs every source-update step EXCEPT the final restart: preflight, fast-forward the checkout, reinstall both binaries. The restart is deliberately left to the caller because it kills the running daemon — so the daemon's self-update can do this part synchronously (and report failures to the client) and only background the restart. Returns a wrapped error naming the step that failed.

func ReplaceExecutable

func ReplaceExecutable(newPath, target string) error

ReplaceExecutable atomically swaps target with the binary at newPath (same directory). On Windows a running .exe can't be overwritten, so the running one is renamed aside first (and rolled back on failure).

func ResolveSourceDir added in v0.8.21

func ResolveSourceDir() string

ResolveSourceDir locates the git checkout a source install was built from, for recording in InstallMeta. Returns "" when it genuinely cannot be found.

Tries three things in order, because the single cwd-derived lookup this replaces was the reason `service install` could silently DESTROY a working record: the meta is written whole, so a run from outside the checkout (say `sudo dejima service install --system` typed from $HOME) resolved nothing, wrote SourceDir:"" over a good value, and left the daemon unable to update itself. Preserving a previously recorded checkout is the important part.

func SaveInstallMeta

func SaveInstallMeta(m InstallMeta) error

SaveInstallMeta writes the install context (0600).

func SourcePreflight

func SourcePreflight(ctx context.Context, dir string) error

SourcePreflight verifies dir is a dejima git checkout with a clean tree (safe to fast-forward + reinstall). Shared by ApplySource and the daemon's self-update so neither force-merges or clobbers local work.

Types

type InstallMeta

type InstallMeta struct {
	// SourceDir is the git checkout a source install was built from (""for a
	// release/binary install — it updates by download instead).
	SourceDir string `json:"source_dir,omitempty"`
	// System is true when installed as a system service (macOS system
	// LaunchDaemon), so a self-restart must target the system domain.
	System bool `json:"system"`
}

InstallMeta is what `dejima service install` records for later self-update.

func LoadInstallMeta

func LoadInstallMeta() (InstallMeta, error)

LoadInstallMeta reads the install context. A missing file yields a zero InstallMeta (no error) — an older install that predates this metadata.

func (InstallMeta) RestartArgs

func (m InstallMeta) RestartArgs() []string

RestartArgs returns the `dejima` args that restart the service in the right domain (system installs need --system).

type Mode

type Mode string

Mode is how this install updates itself.

const (
	ModeSource  Mode = "source"  // repo checkout — git pull + make install
	ModeRelease Mode = "release" // tagged binary — fetch + replace the release asset
)

func DetectMode

func DetectMode() Mode

DetectMode infers the install mode from the build version. A real semver release was produced by `make release` (a packaged client build); anything else ("dev", a git-describe string) is a working checkout.

type ReleaseInfo added in v0.8.40

type ReleaseInfo struct {
	Tag   string
	Notes string
	URL   string
}

ReleaseInfo is the newest published release: its tag, its notes (the curated release body — the source of the in-app "what's in this update" blurb), and the URL of its release page ("view more").

func LatestReleaseInfo added in v0.8.40

func LatestReleaseInfo(ctx context.Context) (ReleaseInfo, error)

LatestReleaseInfo returns the newest published release's tag, notes, and page URL in one request. The notes are the release body we curate on every release; the TUI shows a blurb of it in the update confirm so an operator sees WHAT the update is before applying it (with the URL to read the rest).

type Runner

type Runner func(ctx context.Context, dir, name string, args ...string) error

Runner executes a command in dir (empty = current dir), streaming its output. Injected so apply logic is testable without mutating the host.

func ExecRunner

func ExecRunner(out io.Writer) Runner

ExecRunner runs commands for real, streaming combined output to out.

type Status

type Status struct {
	Current         string // this build's version
	Latest          string // newest published release tag
	Mode            Mode
	UpdateAvailable bool
}

Status is the result of an update check.

func Check

func Check(ctx context.Context) (Status, error)

Check fetches the latest release and evaluates it against this build.

func Evaluate

func Evaluate(current, latest string, mode Mode) Status

Evaluate compares the current version against the latest tag for the given mode. Pure (no I/O) so the decision is testable; Check wires it to the network.

Jump to

Keyboard shortcuts

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