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

presetref

package
v0.14.0 Latest Latest
Warning

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

Go to latest
Published: Oct 14, 2026 License: AGPL-3.0, AGPL-3.0-only Imports: 6 Imported by: 0

Documentation

Overview

Package presetref parses and classifies a preset reference — the string in a `preset:` field that locates a preset fragment, optionally from a remote source at a git ref. Classification decides how the loader resolves it (local read, live fetch, or cache-authoritative), per the identity model's preset-resolution design. This is pure parsing and static classification — no I/O; the one genuinely source-dependent case (a bare ref name that could be a branch or a tag) is marked Named and left for the fetch layer to resolve against the source.

Index

Constants

View Source
const DefaultMaxFallbackAge = 7 * 24 * time.Hour

DefaultMaxFallbackAge is how long a retained copy may stand in for an unreachable source before resolution stops accepting it. Unbounded is not a safe default: it is how a source that quietly stops answering leaves everyone frozen on old content. A week absorbs a long outage while still surfacing one that is not going to end.

Variables

This section is empty.

Functions

func CacheKey

func CacheKey(ref Ref) string

CacheKey is the retention-store key for a ref: source + ref + path, sanitized to a safe relative path. A pinned ref's key includes its immutable ref; a tracked ref's key is stable across runs so a re-fetch overwrites the same entry.

func IsURL added in v0.11.0

func IsURL(raw string) bool

IsURL reports whether raw is an http(s) URL. Only these two schemes: another scheme (ssh://, git://) addresses a repository, which reaches Parse through the separator form and keeps its repo/path split. Exported so the fetch layer routes on the same predicate the parser classified with, rather than a second copy that can drift.

Types

type AgedCache added in v0.11.0

type AgedCache interface {
	Age(key string) (time.Duration, bool)
}

AgedCache is an optional Cache capability: how long ago an entry was retained. Without it a fallback cannot be bounded, because there is no way to tell a copy retained five minutes ago from one retained five months ago.

type Cache

type Cache interface {
	Read(key string) ([]byte, bool)
	Write(key string, content []byte) error
}

Cache is the retention store for fetched presets — the fallback for tracked refs and the authoritative store for pinned refs. Keyed by a ref's CacheKey.

type FSCache

type FSCache struct {
	Root string
}

FSCache is a filesystem-backed Cache rooted at a directory — typically a repo's .stagefreight/preset-cache. It stores each fetched preset under its (sanitized, slash-bearing but ..-free) CacheKey, so pinned refs and tracked-ref fallbacks persist across runs.

func NewFSCache

func NewFSCache(dir string) FSCache

NewFSCache returns an FSCache rooted at dir.

func (FSCache) Age added in v0.11.0

func (c FSCache) Age(key string) (time.Duration, bool)

Age reports how long ago the entry was retained, from its mtime.

func (FSCache) Read

func (c FSCache) Read(key string) ([]byte, bool)

func (FSCache) Write

func (c FSCache) Write(key string, content []byte) error

type FetchMode

type FetchMode int

FetchMode controls network behavior.

const (
	// FetchLive is the default: a tracked ref is fetched each run (cache as fallback); a
	// pinned ref is served from cache if present, else fetched once.
	FetchLive FetchMode = iota
	// FetchOffline never touches the network: everything resolves from cache, and a miss
	// is an error. For air-gapped CI running against a pre-seeded cache.
	FetchOffline
)

type Fetcher

type Fetcher interface {
	// Fetch returns the file at path from source at ref (ref "" = the default branch).
	Fetch(source, ref, path string) ([]byte, error)
	// Classify resolves a BARE Named ref against the source: a tag → Pinned, a branch →
	// Tracked. Called only for Named refs. Takes the path for the same reason Fetch does:
	// it is what distinguishes a repository source from a bare document URL.
	Classify(source, ref, path string) (Kind, error)
}

Fetcher does the actual remote I/O for a preset source; the Resolver stays pure policy over it, so the tracked/pinned/fallback logic is testable without a network.

type Kind

type Kind int

Kind is how a preset reference resolves.

const (
	// Local is an in-repo path (no source): read from the working tree / preset-cache.
	Local Kind = iota
	// Tracked is a source at a branch (or no ref): fetched live each run so a change at
	// the source propagates to every tracking repo, with the cache as offline fallback.
	Tracked
	// Pinned is a source at a provably-immutable ref (a sha or a refs/tags/ tag):
	// cache-authoritative — resolved from cache when present, fetched once otherwise.
	Pinned
	// Named is a source at a BARE ref name (e.g. "main", "v1.0") that can't be classified
	// statically — a branch and a tag look identical as strings. The fetch layer resolves
	// it against the source (a tag → pinned, a branch → tracked). Pinning explicitly
	// (a sha or refs/tags/…) avoids this deferral.
	Named
)

func (Kind) String

func (k Kind) String() string

type MismatchPolicy added in v0.11.0

type MismatchPolicy string

Resolver resolves a SOURCED preset Ref (Tracked/Pinned/Named) to its content, applying the source-tracking policy. Local refs are out of scope — the local loader handles them. MismatchPolicy decides what happens when a PINNED reference's source no longer serves what was retained. Only a pin can mismatch: it asserts a revision is immutable, and that assertion is what the source can contradict. A tracked reference asserts nothing, so a change there is simply the new value.

There is no universally right answer, which is why it is the operator's: one shop sees a moved pin as tampering and wants everything to stop; another trusts the source and wants the newer content; a third wants what it already had, plus a warning.

const (
	// MismatchFail stops. The default, because it is the only option that does not
	// choose for an operator who has not said which side they trust.
	MismatchFail MismatchPolicy = "fail"
	// MismatchSource adopts what the source serves.
	MismatchSource MismatchPolicy = "source"
	// MismatchRetained keeps what was retained.
	MismatchRetained MismatchPolicy = "retained"
)

func (MismatchPolicy) Valid added in v0.11.0

func (p MismatchPolicy) Valid() bool

Valid reports whether p is a policy the resolver understands.

type NoCache added in v0.11.0

type NoCache struct{}

NoCache retains nothing. For a caller that fetches in order to write the content somewhere else — governance materializing a preset into a satellite's cache — where a second copy in the control repo would serve no one.

func (NoCache) Read added in v0.11.0

func (NoCache) Read(string) ([]byte, bool)

func (NoCache) Write added in v0.11.0

func (NoCache) Write(string, []byte) error

type Outcome added in v0.11.0

type Outcome struct {
	Ref       Ref
	Kind      Kind
	Fetched   bool // reached the source on this run
	Drifted   bool // what the source served differs from what was retained
	Fallback  bool // source unreachable; the retained copy was served instead
	Violated  bool // pinned, and the source no longer serves what was retained
	Unchanged bool // the source serves what was retained; nothing written
	// Refreshed reports that THIS run wrote the retained copy — replacing one that
	// differed, or creating one governance never seeded. It is what a satellite
	// republishes: a retained copy the run produced but never committed leaves the
	// working tree dirty, which is a failure, not a diagnostic. Distinct from Drifted,
	// which answers whether the content changed: a first retention changes nothing and
	// still has to be carried back, and an adopted pin mismatch is a write the operator
	// asked for.
	Refreshed bool
}

Outcome records how one reference resolved. A tracked source changing is the behaviour the operator selected by not pinning, so this exists to make the change visible and auditable — not to flag it as suspect.

type PinViolation added in v0.11.0

type PinViolation struct {
	Ref      Ref
	Retained []byte
	Fetched  []byte
}

PinViolation reports a pinned reference whose source no longer serves what was retained. Returned as an error so the default is to stop; a caller that would rather warn can recognize it and continue with Retained.

func (*PinViolation) Error added in v0.11.0

func (e *PinViolation) Error() string

type Ref

type Ref struct {
	Raw    string // the original string
	Kind   Kind
	Source string // "<source>" (forge repo or URL); "" for Local
	Path   string // preset path within the source, or the local path for Local
	Ref    string // the git ref (branch / tag / sha, possibly refs/-qualified); "" = default branch
}

Ref is a parsed preset reference.

func Parse

func Parse(raw string) Ref

Parse classifies a preset reference. Forms:

preset/lint.yml                          → Local
https://example.org/lint.yml             → Tracked (the URL is the whole source)
gitlab:Org/Repo//preset/lint.yml         → Tracked (default branch)
…//preset/lint.yml@main                  → Named (bare — resolved at fetch)
…//preset/lint.yml@refs/heads/main       → Tracked
…//preset/lint.yml@refs/tags/v1.0        → Pinned
…//preset/lint.yml@v1.0                  → Named (bare — resolved at fetch)
…//preset/lint.yml@1a2b3c4               → Pinned (sha)

type Resolver

type Resolver struct {
	Fetcher Fetcher
	Cache   Cache
	Mode    FetchMode
	// Observe, if set, receives one Outcome per resolved reference.
	Observe func(Outcome)
	// MaxFallbackAge bounds how long a retained copy may stand in for an unreachable
	// source. Zero is unbounded. Without a bound, a source that stays unreachable leaves
	// every consumer silently frozen on old content — the failure this whole mechanism
	// exists to remove, arriving by a different route.
	MaxFallbackAge time.Duration
	// OnMismatch decides what a pinned reference does when its source disagrees with
	// what was retained. Empty means MismatchFail.
	OnMismatch MismatchPolicy
	// Warnf, if set, reports a non-fatal condition (e.g. a stale-cache fallback).
	Warnf func(format string, args ...any)
}

func (Resolver) Resolve

func (r Resolver) Resolve(ref Ref) ([]byte, error)

Resolve returns the content for a sourced ref. It errors on a Local ref (wrong resolver) and when a fetch is unrecoverable with no cache to fall back to.

Jump to

Keyboard shortcuts

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