spec

package
v0.1.0 Latest Latest
Warning

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

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

Documentation

Overview

Package spec is the model of a project (docs/product/glossary.md): its applications — usually one git repository each — and its services, each living in the project and attached to one or more of its applications. Agents run environments from it; the workspace server will keep it (ADR-0013).

Index

Constants

View Source
const (
	AllowAll      = "*"        // everything devopus.yaml can say
	AllowVersions = "versions" // services' versions
	AllowEnv      = "env"      // any variable; env:NAME allows one
	AllowPorts    = "ports"    // ports of applications and services
)

Kinds of overrides a project's policy allows (overrides.allowed).

View Source
const (
	DefaultBranch       = "main"
	DefaultAppPort      = 8080
	DefaultMount        = "/app"
	DefaultDatabase     = "clone"
	DefaultSleepAfter   = "2h"
	DefaultCleanup      = "on_merge"
	DefaultIsolation    = "simple"
	DefaultBranchPrefix = "feature/"
)

Defaults.

View Source
const OverrideFile = "devopus.yaml"

OverrideFile is the personal file of overrides in a project's folder (ADR-0013). It stays on the developer's machine: the agent refuses it unless git ignores it.

Variables

View Source
var NameRe = regexp.MustCompile(`^[a-z][a-z0-9-]{0,39}$`)

NameRe is what application, service and project names look like: they become host names and parts of URLs.

Functions

func HasExpr

func HasExpr(s string) bool

HasExpr reports whether s contains an expression.

func PolicyReason

func PolicyReason(allowed []string) string

PolicyReason explains a refusal by the policy: what it allows.

func Risky

func Risky(changes []Change) []string

Risky are the risky changes of a diff.

func Same

func Same(want, got *Project) error

Same reports how two versions differ, as YAML; nil when they are the same.

Types

type App

type App struct {
	// Repo is the git repository; Path a folder of the project's own repository.
	Repo   string `yaml:"repo,omitempty"`
	Path   string `yaml:"path,omitempty"`
	Branch string `yaml:"branch,omitempty"`
	// Image or Build when no runtime service is attached.
	Image string `yaml:"image,omitempty"`
	Build *Build `yaml:"build,omitempty"`
	// Mount is where the code appears in the container.
	Mount  string   `yaml:"mount,omitempty"`
	Routes []string `yaml:"routes,omitempty"`
	Port   int      `yaml:"port,omitempty"`
	// Uses are the other applications it calls.
	Uses        []string           `yaml:"uses,omitempty"`
	Env         map[string]string  `yaml:"env,omitempty"`
	Command     string             `yaml:"command,omitempty"`
	Entrypoint  string             `yaml:"entrypoint,omitempty"`
	Healthcheck *Healthcheck       `yaml:"healthcheck,omitempty"`
	Tmpfs       []string           `yaml:"tmpfs,omitempty"`
	Ulimits     map[string]*Ulimit `yaml:"ulimits,omitempty"`
	Optional    bool               `yaml:"optional,omitempty"`
	Hooks       *Hooks             `yaml:"hooks,omitempty"`
	Volumes     []string           `yaml:"volumes,omitempty"`
}

App is an application: its code, how it is served and prepared.

func (*App) AppPort

func (a *App) AppPort() int

AppPort is the port the application listens on inside its container.

func (*App) BaseBranch

func (a *App) BaseBranch() string

BaseBranch is the branch the base environment runs.

type AppOverride

type AppOverride struct {
	Env  map[string]string `yaml:"env,omitempty"`
	Port int               `yaml:"port,omitempty"`
}

type Build

type Build struct {
	Context    string            `yaml:"context"`
	Dockerfile string            `yaml:"dockerfile,omitempty"`
	Target     string            `yaml:"target,omitempty"`
	Args       map[string]string `yaml:"args,omitempty"`
}

type Change

type Change struct {
	What  string
	Risky bool
	// Section is apps.<name> or services.<name>; empty for the project's own settings.
	Section string
}

Change is one difference.

func Diff

func Diff(old, next *Project) []Change

Diff lists what changed from old to next, risky changes first.

type DataPolicy

type DataPolicy struct {
	Snapshots map[string]*Snapshot `yaml:"snapshots,omitempty"`
}

type FeaturePolicy

type FeaturePolicy struct {
	Database     string `yaml:"database,omitempty"` // clone | shared
	SleepAfter   string `yaml:"sleep_after,omitempty"`
	Cleanup      string `yaml:"cleanup,omitempty"`
	Isolation    string `yaml:"isolation,omitempty"`
	BranchPrefix string `yaml:"branch_prefix,omitempty"`
	MaxRunning   int    `yaml:"max_running,omitempty"`
}

type Healthcheck

type Healthcheck struct {
	Test        []string `yaml:"test,omitempty"`
	Interval    string   `yaml:"interval,omitempty"`
	Timeout     string   `yaml:"timeout,omitempty"`
	Retries     int      `yaml:"retries,omitempty"`
	StartPeriod string   `yaml:"start_period,omitempty"`
	Disable     bool     `yaml:"disable,omitempty"`
}

Healthcheck mirrors the compose healthcheck; Test is CMD/CMD-SHELL/NONE or a command.

type Hooks

type Hooks struct {
	Install string `yaml:"install,omitempty"`
	Migrate string `yaml:"migrate,omitempty"`
	Seed    string `yaml:"seed,omitempty"`
	Build   string `yaml:"build,omitempty"`
}

type Override

type Override struct {
	Apps     map[string]*AppOverride     `yaml:"apps,omitempty"`
	Services map[string]*ServiceOverride `yaml:"services,omitempty"`
}

Override is what devopus.yaml may change: a subset of the project.

func ParseOverride

func ParseOverride(data []byte) (*Override, error)

ParseOverride reads devopus.yaml; unknown keys are errors.

type OverridePolicy

type OverridePolicy struct {
	Allowed []string `yaml:"allowed,omitempty"`
}

type OverrideResult

type OverrideResult struct {
	Applied  []string
	Rejected []string
}

OverrideResult is what an override did: the changes applied and the ones refused, each with its reason.

type Project

type Project struct {
	Name   string `yaml:"name"`
	Domain string `yaml:"domain"`
	// Apps are the parts of the product: frontend, backend, admin.
	Apps map[string]*App `yaml:"apps"`
	// Services live in the project and are attached to applications.
	Services  map[string]*Service `yaml:"services,omitempty"`
	Features  *FeaturePolicy      `yaml:"features,omitempty"`
	Overrides *OverridePolicy     `yaml:"overrides,omitempty"`
	Data      *DataPolicy         `yaml:"data,omitempty"`
}

Project is a product of the workspace: Google Drive, an online shop.

func ParseYAML

func ParseYAML(data []byte) (*Project, error)

ParseYAML decodes a project; unknown keys are errors.

func (*Project) AppNames

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

AppNames and ServiceNames are sorted.

func (*Project) ApplyOverride

func (p *Project) ApplyOverride(o *Override, allowed []string, why string) (*Project, OverrideResult)

ApplyOverride changes a copy of the project by an override, as far as allowed permits: the kinds of the project's policy (or * for admins and teamleads, nothing without overrides.use). A change the engine cannot run refuses the whole override.

func (*Project) Attached

func (p *Project) Attached(app string) []string

Attached are the services attached to an application, sorted.

func (*Project) Check

func (p *Project) Check() error

Check is the validation of the workspace server: what the engine needs (Validate) and what keeps a team's environments the same on every machine — names that make hosts, a source for every application, a pinned version for every service.

func (*Project) Clone

func (p *Project) Clone() *Project

Clone is a deep copy.

func (*Project) CodeMount

func (p *Project) CodeMount(app string) string

CodeMount is where the application's code is mounted; empty: nowhere.

func (*Project) DatabaseName

func (p *Project) DatabaseName(service string) string

DatabaseName is the database the base environment uses in a service: the one the image creates on first start, else the project name.

func (*Project) Expand

func (p *Project) Expand(s string, resolve func(Ref) (string, error)) (string, error)

Expand replaces every expression in s with the value the resolver gives.

func (*Project) Needs

func (p *Project) Needs(name string) []string

Needs is the dependency graph the engine walks, with applications and container services in one name space: an application needs the applications it uses and the container services attached to it; a container service needs the services it uses.

func (*Project) ParseRef

func (p *Project) ParseRef(body string) (Ref, error)

ParseRef parses the body of an expression against the names of the project.

func (*Project) Policy

func (p *Project) Policy() FeaturePolicy

Policy returns the feature policy with defaults filled in.

func (*Project) Processes

func (p *Project) Processes(app, typ string) []string

Processes are the queue and cronjob services of an application, sorted.

func (*Project) Runtime

func (p *Project) Runtime(app string) (string, *Service)

Runtime is the runtime service of an application, if one is attached.

func (*Project) ServiceNames

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

func (*Project) Validate

func (p *Project) Validate() error

Validate checks what the engine relies on. The workspace server validates more.

func (*Project) WithSection

func (p *Project) WithSection(section string, data []byte) (*Project, error)

WithSection is the project with one section replaced by its YAML, as its author sent it; empty YAML removes it.

func (*Project) WithoutApp

func (p *Project) WithoutApp(name string) *Project

WithoutApp is the project without an application, the services attached to it detached: what removing it does.

func (*Project) YAML

func (p *Project) YAML() ([]byte, error)

YAML encodes the project.

type Ref

type Ref struct {
	Kind RefKind
	Name string // secret, application or service; empty for env
	Attr string
	Raw  string // the whole ${{ … }}
}

Ref is a parsed ${{ … }} expression.

type RefKind

type RefKind int
const (
	RefSecret  RefKind = iota // secrets.NAME
	RefEnv                    // env.url | env.slug | env.id
	RefApp                    // <app>.url | .host | .port
	RefService                // <service>.host | .port | .database
)

type Service

type Service struct {
	// Type is a catalog type (php, mysql, queue…) or catalog.Custom.
	Type    string `yaml:"type"`
	Version string `yaml:"version,omitempty"`
	// Image overrides the catalog's image; a custom container needs it.
	Image string `yaml:"image,omitempty"`
	// Apps are the applications the service is attached to.
	Apps []string `yaml:"apps,omitempty"`
	// Uses are the other services a container service needs.
	Uses []string `yaml:"uses,omitempty"`

	Port        int                `yaml:"port,omitempty"`
	UIPort      int                `yaml:"ui_port,omitempty"`
	Expose      string             `yaml:"expose,omitempty"`
	Data        *ServiceData       `yaml:"data,omitempty"`
	Env         map[string]string  `yaml:"env,omitempty"`
	Command     string             `yaml:"command,omitempty"`
	Entrypoint  string             `yaml:"entrypoint,omitempty"`
	Volumes     []string           `yaml:"volumes,omitempty"`
	Healthcheck *Healthcheck       `yaml:"healthcheck,omitempty"`
	Tmpfs       []string           `yaml:"tmpfs,omitempty"`
	Ulimits     map[string]*Ulimit `yaml:"ulimits,omitempty"`
	PerFeature  string             `yaml:"per_feature,omitempty"` // clone | shared | instance
	Optional    bool               `yaml:"optional,omitempty"`
	// Replicas of a queue; Schedule of a cronjob.
	Replicas int    `yaml:"replicas,omitempty"`
	Schedule string `yaml:"schedule,omitempty"`
}

Service is a runtime, a container or a background process of the project.

func (*Service) ExposePort

func (s *Service) ExposePort() int

ExposePort is the port of the service's web UI.

func (*Service) ImageRef

func (s *Service) ImageRef() string

ImageRef is the image of a container or runtime service.

func (*Service) IsContainer

func (s *Service) IsContainer() bool

IsContainer reports whether the service runs as its own container.

func (*Service) Kind

func (s *Service) Kind() catalog.Kind

Kind is how a service runs: its catalog type's kind, Container for unknown types.

type ServiceData

type ServiceData struct {
	Seed string `yaml:"seed,omitempty"`
}

type ServiceOverride

type ServiceOverride struct {
	Version string            `yaml:"version,omitempty"`
	Env     map[string]string `yaml:"env,omitempty"`
	Port    int               `yaml:"port,omitempty"`
}

type Snapshot

type Snapshot struct {
	Source string            `yaml:"source"`
	Mask   map[string]string `yaml:"mask,omitempty"`
}

type Ulimit

type Ulimit struct {
	Single int `yaml:"single,omitempty"`
	Soft   int `yaml:"soft,omitempty"`
	Hard   int `yaml:"hard,omitempty"`
}

Ulimit is a single number (Single) or soft and hard limits.

Jump to

Keyboard shortcuts

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