Help us shape the future of Go! Take the 2026 Go Developer Survey

updatecheck

package
v0.3.0 Latest Latest
Warning

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

Go to latest
Published: Oct 30, 2026 License: Apache-2.0 Imports: 17 Imported by: 0

Documentation

Overview

Package updatecheck tells people and agents about newer Ghostbranch releases (spec 6.4a § 3). It asks GitHub anonymously for the latest release and, only when that is newer, for the repo's security advisories; it caches the answer under GHOSTBRANCH_HOME and works out when to remind whom. It never downloads or installs anything, and it never calls through the forge: it reads Ghostbranch's own releases, without the user's token.

Index

Constants

View Source
const (
	// Repo is where releases and advisories are read. A rename at launch
	// changes this one line.
	Repo = "ghostbranch-labs/ghostbranch"
	// DefaultBaseURL is GitHub's API.
	DefaultBaseURL = "https://api.github.com"
	// Budget caps both requests of one look together.
	Budget = 3 * time.Second
)
View Source
const (
	// WingetID is the winget package ID (submitted after launch).
	WingetID = "GhostbranchLabs.Ghostbranch"
	// NPMPackage is the npm package that installs the binary.
	NPMPackage = "ghostbranch"
)
View Source
const (
	EnvOff = "GHOSTBRANCH_NO_UPDATE_CHECK"
	EnvURL = "GHOSTBRANCH_UPDATE_URL"
)

EnvOff turns the check off when set to anything non-empty. EnvURL replaces the API base URL: test-only, for the owner's hands-on check and the tests.

View Source
const CacheFile = "update-check.json"

CacheFile is the cache's name at the root of GHOSTBRANCH_HOME.

Variables

View Source
var ErrNoRelease = errors.New("no release published yet")

ErrNoRelease means GitHub has no published release to show: before launch the repo is private and answers 404.

Functions

func Affected

func Affected(rng string, v Version) (affected, ok bool)

Affected reports whether v is inside a GitHub advisory's vulnerable_version_range: comma-separated constraints such as "< 0.13.1" or ">= 0.10.0, < 0.13.1", each an operator (<, <=, >, >=, =) and a full version. ok is false when the range can't be read; the caller then counts the advisory as affecting this version (fail toward warning).

func BaseURL

func BaseURL(getenv func(string) string) (base, override string, err error)

BaseURL is the API origin: EnvURL when set (override is its value), else GitHub's. An override that isn't an absolute http(s) URL is an error, and no look is made.

func Compare

func Compare(a, b Version) int

Compare orders a and b by semver precedence: -1, 0 or 1.

func Due

func Due(c Cache, current Version, now time.Time) bool

Due reports whether to look now: never looked, a look by another binary, a look in the future (clock skew), or one at least Interval old.

func InstallScriptCommand

func InstallScriptCommand(goos string) string

InstallScriptCommand re-runs the install script, which upgrades it.

func InstallScriptDir

func InstallScriptDir(env InstallEnv) string

InstallScriptDir is the folder the install scripts put the binary in by default: %LOCALAPPDATA%\Programs\ghostbranch on Windows, ~/.local/bin elsewhere; "" when that isn't known. A binary installed with GHOSTBRANCH_INSTALL_DIR somewhere else gets the release page instead.

func Interval

func Interval(current Version) time.Duration

Interval is how often to look: every 4 hours below 1.0.0, daily from it.

func Module

func Module() string

Module is this binary's module path from its build info, so the go install line follows a rename; the current path when build info is missing.

func NewHTTPClient

func NewHTTPClient() *http.Client

NewHTTPClient is a client with Go's default transport settings, which honour HTTPS_PROXY, HTTP_PROXY and NO_PROXY, and no cookie jar. A look that started on https never follows a redirect to anything else.

func OffReason

func OffReason(getenv func(string) string, version string) string

OffReason says why this binary never looks: EnvOff, "CI" or "development build"; "" when it looks.

func ReleaseURL

func ReleaseURL(tag string) string

ReleaseURL is a release's page, built here from a tag that parsed as a version: the server's html_url is never shown.

func Save

func Save(path string, c Cache) error

Save writes c atomically (a temp file, then a rename), mode 0600 on macOS and Linux, like plans.

func UpgradeCommand

func UpgradeCommand(exe string, env InstallEnv, releasePage string) string

UpgradeCommand works out how this binary was installed from its path (os.Executable with symlinks resolved) and returns the command that upgrades it, or releasePage when no method is recognised.

Types

type Advisory

type Advisory struct {
	ID      string `json:"id"`
	Summary string `json:"summary"`
	Range   string `json:"range"`
	Patched string `json:"patched"`
}

Advisory is a published GitHub security advisory that affects this binary's version.

type Audience

type Audience int

Audience is who a reminder is for.

const (
	// Person: the stderr reminder on a terminal.
	Person Audience = iota
	// Agent: UPDATE_AVAILABLE in --json warnings.
	Agent
)

type Cache

type Cache struct {
	Format           int            `json:"format"`
	CheckedAt        time.Time      `json:"checked_at"`
	Latest           *CachedRelease `json:"latest"`
	Advisories       []Advisory     `json:"advisories"`
	RemindedPersonAt time.Time      `json:"reminded_person_at"`
	RemindedAgentAt  time.Time      `json:"reminded_agent_at"`
	// BinaryVersion is the version the advisories were matched against.
	BinaryVersion string `json:"binary_version"`
	// LastError is why the last look failed ("" when it didn't).
	LastError string `json:"last_error"`
}

Cache is update-check.json. Concurrent commands may both write it; the last write wins, which is harmless.

func Load

func Load(path string) Cache

Load reads the cache; anything missing, damaged, of another format, not a regular file (a FIFO would block every command) or over maxCacheSize reads as an empty cache.

func (*Cache) Merge

func (c *Cache) Merge(r Result, binary Version)

Merge records a look made by binary. A failed look keeps what was known and records why, so a broken network is asked again only at the next interval (R7). Advisories matched for another binary are dropped.

func (*Cache) Reminded

func (c *Cache) Reminded(aud Audience, now time.Time)

Reminded records that aud was just reminded.

type CachedRelease

type CachedRelease struct {
	Version string `json:"version"`
	URL     string `json:"url"`
}

CachedRelease is the newest release seen, without the v.

type Client

type Client struct {
	BaseURL string
	HTTP    *http.Client
}

Client reads releases and advisories anonymously. It never carries a token, a cookie or an ID.

func (Client) Affecting

func (c Client) Affecting(ctx context.Context, current Version) ([]Advisory, error)

Affecting lists the published, not withdrawn advisories whose range holds current. An advisory without a readable range counts (fail toward warning). A 404 is no advisories.

func (Client) Latest

func (c Client) Latest(ctx context.Context) (Release, error)

Latest is the newest release. A 404 is ErrNoRelease.

type InstallEnv

type InstallEnv struct {
	Getenv func(string) string
	Home   string
	Module string
	GOOS   string
}

InstallEnv is what UpgradeCommand reads besides the path: the environment (GOBIN, GOPATH, LOCALAPPDATA), the home directory, the module path for go install, and the OS (runtime.GOOS), which picks the install script.

type Notice

type Notice struct {
	Current, Latest, URL string
	Security             bool
	Advisories           []string
	Upgrade              string
}

Notice is one reminder, for a person or an agent.

func NoticeFor

func NoticeFor(c Cache, current Version, aud Audience, now time.Time) *Notice

NoticeFor is the reminder due for aud now, or nil (spec § 3.3): a security fix for this version every time; below 1.0.0 every time; from 1.0.0 once per 24 h per audience. The URL is rebuilt from the version and the IDs cleaned: nothing printed comes from the cache file as is. Upgrade is left for the caller.

func (Notice) Lines

func (n Notice) Lines() (mark, first, second string)

Lines is the person's reminder: the mark ("!" or "✗"), the first line, and the upgrade line, printed indented under it (spec § 3.5).

func (Notice) Warning

func (n Notice) Warning() contract.Warning

Warning is the agent's UPDATE_AVAILABLE (spec § 3.6).

type Release

type Release struct {
	Version Version
	Tag     string
	URL     string
}

Release is the newest published, non-draft, non-prerelease release.

type Result

type Result struct {
	At         time.Time
	Latest     *Release
	Advisories []Advisory
	Err        error
}

Result is one look: when, what it found, and why it failed.

func Look

func Look(ctx context.Context, c Client, current Version, now func() time.Time, budget time.Duration) Result

Look asks for the latest release and, only when it is newer than current, for the advisories that affect current; both within budget. A failure is in Result.Err and is never shown to a person except by doctor.

type Status

type Status struct {
	Enabled    bool       `json:"enabled"`
	OffReason  string     `json:"off_reason"`
	CheckedAt  *time.Time `json:"checked_at"`
	Current    string     `json:"current"`
	Latest     string     `json:"latest"`
	Security   bool       `json:"security"`
	Advisories []string   `json:"advisories"`
	Upgrade    string     `json:"upgrade"`
	Error      string     `json:"error"`
	Override   string     `json:"override"`
	// contains filtered or unexported fields
}

Status is doctor's update_check (spec § 3.8).

func StatusOf

func StatusOf(off string, current Version, c Cache, override, upgrade string, now time.Time) Status

StatusOf describes the checker for doctor: off and why, or what the cache holds now. As in NoticeFor, nothing comes from the cache file as is: the latest version must parse, and the error and IDs are cleaned.

func (Status) Line

func (s Status) Line() string

Line is doctor's human line.

type Version

type Version struct {
	Major, Minor, Patch int
	Pre                 string
}

Version is a release version: MAJOR.MINOR.PATCH with an optional pre-release. Build metadata is never part of a release.

func ParseRelease

func ParseRelease(s string) (Version, bool)

ParseRelease reads a release version, with or without the leading v. Go pseudo-versions, (devel), (unknown) and anything with build metadata (+dirty) are not releases, so those builds never look for updates.

func (Version) BelowOne

func (v Version) BelowOne() bool

BelowOne reports whether v comes before 1.0.0, pre-releases of 1.0.0 included: the strict schedule applies to it (spec § 3.3).

func (Version) String

func (v Version) String() string

String is the version without the v: 0.13.0, 1.0.0-rc.1.

Jump to

Keyboard shortcuts

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