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
- Variables
- func Affected(rng string, v Version) (affected, ok bool)
- func BaseURL(getenv func(string) string) (base, override string, err error)
- func Compare(a, b Version) int
- func Due(c Cache, current Version, now time.Time) bool
- func InstallScriptCommand(goos string) string
- func InstallScriptDir(env InstallEnv) string
- func Interval(current Version) time.Duration
- func Module() string
- func NewHTTPClient() *http.Client
- func OffReason(getenv func(string) string, version string) string
- func ReleaseURL(tag string) string
- func Save(path string, c Cache) error
- func UpgradeCommand(exe string, env InstallEnv, releasePage string) string
- type Advisory
- type Audience
- type Cache
- type CachedRelease
- type Client
- type InstallEnv
- type Notice
- type Release
- type Result
- type Status
- type Version
Constants ¶
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 )
const ( // WingetID is the winget package ID (submitted after launch). WingetID = "GhostbranchLabs.Ghostbranch" // NPMPackage is the npm package that installs the binary. NPMPackage = "ghostbranch" )
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.
const CacheFile = "update-check.json"
CacheFile is the cache's name at the root of GHOSTBRANCH_HOME.
Variables ¶
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 ¶
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 ¶
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 Due ¶
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 ¶
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 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 ¶
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 ¶
OffReason says why this binary never looks: EnvOff, "CI" or "development build"; "" when it looks.
func ReleaseURL ¶
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 ¶
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 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 ¶
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.
type CachedRelease ¶
CachedRelease is the newest release seen, without the v.
type Client ¶
Client reads releases and advisories anonymously. It never carries a token, a cookie or an ID.
type InstallEnv ¶
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 ¶
Notice is one reminder, for a person or an agent.
func NoticeFor ¶
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.
type Result ¶
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).
type Version ¶
Version is a release version: MAJOR.MINOR.PATCH with an optional pre-release. Build metadata is never part of a release.
func ParseRelease ¶
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.