binarymgr

package
v1.101.0 Latest Latest
Warning

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

Go to latest
Published: Jun 1, 2026 License: MIT Imports: 19 Imported by: 0

Documentation

Overview

Package binarymgr provides a reusable lifecycle for managed CLI binaries distributed through a GitLab project's Generic Package Registry. Each consumer describes its binary with a Spec and gets download, checksum verification, atomic install, scheduled update checks, and run-time pass-through orchestration in return.

Index

Constants

This section is empty.

Variables

View Source
var ErrUnsupportedPlatform = errors.New("unsupported platform")

ErrUnsupportedPlatform is returned when the running OS or architecture is not supported by the Spec.

Functions

func ManagedBinaryPath

func ManagedBinaryPath(spec Spec) (string, error)

ManagedBinaryPath returns the absolute path where Spec's binary lives after installation. Used by callers that need to compare against a user-configured custom path.

Types

type BinaryInfo

type BinaryInfo struct {
	Path     string
	Version  string
	Checksum string
}

BinaryInfo describes an installed (or located) managed binary.

type EnsureResult

type EnsureResult struct {
	Info *BinaryInfo

	// Downloaded is true when this call actually downloaded and installed
	// the binary (vs. returning an existing installation or a custom path).
	Downloaded bool

	// AutoDownloadPreference is set to "true" when the user opted into
	// automatic future downloads during the prompt. Empty otherwise.
	AutoDownloadPreference string
}

EnsureResult is what EnsureInstalled returns: the resolved binary plus metadata the runner needs to react to.

type Executor

type Executor func(ctx context.Context, binaryPath string, args []string) error

Executor runs the resolved binary with the given args. The binarymgr package leaves this to consumers because the right strategy is platform-specific (syscall.Exec on Unix, subprocess on Windows) and may also need to inject distribution-specific environment variables.

type Extractor

type Extractor func(srcPath, destDir string) (binaryPath string, err error)

Extractor pulls the executable out of a downloaded asset and writes it to destDir. It returns the path to the resulting binary file.

func TarGzExtractor

func TarGzExtractor(binaryName string) Extractor

TarGzExtractor returns an Extractor that opens a .tar.gz archive, locates the entry whose basename matches binaryName, and writes it to destDir as an executable file. Symlinks and hardlinks are skipped. Entries whose resolved path escapes destDir are rejected (zip-slip).

func ZipExtractor added in v1.101.0

func ZipExtractor(binaryName string) Extractor

ZipExtractor returns an Extractor that opens a .zip archive, locates the entry whose basename matches binaryName, and writes it to destDir as an executable file. Entries whose resolved path escapes destDir are rejected (zip-slip). Directories and non-regular entries are skipped.

type Manager

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

Manager handles the lifecycle (install, update, validate) of a single managed binary described by Spec.

func NewManager

func NewManager(io *iostreams.IOStreams, spec Spec) *Manager

NewManager constructs a Manager for spec. Network requests use an unauthenticated client because package downloads are public.

func (*Manager) CheckForUpdate

func (m *Manager) CheckForUpdate(ctx context.Context, currentVersion string, lastCheckTime time.Time, forceCheck bool) (UpdateCheck, error)

CheckForUpdate reports whether a newer compatible version exists. If the latest upstream version exceeds Spec.MaxCompatibleMajor, HasUpdate is false and NewMajorVersion is set so callers can surface the gating to the user.

func (*Manager) EnsureInstalled

func (m *Manager) EnsureInstalled(ctx context.Context, installedVersion, installedPath, autoDownload string) (*EnsureResult, error)

EnsureInstalled returns a usable binary path, prompting the user to download if necessary. installedPath/installedVersion come from saved config. If installedPath points outside the managed install directory it is treated as a user-provided custom binary and returned without download.

func (*Manager) Update

func (m *Manager) Update(ctx context.Context) (*BinaryInfo, error)

Update downloads and installs the latest version unconditionally.

type Platform

type Platform struct {
	OS   string
	Arch string
}

Platform is the resolved (OS, arch) pair for the running host. arch is already normalized to the upstream naming used by Spec.AssetName.

type Runner

type Runner struct {
	IO       *iostreams.IOStreams
	Cfg      config.Config
	Spec     Spec
	Manager  *Manager
	Executor Executor

	// Update / Install / Yes mirror the glab-owned flags after the
	// caller has parsed them out of the cobra args. Args holds the
	// remaining pass-through args destined for the managed binary.
	Update  bool
	Install bool
	Yes     bool
	Args    []string

	// UpdateCommand is the glab subcommand chain shown to users in the
	// "Run 'glab X --update'" hint (e.g. "duo cli", "orbit local").
	// Defaults to Spec.ConfigPrefix if empty.
	UpdateCommand string
}

Runner orchestrates the per-invocation lifecycle: ensure the binary is installed, prompt for run consent, save metadata, schedule a background update check, then hand off to Executor.

func (*Runner) HandleInstall

func (r *Runner) HandleInstall(ctx context.Context) error

HandleInstall installs (or refreshes) the managed binary without running it. If the user has configured a custom path, the path is reported and nothing is downloaded.

func (*Runner) HandleUpdate

func (r *Runner) HandleUpdate(ctx context.Context) error

HandleUpdate forces an update check and applies any newer compatible version. If nothing is installed yet, it falls back to a fresh install.

func (*Runner) Run

func (r *Runner) Run(ctx context.Context) error

Run executes the default flow: ensure installed, prompt for consent (when needed), and exec the binary with Args.

func (*Runner) SaveBinaryInfo

func (r *Runner) SaveBinaryInfo(info *BinaryInfo) error

SaveBinaryInfo writes path/version/checksum to config and persists.

func (*Runner) ShouldForceUpdateCheck

func (r *Runner) ShouldForceUpdateCheck() bool

ShouldForceUpdateCheck returns true when the spec's force-update env var is "true". Useful for tests and CI that want to bypass the 24h cache.

type Spec

type Spec struct {
	// DisplayName appears in user-facing prompts and log lines
	// (e.g. "GitLab Duo CLI", "Orbit local CLI").
	DisplayName string

	// ProjectID is the GitLab project ID that hosts the generic package.
	ProjectID string

	// PackageName is the generic-package name (e.g. "duo-cli", "orbit-local").
	PackageName string

	// ConfigPrefix is the config-key namespace. Keys are derived as
	// <prefix>_binary_path, _binary_version, _binary_checksum,
	// _last_update_check, _auto_run, _auto_download.
	ConfigPrefix string

	// EnvVarPrefix is the env-var namespace. Variables are derived as
	// <prefix>_BINARY_PATH, _CHECK_UPDATE.
	EnvVarPrefix string

	// MaxCompatibleMajor caps automatic updates to this major version.
	// 0 disables the cap (every newer version is considered compatible).
	MaxCompatibleMajor int

	// SupportedOS lists the GOOS values the binary is published for.
	SupportedOS []string

	// NormalizeArch converts (GOOS, GOARCH) into the upstream arch name
	// used in asset filenames (e.g. amd64 -> "x64" for duo, "x86_64"
	// for orbit). Should return ErrUnsupportedPlatform-wrapped errors
	// for unsupported combinations.
	NormalizeArch func(goos, goarch string) (string, error)

	// AssetName returns the upstream asset filename for a (os, arch) pair
	// (e.g. "duo-darwin-arm64", "orbit-local-darwin-aarch64.tar.gz").
	AssetName func(os, arch string) string

	// InstalledName returns the local filename of the installed binary
	// (e.g. "duo", "duo.exe", "orbit"). The install directory is shared
	// across managed binaries (<config-dir>/bin).
	InstalledName func(os string) string

	// Extract optionally transforms the downloaded asset into a binary on
	// disk. nil means the downloaded file IS the binary. TarGzExtractor is
	// the typical choice for tarball-distributed binaries.
	Extract Extractor
}

Spec describes a single managed binary. Everything that varies between consumers (project, naming, supported platforms, optional tarball extraction) lives here; the Manager and Runner contain no consumer-specific strings.

type UpdateCheck

type UpdateCheck struct {
	HasUpdate       bool
	LatestVersion   string
	NewMajorVersion string // set when latest exceeds Spec.MaxCompatibleMajor
	NewCheckTime    time.Time
}

UpdateCheck is the result of CheckForUpdate. NewCheckTime is non-zero when the call actually contacted the registry; callers should persist it.

Jump to

Keyboard shortcuts

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