Documentation
¶
Overview ¶
Package provision reconciles a declarative "what should be installed" manifest (`patchcord provision`, ADR-0073) against the agent's plugin, app and bundle catalogs. It exists to turn a custom plugin/app/bundle's dev→prod transition into one reproducible step, usable either inside a Docker multi-stage build (no server running — every install primitive here already works straight against a --data-dir, see internal/cli.openDataStore's own doc comment) or against a live deployment's data directory before a restart.
Apply never runs implicitly. Nothing in internal/runtime calls it, and `patchcord serve`/`dev` never read a manifest on their own — every install path that can reach the network (a configured registry, internal/registry; a GitHub Releases reference, internal/ghrelease) stays an explicit, user-triggered action, exactly as it already is for `plugin install`/`bundle install`. Apply only ever runs when `patchcord provision <file>` is invoked directly.
Index ¶
Constants ¶
const ManifestFileName = "provision.yaml"
ManifestFileName is the conventional name for a provisioning manifest — a plain declarative file, not a package: nothing about it needs archiving, signing, or extracting, unlike a .patchcord-plugin/-app/ -bundle. `patchcord provision` accepts any path; this is a naming convention only, the same role bundle.yaml/patchcord-app.yaml play elsewhere in this codebase.
Variables ¶
var ErrInvalidManifest = errors.New("invalid provisioning manifest")
ErrInvalidManifest is returned by ParseManifest and LoadManifest when the manifest is malformed.
Functions ¶
This section is empty.
Types ¶
type AppOutcome ¶
type AppOutcome struct {
Ref string
App apps.App
// Policy is nil when Ref resolved to a local directory — nothing was
// verified.
Policy *trust.PolicyResult
}
AppOutcome is one apps[] entry Apply resolved and installed.
type BundleOutcome ¶
type BundleOutcome struct {
Ref string
Bundle bundles.Bundle
// Policy is nil when Ref resolved to a local directory — nothing was
// verified.
Policy *trust.PolicyResult
}
BundleOutcome is one bundles[] entry Apply resolved and installed.
type Manifest ¶
Manifest is the parsed content of a provisioning file: three lists of bare reference strings, one per package kind. Each entry is resolved exactly as the equivalent `<kind> install <ref>` command would resolve it:
- plugins: a local file (raw executable or .patchcord-plugin package), or a github.com/<owner>/<repo>[@<tag>] reference (ADR-0067);
- bundles: a local file (.patchcord-bundle package) or directory (unpacked source, dev-style), or an "id[@version]" reference resolved against configured registries (ADR-0044);
- apps: a local file (.patchcord-app package) or directory (unpacked source, dev-style) only — registry/GitHub resolution for a standalone app is not wired up yet, matching `app install`'s own current scope.
There is no separate version field: a reference already pins an exact version (a local file, a "@version"/"@tag" suffix) or names a specific local directory, so nothing here can silently float to a newer release the manifest's author did not intend.
func LoadManifest ¶
LoadManifest reads and parses a provisioning manifest from path.
func ParseManifest ¶
ParseManifest parses a provisioning manifest from its YAML source, returning ErrInvalidManifest if any entry is empty. An empty or all-absent manifest is valid — Apply then has nothing to do.
type Options ¶
type Options struct {
// RequireSignature rejects any resolved package that is unsigned or
// signed by a key not trusted for its id — the same flag `plugin
// install`/`app install`/`bundle install` already expose, applied
// uniformly to every entry in the manifest. It has no effect on a raw
// executable or a local directory: there is nothing to verify, and
// giving it alongside such an entry is an error (mirroring `plugin
// install`'s own behavior for a raw executable path).
RequireSignature bool
// GitHubToken raises GitHub's unauthenticated API rate limit for a
// github.com/<owner>/<repo> plugin reference. Optional.
GitHubToken string
}
Options configures Apply.
type PluginOutcome ¶
type PluginOutcome struct {
Ref string
Entry plugins.CatalogEntry
// Policy is nil when Ref resolved to a raw executable — nothing was
// verified.
Policy *trust.PolicyResult
}
PluginOutcome is one plugins[] entry Apply resolved and installed.
type Result ¶
type Result struct {
Plugins []PluginOutcome
Bundles []BundleOutcome
Apps []AppOutcome
}
Result summarizes everything Apply installed, in manifest order.
func Apply ¶
func Apply(ctx context.Context, db *sql.DB, dataDir string, m *Manifest, opts Options) (Result, error)
Apply reconciles m against db/dataDir's catalogs: every plugins[] entry first (a bundle's requires_plugins dependency must already be installed, ADR-0042), then every bundles[] entry, then every apps[] entry. Each install goes through exactly the primitive its `<kind> install` CLI command already uses — plugins.Install/InstallPackage (already an upsert), bundles.InstallDir/InstallPackage (idempotent on unchanged content, ADR-0053/0044), apps.InstallOrUpdate/InstallOrUpdatePackage (upsert, ADR-0073 for the packaged half) — so re-running Apply against an already-satisfied manifest is a clean no-op. That property is what makes it safe to call from every container build and every restart: baking a deployment's custom plugins/apps/bundles into an image, or reconciling a bind-mounted deployment before a restart, is the same call either way.
A failure stops at the first failing entry — there is no rollback across entries or across kinds, mirroring bundles.InstallPackage's own documented limitation. The returned error names the failing reference; the partial Result still describes whatever was already installed before the failure.