Documentation
¶
Overview ¶
Package release builds immutable, content-addressed release bundles: a deterministic tar holding manifest.json plus every rendered file (as blobs/<sha256>). The tar's sha256 is the release digest.
Index ¶
- Constants
- func BuildRing(org *policy.Org, ring string, opts Options) (rel *Release, variants []*Release, err error)
- func CheckRendered(harnessName string, os harness.OS, files []harness.File, p *policy.Profile, ...) error
- func Diff(a, b *Release) string
- func VariantVersion(ver, ring, exp, variant string) string
- type Artifact
- type ArtifactKind
- type ArtifactResolver
- type Experiment
- type ExperimentVariant
- type FileEntry
- type HarnessEntry
- type Manifest
- type Options
- type ProfileResolver
- type Release
- type ToggleEntry
Constants ¶
const AnyPlatform = "any"
AnyPlatform keys an artifact that is the same on every OS/arch (npm).
Variables ¶
This section is empty.
Functions ¶
func BuildRing ¶
func BuildRing(org *policy.Org, ring string, opts Options) (rel *Release, variants []*Release, err error)
BuildRing builds ring's release plus one release per variant of every running client-axis experiment enrolling ring. The ring release manifest lists those experiments (salt, weights, channel per variant) so halod can assign a device to a variant with the gateway's hash and pull the channel. Each variant release is built from the variant's profile (extends resolved) with Experiment/Variant set, so its harness config carries the attribution.
func CheckRendered ¶
func CheckRendered(harnessName string, os harness.OS, files []harness.File, p *policy.Profile, g *policy.Gateway) error
CheckRendered asserts security invariants on the files an adapter rendered, by parsing the output rather than trusting how it was produced. It is the backstop for adapter regressions and for harnesses.<h>.overrides, which are deep-merged after rendering. Any violation fails the build.
func Diff ¶
Diff returns a human-readable summary of what changes going from a to b: harness version/install changes, and per-file added/removed/changed with a line diff (changed lines only, no context; ponytail: add hunks if reviewers ask). Empty string means no differences.
func VariantVersion ¶
VariantVersion is the version label of the variant release published with ring release ver: "<ver>-x-<experiment>.<variant>" (or the hashed channel suffix, see policy.ChannelName). Deterministic, so a rollback of the ring to ver can re-point every channel at the variant releases published with it.
Types ¶
type Artifact ¶
type Artifact struct {
URL string `json:"url"`
SHA256 string `json:"sha256,omitempty"` // lowercase hex
Integrity string `json:"integrity,omitempty"` // SRI "sha512-<base64>" (npm dist.integrity)
Size int64 `json:"size,omitempty"` // exact byte size when known
Kind ArtifactKind `json:"kind"`
BinPath string `json:"binPath"` // binary: installed file name; npm: bin command name
Package string `json:"package,omitempty"` // npm package name
}
Artifact is one downloadable, hash-pinned installer input.
type ArtifactKind ¶
type ArtifactKind string
ArtifactKind says how halod installs an artifact.
const ( // KindBinary is a single self-contained executable, placed atomically in // halod's root-owned bin dir. KindBinary ArtifactKind = "binary" // KindNPMTgz is an npm package tarball installed with lifecycle scripts // disabled and no user/global npmrc. KindNPMTgz ArtifactKind = "npm-tgz" )
type ArtifactResolver ¶
type ArtifactResolver struct {
HTTP *http.Client // default: 60s timeout
ClaudeBase string // default https://downloads.claude.ai/claude-code-releases
NPMRegistry string // default https://registry.npmjs.org
}
ArtifactResolver fills HarnessEntry.Artifacts from the vendors' release metadata.
type Experiment ¶
type Experiment struct {
Name string `json:"name"`
Salt string `json:"salt"`
Variants []ExperimentVariant `json:"variants"`
}
Experiment is one client-axis experiment in a ring release manifest: just what halod needs to compute the same assignment as the gateway.
func (Experiment) Policy ¶
func (e Experiment) Policy(ring string) *policy.Experiment
Policy returns the policy experiment halod evaluates for a manifest entry: running, enrolling ring, with the manifest's salt and weights, so policy.Experiment.ResolveVariant (the gateway's function) does the hashing.
type ExperimentVariant ¶
type ExperimentVariant struct {
Name string `json:"name"`
Weight float64 `json:"weight"`
Channel string `json:"channel"`
}
ExperimentVariant is a variant and the channel serving its release.
type FileEntry ¶
type FileEntry struct {
Path string `json:"path"`
Mode uint32 `json:"mode"`
SHA256 string `json:"sha256"`
}
FileEntry describes one rendered file in the manifest.
type HarnessEntry ¶
type HarnessEntry struct {
Version string `json:"version"`
InstallCommand map[string]string `json:"installCommand,omitempty"`
Files map[string][]FileEntry `json:"files"`
// Artifacts are verified install artifacts keyed by "<goos>-<goarch>"
// (or "any"), filled by ResolveArtifacts; see artifacts.go.
Artifacts map[string]Artifact `json:"artifacts,omitempty"`
}
HarnessEntry is one harness's pinned version, installer and files, per OS.
func (HarnessEntry) ArtifactFor ¶
func (h HarnessEntry) ArtifactFor(goos, goarch string) (Artifact, bool)
ArtifactFor picks the artifact for goos/goarch, falling back to AnyPlatform.
type Manifest ¶
type Manifest struct {
SchemaVersion int `json:"schemaVersion"`
Org string `json:"org"`
Version string `json:"version"`
Profile string `json:"profile"`
Ring string `json:"ring"`
CreatedAt time.Time `json:"createdAt"`
Harnesses map[string]HarnessEntry `json:"harnesses"`
Warnings []string `json:"warnings,omitempty"`
// Experiment/Variant are set on a client-axis variant release only: the
// release served on channel policy.ChannelName(Ring, Experiment, Variant).
Experiment string `json:"experiment,omitempty"`
Variant string `json:"variant,omitempty"`
// Experiments (ring releases only) lists the running client-axis
// experiments enrolling Ring. Signed with the release, it is what halod
// uses to pick a device's variant channel.
Experiments []Experiment `json:"experiments,omitempty"`
// Toggles are the client-axis feature toggles: targeting rules plus the
// per-harness fragments halod merges for the toggles that are on for it.
Toggles []ToggleEntry `json:"toggles,omitempty"`
}
Manifest is manifest.json inside the bundle.
type Options ¶
type Options struct {
Org string // defaults to the resolver's Org.Name when it is a *policy.Org
Version string // release version label, e.g. "1.4.0"
CreatedAt time.Time // zero => Unix epoch, keeping builds reproducible
OSes []harness.OS // defaults to darwin, linux, windows
Gateway *policy.Gateway // defaults to Org.Gateway when resolver is a *policy.Org
// Experiment/Variant mark a client-axis variant release: stamped into the
// manifest and into the harness config (telemetry resource attributes).
Experiment, Variant string
// Experiments is the ring release's client-axis experiment table (see BuildRing).
Experiments []Experiment
}
Options tunes Build. Zero value is valid.
type ProfileResolver ¶
ProfileResolver is satisfied by *policy.Org once it grows ResolveProfile.
type Release ¶
type Release struct {
Manifest Manifest
Blobs map[string][]byte // sha256 hex -> content
Tar []byte
Digest string // "sha256:<hex>" of Tar
}
Release is a built (or opened) bundle.
func Build ¶
func Build(org ProfileResolver, profileName, ringName string, opts Options) (*Release, error)
Build renders profileName for every enabled harness and OS.
type ToggleEntry ¶
type ToggleEntry struct {
Name string `json:"name"`
Default bool `json:"default"`
Expires string `json:"expires,omitempty"`
Rules []policy.ToggleRule `json:"rules,omitempty"`
// Fragments is harness -> OS -> deltas, one per file the toggle changes
// (FileEntry.Path is the managed file the delta applies to; the blob is
// JSON, see toggle.Delta). The release's own files are the toggle-off state.
Fragments map[string]map[string][]FileEntry `json:"fragments,omitempty"`
}
ToggleEntry is one client-axis toggle in a release manifest. Being inside the signed manifest, neither the rules nor the fragments can be altered in transit.