domain

package
v0.0.2 Latest Latest
Warning

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

Go to latest
Published: Mar 19, 2026 License: AGPL-3.0 Imports: 14 Imported by: 0

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func ExecuteCoreHook added in v0.0.2

func ExecuteCoreHook(ctx context.Context, hookScript string, declaredOutputs []string, env []string, workdir string) (map[string]string, error)

ExecuteCoreHook runs a core service hook script and captures KEY=VALUE outputs. stderr streams to the terminal in real-time for visibility. stdout is captured and parsed for KEY=VALUE pairs. Returns the captured outputs, validated against declaredOutputs.

func ParseComposeFile added in v0.0.2

func ParseComposeFile(path string) (map[string]InfraService, error)

ParseComposeFile reads a docker compose YAML file and extracts infrastructure service definitions including service names, images, and port mappings.

func RenderEnvMap

func RenderEnvMap(envMap map[string]string, ctx *TemplateContext) (map[string]string, error)

RenderEnvMap renders all template variables in a map of env vars.

func RenderTemplate

func RenderTemplate(tmpl string, ctx *TemplateContext) (string, error)

RenderTemplate replaces {{var}} placeholders in a string with values from the context. Supported variable patterns:

  • {{services.<name>.port}} — allocated port for an application service
  • {{infrastructure.<name>.port}} — allocated port for an infrastructure service
  • {{core.<service>.<OUTPUT>}} — output value from a core service

func ResolveEnvironmentFromCwd

func ResolveEnvironmentFromCwd(cwd string, environments map[string]*EnvironmentEntry) (string, error)

ResolveEnvironmentFromCwd determines the environment name by checking if the current working directory is inside any known worktree path from state.

func TopologicalSort

func TopologicalSort(services map[string]ServiceConfig) ([]string, error)

TopologicalSort performs Kahn's algorithm to produce a topological ordering of services based on their dependsOn relationships. Returns an error if a cycle is detected or a dependency references an unknown service.

func ValidateConfig

func ValidateConfig(cfg *ProjectConfig) error

ValidateConfig performs deep validation of a ProjectConfig. It checks structural correctness, port collisions, dependency references, template variable references, and local config. It does NOT check file system paths — use ValidateConfigWithFS for that.

func ValidateConfigWithFS

func ValidateConfigWithFS(cfg *ProjectConfig, projectRoot string, fileExists func(string) bool) error

ValidateConfigWithFS performs all config validation plus file system checks. projectRoot is the directory containing previewctl.yaml. fileExists is a function that checks if a path exists (allows testing).

func WorktreeBasePath added in v0.0.2

func WorktreeBasePath() string

WorktreeBasePath returns the fixed base path for all previewctl worktrees. Worktrees are always stored in ~/.previewctl/worktrees to avoid conflicts with user-managed worktrees.

Types

type ComputePort

type ComputePort interface {
	// Create sets up compute resources for an environment.
	Create(ctx context.Context, envName string, branch string) (*ComputeResources, error)

	// Start starts per-environment services (infra containers, etc).
	Start(ctx context.Context, envName string, ports PortMap) error

	// Stop stops services without destroying data or resources.
	Stop(ctx context.Context, envName string) error

	// Destroy tears down all compute resources.
	Destroy(ctx context.Context, envName string) error

	// IsRunning checks if environment compute resources are active.
	IsRunning(ctx context.Context, envName string) (bool, error)
}

ComputePort manages the compute substrate for an environment. Local: git worktree + docker compose for per-env infrastructure. Preview: VM provisioning + full compose stack. Sandbox: isolated VM with network policies.

type ComputeResources

type ComputeResources struct {
	WorktreePath string `json:"worktreePath,omitempty"` // local mode
	VMId         string `json:"vmId,omitempty"`         // preview/sandbox mode
	ExternalIP   string `json:"externalIp,omitempty"`   // preview/sandbox mode
}

ComputeResources holds the result of creating compute resources for an environment.

type CoreConfig

type CoreConfig struct {
	Services map[string]CoreServiceConfig `yaml:"services,omitempty"`
}

CoreConfig holds managed core services with hook-driven lifecycle.

type CoreServiceConfig added in v0.0.2

type CoreServiceConfig struct {
	Outputs []string          `yaml:"outputs,omitempty"`
	Hooks   *CoreServiceHooks `yaml:"hooks,omitempty"`
}

CoreServiceConfig defines a core service managed by hooks.

type CoreServiceHooks added in v0.0.2

type CoreServiceHooks struct {
	Init    string `yaml:"init,omitempty"`
	Seed    string `yaml:"seed,omitempty"`
	Reset   string `yaml:"reset,omitempty"`
	Destroy string `yaml:"destroy,omitempty"`
}

CoreServiceHooks defines lifecycle hooks for a core service.

type EnvPort

type EnvPort interface {
	// Generate writes .env.local files for all services in the environment.
	Generate(ctx context.Context, envName string, workdir string, ports PortMap, coreOutputs map[string]map[string]string) error

	// SymlinkSharedEnvFiles symlinks shared .env files from the main worktree.
	SymlinkSharedEnvFiles(ctx context.Context, workdir string) error

	// Cleanup removes generated env files.
	Cleanup(ctx context.Context, workdir string) error
}

EnvPort generates environment configuration files (.env.local, etc).

type EnvironmentDetail

type EnvironmentDetail struct {
	Entry        *EnvironmentEntry `json:"entry"`
	InfraRunning bool              `json:"infraRunning"`
}

EnvironmentDetail is an enriched view with live infrastructure checks.

type EnvironmentEntry

type EnvironmentEntry struct {
	Name        string                       `json:"name"`
	Mode        EnvironmentMode              `json:"mode"`
	Branch      string                       `json:"branch"`
	Status      EnvironmentStatus            `json:"status"`
	CreatedAt   time.Time                    `json:"createdAt"`
	UpdatedAt   time.Time                    `json:"updatedAt"`
	Ports       PortMap                      `json:"ports"`
	CoreOutputs map[string]map[string]string `json:"coreOutputs"`
	Local       *LocalMeta                   `json:"local,omitempty"`
	Remote      *RemoteMeta                  `json:"remote,omitempty"`
}

EnvironmentEntry is a tracked environment persisted in state.

type EnvironmentMode

type EnvironmentMode string

EnvironmentMode represents the deployment mode of an environment.

const (
	ModeLocal   EnvironmentMode = "local"
	ModePreview EnvironmentMode = "preview"
	ModeSandbox EnvironmentMode = "sandbox"
)

type EnvironmentStatus

type EnvironmentStatus string

EnvironmentStatus represents the lifecycle status of an environment.

const (
	StatusCreating EnvironmentStatus = "creating"
	StatusRunning  EnvironmentStatus = "running"
	StatusStopped  EnvironmentStatus = "stopped"
	StatusError    EnvironmentStatus = "error"
)

type HookContext

type HookContext struct {
	EnvName      string
	Branch       string
	ProjectName  string
	ProjectRoot  string
	WorktreePath string
	Ports        PortMap
	CoreOutputs  map[string]map[string]string
	Step         string
	Phase        string // "before" or "after"
}

HookContext provides environment variables and working directory for hook execution.

type HookDef

type HookDef struct {
	Run             string `yaml:"run"`
	ContinueOnError bool   `yaml:"continue_on_error,omitempty"`
}

HookDef defines a single hook to execute.

type HookRunner

type HookRunner struct {
	// contains filtered or unexported fields
}

HookRunner executes hooks defined in the config.

func NewHookRunner

func NewHookRunner(hooks HooksConfig, progress ProgressReporter) *HookRunner

NewHookRunner creates a new hook runner.

func (*HookRunner) RunAfter

func (r *HookRunner) RunAfter(ctx context.Context, step string, hctx *HookContext) error

RunAfter executes all "after" hooks for the given step.

func (*HookRunner) RunBefore

func (r *HookRunner) RunBefore(ctx context.Context, step string, hctx *HookContext) error

RunBefore executes all "before" hooks for the given step.

type HooksConfig

type HooksConfig map[string]StepHooks

HooksConfig maps step names to their before/after hooks. Step names match the lifecycle steps: allocate_ports, create_compute, symlink_env, generate_env, start_infra, save_state, load_state, destroy_compute, cleanup_env, remove_state.

Additionally, lifecycle-level hooks can be defined: create, delete — these run before/after the entire operation.

type InfraService added in v0.0.2

type InfraService struct {
	Name   string
	Image  string
	Port   int
	EnvVar string // e.g., "REDIS_PORT" (extracted from ${REDIS_PORT:-6379} patterns)
}

InfraService holds parsed infrastructure service information from a compose file.

type InfrastructureConfig added in v0.0.2

type InfrastructureConfig struct {
	ComposeFile string `yaml:"compose_file"`
}

InfrastructureConfig holds infrastructure configuration.

type LocalConfig

type LocalConfig struct {
	Worktree WorktreeConfig `yaml:"worktree"`
}

LocalConfig holds local-mode specific configuration.

type LocalMeta

type LocalMeta struct {
	WorktreePath       string `json:"worktreePath"`
	ComposeProjectName string `json:"composeProjectName"`
}

LocalMeta holds local-mode specific metadata.

type Manager

type Manager struct {
	// contains filtered or unexported fields
}

Manager orchestrates environment lifecycle by coordinating all ports. It is the single source of truth — all inbound adapters delegate to it.

func NewManager

func NewManager(deps ManagerDeps) *Manager

NewManager creates a new Manager with the given dependencies.

func (*Manager) CoreInit added in v0.0.2

func (m *Manager) CoreInit(ctx context.Context, svcName string) error

CoreInit runs the "init" hook for a core service (one-time setup).

func (*Manager) CoreReset added in v0.0.2

func (m *Manager) CoreReset(ctx context.Context, svcName, envName string) error

CoreReset runs the "reset" hook for a core service on a specific environment.

func (*Manager) Destroy

func (m *Manager) Destroy(ctx context.Context, envName string) error

Destroy tears down an environment and cleans up all resources.

func (*Manager) Init

func (m *Manager) Init(ctx context.Context, envName string, branch string) (*EnvironmentEntry, error)

Init creates a new environment end-to-end.

func (*Manager) List

func (m *Manager) List(ctx context.Context) ([]*EnvironmentEntry, error)

List returns all tracked environments.

func (*Manager) RunCoreHook added in v0.0.2

func (m *Manager) RunCoreHook(ctx context.Context, svcName, action, envName string) (map[string]string, error)

RunCoreHook runs a core service hook for a given environment, loading ports from state.

func (*Manager) Status

func (m *Manager) Status(ctx context.Context, envName string) (*EnvironmentDetail, error)

Status returns detailed status of an environment with live infrastructure checks.

type ManagerDeps

type ManagerDeps struct {
	Compute     ComputePort
	Networking  NetworkingPort
	EnvGen      EnvPort
	State       StatePort
	Progress    ProgressReporter
	Config      *ProjectConfig
	ProjectRoot string
}

ManagerDeps holds the dependencies for creating a Manager.

type NetworkingPort

type NetworkingPort interface {
	// AllocatePorts returns deterministic port assignments for all services and infrastructure.
	AllocatePorts(envName string) (PortMap, error)

	// GetServiceURL returns the URL to reach a named service in the environment.
	GetServiceURL(envName string, service string) (string, error)
}

NetworkingPort handles port allocation and service URL resolution. Local: deterministic offset from base ports. Preview: reverse proxy with subdomain routing (future).

type NoopReporter

type NoopReporter struct{}

NoopReporter is a ProgressReporter that discards all events.

func (NoopReporter) OnStep

func (NoopReporter) OnStep(StepEvent)

type PortMap

type PortMap map[string]int

PortMap maps service names to allocated ports.

func AllocatePortBlock added in v0.0.2

func AllocatePortBlock(envName string, serviceNames []string) (PortMap, error)

AllocatePortBlock selects a block of ports for an environment and assigns one port per service name. Ports are checked for availability. Returns a PortMap with service names mapped to allocated ports.

type ProgressReporter

type ProgressReporter interface {
	OnStep(event StepEvent)
}

ProgressReporter receives lifecycle step events from the manager. Inbound adapters implement this to render progress (CLI spinners, SSE, etc).

type ProjectConfig

type ProjectConfig struct {
	Version        int                      `yaml:"version"`
	Name           string                   `yaml:"name"`
	Core           CoreConfig               `yaml:"core"`
	Infrastructure *InfrastructureConfig    `yaml:"infrastructure,omitempty"`
	Services       map[string]ServiceConfig `yaml:"services"`
	Local          *LocalConfig             `yaml:"local,omitempty"`
	Hooks          HooksConfig              `yaml:"hooks,omitempty"`

	// Mode is the deployment mode (e.g., "local"). Set at load time, not from YAML.
	Mode string `yaml:"-"`

	// InfraServices is populated by parsing the compose file referenced in
	// Infrastructure.ComposeFile. It is not read from YAML directly.
	InfraServices map[string]InfraService `yaml:"-"`
}

ProjectConfig is the top-level previewctl.yaml configuration.

func LoadConfig

func LoadConfig(path string) (*ProjectConfig, error)

LoadConfig reads and parses a previewctl.yaml file.

func LoadConfigWithOverlay added in v0.0.2

func LoadConfigWithOverlay(basePath, mode string) (*ProjectConfig, error)

LoadConfigWithOverlay loads a base config and merges a mode-specific overlay if present.

func ParseConfig

func ParseConfig(data []byte) (*ProjectConfig, error)

ParseConfig parses YAML bytes into a ProjectConfig.

func (*ProjectConfig) ServiceNames added in v0.0.2

func (c *ProjectConfig) ServiceNames() []string

ServiceNames returns a sorted list of all service and infrastructure names that need port assignments.

type ProvisionerPort

type ProvisionerPort interface {
	Provision(ctx context.Context, envName string, spec VMSpec) (*VMInfo, error)
	Deprovision(ctx context.Context, vmID string) error
	Status(ctx context.Context, vmID string) (*VMInfo, error)
}

ProvisionerPort manages VM lifecycle for preview/sandbox modes. Not implemented in POC; exists to validate interface design.

type RemoteMeta

type RemoteMeta struct {
	VMId       string `json:"vmId"`
	ExternalIP string `json:"externalIp"`
}

RemoteMeta holds remote-mode specific metadata (future).

type ServiceConfig

type ServiceConfig struct {
	Path      string            `yaml:"path"`
	Command   string            `yaml:"command,omitempty"`
	DependsOn []string          `yaml:"depends_on,omitempty"`
	Env       map[string]string `yaml:"env,omitempty"`
	EnvFile   string            `yaml:"env_file,omitempty"` // relative to path, defaults to ".env.local"
}

ServiceConfig defines an application service.

func (ServiceConfig) ResolvedEnvFile added in v0.0.2

func (s ServiceConfig) ResolvedEnvFile() string

ResolvedEnvFile returns the env file path relative to the service path. Defaults to ".env.local" if not configured.

type State

type State struct {
	Version      int                          `json:"version"`
	Environments map[string]*EnvironmentEntry `json:"environments"`
}

State is the top-level persisted state.

func NewState

func NewState() *State

NewState returns an initialized empty state.

type StatePort

type StatePort interface {
	// Load returns the full state.
	Load(ctx context.Context) (*State, error)

	// Save persists the full state.
	Save(ctx context.Context, state *State) error

	// GetEnvironment returns a single environment entry, or nil if not found.
	GetEnvironment(ctx context.Context, name string) (*EnvironmentEntry, error)

	// SetEnvironment creates or updates an environment entry.
	SetEnvironment(ctx context.Context, name string, entry *EnvironmentEntry) error

	// RemoveEnvironment deletes an environment entry.
	RemoveEnvironment(ctx context.Context, name string) error
}

StatePort persists previewctl state. File-based for POC; interface accommodates Postgres/etcd later.

type StepEvent

type StepEvent struct {
	Step    string // e.g. "allocate_ports", "create_worktree", "create_database"
	Status  StepStatus
	Message string // human-readable detail
	Error   error  // non-nil when Status == StepFailed
}

StepEvent is emitted by the manager at each lifecycle transition.

type StepHooks

type StepHooks struct {
	Before []HookDef `yaml:"before,omitempty"`
	After  []HookDef `yaml:"after,omitempty"`
}

StepHooks defines before and after hooks for a step.

type StepStatus

type StepStatus string

StepStatus represents the status of a lifecycle step.

const (
	StepStarted   StepStatus = "started"
	StepCompleted StepStatus = "completed"
	StepFailed    StepStatus = "failed"
	StepSkipped   StepStatus = "skipped"
)

type TemplateContext

type TemplateContext struct {
	ServicePorts   PortMap
	InfraPorts     PortMap
	CoreOutputs    map[string]map[string]string
	CurrentService string // set per-service during rendering, enables {{self.port}}
}

TemplateContext holds the values available for template substitution.

type VMInfo

type VMInfo struct {
	ID         string
	ExternalIP string
	Status     string
}

VMInfo describes a provisioned VM (future).

type VMSpec

type VMSpec struct {
	MachineType string
	DiskSizeGB  int
	Image       string
	Region      string
}

VMSpec defines requirements for provisioning a VM (future).

type ValidationError

type ValidationError struct {
	Errors []string
}

ValidationError collects multiple validation issues.

func (*ValidationError) Error

func (e *ValidationError) Error() string

type WorktreeConfig

type WorktreeConfig struct {
	// SymlinkPatterns are glob patterns for gitignored files to symlink from the
	// main worktree into each new worktree (e.g. ".env" matches .env files recursively).
	// These are typically secret/config files that exist in the main repo but aren't
	// tracked by git. Each pattern is matched recursively across the entire repo.
	SymlinkPatterns []string `yaml:"symlink_patterns,omitempty"`
}

WorktreeConfig defines worktree settings.

Jump to

Keyboard shortcuts

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