Documentation
¶
Index ¶
- Constants
- func Init(cfg Config, path string) error
- func NextPort(services map[string]ServiceConfig, shape ServiceShape) int
- func PortInUse(services map[string]ServiceConfig, port int, excludeName string) bool
- func ValidatePort(port int) error
- func ValidateProjectName(name string) error
- func ValidateServiceName(name string) error
- type Config
- type DBEngine
- type DBMode
- type DevConfig
- type MetaConfig
- type ProjectConfig
- type RedisMode
- type ScaffoldConfig
- type SecretsConfig
- type SecretsProvider
- type ServiceConfig
- type ServiceShape
Constants ¶
const ( HTTPPortBase = 8001 GRPCPortBase = 9001 )
Port ranges per shape. HTTP services start at 8001 and gRPC at 9001 so the 8xxx/9xxx convention stays intact when scanning compose / `docker ps` output.
const CurrentSchema = 1
CurrentSchema is the version of the project.toml schema this maestro understands. Bump when a release introduces a breaking schema change — renamed sections, removed fields, changed types. Pair the bump with a migration in the same release so projects on the old schema upgrade transparently on the next Load.
const FileConfigName = "project.toml"
Variables ¶
This section is empty.
Functions ¶
func NextPort ¶
func NextPort(services map[string]ServiceConfig, shape ServiceShape) int
NextPort returns the next free port for shape, scanning services for the highest assigned port in the same range and returning max+1. If no service in that range exists yet, returns the range base (8001 for HTTP, 9001 for gRPC). Returns 0 when shape doesn't bind a port.
func PortInUse ¶
func PortInUse(services map[string]ServiceConfig, port int, excludeName string) bool
PortInUse reports whether port is already assigned to a different service. excludeName lets callers skip the service currently being edited.
func ValidatePort ¶
ValidatePort returns nil if port is in the user-port range, an error otherwise. We reject 0 explicitly so it can stay the "unset" sentinel.
func ValidateProjectName ¶
ValidateProjectName returns nil if name is a legal project identifier. Same shape rules as a service name but no reserved-set check — the project name lives at the top level and doesn't collide with anything internal.
func ValidateServiceName ¶
ValidateServiceName returns nil if name is a legal service identifier, or an error describing what's wrong. Run this at the CLI boundary, before anything touches disk or shells out — bad input here cascades into a half-scaffolded project that's a pain to clean up.
Types ¶
type Config ¶
type Config struct {
// Meta is first so it lands at the top of the marshalled project.toml,
// where users will look for "what version of this file is this."
Meta MetaConfig `toml:"meta"`
Project ProjectConfig `toml:"project"`
Dev DevConfig `toml:"dev"`
Secrets SecretsConfig `toml:"secrets"`
Scaffold ScaffoldConfig `toml:"scaffold"`
Service map[string]ServiceConfig `toml:"service,omitempty"`
}
func DefaultConfig ¶
func DefaultConfig() Config
func (Config) AnyServiceUsesDB ¶
AnyServiceUsesDB reports whether at least one service is wired to a DB. The doctor uses this to decide whether sqlc/goose are required for this project (vs. just recommended in general).
type DBMode ¶
type DBMode string
DBMode is how the database is provisioned: a Docker compose service in this project, or a remote/live database whose URL the user supplies separately.
type MetaConfig ¶
type MetaConfig struct {
// Schema is the project.toml schema version. Written by maestro at
// init time; bumped by migrations.
Schema int `toml:"schema"`
}
MetaConfig stamps the schema version into project.toml so future maestro versions can detect what shape the file was scaffolded against.
Pre-versioning projects (scaffolded before v0.2.0) carry no [meta] section and decode with Schema = 0. They're accepted as legacy today; a future schema change can introduce a migration keyed on that value.
func (MetaConfig) Validate ¶
func (m MetaConfig) Validate() error
Validate fails when the file declares a schema newer than this maestro can read. Older or missing schemas pass — that's the migration surface, handled at Load by future maestro versions.
type ProjectConfig ¶
ProjectConfig holds identity metadata written at init time and read back by any command that needs project context.
type RedisMode ¶
type RedisMode string
RedisMode is how a service's Redis dependency is provisioned: a Docker compose sidecar in this project, or a remote/live Redis whose URL the user supplies separately. Empty means the service uses no Redis.
type ScaffoldConfig ¶
type ScaffoldConfig struct {
// CI controls whether `.github/workflows/ci.yml` is scaffolded.
CI bool `toml:"ci"`
// License controls whether a starter `LICENSE` is scaffolded at the
// project root.
License bool `toml:"license"`
}
ScaffoldConfig toggles the once-only files maestro drops at the project root during `maestro init`. The defaults (everything on) match the behaviour a fresh `maestro init` had before this section existed.
Scaffolded files are user-owned the moment they land, so flipping a flag after init has no retroactive effect — it controls only whether the file gets created on the *next* init. The flag still has documentary value (it records the project's choice) and gates re-init in fresh directories.
.editorconfig and .golangci.yml are intentionally not toggleable: the first is a near-universal editor convention, the second is the file `task lint` reads. Treating them as part of the baseline keeps both the developer loop and CI lint job working out of the box.
type SecretsConfig ¶
type SecretsConfig struct {
Provider SecretsProvider `toml:"provider"`
// DopplerProject is the Doppler project the whole repo belongs to; each
// service maps to its own config within it. Empty unless Provider is
// Doppler.
DopplerProject string `toml:"doppler_project,omitempty"`
}
type SecretsProvider ¶
type SecretsProvider string
const ( SecretsNone SecretsProvider = "none" SecretsDoppler SecretsProvider = "doppler" )
func (SecretsProvider) String ¶
func (sp SecretsProvider) String() string
func (SecretsProvider) Validate ¶
func (sp SecretsProvider) Validate() error
type ServiceConfig ¶
type ServiceConfig struct {
Shape ServiceShape `toml:"shape,omitempty"`
DB DBEngine `toml:"db,omitempty"`
DBMode DBMode `toml:"db_mode,omitempty"`
// Redis records a Redis dependency provisioned alongside this service
// (docker sidecar) or pointed at a live instance. Independent of the DB
// engine — a service can use Redis without a database, like the gateway.
Redis RedisMode `toml:"redis,omitempty"`
Port int `toml:"port,omitempty"`
// DBRef names another service in the same project whose Postgres sidecar
// this service should share, instead of provisioning its own. Mutually
// exclusive with DB and DBMode — the target decides the engine and mode.
// Validated cross-service in Config.Validate: the target must exist, run
// postgres in docker mode, and not itself be a ref (no chains).
DBRef string `toml:"db_ref,omitempty"`
// Preset records the preset that scaffolded this service, if any. It lets
// refresh regenerate the service's provider=none dev secrets, which live
// under the git-ignored .secrets/ and so are absent on a fresh clone.
// Empty for hand-created services (`maestro service`).
Preset string `toml:"preset,omitempty"`
}
ServiceConfig records per-service settings that the generators need to keep across runs. It is written under `[service.<name>]` in project.toml.
func (ServiceConfig) NeedsDBContainer ¶
func (s ServiceConfig) NeedsDBContainer() bool
NeedsDBContainer reports whether the service should get a Docker compose DB instance scaffolded for it — true only for engines that need a server *and* when the user chose docker over live mode *and* the service is not borrowing another service's sidecar via DBRef.
func (ServiceConfig) NeedsPort ¶
func (s ServiceConfig) NeedsPort() bool
NeedsPort reports whether the service shape binds a network port — true for HTTP and gRPC, false for bare (no listener) and worker (long-running loop, no socket). The compose generator uses this to decide whether to emit a host port mapping and a PORT env var.
func (ServiceConfig) NeedsRedisContainer ¶
func (s ServiceConfig) NeedsRedisContainer() bool
NeedsRedisContainer reports whether the service should get a Docker compose Redis sidecar — true only when the user chose docker mode (live points at a managed Redis whose URL arrives via the secret manager).
func (ServiceConfig) UsesDB ¶
func (s ServiceConfig) UsesDB() bool
UsesDB reports whether the service is wired to a database engine — either its own (DB set) or one borrowed via DBRef.
func (ServiceConfig) Validate ¶
func (s ServiceConfig) Validate() error
type ServiceShape ¶
type ServiceShape string
ServiceShape is the starter scaffold a service is generated from. It picks the entrypoint shape (HTTP server, gRPC server, worker loop, …) and any helper packages that go with it.
const ( ShapeBare ServiceShape = "bare" ShapeHTTP ServiceShape = "http" ShapeGRPC ServiceShape = "grpc" ShapeWorker ServiceShape = "worker" )
func (ServiceShape) String ¶
func (s ServiceShape) String() string
func (ServiceShape) Validate ¶
func (s ServiceShape) Validate() error