Documentation
¶
Overview ¶
Package deployconfig owns the schema for the deploy config: the machine-readable document stored at .sprout/deploy.json that names where a project ships, plus the validator every reader must run.
It is the file-system-facing half of deploys, mirroring pkg/startermanifest (+ pkg/starterstore): this package defines the on-disk shape, enforces its invariants, and resolves a config against a project root into a deploy.DeployRequest. The build output is deliberately NOT a required field of the config — the starter manifest's build_output is the single source of build output, and the config only overrides it when a project's deploy target needs a different directory.
The package is a pure data + validation + resolution contract over the filesystem reads it needs: it reaches only for the standard library and pkg/startermanifest / pkg/starterstore / pkg/deploy, so the CLI, agent tools, and Ship mode all resolve a project's deploy config the same way.
JSON field names are part of the on-disk contract and must stay in sync with the spec.
Index ¶
Constants ¶
const DeployJSONName = "deploy.json"
On-disk location of the deploy config, under the project root. It lives in the same .sprout/ per-project state directory as the starter manifest (pkg/startermanifest.SproutDir). DeployJSONName is the on-disk file name of the deploy config, relative to the .sprout/ state directory (startermanifest.SproutDir).
Variables ¶
var ErrNoDeployConfig = errors.New("no deploy config found")
ErrNoDeployConfig is returned by LoadDeployConfig when the project has no .sprout/deploy.json (or no .sprout directory at all). It is an expected, distinguishable not-found (not a failure): callers detect it with errors.Is(err, ErrNoDeployConfig) and treat it as "deploy is not configured for this project", exactly as starterstore.ErrNoManifest marks a missing starter manifest. Deploying is opt-in per project, so a missing file is the normal state rather than an error callers must special-case.
Functions ¶
func DeployConfigPath ¶
DeployConfigPath returns the path to the project's .sprout/deploy.json for the given project root. It joins through startermanifest.SproutDir so the state directory name has a single home.
func Validate ¶
func Validate(c *DeployConfig, root string) error
Validate reports every structural problem with c and returns a *ValidationError when the config is invalid, or nil when it is valid.
It is a pure function over the in-memory struct and a project root, so it can be used both when building a new config and on every read of .sprout/deploy.json. root is the project root that build_output must stay under; pass the real root (an empty root skips the resolve-against-root re-check and should be avoided). What is enforced:
- target is required (non-blank);
- project is required (non-blank);
- build_output, if present, is not whitespace-only and is a relative path that stays under root (no absolute path, no ".." segment that escapes the project root).
Unknown fields are tolerated rather than rejected: the decoder ignores them, matching the starter manifest validator's choice.
Types ¶
type DeployConfig ¶
type DeployConfig struct {
// Target identifies the deploy target adapter to use (e.g. "cloudflare"
// or a test adapter's id). Required.
Target string `json:"target"`
// Project is the project name on the target. Required: it is what the
// target's history and rollback are keyed by.
Project string `json:"project"`
// BuildOutput overrides the starter manifest's build_output for this
// project's deploy. Optional: when absent (or present-but-blank) the
// manifest's build_output is the source of the build directory.
// When present it must be a relative path that does not
// escape the project root.
BuildOutput string `json:"build_output,omitempty"`
}
DeployConfig is the in-memory form of .sprout/deploy.json. It names where a project ships: the target, the project name on that target, and — optionally — a build output directory that overrides the starter manifest's build_output.
The config is deliberately small and lenient, matching the starter manifest's style: only the target and project name are required, and the build output is optional. Unknown JSON fields are tolerated (ignored), so a config written against a later schema still loads — the same choice the starter manifest validator makes.
func LoadDeployConfig ¶
func LoadDeployConfig(projectRoot string) (*DeployConfig, error)
LoadDeployConfig reads and validates the deploy config from .sprout/deploy.json under projectRoot.
- When the file does not exist (or .sprout/ does not exist), LoadDeployConfig returns (nil, ErrNoDeployConfig) — the normal "deploy is not configured" case.
- When the file is corrupt JSON or fails validation, LoadDeployConfig returns (nil, err), where err wraps a JSON decode error or a *ValidationError. An invalid config is a hard error, never a guessed one.
- When the file is valid, LoadDeployConfig returns the validated config and a nil error.
On any error the returned config is nil, so a caller can never observe an invalid config through the loader.
type Resolved ¶
type Resolved struct {
// Target is the deploy target adapter id from the config.
Target string
// Project is the project name on the target.
Project string
// Kind is the deployment kind. It defaults to deploy.KindPreview; a
// caller promoting to production sets deploy.KindProduction explicitly.
Kind deploy.DeploymentKind
// BuildDir is the absolute build output directory to upload. It is the
// resolved build output: the config's build_output when it overrides,
// otherwise the starter manifest's build_output.
BuildDir string
}
Resolved is a deploy config merged with the starter manifest, ready to build a deploy.DeployRequest: the project name, the deployment kind (defaulting to preview), and the build directory resolved to an absolute path under the project root.
func Resolve ¶
func Resolve(c *DeployConfig, projectRoot string) (Resolved, error)
Resolve merges a deploy config with the starter manifest under projectRoot and returns the resolved deploy shape. It is the "build output taken from the starter manifest" step: the build directory is the config's build_output when it overrides, and the starter manifest's build_output otherwise (the manifest is the single source of build output).
It is a hard error when neither source names a build output: a deploy with nothing to upload is a misconfiguration, not an empty deploy. The config must already be valid (Validate); Resolve re-checks so a nil config or a blank target/project is never silently accepted.
The returned BuildDir is absolute (resolved against projectRoot), so the caller passes the same directory the verification/build steps produced regardless of its own working directory.
The returned Resolved always starts as a preview deployment; a caller promoting to production sets Resolved.Kind = deploy.KindProduction before calling Request() (production always needs explicit user confirmation).
func (Resolved) Request ¶
func (r Resolved) Request() deploy.DeployRequest
Request returns the deploy.DeployRequest this resolved config describes, ready to hand to a deploy.DeployTarget. Version is left empty — the caller fills it from the starter version or plan revision it is shipping.
type ValidationError ¶
type ValidationError struct {
Problems []string
}
ValidationError describes the structural problems found in a deploy config. It carries one entry per problem so callers can surface them all at once (instead of fixing-and-revalidating one at a time), mirroring startermanifest.ValidationError. Use errors.As to recover the structured list from the error returned by Validate.
func (*ValidationError) Error ¶
func (e *ValidationError) Error() string
Error implements error. It always lists every problem so the message is actionable on its own.