Documentation
¶
Overview ¶
Package release is the console's bytes: the ACTIVE release of a published site, held in memory and kept current.
The console used to be //go:embed'd into this binary, which welded the frontend's lifecycle to the backend's — a CSS fix cost a ~22-minute cloud build and a `strategy: Recreate` rollout that took api.hanzo.ai down for 2m15s. The console is now published like any other site (apps/projects → apps/sites): a publish is under a second, a rollback is faster, and neither builds or restarts anything.
It is the SAME release, read from the SAME store, resolved through the SAME registry the site edge uses (sites.CurrentResolver) — not a second copy of any of it. What differs is only where the bytes go: the edge STREAMS them for a site host, and this loads them once and hands webui an fs.FS, because console.hanzo.ai is deliberately NOT a site host (it must keep answering /v1 on the same origin, or the console's first-party session cookie stops working).
A leaf, like webui itself: apps/sites + apps/s3admin + stdlib, never package cloud — both composition roots import it.
Index ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func FS ¶
FS presents a Source as the fs.FS webui.Mount takes, INCLUDING the nil case.
A nil *Source assigned straight to an fs.FS is a non-nil interface holding a nil pointer — Go's oldest trap — and here it would turn "this process mounted no console" into a nil dereference on the first request instead of the 503 webui is written to answer. One conversion, so neither composition root can spell it wrong.
Types ¶
type Config ¶
type Config struct {
// Org owns the console site. Resolution is PINNED to it — never
// unique-across-orgs — so a customer project of the same name can never be
// served as our console.
Org string
// Slug is the console site's project slug.
Slug string
// Poll is how long a published release waits before it is live everywhere.
Poll time.Duration
}
Config names the site whose active release IS the console, and how often to look for a new one.
func ConfigFromEnv ¶
func ConfigFromEnv() Config
The ONE resolution of the console-source configuration, for the same reason apps/sites owns its own (env.go there): TWO processes mount the console — the light router that owns the public port (cmd/cloud) and cloud.Listen in every per-app child — and a key spelled at each call site is a key the two can disagree about. It happened already with CLOUD_SITES_FIRSTPARTY_* against CLOUD_SITES_FIRST_PARTY_*, where which policy applied depended on which process a request reached.
CLOUD_CONSOLE_SITE the console site's slug (default hanzo-console)
CLOUD_CONSOLE_ORG the org that owns it (default: the sites
first-party org, CLOUD_SITES_FIRSTPARTY_ORG, itself
defaulting to hanzo)
CLOUD_CONSOLE_POLL how often to re-read the active-release pointer
(default 30s; anything Go's time.ParseDuration accepts)
The org DEFAULT is not a second literal "hanzo": the console is a first-party site, and which org holds our first-party sites is already stated once, in apps/sites. A white-label deployment that moves it moves the console with it.
type Source ¶
type Source struct {
// contains filtered or unexported fields
}
Source is a live fs.FS over one site's active release.
The pointer to the loaded bundle is swapped ATOMICALLY, never mutated: a request that started against the old release finishes against it, and the next one gets the new. There is no window in which a shell from one release is served beside chunks from another.
func Load ¶
Load reads the configured site's active release and returns it as an fs.FS.
It FAILS rather than degrading. A console that came up empty, or on a placeholder shell, would be a front door serving a page that looks like the product and is not — and it would do so silently, which is how a broken deploy becomes a mystery instead of an alert. Every failure below names what could not be reached, so the log line is the diagnosis.
The resolver must already be installed: the site edge is mounted before the console in both composition roots (cmd/cloud's TestSitesEdgeIsMountedInTheRouter pins that order for the front door), so "no resolver" means a caller mounted them backwards.
func (*Source) Release ¶
Release is the S3 prefix of the mounted release — the release id is its last segment. Reported at boot and on every swap so "which console is live" is a question the logs answer.
func (*Source) Watch ¶
Watch keeps the console current with what was published, and is the whole reason this indirection exists: a `hanzo sites publish` reaches users through THIS loop, in one poll interval, instead of through a cloud build and a rollout.
The steady state costs one resolver call per interval and nothing else — the bytes are re-read only when the active-release pointer actually moves. A failed poll is logged and the mounted release keeps serving: the bundle in memory is already complete, so there is nothing to fall back to and nothing to gain by tearing it down.