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

updatecheck

package
v1.4.13 Latest Latest
Warning

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

Go to latest
Published: Oct 11, 2026 License: MIT Imports: 13 Imported by: 0

Documentation

Overview

Package updatecheck is the opt-in, once-per-24h "newer nself exists" hint.

Nothing here runs unless NSELF_UPDATE_CHECK=1 (VMI: nothing is sent by default). A background goroutine refreshes a small cache from ping's GET /version at most once per 24 h; the hint itself reads only the cache and never touches the network. Contract: cap:cli.version-nudge.

Index

Constants

View Source
const Budget = 250 * time.Millisecond

Budget is the whole-request limit of one refresh.

View Source
const EnvOptIn = "NSELF_UPDATE_CHECK"

EnvOptIn is the opt-in switch: the value "1" turns the feature on.

View Source
const Interval = 24 * time.Hour

Interval is the minimum time between refreshes and between hints.

View Source
const VersionURL = "https://ping.nself.org/version"

VersionURL is ping's release-channel endpoint (contract:ping.release-channel).

Variables

This section is empty.

Functions

func Allowed

func Allowed(g Guards) bool

Allowed reports whether the feature may run at all: opted in, not JSON mode, no CI marker, stderr is a terminal. Without the opt-in nothing else is read.

func DefaultPath

func DefaultPath() string

DefaultPath returns ~/.nself/cache/update-check.json, or "" when the home directory cannot be resolved (the feature is then off).

func Hint

func Hint(g Guards) (string, bool)

Hint returns the one-line hint when it is due: allowed, the cached latest is a valid release newer than Current, and no hint was printed within Interval. It reads only the cache and records HintedAt before returning the line; if that record cannot be saved no line is returned, so it never repeats.

func MaybeStartRefresh

func MaybeStartRefresh(g Guards) <-chan struct{}

MaybeStartRefresh starts the background refresh when the feature is allowed and the cache is older than Interval. It never blocks: the returned channel closes when the refresh finishes (nil when none started), and production callers ignore it, so the goroutine is simply abandoned at process exit. A failed refresh keeps the old Latest and records CheckedAt and LastError.

func NewClient

func NewClient() *http.Client

NewClient returns the refresh client: Budget timeout through the httptimeout funnel, compression off so no Accept-Encoding header is sent. The request then carries only Host and User-Agent.

func Refresh

func Refresh(ctx context.Context, client *http.Client, url string) (string, error)

Refresh asks url for the latest released CLI version and returns it normalised (no leading "v"). An empty, invalid or non-2xx answer is an error. The only request header besides Host is User-Agent: nself/<version>.

func Save

func Save(path string, c Cache) error

Save writes the cache atomically (temp file in the same directory, then rename) with mode 0600 inside a 0700 directory.

Types

type Cache

type Cache struct {
	CheckedAt time.Time `json:"checked_at"`
	Latest    string    `json:"latest"`
	LastError string    `json:"last_error,omitempty"`
	HintedAt  time.Time `json:"hinted_at"`

	AttemptedAt time.Time `json:"attempted_at"`
}

Cache is the on-disk state at ~/.nself/cache/update-check.json.

CheckedAt is the time of the last refresh attempt (success or failure), so a stale cache is visible to `nself doctor`. LastError is empty after a good refresh. HintedAt is the time the hint was last printed. AttemptedAt is the time a refresh was last started, written before the request goes out, so a refresh cut short by process exit still counts for the retry backoff.

func Load

func Load(path string) Cache

Load reads the cache. A missing, unreadable or corrupt file yields the zero Cache: the next Save replaces it.

type Guards

type Guards struct {
	JSON    bool
	TTY     func() bool
	Env     func(string) string
	Now     func() time.Time
	Path    string
	Current string
	URL     string
	Client  *http.Client
}

Guards carries everything the feature reads from the outside world, so tests inject a clock, a TTY answer, an environment and a server.

JSON is the recorded JSON mode of the invocation. TTY reports whether stderr is a terminal. Path is the cache file, Current the running version, URL the endpoint and Client the HTTP client (nil means NewClient).

Jump to

Keyboard shortcuts

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