updatecheck

package
v1.3.5 Latest Latest
Warning

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

Go to latest
Published: Aug 20, 2026 License: AGPL-3.0 Imports: 14 Imported by: 0

Documentation

Overview

Package updatecheck reports whether a newer NinerLog build has been published. A component carrying a semantic version is compared against the newest GitHub release of its repository; one carrying only a build commit — what the :latest images have — is compared against the head of the tracked branch. A component with neither reports StateUnknown.

The API knows its own version and commit from link-time stamps; the frontend's are supplied by the browser with the request.

Index

Constants

View Source
const (
	ComponentAPI      = "api"
	ComponentFrontend = "frontend"
)

Component names used in the API response and in metric labels.

View Source
const (
	StateUpToDate        = "up_to_date"
	StateUpdateAvailable = "update_available"
	StateUnknown         = "unknown"
)

Component states.

View Source
const (
	// ChannelRelease compares a semantic version against the newest release.
	ChannelRelease = "release"
	// ChannelCommit compares a build commit against the tracked branch, which
	// is what a deployment running the :latest tag gets.
	ChannelCommit = "commit"
)

How a component's state was determined.

View Source
const (
	DefaultInterval     = 24 * time.Hour
	DefaultAPIRepo      = "fjaeckel/ninerlog-api"
	DefaultFrontendRepo = "fjaeckel/ninerlog-frontend"
	// DefaultBranch is the branch a :latest image is built from.
	DefaultBranch = "main"
)

Defaults applied when the corresponding environment variable is unset.

View Source
const DevVersion = "dev"

DevVersion is the version reported by a binary that was neither stamped at build time nor given APP_VERSION.

Variables

View Source
var (
	// RunsTotal counts release check runs. Results: success, error.
	RunsTotal = prometheus.NewCounterVec(
		prometheus.CounterOpts{
			Name: "update_check_runs_total",
			Help: "Total release check runs by result.",
		},
		[]string{"result"},
	)

	// ErrorsTotal counts failed release checks. Reasons: request, status,
	// decode, empty.
	ErrorsTotal = prometheus.NewCounterVec(
		prometheus.CounterOpts{
			Name: "update_check_errors_total",
			Help: "Total release check failures by reason.",
		},
		[]string{"reason"},
	)

	// DurationSeconds tracks how long one release check run takes, covering
	// every component queried.
	DurationSeconds = prometheus.NewHistogram(
		prometheus.HistogramOpts{
			Name:    "update_check_duration_seconds",
			Help:    "Latency of one release check run.",
			Buckets: prometheus.ExponentialBuckets(0.05, 2, 10),
		},
	)

	// LastSuccessTimestampSeconds is the Unix timestamp of the last run in
	// which every component's latest release was read.
	LastSuccessTimestampSeconds = prometheus.NewGauge(
		prometheus.GaugeOpts{
			Name: "update_check_last_success_timestamp_seconds",
			Help: "Unix timestamp of the last fully successful release check.",
		},
	)

	// UpdateAvailable reports whether a newer release exists for a component.
	// 1 = behind, 0 = current. Components: api. The frontend's running version
	// is known only to the browser, so it has no series here.
	UpdateAvailable = prometheus.NewGaugeVec(
		prometheus.GaugeOpts{
			Name: "app_update_available",
			Help: "1 when a newer release is published for the component, 0 when current.",
		},
		[]string{"component"},
	)

	// CommitsBehind reports how many commits behind the tracked branch a
	// component's build is. Components: api. Absent for a build compared by
	// release version rather than by commit.
	CommitsBehind = prometheus.NewGaugeVec(
		prometheus.GaugeOpts{
			Name: "app_commits_behind",
			Help: "Commits the tracked branch is ahead of the running build.",
		},
		[]string{"component"},
	)

	// LatestVersionInfo carries the newest published release per component.
	// Components: api, frontend.
	LatestVersionInfo = prometheus.NewGaugeVec(
		prometheus.GaugeOpts{
			Name: "update_check_latest_version_info",
			Help: "Newest published release per component, as a labelled constant 1.",
		},
		[]string{"component", "version"},
	)
)

Prometheus instrumentation for the release check. No series at all are emitted when the check is disabled.

Functions

func RunningCommit

func RunningCommit() string

RunningCommit returns the commit this binary was built from: the link-time stamp, then APP_COMMIT. Empty when neither is set or the value is not a commit SHA.

func RunningVersion

func RunningVersion() string

RunningVersion returns the version of this binary: the link-time stamp, then APP_VERSION, then DevVersion.

Types

type Checker

type Checker struct {
	// contains filtered or unexported fields
}

Checker holds the last known releases and commit comparisons and refreshes them on a timer.

func New

func New(cfg Config) *Checker

New returns a Checker, filling unset Config fields with their defaults.

func (*Checker) Enabled

func (c *Checker) Enabled() bool

Enabled reports whether the check runs.

func (*Checker) Interval

func (c *Checker) Interval() time.Duration

Interval is how often the check repeats. Zero or less means it runs only at startup.

func (*Checker) Refresh

func (c *Checker) Refresh(ctx context.Context) error

Refresh looks up the newest release of every component, and the branch position of every build commit it knows about, and stores them. A lookup that fails leaves the previously known answer in place.

func (*Checker) Start

func (c *Checker) Start(ctx context.Context)

Start runs a check immediately and then every configured interval until ctx is done. It returns at once; a disabled Checker starts nothing.

func (*Checker) Status

func (c *Checker) Status(frontendVersion, frontendCommit string) Status

Status reports every component against the last known releases, falling back to the branch position of its build commit. frontendVersion and frontendCommit describe the calling browser's build; a component that reports neither a semantic version nor a commit yields StateUnknown.

type Comparison

type Comparison struct {
	// Status is identical, ahead (the branch has moved on), behind (the build
	// is ahead of the branch) or diverged.
	Status string
	// BehindBy is how many commits the branch is ahead of this build.
	BehindBy int
	URL      string
	// CheckedAt is when the comparison was made.
	CheckedAt time.Time
}

Comparison is one build commit measured against the tracked branch head.

type ComponentStatus

type ComponentStatus struct {
	Name           string
	CurrentVersion string
	// CurrentCommit is the short commit the component was built from, empty
	// when it reported none.
	CurrentCommit string
	LatestVersion string
	State         string
	// Channel is how State was reached: ChannelRelease or ChannelCommit.
	// Empty when neither comparison could be made.
	Channel     string
	ReleaseURL  string
	PublishedAt *time.Time
	// BehindBy is how many commits behind the tracked branch this build is,
	// set only on ChannelCommit.
	BehindBy int
	// CompareURL is the GitHub comparison between this build and the branch
	// head, set only on ChannelCommit.
	CompareURL string
}

ComponentStatus is one component's running build measured against the newest published release, or against the tracked branch when it carries no semantic version.

type Config

type Config struct {
	// Enabled is false when the deployment opted out of the check; a disabled
	// Checker performs no outbound request and reports StateUnknown.
	Enabled bool
	// Interval between checks. Zero or less disables the periodic refresh,
	// leaving only the check performed at startup.
	Interval time.Duration
	// APIRepo and FrontendRepo are "owner/name" GitHub repository paths.
	APIRepo      string
	FrontendRepo string
	// Branch is the branch the :latest images are built from; commit
	// comparisons are made against its head.
	Branch string
	// APIVersion is the running version of this binary.
	APIVersion string
	// APICommit is the commit this binary was built from, empty when unstamped.
	APICommit string
	// BaseURL is the GitHub API root.
	BaseURL string
	// HTTPClient performs the release lookups.
	HTTPClient *http.Client
}

Config configures a Checker.

func FromEnv

func FromEnv() Config

FromEnv builds a Config from UPDATE_CHECK_ENABLED, UPDATE_CHECK_INTERVAL, UPDATE_CHECK_API_REPO, UPDATE_CHECK_FRONTEND_REPO and UPDATE_CHECK_BRANCH.

type Release

type Release struct {
	Version     string
	URL         string
	PublishedAt time.Time
}

Release is the newest published release of one component's repository.

type Status

type Status struct {
	Enabled bool
	// UpdateAvailable is true when any component is behind its newest
	// published release.
	UpdateAvailable bool
	LastCheckedAt   *time.Time
	// LastError is a coarse reason for the last failed check, empty when the
	// last check succeeded or none has run.
	LastError string
	// Branch is the branch commit comparisons are made against.
	Branch     string
	Components []ComponentStatus
}

Status is the result of the most recent check, evaluated against the versions currently running.

Jump to

Keyboard shortcuts

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