goupd

package module
v0.4.8 Latest Latest
Warning

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

Go to latest
Published: Jan 11, 2026 License: MIT Imports: 18 Imported by: 4

README

goupd

Go Reference

An auto-updater library for Go applications built with make-go. It handles automatic update checking, downloading, and in-place binary replacement with seamless restarts.

Features

  • Automatic hourly update checks
  • Manual update triggering via SIGHUP
  • Channel-based release management (e.g., stable, testing)
  • Atomic binary replacement
  • Cross-platform support (Linux, macOS, FreeBSD, Windows)
  • Busy state management to prevent updates during critical operations
  • Peer version signaling for cluster-aware updates

Installation

go get github.com/KarpelesLab/goupd

Quick Start

package main

import "github.com/KarpelesLab/goupd"

func main() {
    // Start the auto-updater (only active in production mode)
    goupd.AutoUpdate(false)

    // Your application code here
}

Build Configuration

Most variables are auto-detected from Go's build info at runtime:

Variable Source Description
PROJECT_NAME Auto-detected Derived from module path
GIT_TAG Auto-detected First 7 chars of vcs.revision
DATE_TAG Auto-detected Commit timestamp from vcs.time (YYYYMMDDhhmmss)
VERSION Auto-detected Module version from build info

The following variables should be set at build time via -ldflags:

Variable Description Example
MODE Build mode (DEV or PROD) PROD
CHANNEL Release channel (branch name) master

Example build command:

go build -ldflags "-X github.com/KarpelesLab/goupd.MODE=PROD \
                   -X github.com/KarpelesLab/goupd.CHANNEL=master"

Note: When using make-go, these variables are set automatically.

Environment Variables

Variable Description
GOUPD_DELAY Seconds to delay startup after restart (set automatically)
GOUPD_NOW If set, triggers an immediate update check on startup

API Overview

Auto-Update
// Start the auto-updater
goupd.AutoUpdate(allowTest bool)

// Manually trigger an update check
updated := goupd.RunAutoUpdateCheck()

// Switch to a different release channel
switched := goupd.SwitchChannel("testing")
Busy State Management

Prevent updates during critical operations:

goupd.Busy()
defer goupd.Unbusy()

// Critical operation that shouldn't be interrupted

Or use TryBusy() for non-blocking acquisition:

if goupd.TryBusy() {
    defer goupd.Unbusy()
    // Perform work
}
Version Management
// Get latest version info
version, err := goupd.GetLatest("myproject", "master")

// Check if version matches current
if !version.IsCurrent() {
    // Install the update
    err := version.Install()
}

// Save to a specific path
err := version.SaveAs("/path/to/binary")
Peer Version Signaling

For clustered applications, notify when peers have newer versions:

// Signal a peer's version (triggers update if peer is newer)
goupd.SignalVersion(peerGitTag, peerDateTag)

// With channel filtering
goupd.SignalVersionChannel(peerGitTag, peerDateTag, peerChannel)
Restart Control
// Customize pre-restart behavior
goupd.BeforeRestart = func() {
    // Cleanup before restart
}

// Trigger a restart
goupd.Restart()

Update Server Protocol

The library expects updates to be hosted at HOST (default: https://dist-go.tristandev.net/) with the following structure:

/{project}/LATEST                    # Latest version info (space-separated: date git prefix)
/{project}/LATEST-{channel}          # Channel-specific latest version
/{project}/{prefix}.arch             # Supported architectures (space-separated)
/{project}/{prefix}/{project}_{os}_{arch}.bz2  # Compressed binary

License

MIT License - see LICENSE for details.

Documentation

Overview

Package goupd provides an auto-update mechanism for Go applications built with the make-go build system. It handles checking for updates, downloading new versions, and performing in-place binary replacement with automatic restart.

The package works by connecting to an update server to check for newer versions based on git tags and build dates. When an update is found, it downloads the new binary, replaces the current executable atomically, and restarts the program.

Basic usage:

func main() {
    goupd.AutoUpdate(false) // Start auto-updater in production mode
    // ... rest of your application
}

Index

Constants

This section is empty.

Variables

View Source
var (
	// PROJECT_NAME is the project identifier used for update lookups.
	// It is auto-detected from the module path at runtime, or can be
	// overridden via ldflags if needed.
	PROJECT_NAME string = "unconfigured"

	// MODE indicates the build mode, either "DEV" or "PROD".
	// Auto-updates only run when MODE is "PROD".
	MODE string = "DEV"

	// CHANNEL is the release channel (git branch name) for updates.
	// Typically set at build time from: git rev-parse --abbrev-ref HEAD
	CHANNEL string = ""

	// GIT_TAG is the first 7 characters of the git commit hash,
	// auto-detected from vcs.revision build info. Used to identify
	// the current version and compare with available updates.
	GIT_TAG string = ""

	// DATE_TAG is the commit timestamp in YYYYMMDDhhmmss format,
	// auto-detected from vcs.time build info. Used as a secondary
	// version comparison when git tags differ.
	DATE_TAG string = "0"

	// VERSION is the full version string from Go module info.
	VERSION string = ""

	// HOST is the base URL of the update distribution server.
	HOST string = "https://dist-go.tristandev.net/"
)
View Source
var BeforeRestart func() = shutdown.RunDefer

BeforeRestart is called just before the program is restarted, and can be used to prepare for restart, such as duplicating fds before exec/etc.

View Source
var RestartFunction func() error = RestartProgram

RestartFunction is the function that actually performs the restart, and by default will be RestartProgram which is an OS dependent implementation

View Source
var UnameArchMatch = map[string]string{
	"x86_64":     "amd64",
	"amd64":      "amd64",
	"i686":       "386",
	"powerpc":    "ppc",
	"ppc":        "ppc",
	"ppc64":      "ppc64",
	"armv7l":     "arm",
	"armv6l":     "arm",
	"armv7b":     "armbe",
	"armv6b":     "armbe",
	"aarch64":    "arm64",
	"aarch64_be": "arm64be",
	"armv8b":     "arm64be",
	"armv8l":     "arm64",
	"mips":       "mips",
}

uname -m

View Source
var UnameOsMatch = map[string]string{
	"Linux":    "linux",
	"CYGWIN_*": "windows",
	"MINGW*":   "windows",
	"WIN32":    "windows",
	"WINNT":    "windows",
	"Windows":  "windows",
	"Darwin*":  "darwin",
	"FreeBSD":  "freebsd",
}

uname -s

Functions

func AutoUpdate

func AutoUpdate(allowTest bool)

AutoUpdate initializes the auto-updater system. It logs the current version, sets up a SIGHUP signal handler to trigger manual update checks, and starts a background goroutine that checks for updates hourly.

If allowTest is true, updates are checked even in non-production mode. Otherwise, updates only run when MODE is "PROD".

The function respects the following environment variables:

  • GOUPD_DELAY: If set, delays startup by that many seconds (used after restarts)
  • GOUPD_NOW: If set, triggers an immediate update check instead of waiting

Updates can also be triggered by emitting a "check_update" event via the global emitter.

func Busy added in v0.1.3

func Busy()

Busy marks the program as busy, preventing updates and restarts until Unbusy is called. Multiple goroutines can call Busy concurrently; the program will remain busy until all have called Unbusy. This is useful for protecting critical sections that should not be interrupted by an update.

func Fetch deprecated added in v0.1.4

func Fetch(projectName, curTag, os, arch, channel string, cb func(dateTag, gitTag string, r io.Reader) error) error

Fetch will check for updates and call the provided callback cb if there is an update.

Deprecated: Use GetLatest instead

func GetUpdate deprecated added in v0.1.4

func GetUpdate(projectName, curTag, os, arch, channel string) (string, string, string, error)

GetUpdate returns update details for a given project.

Deprecated: You should be using GetLatest instead

func GetVars added in v0.2.6

func GetVars() map[string]string

GetVars returns all configuration variables as a map of strings. This is useful for debugging or logging the current build configuration.

func Restart added in v0.4.0

func Restart()

Restart triggers a program restart. It first waits for any busy operations to complete (with a 1-hour timeout), calls BeforeRestart for cleanup, then executes RestartFunction to replace the current process with a new instance.

func RestartProgram added in v0.2.2

func RestartProgram() error

func RunAutoUpdateCheck

func RunAutoUpdateCheck() bool

RunAutoUpdateCheck will perform the update check, update the executable and return false if no update was performed. In case of update the program should restart and RunAutoUpdateCheck() should not return, but if it does, it'll return true.

func SignalVersion

func SignalVersion(git, build string)

SignalVersion is called when seeing another peer running the same software to notify of its version. This will check if the peer is updated compared to us, and call RunAutoUpdateCheck() if necessary

func SignalVersionChannel added in v0.3.1

func SignalVersionChannel(git, build, channel string)

SignalVersionChannel performs the same as SignalVersion but will also check channel

func SwitchChannel added in v0.3.0

func SwitchChannel(channel string) bool

SwitchChannel will update the current running daemon to run on the given channel. It will return false if the running instance is already the latest version on that channel

func TryBusy added in v0.4.7

func TryBusy() bool

TryBusy attempts to mark the program as busy without blocking. It returns true if successful, false if the busy lock could not be acquired immediately. If true is returned, the caller must call Unbusy when done.

func Unbusy added in v0.1.3

func Unbusy()

Unbusy decrements the busy counter. When the counter reaches zero, any pending restart or update operations are unblocked. Each call to Busy must be paired with a call to Unbusy.

Types

type Version added in v0.3.3

type Version struct {
	ProjectName  string // project's name
	Channel      string // project channel (typically, branch name)
	DateTag      string // version's date tag in YYYYMMDDhhmmss format
	GitTag       string // version's git tag (first 7 characters of git hash)
	UpdatePrefix string // internally used prefix for constructing download URLs
}

Version represents a specific version of a project available on the update server. It contains all the information needed to download and install the update, including version identifiers and download URL components.

func GetLatest added in v0.3.3

func GetLatest(projectName, channel string) (*Version, error)

GetLatest returns the latest version information for a given projectName and channel

func (*Version) CheckArch added in v0.3.3

func (v *Version) CheckArch(os, arch string) error

CheckArch checks if the provided version is compatible with the provided os and arch

func (*Version) Download added in v0.3.3

func (v *Version) Download(os, arch string) (io.ReadCloser, error)

Download returns a ReadCloser that allows reading the updated executable data. It will handle any decompression that might be needed, so the data can be read directly. Make sure to close the returned ReadCloser after usage.

func (*Version) Install added in v0.4.0

func (v *Version) Install() error

Install will download the update and replace the currently running executable data

func (*Version) IsCurrent added in v0.4.0

func (v *Version) IsCurrent() bool

IsCurrent returns true if the version matches the currently running program

func (*Version) SaveAs added in v0.4.1

func (v *Version) SaveAs(fn string) error

SaveAs will download the update to the given local filename, performing an atomic replacement of the file

func (*Version) URL added in v0.3.3

func (v *Version) URL(os, arch string) string

URL generates the download url for the provided os and arch. Note that the URL will point to a compressed file, use Download() to instead directly receive decompressed data.

Jump to

Keyboard shortcuts

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