Documentation
¶
Overview ¶
Package plugin provides the compile-time plugin system for TerraCi.
The plugin system is organized into three packages:
- pkg/plugin: core interfaces, BasePlugin[C], AppContext, EnablePolicy, RuntimeProvider
- pkg/plugin/registry: global plugin registration and resolution (Register, ByCapability, ResolveProvider)
- pkg/plugin/initwiz: init wizard types (StateMap, InitContributor, InitGroupSpec)
Preferred plugin architecture for runtime-heavy built-in and external plugins:
- plugin.go: registration shell and typed BasePlugin config
- lifecycle.go: cheap Preflight checks only
- runtime.go: lazy RuntimeProvider implementation
- usecases.go: command orchestration over typed runtime
- output.go / report.go: rendering and report assembly
Framework-owned lifecycle stops at configuration and preflight. Heavy clients, caches, and command-specific state should be created lazily from Runtime() and consumed by plugin commands or use-cases rather than cached during startup hooks.
Package plugin provides the compile-time plugin system for TerraCi. Plugins register themselves via init() and blank imports, following the same pattern as database/sql drivers and Caddy modules.
Core types (interfaces, BasePlugin, AppContext) live in this package. Global registry functions live in pkg/plugin/registry. Init wizard types live in pkg/plugin/initwiz.
Index ¶
- func BuildRuntime[T any](ctx context.Context, p RuntimeProvider, appCtx *AppContext) (T, error)
- func CheckBlobStore(ctx context.Context, store BlobStore) error
- func RuntimeAs[T any](runtime any) (T, error)
- type AppContext
- func (ctx *AppContext) Config() *config.Config
- func (ctx *AppContext) Freeze()
- func (ctx *AppContext) IsFrozen() bool
- func (ctx *AppContext) Reports() *ReportRegistry
- func (ctx *AppContext) ServiceDir() string
- func (ctx *AppContext) Update(cfg *config.Config, workDir, serviceDir, version string)
- func (ctx *AppContext) Version() string
- func (ctx *AppContext) WorkDir() string
- type BasePlugin
- func (b *BasePlugin[C]) Config() C
- func (b *BasePlugin[C]) ConfigKey() string
- func (b *BasePlugin[C]) DecodeAndSet(decode func(target any) error) error
- func (b *BasePlugin[C]) Description() string
- func (b *BasePlugin[C]) IsConfigured() bool
- func (b *BasePlugin[C]) IsEnabled() bool
- func (b *BasePlugin[C]) Name() string
- func (b *BasePlugin[C]) NewConfig() any
- func (b *BasePlugin[C]) Reset()
- func (b *BasePlugin[C]) SetTypedConfig(cfg C)
- type BlobMeta
- type BlobObject
- type BlobStore
- type BlobStoreDescriber
- type BlobStoreHealthChecker
- type BlobStoreInfo
- type BlobStoreInspector
- type BlobStoreOptions
- type BlobStoreProvider
- type BlobStoreProviderWithOptions
- type CIInfoProvider
- type ChangeDetectionProvider
- type CommandProvider
- type CommentServiceFactory
- type ConfigLoader
- type EnablePolicy
- type EnvDetector
- type FlagOverridable
- type KVCache
- type KVCacheProvider
- type PipelineContributor
- type PipelineGeneratorFactory
- type Plugin
- type Preflightable
- type PutBlobOptions
- type ReportRegistry
- type Resettable
- type ResolvedCIProvider
- func (c *ResolvedCIProvider) CommitSHA() string
- func (c *ResolvedCIProvider) Description() string
- func (c *ResolvedCIProvider) Name() string
- func (c *ResolvedCIProvider) NewCommentService(ctx *AppContext) (ci.CommentService, bool)
- func (c *ResolvedCIProvider) NewGenerator(ctx *AppContext, depGraph *graph.DependencyGraph, modules []*discovery.Module) pipeline.Generator
- func (c *ResolvedCIProvider) PipelineID() string
- func (c *ResolvedCIProvider) Plugin() Plugin
- func (c *ResolvedCIProvider) ProviderName() string
- type RuntimeProvider
- type VersionProvider
Examples ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func BuildRuntime ¶ added in v0.9.0
func BuildRuntime[T any](ctx context.Context, p RuntimeProvider, appCtx *AppContext) (T, error)
BuildRuntime calls p.Runtime and type-asserts the result to T in one step. It combines the Runtime() call and RuntimeAs[T]() assertion — the recommended shorthand for plugin use-cases:
func (p *Plugin) runtime(ctx context.Context, appCtx *AppContext) (*myRuntime, error) {
return plugin.BuildRuntime[*myRuntime](ctx, p, appCtx)
}
func CheckBlobStore ¶ added in v0.9.4
CheckBlobStore runs the optional blob-store health check when implemented.
Types ¶
type AppContext ¶
type AppContext struct {
// contains filtered or unexported fields
}
AppContext is the public API available to plugins.
ServiceDir is the resolved absolute path — use it for runtime file I/O. For pipeline artifact paths (CI templates), use Config.ServiceDir which preserves the original relative value from .terraci.yaml.
After initialization, call Freeze() to prevent the framework from refreshing this shared context from App state again during the current command run.
func NewAppContext ¶ added in v0.9.0
func NewAppContext(cfg *config.Config, workDir, serviceDir, version string, reports *ReportRegistry) *AppContext
NewAppContext creates a framework-managed plugin context.
func (*AppContext) Config ¶
func (ctx *AppContext) Config() *config.Config
Config returns a defensive copy of the loaded TerraCi configuration. For repeated access within a single use-case, cache the result locally:
cfg := appCtx.Config() // use cfg throughout the function
This avoids repeated deep copies while preserving immutability guarantees.
func (*AppContext) Freeze ¶ added in v0.7.5
func (ctx *AppContext) Freeze()
Freeze marks the context as final for framework-managed updates.
func (*AppContext) IsFrozen ¶ added in v0.7.5
func (ctx *AppContext) IsFrozen() bool
IsFrozen returns whether the context has been frozen.
func (*AppContext) Reports ¶ added in v0.7.5
func (ctx *AppContext) Reports() *ReportRegistry
Reports returns the shared in-process report registry.
func (*AppContext) ServiceDir ¶ added in v0.7.3
func (ctx *AppContext) ServiceDir() string
ServiceDir returns the resolved absolute service directory path.
func (*AppContext) Update ¶ added in v0.9.0
func (ctx *AppContext) Update(cfg *config.Config, workDir, serviceDir, version string)
Update refreshes the framework-managed view of app state until the context is frozen.
func (*AppContext) Version ¶
func (ctx *AppContext) Version() string
Version returns the current TerraCi version string.
func (*AppContext) WorkDir ¶
func (ctx *AppContext) WorkDir() string
WorkDir returns the working directory for the current command.
type BasePlugin ¶ added in v0.7.5
type BasePlugin[C any] struct { PluginName string PluginDesc string PluginKey string // config key; defaults to PluginName if empty EnableMode EnablePolicy // how the framework checks if this plugin is active DefaultCfg func() C // factory for default config // IsEnabledFn is an optional custom check for EnabledExplicitly and EnabledByDefault. // For EnabledExplicitly: called when configured, must return true to activate. // For EnabledByDefault: called when configured, return false to deactivate. IsEnabledFn func(C) bool // contains filtered or unexported fields }
BasePlugin provides shared implementation for all plugins that have configuration. C is the plugin's concrete config type. Embedding this gives you:
- Name(), Description()
- ConfigKey(), NewConfig(), DecodeAndSet(), IsConfigured(), IsEnabled()
- Config() (typed access to config)
- Reset() (resets config state; override to reset custom fields)
func (*BasePlugin[C]) Config ¶ added in v0.7.5
func (b *BasePlugin[C]) Config() C
Config returns the typed plugin configuration.
func (*BasePlugin[C]) ConfigKey ¶ added in v0.7.5
func (b *BasePlugin[C]) ConfigKey() string
ConfigKey returns the config section key under "plugins:" in .terraci.yaml.
func (*BasePlugin[C]) DecodeAndSet ¶ added in v0.7.5
func (b *BasePlugin[C]) DecodeAndSet(decode func(target any) error) error
DecodeAndSet decodes plugin config via the provided decoder and stores it.
func (*BasePlugin[C]) Description ¶ added in v0.7.5
func (b *BasePlugin[C]) Description() string
Description returns a human-readable description.
func (*BasePlugin[C]) IsConfigured ¶ added in v0.7.5
func (b *BasePlugin[C]) IsConfigured() bool
IsConfigured returns true if config was loaded for this plugin.
func (*BasePlugin[C]) IsEnabled ¶ added in v0.7.5
func (b *BasePlugin[C]) IsEnabled() bool
IsEnabled returns whether the plugin should be active, based on EnablePolicy.
func (*BasePlugin[C]) Name ¶ added in v0.7.5
func (b *BasePlugin[C]) Name() string
Name returns the plugin's unique identifier.
func (*BasePlugin[C]) NewConfig ¶ added in v0.7.5
func (b *BasePlugin[C]) NewConfig() any
NewConfig returns a new instance of the default config for schema generation.
func (*BasePlugin[C]) Reset ¶ added in v0.7.5
func (b *BasePlugin[C]) Reset()
Reset resets the config state. Override in your plugin to also reset custom fields.
func (*BasePlugin[C]) SetTypedConfig ¶ added in v0.7.5
func (b *BasePlugin[C]) SetTypedConfig(cfg C)
SetTypedConfig sets the typed config directly (used by tests and flag overrides).
type BlobMeta ¶ added in v0.9.4
type BlobMeta struct {
Size int64
UpdatedAt time.Time
ExpiresAt *time.Time
ETag string
ContentType string
Metadata map[string]string
}
BlobMeta describes a stored blob object.
type BlobObject ¶ added in v0.9.4
BlobObject describes a listed blob object.
type BlobStore ¶ added in v0.9.4
type BlobStore interface {
Get(ctx context.Context, namespace, key string) ([]byte, bool, BlobMeta, error)
Put(ctx context.Context, namespace, key string, value []byte, opts PutBlobOptions) (BlobMeta, error)
Open(ctx context.Context, namespace, key string) (io.ReadCloser, bool, BlobMeta, error)
PutStream(ctx context.Context, namespace, key string, r io.Reader, opts PutBlobOptions) (BlobMeta, error)
Delete(ctx context.Context, namespace, key string) error
DeleteNamespace(ctx context.Context, namespace string) error
List(ctx context.Context, namespace string) ([]BlobObject, error)
}
BlobStore stores opaque binary objects addressed by namespace + key.
Consumers own key layout, serialization, TTL policy, and stale fallback semantics. Backends only persist bytes and metadata.
type BlobStoreDescriber ¶ added in v0.9.4
type BlobStoreDescriber interface {
DescribeBlobStore() BlobStoreInfo
}
BlobStoreDescriber exposes optional diagnostics for a blob store backend.
type BlobStoreHealthChecker ¶ added in v0.9.4
BlobStoreHealthChecker exposes an optional health check for a blob store backend.
type BlobStoreInfo ¶ added in v0.9.4
type BlobStoreInfo struct {
Backend string
Root string
SupportsList bool
SupportsStream bool
SupportsDeleteNamespace bool
}
BlobStoreInfo describes optional backend diagnostics exposed by a blob store.
func DescribeBlobStore ¶ added in v0.9.4
func DescribeBlobStore(store BlobStore, fallbackBackend string) BlobStoreInfo
DescribeBlobStore returns the optional backend diagnostics exposed by a blob store, applying a fallback backend name when the store omits one.
type BlobStoreInspector ¶ added in v0.9.4
type BlobStoreInspector interface {
BlobStoreRootDir() string
}
BlobStoreInspector exposes optional store details for diagnostics.
type BlobStoreOptions ¶ added in v0.9.4
type BlobStoreOptions struct {
RootDir string
}
BlobStoreOptions carries optional backend-specific initialization overrides.
type BlobStoreProvider ¶ added in v0.9.4
type BlobStoreProvider interface {
Plugin
NewBlobStore(ctx context.Context, appCtx *AppContext) (BlobStore, error)
}
BlobStoreProvider creates a blob store backend for plugin consumers.
type BlobStoreProviderWithOptions ¶ added in v0.9.4
type BlobStoreProviderWithOptions interface {
BlobStoreProvider
NewBlobStoreWithOptions(ctx context.Context, appCtx *AppContext, opts BlobStoreOptions) (BlobStore, error)
}
BlobStoreProviderWithOptions allows a backend provider to accept optional initialization overrides from a consumer.
type CIInfoProvider ¶ added in v0.9.4
type CIInfoProvider interface {
Plugin
ProviderName() string
PipelineID() string
CommitSHA() string
}
CIInfoProvider provides CI-specific metadata.
type ChangeDetectionProvider ¶
type ChangeDetectionProvider interface {
Plugin
DetectChangedModules(ctx context.Context, appCtx *AppContext, baseRef string, moduleIndex *discovery.ModuleIndex) (changed []*discovery.Module, changedFiles []string, err error)
DetectChangedLibraries(ctx context.Context, appCtx *AppContext, baseRef string, libraryPaths []string) ([]string, error)
}
ChangeDetectionProvider detects changed modules from git (or other VCS).
type CommandProvider ¶
type CommandProvider interface {
Plugin
Commands(ctx *AppContext) []*cobra.Command
}
CommandProvider adds CLI subcommands to TerraCi.
type CommentServiceFactory ¶ added in v0.9.4
type CommentServiceFactory interface {
Plugin
NewCommentService(ctx *AppContext) ci.CommentService
}
CommentServiceFactory creates PR/MR comment services.
type ConfigLoader ¶ added in v0.7.5
type ConfigLoader interface {
Plugin
ConfigKey() string
NewConfig() any
DecodeAndSet(decode func(target any) error) error
IsConfigured() bool
IsEnabled() bool
}
ConfigLoader declares a config section under "plugins:" in .terraci.yaml. Implemented automatically by embedding BasePlugin[C].
type EnablePolicy ¶ added in v0.7.5
type EnablePolicy int
EnablePolicy controls how the framework determines if a plugin is active.
const ( // EnabledWhenConfigured means the plugin is active if its config section // exists in .terraci.yaml (e.g., gitlab, github). EnabledWhenConfigured EnablePolicy = iota // EnabledExplicitly requires an explicit opt-in beyond having config (e.g., cost, policy). // When IsEnabledFn is set: called after config is loaded, must return true to activate. // When IsEnabledFn is nil: always returns false, even if configured. EnabledExplicitly // EnabledByDefault means the plugin is active unless enabled: false is set (e.g., summary). EnabledByDefault // EnabledAlways means the plugin is always active regardless of config (e.g., git). EnabledAlways )
type EnvDetector ¶ added in v0.7.5
EnvDetector detects whether this plugin's CI environment is active.
type FlagOverridable ¶ added in v0.7.5
FlagOverridable plugins support direct CLI flag overrides on their config.
type KVCache ¶ added in v0.9.4
type KVCache interface {
Get(ctx context.Context, namespace, key string) ([]byte, bool, error)
Set(ctx context.Context, namespace, key string, value []byte, ttl time.Duration) error
Delete(ctx context.Context, namespace, key string) error
DeleteNamespace(ctx context.Context, namespace string) error
}
KVCache is a pluggable key/value cache backend.
Values are stored as opaque bytes. Consumers own serialization, key layout, namespaces, and write-time TTL selection.
type KVCacheProvider ¶ added in v0.9.4
type KVCacheProvider interface {
Plugin
NewKVCache(ctx context.Context, appCtx *AppContext) (KVCache, error)
}
KVCacheProvider creates a KV cache backend for plugin consumers.
Providers are registered like any other TerraCi plugin and resolved by name through the global plugin registry.
type PipelineContributor ¶
type PipelineContributor interface {
Plugin
PipelineContribution(ctx *AppContext) *pipeline.Contribution
}
PipelineContributor plugins add steps or jobs to the generated CI pipeline.
type PipelineGeneratorFactory ¶ added in v0.9.4
type PipelineGeneratorFactory interface {
Plugin
NewGenerator(ctx *AppContext, depGraph *graph.DependencyGraph, modules []*discovery.Module) pipeline.Generator
}
PipelineGeneratorFactory creates pipeline generators.
type Plugin ¶
type Plugin interface {
// Name returns a unique identifier (e.g., "gitlab", "cost", "slack").
Name() string
// Description returns a human-readable description.
Description() string
}
Plugin is the core interface every plugin must implement.
type Preflightable ¶ added in v0.9.0
type Preflightable interface {
Plugin
Preflight(ctx context.Context, appCtx *AppContext) error
}
Preflightable plugins run cheap validation after config is loaded, before any command runs. Preflight should stay side-effect-light: do not cache mutable command state or perform heavy runtime setup that can be created lazily inside plugin use-cases.
type PutBlobOptions ¶ added in v0.9.4
PutBlobOptions controls how a blob is persisted by the backend.
type ReportRegistry ¶ added in v0.7.5
type ReportRegistry struct {
// contains filtered or unexported fields
}
ReportRegistry allows plugins to publish and consume reports in-memory. In CI (multi-process), reports are still written to JSON files for artifacts. The registry provides an in-process fast path for single-process runs.
func NewReportRegistry ¶ added in v0.7.5
func NewReportRegistry() *ReportRegistry
NewReportRegistry creates a new empty ReportRegistry.
func (*ReportRegistry) All ¶ added in v0.7.5
func (r *ReportRegistry) All() []*ci.Report
All returns all published reports.
func (*ReportRegistry) Get ¶ added in v0.7.5
func (r *ReportRegistry) Get(pluginName string) (*ci.Report, bool)
Get retrieves a report by plugin name.
func (*ReportRegistry) Publish ¶ added in v0.7.5
func (r *ReportRegistry) Publish(report *ci.Report)
Publish stores a report in the registry, keyed by plugin name.
type Resettable ¶ added in v0.7.5
type Resettable interface {
Plugin
Reset()
}
Resettable plugins can reset their mutable state to zero values. Used by test infrastructure to isolate tests from shared plugin singletons.
type ResolvedCIProvider ¶ added in v0.9.4
type ResolvedCIProvider struct {
// contains filtered or unexported fields
}
ResolvedCIProvider is the resolved CI provider, assembled from the focused interfaces above. Returned by ResolveCIProvider(). CommentServiceFactory is optional — not all CI providers support PR/MR comments.
func NewResolvedCIProvider ¶ added in v0.9.4
func NewResolvedCIProvider(p Plugin, meta CIInfoProvider, gen PipelineGeneratorFactory, comment CommentServiceFactory) *ResolvedCIProvider
NewResolvedCIProvider constructs a ResolvedCIProvider. The comment parameter may be nil for CI providers that do not support PR/MR comments.
func (*ResolvedCIProvider) CommitSHA ¶ added in v0.9.4
func (c *ResolvedCIProvider) CommitSHA() string
func (*ResolvedCIProvider) Description ¶ added in v0.9.4
func (c *ResolvedCIProvider) Description() string
func (*ResolvedCIProvider) Name ¶ added in v0.9.4
func (c *ResolvedCIProvider) Name() string
func (*ResolvedCIProvider) NewCommentService ¶ added in v0.9.4
func (c *ResolvedCIProvider) NewCommentService(ctx *AppContext) (ci.CommentService, bool)
NewCommentService returns the comment service and true, or nil and false if the CI provider does not support PR/MR comments.
func (*ResolvedCIProvider) NewGenerator ¶ added in v0.9.4
func (c *ResolvedCIProvider) NewGenerator(ctx *AppContext, depGraph *graph.DependencyGraph, modules []*discovery.Module) pipeline.Generator
func (*ResolvedCIProvider) PipelineID ¶ added in v0.9.4
func (c *ResolvedCIProvider) PipelineID() string
func (*ResolvedCIProvider) Plugin ¶ added in v0.9.4
func (c *ResolvedCIProvider) Plugin() Plugin
Plugin returns the underlying plugin instance.
func (*ResolvedCIProvider) ProviderName ¶ added in v0.9.4
func (c *ResolvedCIProvider) ProviderName() string
type RuntimeProvider ¶ added in v0.9.0
type RuntimeProvider interface {
Plugin
Runtime(ctx context.Context, appCtx *AppContext) (any, error)
}
RuntimeProvider is the preferred pattern for plugins with heavy command-time setup. Runtime creation is lazy and command-driven; the framework does not invoke it automatically during startup or preflight.
Use Preflightable for cheap validation and environment checks. Use RuntimeProvider for typed runtime construction inside plugin commands and use-cases.
Typical shape:
func (p *Plugin) Runtime(_ context.Context, appCtx *AppContext) (any, error) {
return newRuntime(appCtx, p.Config(), runtimeOptions{})
}
func (p *Plugin) runtime(ctx context.Context, appCtx *AppContext, opts runtimeOptions) (*myRuntime, error) {
if opts == (runtimeOptions{}) {
rawRuntime, err := p.Runtime(ctx, appCtx)
if err != nil {
return nil, err
}
return RuntimeAs[*myRuntime](rawRuntime)
}
return newRuntime(appCtx, p.Config(), opts)
}
Example ¶
package main
import (
"context"
"fmt"
"github.com/edelwud/terraci/pkg/plugin"
)
type exampleRuntime struct {
workDir string
}
type exampleRuntimePlugin struct {
plugin.BasePlugin[*exampleRuntimeConfig]
}
type exampleRuntimeConfig struct {
Enabled bool
}
func (p *exampleRuntimePlugin) Runtime(_ context.Context, appCtx *plugin.AppContext) (any, error) {
if p.Config() == nil || !p.Config().Enabled {
return nil, fmt.Errorf("example runtime is not enabled")
}
return &exampleRuntime{workDir: appCtx.WorkDir()}, nil
}
func main() {
p := &exampleRuntimePlugin{
BasePlugin: plugin.BasePlugin[*exampleRuntimeConfig]{
PluginName: "example",
PluginDesc: "example runtime plugin",
EnableMode: plugin.EnabledExplicitly,
DefaultCfg: func() *exampleRuntimeConfig { return &exampleRuntimeConfig{} },
IsEnabledFn: func(cfg *exampleRuntimeConfig) bool { return cfg != nil && cfg.Enabled },
},
}
p.SetTypedConfig(&exampleRuntimeConfig{Enabled: true})
appCtx := plugin.NewAppContext(nil, "/repo", "/repo/.terraci", "test", nil)
rawRuntime, _ := p.Runtime(context.Background(), appCtx)
runtime, _ := plugin.RuntimeAs[*exampleRuntime](rawRuntime)
fmt.Println(runtime.workDir)
}
Output: /repo
type VersionProvider ¶
VersionProvider plugins contribute version info to `terraci version`.
Source Files
¶
Directories
¶
| Path | Synopsis |
|---|---|
|
Package initwiz provides init wizard state management and types for TerraCi.
|
Package initwiz provides init wizard state management and types for TerraCi. |
|
Package registry provides the global plugin registry for TerraCi.
|
Package registry provides the global plugin registry for TerraCi. |