Documentation
¶
Overview ¶
Package remotestate publishes one machine's WB fleet state to a shared store and reads every machine's state back. The store is pluggable; the snapshot format is not.
Index ¶
- Constants
- Variables
- func Encode(s Snapshot) ([]byte, error)
- func EncodeClaim(c Claim) ([]byte, error)
- func ValidTaskName(task string) error
- func ValidateHubURL(raw string) error
- type Claim
- type ClaimEntry
- type ClaimMode
- type ClaimOutcome
- type ClaimOutcomeKind
- type Config
- type Entry
- type Provider
- type PublishConfig
- type PublishResult
- type PullRequestState
- type Redaction
- type ReleaseOutcome
- type ReleaseOutcomeKind
- type RepositoryInput
- type RepositoryState
- type Snapshot
- type StatusProvider
- type StatusSnapshot
- type UnconfiguredError
- type WorktreeState
Constants ¶
const ( StatusAttention = "attention" StatusError = "error" )
Status constants for RepositoryState.
const ClaimSchemaVersion = 1
ClaimSchemaVersion is the claim format this binary writes and the newest it can read.
const ConfigSnippet = `` /* 137-byte string literal not displayed */
ConfigSnippet is printed whenever the remote section is absent or incomplete, so the fix is copy-paste rather than documentation lookup.
const HubConfigSnippet = `` /* 180-byte string literal not displayed */
HubConfigSnippet is the explicit hosted alternative. It has no anonymous or insecure default and defaults to privacy-safe unpushed counts.
const SchemaVersion = 1
SchemaVersion is the snapshot format this binary writes and the newest it can read.
Variables ¶
var ErrHubURL = errors.New("remote.url must be an HTTPS origin without credentials, query, or fragment, or an http:// origin on a loopback host")
ErrHubURL is the single explanation both the configuration loader and the HTTP provider give for a hub endpoint they will not talk to.
Functions ¶
func EncodeClaim ¶ added in v0.45.0
EncodeClaim renders a claim as YAML.
func ValidTaskName ¶ added in v0.45.0
ValidTaskName enforces the machine-name rule on task names, which also keeps claims/<task>.yaml a safe path.
func ValidateHubURL ¶ added in v0.124.5
ValidateHubURL accepts an HTTPS origin, and an http:// origin only when its host is a loopback address.
Plain http is otherwise refused because a machine credential travels in the Authorization header on every request. A loopback origin is the one case where there is no network to intercept: the self-hosted bench in spec/features/self-hosted-bench runs the hub inside the same daemon the provider talks to, reachable only from this machine, and demanding a certificate for 127.0.0.1 would mean "deploy a service" rather than "run wb".
Types ¶
type Claim ¶ added in v0.45.0
type Claim struct {
SchemaVersion int `yaml:"schema_version" json:"schema_version"`
Task string `yaml:"task" json:"task"`
Login string `yaml:"login" json:"login"`
Machine string `yaml:"machine" json:"machine"`
ClaimedAt time.Time `yaml:"claimed_at" json:"claimed_at"`
Note string `yaml:"note,omitempty" json:"note,omitempty"`
}
Claim says one task is being worked on by one login/machine. The claim file's existence in the store IS the claim; releasing deletes it, so git history is the audit trail and no state field exists.
func DecodeClaim ¶ added in v0.45.0
DecodeClaim parses a claim, refusing formats newer than this binary knows.
type ClaimEntry ¶ added in v0.45.0
ClaimEntry is one claim as read from the store; Error is set when the file could not be decoded (Claim then carries only Task from the path).
type ClaimMode ¶ added in v0.45.0
type ClaimMode int
ClaimMode selects how an existing claim by someone else is treated.
const ( // ClaimNormal refuses to touch anyone else's claim. ClaimNormal ClaimMode = iota // ClaimTakeOverStale replaces another holder's claim; callers must have // established staleness first — the provider does not judge it. ClaimTakeOverStale // ClaimForce replaces anything, including an unreadable claim file. ClaimForce )
type ClaimOutcome ¶ added in v0.45.0
type ClaimOutcome struct {
Kind ClaimOutcomeKind `json:"kind"`
Current Claim `json:"current"`
Previous *Claim `json:"previous,omitempty"` // set on took_over
Location string `json:"location,omitempty"` // commit SHA / URL
}
ClaimOutcome reports a Claim call so commands own all messaging.
type ClaimOutcomeKind ¶ added in v0.45.0
type ClaimOutcomeKind string
ClaimOutcomeKind is what a Claim call did.
const ( ClaimAcquired ClaimOutcomeKind = "acquired" ClaimRefreshed ClaimOutcomeKind = "refreshed" // ClaimHeld means no write happened; Current is the other holder's claim. ClaimHeld ClaimOutcomeKind = "held" ClaimTookOver ClaimOutcomeKind = "took_over" )
type Config ¶
type Config struct {
Provider string `yaml:"provider"`
Repo string `yaml:"repo"`
URL string `yaml:"url"`
TokenFile string `yaml:"token_file"`
Machine string `yaml:"machine"`
Publish PublishConfig `yaml:"publish"`
}
Config is the remote section of ~/.config/wb/wb.yaml.
func LoadConfig ¶
LoadConfig reads the remote section from path. A missing file or section is an UnconfiguredError; a present but invalid value is a plain error.
type Entry ¶
Entry is one machine as read from the store. Error is set when the stored snapshot could not be decoded; Snapshot then carries only Login/Machine.
type Provider ¶
type Provider interface {
// Publish overwrites the caller's own login/machine entry. It is
// self-contained: implementations refresh their own view of the store
// before writing, so callers never need a separate refresh step first.
Publish(ctx context.Context, snapshot Snapshot) (PublishResult, error)
// List returns every machine currently in the store, including the
// caller's own last-published entry, sorted by Key(). It is also
// self-contained, refreshing the store view itself before reading.
List(ctx context.Context) ([]Entry, error)
// Claim acquires or refreshes a claim on a task. It is self-contained:
// implementations refresh the store view before acting. The provider never
// judges staleness; ClaimTakeOverStale merely authorizes replacing another
// holder — commands establish staleness first.
//
// expectedHolder is the "<login>/<machine>" the caller judged stale and
// is authorizing replacement of; it is "" for ClaimNormal and
// ClaimForce, which do not need one. For ClaimTakeOverStale it is a
// precondition: a hub provider maps this to a conditional PUT keyed on
// the current holder, and a git-backed provider re-checks it against
// the freshly fetched store before writing. If the actual current
// holder no longer matches (they released and a third party claimed,
// or refreshed away their own staleness, between the caller's judgment
// and this call), the provider must not replace them — it reports an
// ordinary ClaimHeld naming the real current holder instead.
Claim(ctx context.Context, claim Claim, mode ClaimMode, expectedHolder string) (ClaimOutcome, error)
// Release removes a claim. It is self-contained, refreshing the store view
// before acting.
Release(ctx context.Context, task, login, machine string, force bool) (ReleaseOutcome, error)
// Claims returns every claim currently in the store, sorted by task name.
// It is self-contained, refreshing the store view itself before reading.
Claims(ctx context.Context) ([]ClaimEntry, error)
}
Provider is a shared store of machine snapshots. Implementations must be safe to call from several machines at once; the git provider relies on per-machine files plus rebase for that.
type PublishConfig ¶
type PublishConfig struct {
Unpushed Redaction `yaml:"unpushed"`
}
PublishConfig tunes what a snapshot contains.
type PublishResult ¶
type PublishResult struct {
Location string `json:"location"`
}
PublishResult says where a snapshot landed: a commit SHA for a git store, a URL for a hub.
type PullRequestState ¶ added in v0.112.0
type PullRequestState struct {
Number int `yaml:"number" json:"number"`
URL string `yaml:"url" json:"url"`
State string `yaml:"state" json:"state"`
}
PullRequestState is the navigable PR evidence that was available when the machine published its worktree snapshot. It deliberately omits commit and local checkout details that the hosted dashboard does not need.
type ReleaseOutcome ¶ added in v0.45.0
type ReleaseOutcome struct {
Kind ReleaseOutcomeKind `json:"kind"`
Current *Claim `json:"current,omitempty"`
Location string `json:"location,omitempty"`
}
ReleaseOutcome reports a Release call.
type ReleaseOutcomeKind ¶ added in v0.45.0
type ReleaseOutcomeKind string
ReleaseOutcomeKind is what a Release call did.
const ( Released ReleaseOutcomeKind = "released" // ReleaseNoop: no claim existed; releasing is idempotent. ReleaseNoop ReleaseOutcomeKind = "noop" // ReleaseHeldByOther: refused (force was false); Current names the holder. ReleaseHeldByOther ReleaseOutcomeKind = "held_by_other" )
type RepositoryInput ¶
type RepositoryInput struct {
Repository string
Path string
Status gitops.RepoStatus
Tracking gitops.TrackingState
Err error
}
RepositoryInput is the per-repository scan result Build consumes. Err set means the scan itself failed; Status and Tracking are then ignored.
type RepositoryState ¶
type RepositoryState struct {
Repository string `yaml:"repository" json:"repository"`
Path string `yaml:"path" json:"path"`
Status string `yaml:"status" json:"status"` // attention | error
Summary string `yaml:"summary,omitempty" json:"summary,omitempty"`
Branch string `yaml:"branch,omitempty" json:"branch,omitempty"`
Upstream string `yaml:"upstream,omitempty" json:"upstream,omitempty"`
Ahead int `yaml:"ahead,omitempty" json:"ahead,omitempty"`
Behind int `yaml:"behind,omitempty" json:"behind,omitempty"`
Modified []string `yaml:"modified,omitempty" json:"modified,omitempty"`
Untracked []string `yaml:"untracked,omitempty" json:"untracked,omitempty"`
Conflicted []string `yaml:"conflicted,omitempty" json:"conflicted,omitempty"`
Unpushed []string `yaml:"unpushed,omitempty" json:"unpushed,omitempty"`
UnpushedBranches []gitops.UnpushedBranch `yaml:"unpushed_branches,omitempty" json:"unpushed_branches,omitempty"`
UnpushedCount int `yaml:"unpushed_count,omitempty" json:"unpushed_count,omitempty"`
Stashed []string `yaml:"stashed,omitempty" json:"stashed,omitempty"`
Error string `yaml:"error,omitempty" json:"error,omitempty"`
}
RepositoryState is one non-clean repository on the publishing machine.
type Snapshot ¶
type Snapshot struct {
SchemaVersion int `yaml:"schema_version" json:"schema_version"`
Login string `yaml:"login" json:"login"`
Machine string `yaml:"machine" json:"machine"`
PublishedAt time.Time `yaml:"published_at" json:"published_at"`
// LastSeenAt records the last time this machine acted through the store
// via a claim mutation (claim, refresh, release, take-over); it is
// stamped by the provider, never by Build. Zero means no claim activity
// has been recorded. See Heartbeat.
LastSeenAt time.Time `yaml:"last_seen_at,omitempty" json:"last_seen_at,omitempty"`
WBVersion string `yaml:"wb_version" json:"wb_version"`
RemoteStore string `yaml:"remote_store,omitempty" json:"remote_store,omitempty"`
ProjectsRoot string `yaml:"projects_root" json:"projects_root"`
RepositoriesScanned int `yaml:"repositories_scanned" json:"repositories_scanned"`
KnownRepositories []string `yaml:"known_repositories,omitempty" json:"known_repositories,omitempty"`
Repositories []RepositoryState `yaml:"repositories" json:"repositories"`
Worktrees []WorktreeState `yaml:"worktrees" json:"worktrees"`
}
Snapshot is one machine's published fleet state.
func Build ¶
func Build(identity Snapshot, repos []RepositoryInput, wts []worktrees.ListResult, redaction Redaction) Snapshot
Build assembles a snapshot. identity supplies Login, Machine, PublishedAt, WBVersion, and ProjectsRoot; everything else is derived here. Clean repositories are counted but not listed. Output is sorted by repository.
func (Snapshot) Heartbeat ¶ added in v0.54.0
Heartbeat is the effective liveness signal for staleness judgments: the later of PublishedAt (last full scan) and LastSeenAt (last claim-mutation activity through the store). This is the single definition of that max — callers must not compute it themselves.
type StatusProvider ¶ added in v0.116.0
type StatusProvider interface {
Status(ctx context.Context) (StatusSnapshot, error)
}
StatusProvider is the optional provider capability used by remote status to refresh once and read both projections from that same store view. Providers that cannot batch the reads keep the Provider contract below; ReadStatus falls back to its two self-contained methods.
type StatusSnapshot ¶ added in v0.116.0
type StatusSnapshot struct {
Machines []Entry `json:"machines"`
Claims []ClaimEntry `json:"claims"`
}
StatusSnapshot is one consistent read of the machine snapshots and task claims currently held by a remote store.
func ReadStatus ¶ added in v0.116.0
func ReadStatus(ctx context.Context, provider Provider) (StatusSnapshot, error)
ReadStatus returns the machine and claim projections needed by remote status. A provider-level Status implementation can share one refresh; the fallback preserves compatibility with providers that expose only the self-contained Provider methods.
type UnconfiguredError ¶
UnconfiguredError reports a missing or incomplete remote section. Commands map it to the usage exit code.
func (*UnconfiguredError) Error ¶
func (e *UnconfiguredError) Error() string
type WorktreeState ¶
type WorktreeState struct {
Task string `yaml:"task" json:"task"`
TaskSummary string `yaml:"task_summary,omitempty" json:"task_summary,omitempty"`
Stream string `yaml:"stream,omitempty" json:"stream,omitempty"`
Repository string `yaml:"repository" json:"repository"`
Branch string `yaml:"branch" json:"branch"`
HeadSHA string `yaml:"head_sha" json:"head_sha"`
Dir string `yaml:"dir" json:"dir"`
Lifecycle string `yaml:"lifecycle,omitempty" json:"lifecycle,omitempty"`
// OwnerState is worktrees.ListResult.OwnerState: "active", "orphaned", or
// "unknown". Empty only if the underlying scan left it unset.
OwnerState string `yaml:"owner_state,omitempty" json:"owner_state,omitempty"`
Owner string `yaml:"owner,omitempty" json:"owner,omitempty"`
LastActivityAt time.Time `yaml:"last_activity_at,omitempty" json:"last_activity_at,omitempty"`
NeedsAttention bool `yaml:"needs_attention,omitempty" json:"needs_attention,omitempty"`
Attention string `yaml:"attention,omitempty" json:"attention,omitempty"`
PullRequest *PullRequestState `yaml:"pull_request,omitempty" json:"pull_request,omitempty"`
}
WorktreeState is one WB task worktree on the publishing machine, whether or not its owning session is still alive.