remotestate

package
v0.67.13 Latest Latest
Warning

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

Go to latest
Published: Aug 30, 2026 License: MIT Imports: 11 Imported by: 0

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

View Source
const (
	StatusAttention = "attention"
	StatusError     = "error"
)

Status constants for RepositoryState.

View Source
const ClaimSchemaVersion = 1

ClaimSchemaVersion is the claim format this binary writes and the newest it can read.

View Source
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.

View Source
const SchemaVersion = 1

SchemaVersion is the snapshot format this binary writes and the newest it can read.

Variables

This section is empty.

Functions

func Encode

func Encode(s Snapshot) ([]byte, error)

Encode renders a snapshot as YAML.

func EncodeClaim added in v0.45.0

func EncodeClaim(c Claim) ([]byte, error)

EncodeClaim renders a claim as YAML.

func ValidTaskName added in v0.45.0

func ValidTaskName(task string) error

ValidTaskName enforces the machine-name rule on task names, which also keeps claims/<task>.yaml a safe path.

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

func DecodeClaim(data []byte) (Claim, error)

DecodeClaim parses a claim, refusing formats newer than this binary knows.

func (Claim) Holder added in v0.45.0

func (c Claim) Holder() string

Holder identifies the claimant: "<login>/<machine>". Mutual exclusion is per machine — the same login on another machine is another holder.

type ClaimEntry added in v0.45.0

type ClaimEntry struct {
	Claim Claim  `json:"claim"`
	Error string `json:"error,omitempty"`
}

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"`
	Machine  string        `yaml:"machine"`
	Publish  PublishConfig `yaml:"publish"`
}

Config is the remote section of ~/.config/wb/wb.yaml.

func LoadConfig

func LoadConfig(path string) (Config, error)

LoadConfig reads the remote section from path. A missing file or section is an UnconfiguredError; a present but invalid value is a plain error.

func (Config) RepoName

func (c Config) RepoName() string

RepoName returns the part of Repo after the slash.

func (Config) RepoOwner

func (c Config) RepoOwner() string

RepoOwner returns the part of Repo before the slash.

type Entry

type Entry struct {
	Snapshot Snapshot `json:"snapshot"`
	Error    string   `json:"error,omitempty"`
}

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 Redaction

type Redaction string

Redaction selects how unpushed commits are published.

const (
	// RedactNone publishes `git log --oneline` subjects of unpushed commits.
	RedactNone Redaction = "subjects"
	// RedactUnpushed publishes only the number of unpushed commits.
	RedactUnpushed Redaction = "counts"
)

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"`
	ProjectsRoot        string            `yaml:"projects_root" json:"projects_root"`
	RepositoriesScanned int               `yaml:"repositories_scanned" json:"repositories_scanned"`
	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 Decode

func Decode(data []byte) (Snapshot, error)

Decode parses a snapshot, refusing formats newer than this binary knows.

func (Snapshot) Heartbeat added in v0.54.0

func (s Snapshot) Heartbeat() time.Time

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.

func (Snapshot) Key

func (s Snapshot) Key() string

Key identifies the machine inside a store: "<login>/<machine>".

type UnconfiguredError

type UnconfiguredError struct {
	Path    string
	Missing []string
}

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"`
	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"`
	// 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"`
}

WorktreeState is one WB task worktree on the publishing machine, whether or not its owning session is still alive.

Directories

Path Synopsis
Package gitrepo stores machine snapshots in a git repository: one file per machine, history for free, no server.
Package gitrepo stores machine snapshots in a git repository: one file per machine, history for free, no server.

Jump to

Keyboard shortcuts

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