spec

package
v0.11.4 Latest Latest
Warning

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

Go to latest
Published: Oct 7, 2026 License: Apache-2.0 Imports: 15 Imported by: 0

Documentation

Overview

Package spec is the rig.yaml schema: services, environments and the components that serve them.

Index

Constants

View Source
const (
	RoleApp   = "app"
	RoleInfra = "infra"
	RoleLoad  = "load"
)
View Source
const CurrentVersion = 1

CurrentVersion is the rig.yaml schema version this build understands. Bump it and add a Migration below whenever a change needs an old rig.yaml rewritten to keep loading.

View Source
const SchemaHeader = "# yaml-language-server: $schema=" + SchemaURL

SchemaHeader is the first line of a rig.yaml that gives editors its schema.

View Source
const SchemaURL = "https://raw.githubusercontent.com/goxang/rig/main/spec/rig.schema.json"

SchemaURL is where editors fetch SchemaJSON (the yaml-language-server header rig init writes).

Variables

View Source
var ErrNotFound = errors.New("no rig.yaml found in this directory or any parent (run `rig init`)")
View Source
var FileNames = []string{"rig.yaml", "rig.yml", ".rig.yaml", ".rig.yml"}
View Source
var SchemaJSON []byte

SchemaJSON is the JSON Schema of rig.yaml, generated from these types (Schema) by go generate.

View Source
var Screens = []string{"services", "logs", "metrics", "traces", "queries", "kv", "data", "load", "manifests", "hosts", "tests"}

Screens are the UI's screens in their default order.

Functions

func DataDir

func DataDir(projectDir string) (string, error)

DataDir is where rig keeps what it writes for a project checkout outside the repository (saved sessions): the user's config directory, one folder per project path.

func Expand

func Expand(s string, lookup func(string) (string, bool)) string

Expand replaces ${NAME} and ${NAME:-default}; $$ is a literal $. Unknown names stay as written.

func Find

func Find(dir string) (string, error)

Find walks up from dir to the first project file; $RIG_FILE wins when set.

func Importers

func Importers() []string

func Load

func Load(file, env string) (*Project, *Environment, error)

Load reads the project and resolves it for one environment: variables expanded, the environment's service patches merged, its components layered over the shared ones. env "" picks $RIG_ENV, then the project's default, then the only environment.

func LoadData added in v0.6.0

func LoadData(raw []byte, file, env string, overrides map[string]string) (*Project, *Environment, error)

LoadData is LoadWith on a rig.yaml already read (or never written: an inferred one); file is where it stands, for its directory and messages.

func LoadSecrets

func LoadSecrets(project string) (map[string]string, error)

func LoadWith

func LoadWith(file, env string, overrides map[string]string) (*Project, *Environment, error)

LoadWith is Load with variable overrides (`rig vars set`): they win over rig.yaml's vars, not over the OS environment.

func Migrate added in v0.4.0

func Migrate(file string) (from int, changed bool, err error)

Migrate brings a rig.yaml up to CurrentVersion in place, keeping comments and formatting. It reports the version found and whether the file was rewritten.

func ReadEnvFile added in v0.8.0

func ReadEnvFile(path string) (map[string]string, error)

ReadEnvFile reads a dotenv file: KEY=VALUE lines, optional export, # comments, quoted values.

func RegisterImporter

func RegisterImporter(name string, f Importer)

func Schema added in v0.6.0

func Schema(describe func(typ, key string) string) ([]byte, error)

Schema builds rig.yaml's JSON Schema from Project by reflection; describe gives a key of a type its description ("" for none).

func SecretsFile

func SecretsFile(project string) (string, error)

SecretsFile is where `rig secret set` keeps a project's secrets: the user's config directory, readable by the user only, never inside the repository.

func SetSecret

func SetSecret(project, name, value string) error

SetSecret stores (or with value "" removes) one secret of a project.

Types

type AI

type AI struct {
	// Deny are project paths (globs) the assistant never reads, e.g. configs/** holding credentials.
	Deny         []string `yaml:"deny"`
	Instructions string   `yaml:"instructions"`
	// Ideas are the questions tab offers in an empty chat, by screen (services, logs, ...) or "all";
	// they come before rig's own.
	Ideas map[string][]string `yaml:"ideas"`
}

type Alert

type Alert struct {
	Name   string  `yaml:"name"`
	Source string  `yaml:"source"`
	Metric string  `yaml:"metric"`
	Query  string  `yaml:"query"`
	Warn   float64 `yaml:"warn"`
	Crit   float64 `yaml:"crit"`
	// Below fires when the number drops under the thresholds instead (consumers, ready replicas).
	Below bool   `yaml:"below"`
	Unit  string `yaml:"unit"`
}

Alert fires when a number crosses Warn or Crit. Source "hosts" watches every node's Metric (cpu, memory or disk, in percent); any other source is a component whose Query returns rows, each row's first number checked and its text cells naming it.

type Build

type Build struct {
	Go         string            `yaml:"go"`
	Dockerfile string            `yaml:"dockerfile"`
	Context    string            `yaml:"context"`
	Command    []string          `yaml:"command"`
	Args       map[string]string `yaml:"args"`
}

type Component

type Component struct {
	Name string `yaml:"-"`
	Kind string `yaml:"kind"`
	Type string `yaml:"type"`
	Node yaml.Node
}

Component is one adapter instance: Kind picks the interface, Type the implementation, and the rest of the mapping is the adapter's own options.

func (*Component) Decode

func (c *Component) Decode(v any) error

Decode fills an adapter's options struct from the component mapping.

func (*Component) UnmarshalYAML

func (c *Component) UnmarshalYAML(n *yaml.Node) error

type DashVar

type DashVar struct {
	Values  []string `yaml:"values"`
	Source  string   `yaml:"source"`
	Query   string   `yaml:"query"`
	Label   string   `yaml:"label"`
	Default string   `yaml:"default"`
	Multi   bool     `yaml:"multi"`
	All     bool     `yaml:"all"`
}

DashVar is a dashboard variable: fixed Values, or the values of Label over the series Query returns (Grafana's label_values). Multi lets several be picked; All adds an "all" choice.

type Dashboard

type Dashboard struct {
	Help string `yaml:"help"`
	// Vars are the dashboard's $variables, picked in the UI; queries use them as $name.
	Vars   map[string]*DashVar `yaml:"vars"`
	Panels []Panel             `yaml:"panels"`
	// VarOrder is Vars as rig.yaml lists them.
	VarOrder []string `yaml:"-"`
}

func (*Dashboard) UnmarshalYAML

func (d *Dashboard) UnmarshalYAML(n *yaml.Node) error

type Environment

type Environment struct {
	Name        string     `yaml:"-"`
	Description string     `yaml:"description"`
	Runtime     *Component `yaml:"runtime"`
	Protected   bool       `yaml:"protected"`
	// ReadOnly refuses every change (start, stop, deploy, exec, data and KV writes, load), even with
	// --yes; reads, logs, metrics, traces and read-only queries still work.
	ReadOnly   bool                  `yaml:"readonly"`
	Vars       map[string]string     `yaml:"vars"`
	Only       []string              `yaml:"only"`
	Components map[string]*Component `yaml:"components"`
	Services   map[string]yaml.Node  `yaml:"services"`
	// Tasks replace the project's tasks of the same name in this environment.
	Tasks map[string]Task `yaml:"tasks"`
	// Queries replace the project's queries of the same name in this environment.
	Queries map[string]*Query `yaml:"queries"`
	// Alerts add to the project's alerts in this environment.
	Alerts []Alert `yaml:"alerts"`
	// OTel replaces the fields it sets of the project's otel:.
	OTel *OTel `yaml:"otel"`
	// Infra names the environment that runs this one's shared services, so heavy infrastructure
	// (a database, a broker) runs once for local, docker and kind alike.
	Infra string `yaml:"infra"`
}

type Import

type Import map[string]string

Import pulls services from another tool's file, e.g. {godev: .godev.yaml}.

type Importer

type Importer func(path, dir string) (map[string]*Service, error)

Importer turns another tool's service file into rig services; paths in them are relative to dir, the project's directory.

type LogsUI

type LogsUI struct {
	Wrap bool `yaml:"wrap"`
	// Raw shows lines as written instead of "LEVEL message key=value"; s switches.
	Raw bool `yaml:"raw"`
	// Time, Level and Message are the JSON keys of those parts, first match wins.
	Time    []string `yaml:"time"`
	Level   []string `yaml:"level"`
	Message []string `yaml:"message"`
	// Fields, when set, are the only other keys shown, in this order; Hide are keys left out (stack,
	// caller, ...) until h shows them.
	Fields []string `yaml:"fields"`
	Hide   []string `yaml:"hide"`
}

LogsUI says how the Logs screen reads structured (JSON) lines; every key has a default.

type Migration added in v0.4.0

type Migration struct {
	From  int
	Apply func(root *yaml.Node) error
}

Migration rewrites a project file's root mapping from one version to the next; From is the version it expects going in, and it must leave "version" one higher.

type OTel

type OTel struct {
	// Endpoint takes every signal (an OpenTelemetry Collector: svc://otel-collector:4318); Traces,
	// Metrics and Logs send one signal elsewhere, with its full path (svc://jaeger:4318/v1/traces).
	// A signal with no address is off.
	Endpoint string `yaml:"endpoint"`
	Traces   string `yaml:"traces"`
	Metrics  string `yaml:"metrics"`
	Logs     string `yaml:"logs"`
	// Protocol is http/protobuf (default), http/json or grpc.
	Protocol string `yaml:"protocol"`
	// Sample is the fraction of traces kept (parent based); left out, the SDK's default (all).
	Sample *float64 `yaml:"sample"`
	// Attributes are added to every service's resource, after service.namespace (the project) and
	// deployment.environment (the environment).
	Attributes map[string]string `yaml:"attributes"`
}

OTel becomes the standard OTEL_* variables of every app and load service; a variable the service sets itself wins. Addresses take svc://service:port[/path]: inside the runtime's network for containers and pods, forwarded for local processes.

type Panel

type Panel struct {
	// Row starts a new titled row of panels; a panel with only row: is the row's header.
	Row   string `yaml:"row"`
	Title string `yaml:"title"`
	Query string `yaml:"query"`
	// Queries are several queries drawn together (p50, p95 and p99), each with its own legend.
	Queries []PanelQuery `yaml:"queries"`
	Unit    string       `yaml:"unit"`
	Source  string       `yaml:"source"`
	Legend  string       `yaml:"legend"`
	Help    string       `yaml:"help"`
	// Kind: line (default), stat, gauge, bar (one bar per series, its last value), table.
	Kind string `yaml:"kind"`
	// Width is out of 24 columns, like Grafana (default 12, stat and gauge 6); Height in lines.
	Width  int `yaml:"width"`
	Height int `yaml:"height"`
	// Min and Max bound a gauge (default 0..100 for %, else 0..the largest value).
	Min *float64 `yaml:"min"`
	Max *float64 `yaml:"max"`
	// Warn and Crit colour stat, gauge and bar values amber and red past them.
	Warn *float64 `yaml:"warn"`
	Crit *float64 `yaml:"crit"`
	// Stack draws line series stacked.
	Stack bool `yaml:"stack"`
}

func (Panel) Targets

func (p Panel) Targets() []PanelQuery

Targets are the panel's queries: Queries, else Query with the panel's legend.

type PanelQuery

type PanelQuery struct {
	Query  string `yaml:"query"`
	Legend string `yaml:"legend"`
}

type Probe

type Probe struct {
	Port string `yaml:"port"`
	Path string `yaml:"path"`
}

Probe points at an HTTP path on a named or numbered port.

type Project

type Project struct {
	Version      int                     `yaml:"version"`
	Name         string                  `yaml:"project"`
	Default      string                  `yaml:"default"`
	Imports      []Import                `yaml:"imports"`
	Vars         map[string]string       `yaml:"vars"`
	Services     map[string]*Service     `yaml:"services"`
	Environments map[string]*Environment `yaml:"environments"`
	Components   map[string]*Component   `yaml:"components"`
	Dashboards   map[string]*Dashboard   `yaml:"dashboards"`
	// Tests are named test suites: `rig test <name>` and the Tests screen.
	Tests     map[string]*TestSuite `yaml:"tests"`
	Manifests []string              `yaml:"manifests"`
	// Tasks are named lists of shell steps: `rig task <name>`.
	Tasks map[string]Task `yaml:"tasks"`
	// Queries are saved queries: run on demand, or on a schedule while the UI is open.
	Queries map[string]*Query `yaml:"queries"`
	// Secrets are names ${NAME} may use whose values live outside the repo: the environment, then
	// `rig secret set`, then the default written here.
	Secrets map[string]Secret `yaml:"secrets"`
	// Alerts are watched while the UI is open and shown in its header; `rig alerts` checks them once.
	Alerts []Alert `yaml:"alerts"`
	// Reports name the metrics a run is measured by: `rig report <name>`, a test suite's report:,
	// the Load screen's W.
	Reports map[string]*Report `yaml:"reports"`
	// Sections split the Services screen by business area; services in none fall under "other".
	Sections map[string]*Section `yaml:"sections"`
	// OTel points every app and load service at OpenTelemetry backends.
	OTel *OTel `yaml:"otel"`
	// UI picks the screens of `rig` and their order.
	UI *UI `yaml:"ui"`
	// AI tells the assistant (`rig ai`, @ in the UI) about the project: paths it must not read, notes.
	AI *AI `yaml:"ai"`
	// Help is shown by `rig -h` under the project name: this project's own quick-start for its main
	// CLI workflows (e.g. build/deploy/ship with a target database and image tag). Plain text, a few
	// example command lines; left out, `rig -h` shows only its own generic help.
	Help string `yaml:"help"`

	// DashboardOrder, TestOrder and SectionOrder are the names as rig.yaml lists them.
	DashboardOrder []string `yaml:"-"`
	TestOrder      []string `yaml:"-"`
	SectionOrder   []string `yaml:"-"`

	// Unset are the ${NAME}s the file uses (outside other environments) that nothing sets and that
	// have no :-default: they stay as written.
	Unset []string `yaml:"-"`
	// FromEnv are the ${NAME}s the file took from the process environment, with their values.
	FromEnv map[string]string `yaml:"-"`

	// Dir is where the project file lives; relative paths in it resolve from here.
	Dir  string `yaml:"-"`
	File string `yaml:"-"`
}

func (*Project) EnvironmentNames

func (p *Project) EnvironmentNames() []string

func (*Project) ImportPaths added in v0.9.0

func (p *Project) ImportPaths(kinds ...string) []string

ImportPaths are the absolute paths of the project's imports of these kinds, in file order.

func (*Project) Order

func (p *Project) Order(names []string) ([][]string, error)

Order groups names into start layers: every service comes after what it depends on, and services in one layer can start together. Dependencies outside names are ignored.

func (*Project) SecretValues added in v0.6.0

func (p *Project) SecretValues() map[string]string

SecretValues are the values the project's secrets resolve to, as Load expands them: the environment, then `rig secret set`, then the default. Empty ones are left out.

func (*Project) SectionMap

func (p *Project) SectionMap() map[string]string

SectionMap maps each service to the first section listing it; services in none are left out.

func (*Project) Select

func (p *Project) Select(targets []string) []string

Select expands targets (service names, group names, roles, or "all") to service names, sorted and without duplicates. No targets means every app and infra service.

func (*Project) ServiceNames

func (p *Project) ServiceNames() []string

func (*Project) Unknown

func (p *Project) Unknown(targets []string) []string

Unknown lists targets that match no service, group or role.

func (*Project) WithDeps

func (p *Project) WithDeps(names []string) []string

WithDeps adds every transitive dependency of names.

type Query

type Query struct {
	Name   string            `yaml:"-"`
	Source string            `yaml:"source"`
	Query  string            `yaml:"query"`
	Help   string            `yaml:"help"`
	Group  string            `yaml:"group"`
	Params map[string]string `yaml:"params"`
	// Every runs the query on a schedule while the UI is open, when Active (or activated there).
	Every  time.Duration `yaml:"every"`
	Active bool          `yaml:"active"`
}

Query is a saved query against a component. {{name}} placeholders are filled from Params (the defaults) or from the caller.

type Report

type Report struct {
	Help string `yaml:"help"`
	// Source is the metrics component (default the first).
	Source  string         `yaml:"source"`
	Metrics []ReportMetric `yaml:"metrics"`
}

type ReportMetric

type ReportMetric struct {
	Title  string   `yaml:"title"`
	Query  string   `yaml:"query"`
	Unit   string   `yaml:"unit"`
	Legend string   `yaml:"legend"`
	Stats  []string `yaml:"stats"`
}

ReportMetric is one query, summarised per series by Stats over the run's window: avg, min, max, last, p50, p90, p95, p99 (default avg, max, last).

type Run

type Run struct {
	Command []string `yaml:"command"`
	Args    []string `yaml:"args"`
	Dir     string   `yaml:"dir"`
}

type Secret

type Secret struct {
	Help    string `yaml:"help"`
	Default string `yaml:"default"`
}

type Section

type Section struct {
	Name     string   `yaml:"-"`
	Help     string   `yaml:"help"`
	Services []string `yaml:"services"`
}

Section is a part of the Services screen; Services are names, groups or roles.

type Service

type Service struct {
	Name      string            `yaml:"-"`
	Role      string            `yaml:"role"`
	Groups    []string          `yaml:"groups"`
	DependsOn []string          `yaml:"depends_on"`
	Ports     map[string]int    `yaml:"ports"`
	Env       map[string]string `yaml:"env"`
	// EnvFile are KEY=VALUE files (from the project directory) read under env:, later files winning.
	EnvFile []string `yaml:"env_file"`
	Image   string   `yaml:"image"`
	// Replicas left out keeps what the environment has (the manifest's count, or a running workload's);
	// 0 keeps a service deployed but stopped.
	Replicas *int   `yaml:"replicas"`
	Build    *Build `yaml:"build"`
	Run      *Run   `yaml:"run"`
	Health   *Probe `yaml:"health"`
	Metrics  *Probe `yaml:"metrics"`
	Pprof    *Probe `yaml:"pprof"`
	// Shared marks infrastructure that one environment runs for others (see Environment.Infra).
	Shared bool `yaml:"shared"`
	// Delay is how long up waits after the service's dependencies are ready before starting it.
	Delay time.Duration `yaml:"delay"`
	// Manual services start only when named (or through their group or section), never with "all"
	// or their role (rig infra up).
	Manual bool `yaml:"manual"`
	// Watch is what rig watch (ctrl+w in the UI) rebuilds and restarts the service on.
	Watch *Watch `yaml:"watch"`

	// Sections owned by adapters (local:, docker:, k8s:, ...), decoded by the adapter that reads them.
	Sections map[string]yaml.Node `yaml:",inline"`
}

func (*Service) Count

func (s *Service) Count() (int, bool)

Count is the replica count rig.yaml asks for, and whether it asks at all.

func (*Service) CountOr

func (s *Service) CountOr(def int) int

CountOr is the replica count rig.yaml asks for, else def.

func (*Service) FirstPort

func (s *Service) FirstPort() int

func (*Service) InGroup

func (s *Service) InGroup(g string) bool

func (*Service) PortNumber

func (s *Service) PortNumber(p string) int

PortNumber resolves a port by name or number; 0 when unknown.

func (*Service) Section

func (s *Service) Section(name string, v any) (bool, error)

Section decodes an adapter-owned section of the service, false when absent.

type Task

type Task struct {
	Help string    `yaml:"help"`
	Args []TaskArg `yaml:"args"`
	// Confirm asks before the first step, on any environment; --yes answers it.
	Confirm bool `yaml:"confirm"`
	// ReadOnly marks a task that changes nothing, so it runs in a read-only environment too.
	ReadOnly bool     `yaml:"readonly"`
	Steps    []string `yaml:"steps"`
}

Dashboard is a list of panels, or {vars:, panels:} when its queries use $variables. Task is a list of shell steps, or {help, steps} to say what it is for.

func (*Task) UnmarshalYAML

func (t *Task) UnmarshalYAML(n *yaml.Node) error

type TaskArg added in v0.5.0

type TaskArg struct {
	Name    string   `yaml:"name"`
	Help    string   `yaml:"help"`
	Default string   `yaml:"default"`
	Choices []string `yaml:"choices"`
	From    string   `yaml:"from"`
	Multi   bool     `yaml:"multi"`
}

TaskArg is an input a task asks for before it runs (rig task <name> on a terminal, T in the UI). An UPPER_CASE name reaches the steps as that env var; a lower-case one as positional words ($1..., $RIG_ARGS). Choices, or From (services: every service and group; hosts), offer a pick list.

func (TaskArg) Env added in v0.5.0

func (a TaskArg) Env() bool

Env is whether the arg is passed as NAME=value rather than as positional words.

type TestSuite

type TestSuite struct {
	Name  string `yaml:"-"`
	Help  string `yaml:"help"`
	Group string `yaml:"group"`
	// Command runs the suite through sh instead of go test: pytest, jest, mvn test, cargo test, ...
	// Writing JUnit XML to $RIG_JUNIT gives the screen one row per test; without it the suite passes
	// or fails as a whole by its exit status.
	Command  string   `yaml:"command"`
	Packages []string `yaml:"packages"`
	// Exclude drops packages from Packages (go list patterns: ./pkg/tests/...), so a suite can be
	// "everything but the integration tests".
	Exclude []string `yaml:"exclude"`
	// Dir is where go test runs (default the project directory).
	Dir  string `yaml:"dir"`
	Run  string `yaml:"run"`
	Skip string `yaml:"skip"`
	Tags string `yaml:"tags"`
	// Env reaches the test binaries; svc:// addresses resolve in the active environment.
	Env      map[string]string `yaml:"env"`
	Timeout  time.Duration     `yaml:"timeout"`
	Race     bool              `yaml:"race"`
	Cover    bool              `yaml:"cover"`
	Short    bool              `yaml:"short"`
	Count    int               `yaml:"count"`
	Parallel int               `yaml:"parallel"`
	// Bench runs benchmarks matching it (go test -bench); Benchtime and Benchmem tune them.
	Bench     string `yaml:"bench"`
	Benchtime string `yaml:"benchtime"`
	Benchmem  bool   `yaml:"benchmem"`
	// Flags are more go test flags; Args go to the test binary after -args.
	Flags []string `yaml:"flags"`
	Args  []string `yaml:"args"`
	// Needs are services (or groups) the suite expects up; the UI warns when they are not.
	Needs []string `yaml:"needs"`
	// Report is a reports: entry measured over each run and saved with it.
	Report string `yaml:"report"`
}

TestSuite is a set of Go packages tested together (go test -json), with the flags it always needs, or a Command of any stack.

type UI

type UI struct {
	// Tabs are the screens shown, in order (number keys follow it); left out, every screen the
	// project configures something for shows, in the order of Screens.
	Tabs []string `yaml:"tabs"`
	// Mode is simple (fewer columns, keys and panels, for newcomers) or detailed (the default); V
	// switches it in the UI.
	Mode string  `yaml:"mode"`
	Logs *LogsUI `yaml:"logs"`
}

type Watch added in v0.6.0

type Watch struct {
	// Paths are directories or files (from the project directory); left out, the packages a build.go
	// main imports from the project, else build.context, else run.dir.
	Paths []string `yaml:"paths"`
	// Ignore are globs matched against a changed file's path and name (*_test.go, docs/**).
	Ignore []string `yaml:"ignore"`
}

Watch is a service's sources for live rebuilds; .gitignore'd files never count.

Jump to

Keyboard shortcuts

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