plugin

package
v0.9.6 Latest Latest
Warning

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

Go to latest
Published: Apr 14, 2026 License: MIT Imports: 12 Imported by: 1

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

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

func CheckBlobStore(ctx context.Context, store BlobStore) error

CheckBlobStore runs the optional blob-store health check when implemented.

func RuntimeAs added in v0.9.0

func RuntimeAs[T any](runtime any) (T, error)

RuntimeAs converts a runtime returned by RuntimeProvider into the expected plugin-local type at the plugin boundary. The framework intentionally treats runtime values as opaque.

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

type BlobObject struct {
	Key  string
	Meta BlobMeta
}

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

type BlobStoreHealthChecker interface {
	CheckBlobStore(ctx context.Context) error
}

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

type EnvDetector interface {
	Plugin
	DetectEnv() bool
}

EnvDetector detects whether this plugin's CI environment is active.

type FlagOverridable added in v0.7.5

type FlagOverridable interface {
	Plugin
	SetPlanOnly(bool)
	SetAutoApprove(bool)
}

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

type PutBlobOptions struct {
	ContentType string
	ExpiresAt   *time.Time
	Metadata    map[string]string
}

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

type VersionProvider interface {
	Plugin
	VersionInfo() map[string]string
}

VersionProvider plugins contribute version info to `terraci version`.

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.

Jump to

Keyboard shortcuts

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