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

update

package
v0.17.1 Latest Latest
Warning

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

Go to latest
Published: Nov 1, 2026 License: AGPL-3.0 Imports: 25 Imported by: 0

Documentation

Overview

Package update knows whether a newer Pando has been released (R-349–R-352).

It reads GitHub's release list for trypando/pando, which the release workflow writes: one release per tag, its body exactly that version's CHANGELOG.md section, prerelease set for a tag with a suffix. Nothing else is published for it to read, so there is nothing else to keep in step.

It tells; it does not upgrade. Replacing the running container is issue #53's second half, and is opt-in through the deployment config.

Index

Constants

View Source
const (
	InstallContainer = "container"
	InstallBinary    = "binary"
)

How the server was installed, which decides how it is upgraded (R-352).

The server ships as the container image, run by the release's Compose file (internal/reference/install.go); packages and the Homebrew cask carry the CLI. So a server is either in a container, or a binary somebody started by hand — and the CLI's own upgrade is the CLI's business (internal/cli).

View Source
const (
	Issuer          = "https://token.actions.githubusercontent.com"
	ImageIdentity   = `^https://github\.com/(bemeek-io|trypando)/pando/\.github/workflows/image\.yml@refs/(heads/main|tags/v)`
	ReleaseIdentity = `^https://github\.com/(bemeek-io|trypando)/pando/\.github/workflows/release\.yml@refs/(heads/main|tags/v)`
)

What a release's signatures must say about who made them (R-357, R-363): GitHub's OIDC provider, vouching for a workflow in Pando's repository on its main branch or a version tag. The same identities docs/releasing.md tells a person to check with cosign by hand.

View Source
const DefaultInterval = 6 * time.Hour

DefaultInterval is how often the check runs. Four requests a day is well inside GitHub's unauthenticated limit of sixty an hour per address, and a security release is seen within a working morning of being published.

View Source
const Image = "trypando/pando"

Image is the published server image.

View Source
const MinCheckGap = time.Minute

MinCheckGap is the least time between two checks someone asks for. A request inside it is answered from the last check, so a button pressed repeatedly stays inside GitHub's limit for every installation behind one address.

View Source
const ReleasesURL = "https://api.github.com/repos/trypando/pando/releases?per_page=100"

ReleasesURL is where the release workflow publishes. A renamed repository redirects, and the client follows.

View Source
const VersionAnnotation = "org.opencontainers.image.version"

VersionAnnotation is the annotation the image workflow signs with each image (`cosign sign -a`), naming the version it was built as. A signature covers a digest, not a tag, so without it any image the workflow ever signed would pass for any version a tag was pointed at (R-357).

Variables

This section is empty.

Functions

func Breaks

func Breaks(from, to string) bool

Breaks reports whether moving from one version to the next may break something: a MAJOR bump, or before 1.0 a MINOR one (docs/releasing.md).

func HasSecurityFix

func HasSecurityFix(notes string) bool

HasSecurityFix reads a CHANGELOG.md section's Security subsection. Every release carries one; "No new advisories." is what an empty one says.

func Newer

func Newer(a, b string) bool

Newer reports whether b is a later version than a.

func Skewed

func Skewed(a, b string) bool

Skewed reports whether two versions differ in a way their interfaces may: MAJOR or MINOR. A PATCH release changes no interface (docs/releasing.md). Development builds are never skewed — there is nothing to compare.

func TrustedRoot

func TrustedRoot(ctx context.Context, dir string) (root.TrustedMaterial, error)

TrustedRoot fetches Sigstore's public-good trusted root through its TUF repository, caching under dir. The root it starts from is embedded in sigstore-go, so a compromised mirror cannot substitute one.

func VerifyChecksums

func VerifyChecksums(tm root.TrustedMaterial, checksums, raw []byte) error

VerifyChecksums checks a release's checksums.txt against its signature bundle and the release workflow's identity (R-363).

func VerifyImageBundle

func VerifyImageBundle(tm root.TrustedMaterial, raw []byte, digest v1.Hash, version string) error

VerifyImageBundle checks a cosign signature bundle against an image's index digest and the image workflow's identity, and that what was signed names version: the image was built as that version, not merely signed once.

Types

type Checker

type Checker struct {
	Source   Source
	Settings func(ctx context.Context) (Settings, error)
	// Current is this binary's version, "dev" for a development build.
	Current  string
	Install  Install
	Clock    clock.Clock
	Logger   *zap.Logger
	Interval time.Duration
	// contains filtered or unexported fields
}

Checker asks Source on an interval while policy allows it, and answers Status from what it last heard.

func (*Checker) Check

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

Check asks Source once, if policy allows it.

func (*Checker) CheckNow added in v0.6.0

func (c *Checker) CheckNow(ctx context.Context) (Status, error)

CheckNow asks Source on request rather than waiting for the next tick, and answers with what it found. Within MinCheckGap of the last check it sends nothing and answers from that one; while policy has the check off it sends nothing at all (R-349).

func (*Checker) Run

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

Run checks at startup and every Interval until ctx ends. While the check is off nothing is sent (R-349); turning it back on is seen at the next tick.

func (*Checker) Status

func (c *Checker) Status(ctx context.Context) (Status, error)

Status reports what the last check found, filtered by the channel policy names now, so changing the channel needs no new request.

type GitHub

type GitHub struct {
	HTTP    *http.Client
	URL     string
	Version string
}

GitHub lists releases from GitHub's API.

The request carries a User-Agent naming the version, which GitHub requires, and nothing else about the installation (R-349).

func NewGitHub

func NewGitHub(version string) *GitHub

NewGitHub is a GitHub source with the timeouts an unattended outbound call needs: without them a black-holed route holds the check open forever.

func (*GitHub) Releases

func (g *GitHub) Releases(ctx context.Context) ([]Release, error)

Releases implements Source.

type ImageVerifier

type ImageVerifier struct {
	// Repository is the image, without a tag: index.docker.io/trypando/pando.
	Repository string
	Trusted    func(ctx context.Context) (root.TrustedMaterial, error)
	Remote     []remote.Option
}

ImageVerifier checks a released image's signature before Pando runs it (R-357).

func (*ImageVerifier) Verify

func (v *ImageVerifier) Verify(ctx context.Context, version string) (string, error)

Verify resolves version to its index digest, fetches the signature attached to that digest and checks it. It returns the digest, which is what is run from then on: a tag resolved again later could name something else.

type Install

type Install struct {
	Kind string `json:"kind"`
}

Install is how this server was installed.

func DetectInstall

func DetectInstall() Install

DetectInstall reads how this process was started. Docker writes /.dockerenv into every container it runs; a PANDO_ variable would be read as configuration.

func (Install) Upgrade

func (i Install) Upgrade(version string) Upgrade

Upgrade says how to move this installation to version.

type Release

type Release struct {
	Version     string    `json:"version"`
	Prerelease  bool      `json:"prerelease"`
	PublishedAt time.Time `json:"published_at"`
	URL         string    `json:"url"`
	// Notes is the version's CHANGELOG.md section, as Markdown.
	Notes string `json:"notes"`
	// Security is set when the Security section names an advisory rather than
	// saying "No new advisories." (docs/releasing.md).
	Security bool `json:"security"`
	// Breaking is set when the version may break what the one before it did:
	// a MAJOR bump, or a MINOR one before 1.0 (docs/releasing.md).
	Breaking bool `json:"breaking"`
}

Release is one published version.

func Between

func Between(offered []Release, current string) []Release

Between is the releases newer than current, from a newest-first list. The oldest of them is marked Breaking against current itself.

func Offered

func Offered(all []Release, channel policy.UpdateChannel) []Release

Offered is the releases the channel offers, newest first, invalid versions dropped and Breaking set against the release before each.

type Settings

type Settings struct {
	Enabled bool
	Channel policy.UpdateChannel
}

Settings is what host policy says about the check.

func SettingsFrom

func SettingsFrom(d policy.Document) Settings

SettingsFrom reads the check's settings from a policy document.

type Source

type Source interface {
	Releases(ctx context.Context) ([]Release, error)
}

Source lists published releases, newest or not, prereleases included.

type Status

type Status struct {
	Current string `json:"current"`
	// Development is set for a binary no release built, which has no version
	// to compare: it is told what the latest is, never that it is behind.
	Development bool                 `json:"development"`
	Enabled     bool                 `json:"enabled"`
	Channel     policy.UpdateChannel `json:"channel"`
	CheckedAt   *time.Time           `json:"checked_at,omitempty"`
	// Error is why the last check failed, when it did. What an earlier check
	// found is still reported beside it.
	Error  string `json:"error,omitempty"`
	Latest string `json:"latest,omitempty"`
	// Available is set when Latest is newer than Current.
	Available bool `json:"available"`
	// Releases are the versions after Current up to Latest, newest first.
	Releases []Release `json:"releases"`
	Security bool      `json:"security"`
	Breaking bool      `json:"breaking"`
	// Upgrade says how to move this installation to Latest (R-352).
	Upgrade *Upgrade `json:"upgrade,omitempty"`
}

Status is what the check knows, as every surface shows it (R-351).

type Upgrade

type Upgrade struct {
	Version string `json:"version"`
	// Image is the image to run, for a container install.
	Image string `json:"image,omitempty"`
	// Command upgrades an installation run from the release's Compose file,
	// from the directory that file is in.
	Command string `json:"command"`
	// Instructions says the same in a sentence, including the case the
	// command does not cover.
	Instructions string `json:"instructions"`
}

Upgrade is how to move this installation to a version, in the words and commands somebody would paste.

Jump to

Keyboard shortcuts

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