updater

package
v1.111.3 Latest Latest
Warning

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

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

README

Updater

This package implements an updater in Golang that automatically updates binaries.

Usage

There's a few different ways to use the updater. Our best integration is with the urfave/cli framework, which is a very popular framework for writing command line applications.

urfave/cli integration

To use this, simply take your existing cli.App and create a new one with the NewUpdater function.

func main() {
  a := &cli.App{}

  // Note: If you're using logrus (highly recommended) you'll also want to do
  // updater.WithLogger(log)
	if _, err := updater.UseUpdater(ctx, updater.WithApp(a)); err != nil {
    // Do something better than panic ;)
		panic(err)
	}
}

This will automatically update your application if there's an update available, as well as expose commands on the updater sub-command, such as:

  • updater set-channel <channel> - set the current channel (release channel) this application is using
  • updater get-channels - list all available release channels for the current application
  • updater use <version> - replaces the current binary with a specific version of the application
  • updater rollback - rollback to the previous version of the application used before the last update
  • updater status - get information on the updater
Other Places

You can use the updater.UseUpdater function in other places as well, but you will not get the tooling provided by the urfave/cli framework version (such as the ability to set the current release channel).

Example:

func main() {
  updated, err := updater.UseUpdater(context.Background())
  if err != nil {
    panic(err)
  }

  if updated {
    // tell user to restart their application
    fmt.Println("Updated. Please restart your application")
  }
}

How the Updater Works / Requirements

The updater works by reading version information out of the current binary and using git tags on the remote repository to source release versions / channels. The only hard requirement, at a minimum, of the updater is that the binary must use the pkg/app package as well as use semantic versioning.

The updater derives the current version and release channel from a version string. The version string comes from normal semantic versioning, e.g. v1.0.0 -> 1.0.0. A channel comes from the pre-release field of a semantic-version, e.g. v1.0.0-alpha.1 -> alpha. If there is no pre-release field, the channel is stable.

Mutable Tags

Another concept supported by the updater is a concept called "mutable tags", this allows you to release code with binaries while not increase the version number. This is useful for HEAD based development where you don't want to release a new version every time you make a change, but you do want it to still be testable.

For example, and this is how Outreach does CLI tooling releasing, you could use mutable tags to create a flow like this:

  • Merges into main go to unstable
  • Merges into rc branch go to rc
  • Merges into release go to stable

This would be done by doing the following via CI:

  • main: Create a Github Release (or tag) named unstable on the latest commit
  • rc: Force-push rc with the contents of main, then create a Github Release (or tag) with a rc pre-release version (v1.0.0-rc.1 for example)
  • release: Force-push release with the contents of rc, then create a Github Release (or tag) without a pre-release version (v1.0.0 for example)

The updater would then consider the list of channels to be stable, unstable, and rc respectively

Note: This doesn't cover uploading release binaries to CI, which is also something you'd need to do. The updater supports the following archive types: .tar .tar.gz .tar.xz .tar.bz2 .zip. The name must be of a certain format, which is documented in updater_test.go (Test_generatePossibleAssetNames) and must contain the binary with the same name as the current executable.

Documentation

Overview

Description: Provides miscellaneous helpers for the updater

Package updater implements an updater for CLIs that support multiple channels and version checks

Index

Constants

This section is empty.

Variables

View Source
var (
	// ConfigVersion is the current version of the configuration schema.
	ConfigVersion = 1

	// ConfigFile is the non-HOME containing path to the config file for the updater
	ConfigFile = filepath.Join(".outreach", ".config", "updater", "config.yaml")
)

This block contains constants for the updater's configuration and cache files.

View Source
var Disabled = "false"

Disabled globally disables the automatic updater. This is helpful for when using an external package manager, such as brew. This should usually be done with an ldflag:

go run -ldflags "-X github.com/getoutreach/gobox/pkg/cli/updater.Disabled=true" ...

or you can do it in main() before UseUpdater is called:

updater.Disabled = "true"

Any value other than "true" is considered false. The type is string to allow for invoking via `go run -ldflags "-X ..."`.

View Source
var ForceFlag = BoolFlag{
	Name:  "force-update-check",
	Usage: "Force checking for an update",
}

ForceFlag is a CLI flag used to force the updater check.

View Source
var SkipFlag = BoolFlag{
	Name:  "skip-update",
	Usage: "Skips the updater check",
}

SkipFlag is a CLI flag used to skip the updater check.

View Source
var UpdaterFlags = []cliV2.Flag{
	SkipFlag.ToUrfaveV2(),
	ForceFlag.ToUrfaveV2(),
}

The urfave (V2) flags the updater will inject.

View Source
var UpdaterFlagsV3 = []cliV3.Flag{
	SkipFlag.ToUrfaveV3(),
	ForceFlag.ToUrfaveV3(),
}

The urfave (V3) flags the updater will inject.

Functions

func UseUpdater

func UseUpdater(ctx context.Context, opts ...Option) (*updater, error)

UseUpdater creates an automatic updater.

Types

type BoolFlag added in v1.107.0

type BoolFlag struct {
	// The name of the flag, sans the leading double-hyphen.
	Name string
	// The short description of the flag.
	Usage string
}

BoolFlag is a CLI library-agnostic representation of a CLI boolean flag.

func (*BoolFlag) ToUrfaveV2 added in v1.107.0

func (f *BoolFlag) ToUrfaveV2() cliV2.Flag

func (*BoolFlag) ToUrfaveV3 added in v1.107.0

func (f *BoolFlag) ToUrfaveV3() cliV3.Flag

type CLIArgs added in v1.107.0

type CLIArgs interface {
	First() string
	// Get returns the value of the argument at the given index.
	Get(index int) string
}

CLIArgs is an interface for urfave/cli/v2.Args and urfave/cli/v3.Args.

type CLICmd added in v1.107.0

type CLICmd struct {
	V2 *cliV2.Context
	V3 *cliV3.Command
}

CLICmd is an interface for urfave/cli/v2.Command and urfave/cli/v3.Command.

func CmdForV2 added in v1.107.0

func CmdForV2(ctx *cliV2.Context) *CLICmd

func CmdForV3 added in v1.107.0

func CmdForV3(cmd *cliV3.Command) *CLICmd

func (*CLICmd) Args added in v1.107.0

func (c *CLICmd) Args() CLIArgs

func (*CLICmd) Bool added in v1.107.0

func (c *CLICmd) Bool(name string) bool

func (*CLICmd) String added in v1.107.0

func (c *CLICmd) String(name string) string

type Command added in v1.107.0

type Command struct {
	Name     string
	Usage    string
	Commands []*Command
	Flags    []Flag
	Action   CommandAction
}

Command is a CLI library-agnostic representation of a CLI (sub)command.

func (*Command) ToUrfaveV2 added in v1.107.0

func (c *Command) ToUrfaveV2() *cliV2.Command

ToUrfaveV2 converts the command to a urfave/cli/v2.Command.

func (*Command) ToUrfaveV3 added in v1.107.0

func (c *Command) ToUrfaveV3() *cliV3.Command

ToUrfaveV3 converts the command to a urfave/cli/v3.Command.

type CommandAction added in v1.107.0

type CommandAction func(ctx context.Context, c *CLICmd) error

type Config added in v1.106.0

type Config struct {
	Version int `yaml:"version"`

	// GlobalConfig is the global configuration for the updater
	GlobalConfig *UpdateConfiguration `yaml:"global"`

	// PerRepositoryConfiguration is configuration for each repository
	PerRepositoryConfiguration map[string]*UpdateConfiguration `yaml:"perRepository"`

	// UpdaterCache contains the cache for the updater
	UpdaterCache map[string]updateCache `yaml:"cache,omitempty"`
}

Config is the configuration for the updater.

func ReadConfig added in v1.106.0

func ReadConfig() (*Config, error)

ReadConfig loads the configuration for the updater.

func (*Config) Get added in v1.106.0

func (c *Config) Get(repoURL string) (UpdateConfiguration, bool)

Get returns a copy of a specific repository's configuration.

func (*Config) GetGlobal added in v1.106.0

func (c *Config) GetGlobal() UpdateConfiguration

/ GetGlobal returns a copy of the global configuration.

func (*Config) Save added in v1.106.0

func (c *Config) Save() error

Save saves the changes to the configuration.

func (*Config) Set added in v1.106.0

func (c *Config) Set(repoURL string, conf *UpdateConfiguration)

Set updates a repository's configuration. Call Save() to save the changes.

func (*Config) SetGlobal added in v1.106.0

func (c *Config) SetGlobal(conf *UpdateConfiguration)

SetGlobal updates the global configuration. Call Save() to save the changes.

type Flag added in v1.107.0

type Flag interface {
	// ToUrfaveV2 converts the flag to a urfave/cli/v2.Flag.
	ToUrfaveV2() cliV2.Flag
	// ToUrfaveV3 converts the flag to a urfave/cli/v3.Flag.
	ToUrfaveV3() cliV3.Flag
}

type Option

type Option func(*updater)

Options configures an updater

func WithApp

func WithApp(app *cliV2.App) Option

WithApp sets the cli/v2.App to setup commands on.

func WithAppV3 added in v1.107.0

func WithAppV3(cmd *cliV3.Command) Option

WithApp sets the cli/v3.App to setup commands on.

func WithChannel

func WithChannel(channel string) Option

WithChannel sets the channel to use for checking for updates

func WithCheckInterval

func WithCheckInterval(interval time.Duration) Option

WithCheckInterval sets the interval to check for updates. Defaults to 30 minutes.

func WithDisabled

func WithDisabled(disabled bool) Option

WithDisabled sets if we should disable the updater or not

func WithExecutableName deprecated

func WithExecutableName(execName string) Option

WithExecutableName overrides the name of the executable. See u.executablePath.

Deprecated: Use WithExecutablePath

func WithExecutablePath added in v1.53.2

func WithExecutablePath(execPath string) Option

WithExecutablePath overrides the path of the executable. See u.executablePath.

func WithForceCheck

func WithForceCheck(forceCheck bool) Option

WithForceCheck sets whether or not to force the updater to check for updates otherwise updates are checked for only if the last check was more than the update check interval.

func WithLogger

func WithLogger(logger logrus.FieldLogger) Option

WithLogger sets the logger to use for logging. If not set a io.Discard logger is created.

func WithNoProgressBar

func WithNoProgressBar(noProgressBar bool) Option

WithNoProgressBar sets whether or not to show the progress bar.

func WithPrereleases deprecated

func WithPrereleases(_ bool) Option

Deprecated: Set the channel via the WithChannel option. WithPrereleases sets whether or not to include prereleases in the update check.

func WithRepoURL

func WithRepoURL(repo string) Option

WithRepoURL sets the repository to use for checking for updates. The expected format is: https://<host>/<repo> Note: It should not contain .git at the end

func WithSkipInstall

func WithSkipInstall(skipInstall bool) Option

WithSkipInstall sets whether or not to skip the installation of the update

func WithSkipMajorVersionPrompt

func WithSkipMajorVersionPrompt(skip bool) Option

WithSkipMajorVersionPrompt sets whether or not to skip the prompt for major version upgrades

func WithVersion

func WithVersion(version string) Option

WithVersion sets the version to use as the current version when checking for updates. Defaults to app.Info().Version.

type StringFlag added in v1.107.0

type StringFlag struct {
	// The name of the flag, sans the leading double-hyphen.
	Name string
	// The short description of the flag.
	Usage string
	// The default value of the flag.
	Value string
}

StringFlag is a CLI library-agnostic representation of a CLI string flag.

func (*StringFlag) ToUrfaveV2 added in v1.107.0

func (f *StringFlag) ToUrfaveV2() cliV2.Flag

func (*StringFlag) ToUrfaveV3 added in v1.107.0

func (f *StringFlag) ToUrfaveV3() cliV3.Flag

type UpdateConfiguration added in v1.106.0

type UpdateConfiguration struct {
	// CheckEvery is the interval at which the updater will check for updates
	// for the provided tool.
	CheckEvery time.Duration `yaml:"checkEvery,omitempty"`

	// Channel is the channel to use for this tool
	Channel string `yaml:"channel,omitempty"`

	// SkipPaths is a list of path substrings to skip when checking for updates.
	// For example, if you want to skip all installations from Homebrew, add the
	// path "/usr/local/Cellar/" to this list.
	// This is useful for tools that are installed in multiple ways, such as
	// Homebrew and mise. This specifically checks the absolute executable path,
	// as determined by `pkg/exec.ResolveExecutable()`.
	SkipPaths []string `yaml:"skipPaths,omitempty"`
}

UpdateConfiguration is the configuration for a specific tool, or the global configuration.

Directories

Path Synopsis
Package archive contains methods for extracting file(s) from arbitrary archive types.
Package archive contains methods for extracting file(s) from arbitrary archive types.
Package release contains methods that interact with releases from VCS providers that do not exist natively in git.
Package release contains methods that interact with releases from VCS providers that do not exist natively in git.
Package resolver contains a git tag aware version resolver that supports channels to determine the latest version.
Package resolver contains a git tag aware version resolver that supports channels to determine the latest version.

Jump to

Keyboard shortcuts

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