Documentation
¶
Overview ¶
Package action provides types and execution logic for the Actions system. Actions consume resolved data from resolvers and perform side-effect operations.
Index ¶
- Constants
- func CreateIterationName(baseName string, index int) string
- func ExpandForEachItems(ctx context.Context, forEach *spec.ForEachClause, resolverData map[string]any) ([]any, error)
- func GetDeferredInputNames(values map[string]any) []string
- func GetFormat(format string) (string, error)
- func HasDeferredValues(values map[string]any) bool
- func IsForEachIteration(name string) bool
- func Materialize(ctx context.Context, v *spec.ValueRef, resolverData map[string]any) (any, error)
- func MaterializeInputs(ctx context.Context, inputs map[string]*spec.ValueRef, ...) (map[string]any, error)
- func ParseIterationName(name string) (baseName string, index int, ok bool)
- func Render(graph *Graph, opts *RenderOptions) ([]byte, error)
- func ResolveDeferredValues(ctx context.Context, values, resolverData, actionsData map[string]any) (map[string]any, error)
- func ValidateResult(result any, schema *jsonschema.Schema) error
- func ValidateWorkflow(w *Workflow, registry RegistryInterface) error
- type Action
- type ActionResult
- type ActionStatus
- type AggregatedValidationError
- type BackoffType
- type BuildGraphOptions
- type ConfigInput
- type Context
- func (c *Context) ActionCount() int
- func (c *Context) AddIteration(actionName string, result *ForEachIterationResult)
- func (c *Context) AllActionNames() []string
- func (c *Context) Clone() *Context
- func (c *Context) FinalizeForEach(actionName string, inputs map[string]any) *ActionResult
- func (c *Context) GetIterations(actionName string) []*ForEachIterationResult
- func (c *Context) GetNamespace() map[string]any
- func (c *Context) GetResult(name string) (*ActionResult, bool)
- func (c *Context) HasResult(name string) bool
- func (c *Context) MarkCancelled(name string)
- func (c *Context) MarkFailed(name, errMsg string)
- func (c *Context) MarkRunning(name string, inputs map[string]any)
- func (c *Context) MarkSkipped(name string, reason SkipReason)
- func (c *Context) MarkStreamed(name string)
- func (c *Context) MarkSucceeded(name string, results any)
- func (c *Context) MarkTimeout(name string)
- func (c *Context) Reset()
- func (c *Context) SetResult(name string, result *ActionResult)
- type DeferredValue
- type ErrorContext
- type ExecuteFunc
- type ExecuteResult
- type ExecutionResult
- type ExecutionStatus
- type Executor
- type ExecutorOption
- func OptionsFromAppConfig(cfg ConfigInput) []ExecutorOption
- func WithDefaultTimeout(d time.Duration) ExecutorOption
- func WithGracePeriod(d time.Duration) ExecutorOption
- func WithIOStreams(streams *provider.IOStreams) ExecutorOption
- func WithMaxConcurrency(n int) ExecutorOption
- func WithProgressCallback(callback ProgressCallback) ExecutorOption
- func WithRegistry(registry RegistryInterface) ExecutorOption
- func WithResolverData(data map[string]any) ExecutorOption
- type ExpandedAction
- type ForEachExecuteFunc
- type ForEachExecutor
- type ForEachExecutorOption
- type ForEachExpansionMetadata
- type ForEachIterationResult
- type Graph
- func (g *Graph) GetActionsByPhase(phase int) []*ExpandedAction
- func (g *Graph) GetAllActionNames() []string
- func (g *Graph) GetFinallyActionNames() []string
- func (g *Graph) GetFinallyActionsByPhase(phase int) []*ExpandedAction
- func (g *Graph) GetForEachIterations(baseName string) []string
- func (g *Graph) GetMainActionNames() []string
- func (g *Graph) TotalFinallyPhases() int
- func (g *Graph) TotalPhases() int
- type GraphVisualization
- type HTTPError
- type NoOpProgressCallback
- func (NoOpProgressCallback) OnActionCancelled(_ string)
- func (NoOpProgressCallback) OnActionComplete(_ string, _ any)
- func (NoOpProgressCallback) OnActionFailed(_ string, _ error)
- func (NoOpProgressCallback) OnActionSkipped(_, _ string)
- func (NoOpProgressCallback) OnActionStart(_ string)
- func (NoOpProgressCallback) OnActionTimeout(_ string, _ time.Duration)
- func (NoOpProgressCallback) OnFinallyComplete()
- func (NoOpProgressCallback) OnFinallyStart()
- func (NoOpProgressCallback) OnForEachProgress(_ string, _, _ int)
- func (NoOpProgressCallback) OnPhaseComplete(_ int)
- func (NoOpProgressCallback) OnPhaseStart(_ int, _ []string)
- func (NoOpProgressCallback) OnRetryAttempt(_ string, _, _ int, _ error)
- type ProgressCallback
- type RegistryInterface
- type RenderOptions
- type RenderedAction
- type RenderedForEachMetadata
- type RenderedGraph
- type RenderedMetadata
- type RenderedRetryConfig
- type ResultSchemaMode
- type RetryCallback
- type RetryConfig
- type RetryExecutor
- func (r *RetryExecutor) CalculateDelay(attempt int) time.Duration
- func (r *RetryExecutor) ExecuteWithRetry(ctx context.Context, actionName string, execute ExecuteFunc, ...) (*provider.Output, error)
- func (r *RetryExecutor) ExecuteWithRetryDetailed(ctx context.Context, actionName string, execute ExecuteFunc, ...) *RetryResult
- func (r *RetryExecutor) MaxAttempts() int
- func (r *RetryExecutor) ShouldRetry(ctx context.Context, err error, attempt int) (bool, error)
- func (r *RetryExecutor) WithJitter(fn func(time.Duration) time.Duration) *RetryExecutor
- type RetryResult
- type SkipReason
- type ValidationError
- type VisualizationEdge
- type VisualizationPhase
- type VisualizationStats
- type Workflow
Constants ¶
const ( // ErrorTypeHTTP indicates an HTTP-related error with a status code. ErrorTypeHTTP = "http" // ErrorTypeExec indicates a process execution error with an exit code. ErrorTypeExec = "exec" // ErrorTypeTimeout indicates a timeout or deadline exceeded error. ErrorTypeTimeout = "timeout" // ErrorTypeValidation indicates a validation error. ErrorTypeValidation = "validation" // ErrorTypeUnknown indicates an unclassified error. ErrorTypeUnknown = "unknown" )
Error type constants for categorization.
const ( // APIVersion is the version of the rendered graph format. APIVersion = "scafctl.oakwood-commons.github.io/v1alpha1" // KindActionGraph is the kind for rendered action graphs. KindActionGraph = "ActionGraph" // FormatJSON indicates JSON output format. FormatJSON = "json" // FormatYAML indicates YAML output format. FormatYAML = "yaml" )
Variables ¶
This section is empty.
Functions ¶
func CreateIterationName ¶
CreateIterationName creates the expanded name for a forEach iteration. Format: "baseName[index]" (e.g., "deploy[0]", "deploy[1]")
func ExpandForEachItems ¶
func ExpandForEachItems(ctx context.Context, forEach *spec.ForEachClause, resolverData map[string]any) ([]any, error)
ExpandForEachItems evaluates the forEach.In expression and returns the items to iterate over. This is a convenience function that wraps evaluateForEachArray for external use.
func GetDeferredInputNames ¶
GetDeferredInputNames returns the names of inputs that contain deferred values.
func HasDeferredValues ¶
HasDeferredValues checks if any values in the map are deferred.
func IsForEachIteration ¶
IsForEachIteration checks if an action name represents a forEach iteration. Returns true if the name matches the pattern "baseName[index]".
func Materialize ¶
Materialize evaluates a ValueRef, returning either a concrete value or a DeferredValue if it references __actions. This is used during the render phase to prepare action inputs.
func MaterializeInputs ¶
func MaterializeInputs(ctx context.Context, inputs map[string]*spec.ValueRef, resolverData map[string]any) (map[string]any, error)
MaterializeInputs processes all inputs for an action, materializing immediate values and preserving deferred values that reference __actions. Returns a map where concrete values are resolved and __actions references are DeferredValues.
func ParseIterationName ¶
ParseIterationName extracts the base name and index from a forEach iteration name. Returns the base name, index, and true if successful. Returns empty string, -1, false if not a valid iteration name.
func Render ¶
func Render(graph *Graph, opts *RenderOptions) ([]byte, error)
Render produces an executor-ready action graph artifact from the built graph. The output can be serialized to JSON or YAML based on options.
func ResolveDeferredValues ¶
func ResolveDeferredValues(ctx context.Context, values, resolverData, actionsData map[string]any) (map[string]any, error)
ResolveDeferredValues evaluates all deferred values in the map using the provided action results. Non-deferred values are passed through unchanged.
func ValidateResult ¶
func ValidateResult(result any, schema *jsonschema.Schema) error
ValidateResult validates a provider result against the JSON Schema. Returns nil if validation passes or schema is nil.
func ValidateWorkflow ¶
func ValidateWorkflow(w *Workflow, registry RegistryInterface) error
ValidateWorkflow validates the entire workflow definition. It checks all validation rules and returns an aggregated error if any fail. Pass nil for registry to skip provider capability checks.
Types ¶
type Action ¶
type Action struct {
// Name is the action identifier, set from the map key.
// Cannot start with "__" (reserved) or contain "[" or "]".
Name string `` /* 225-byte string literal not displayed */
// Description provides documentation for the action.
Description string `` /* 130-byte string literal not displayed */
// DisplayName is a human-friendly name for UI display.
DisplayName string `json:"displayName,omitempty" yaml:"displayName,omitempty" doc:"Human-friendly display name" maxLength:"100"`
// Sensitive indicates the action handles sensitive data (masks in logs).
Sensitive bool `json:"sensitive,omitempty" yaml:"sensitive,omitempty" doc:"If true, inputs and outputs are masked in logs"`
// Provider specifies which action provider to use for execution.
// The provider must have CapabilityAction.
Provider string `json:"provider" yaml:"provider" doc:"Action provider name" maxLength:"100" example:"shell"`
// Inputs is a map of input values passed to the provider.
// Values can be literals, resolver references, expressions, or templates.
// Expressions referencing __actions are deferred until runtime.
Inputs map[string]*spec.ValueRef `json:"inputs,omitempty" yaml:"inputs,omitempty" doc:"Input values for the provider"`
// DependsOn lists action names that must complete before this action runs.
// For regular actions, only other regular actions can be referenced.
// For finally actions, only other finally actions can be referenced.
DependsOn []string `json:"dependsOn,omitempty" yaml:"dependsOn,omitempty" doc:"Actions that must complete before this action runs" maxItems:"100"`
// When is a condition that must evaluate to true for the action to execute.
// If false, the action is skipped with SkipReasonCondition.
When *spec.Condition `json:"when,omitempty" yaml:"when,omitempty" doc:"Condition for execution (skipped if false)"`
// OnError defines behavior when this action fails.
// Default is "fail" which stops workflow execution.
OnError spec.OnErrorBehavior `json:"onError,omitempty" yaml:"onError,omitempty" doc:"Error handling behavior" example:"fail" default:"fail"`
// Timeout limits how long the action can run.
// If exceeded, the action fails with StatusTimeout.
Timeout *duration.Duration `json:"timeout,omitempty" yaml:"timeout,omitempty" doc:"Maximum execution duration" example:"30s"`
// Retry configures automatic retry on failure.
Retry *RetryConfig `json:"retry,omitempty" yaml:"retry,omitempty" doc:"Retry configuration for transient failures"`
// ForEach enables iteration, executing the action once per array element.
// Only allowed in workflow.actions, not workflow.finally.
ForEach *spec.ForEachClause `json:"forEach,omitempty" yaml:"forEach,omitempty" doc:"Iteration configuration (not allowed in finally)"`
// ResultSchema defines the expected structure of the action's output using JSON Schema.
// If provided, the provider's output is validated against this schema at runtime.
// Supports full JSON Schema 2020-12 specification including $ref, allOf, anyOf, oneOf, etc.
// This enables self-documenting actions and catches mismatches early.
// Use ResultSchemaMode to control validation behavior (error, warn, ignore).
ResultSchema *jsonschema.Schema `json:"resultSchema,omitempty" yaml:"resultSchema,omitempty" doc:"JSON Schema for result validation"`
// ResultSchemaMode controls behavior when result schema validation fails.
// Overrides the workflow-level default. Options: "error" (fail action), "warn" (log and continue), "ignore" (skip validation).
ResultSchemaMode ResultSchemaMode `json:"resultSchemaMode,omitempty" yaml:"resultSchemaMode,omitempty" doc:"Result schema validation mode" example:"error"`
}
Action represents a single action definition. Actions perform side-effect operations using providers and can depend on other actions for sequencing and data flow.
type ActionResult ¶
type ActionResult struct {
// Inputs contains the resolved input values that were passed to the provider.
Inputs map[string]any `json:"inputs" yaml:"inputs" doc:"Resolved inputs passed to provider"`
// Results contains the output data from the provider.
// This is accessible as __actions.<name>.results in CEL/templates.
Results any `json:"results,omitempty" yaml:"results,omitempty" doc:"Provider output data"`
// Status is the final execution status.
Status ActionStatus `json:"status" yaml:"status" doc:"Execution status"`
// SkipReason explains why the action was skipped (if Status is StatusSkipped).
SkipReason SkipReason `json:"skipReason,omitempty" yaml:"skipReason,omitempty" doc:"Reason for skipping (if skipped)"`
// StartTime is when execution began.
StartTime *time.Time `json:"startTime,omitempty" yaml:"startTime,omitempty" doc:"Execution start time"`
// EndTime is when execution completed.
EndTime *time.Time `json:"endTime,omitempty" yaml:"endTime,omitempty" doc:"Execution end time"`
// Error contains the error message if Status is StatusFailed or StatusTimeout.
Error string `json:"error,omitempty" yaml:"error,omitempty" doc:"Error message (if failed)"`
// Streamed indicates the provider already wrote its output to the terminal.
// When true, the CLI output layer should not re-print the action's results.
Streamed bool `json:"streamed,omitempty" yaml:"streamed,omitempty" doc:"Whether output was streamed to terminal"`
}
ActionResult represents the result of an action execution. It is stored in the __actions namespace and accessible to dependent actions.
func AggregateForEachResults ¶
func AggregateForEachResults( _ string, iterations []*ForEachIterationResult, inputs map[string]any, ) *ActionResult
AggregateForEachResults aggregates forEach iteration results into an ActionResult. This creates the combined result that will be stored in __actions namespace.
func (*ActionResult) Duration ¶
func (r *ActionResult) Duration() time.Duration
Duration returns the execution duration, or zero if not available.
type ActionStatus ¶
type ActionStatus string
ActionStatus represents the execution status of an action.
const ( // StatusPending indicates the action has not started. StatusPending ActionStatus = "pending" // StatusRunning indicates the action is currently executing. StatusRunning ActionStatus = "running" // StatusSucceeded indicates the action completed successfully. StatusSucceeded ActionStatus = "succeeded" // StatusFailed indicates the action failed. StatusFailed ActionStatus = "failed" // StatusSkipped indicates the action was not executed. StatusSkipped ActionStatus = "skipped" // StatusTimeout indicates the action exceeded its timeout. StatusTimeout ActionStatus = "timeout" // StatusCancelled indicates the action was cancelled. StatusCancelled ActionStatus = "cancelled" )
func (ActionStatus) IsSuccess ¶
func (s ActionStatus) IsSuccess() bool
IsSuccess returns true if the status indicates successful completion.
func (ActionStatus) IsTerminal ¶
func (s ActionStatus) IsTerminal() bool
IsTerminal returns true if the status is a terminal state.
type AggregatedValidationError ¶
type AggregatedValidationError struct {
// Errors contains all validation errors found.
Errors []*ValidationError `json:"errors" yaml:"errors" doc:"All validation errors" minItems:"1"`
}
AggregatedValidationError represents multiple validation errors. This is returned when ValidateWorkflow finds multiple issues.
func (*AggregatedValidationError) AddError ¶
func (e *AggregatedValidationError) AddError(err *ValidationError)
AddError adds a validation error.
func (*AggregatedValidationError) Error ¶
func (e *AggregatedValidationError) Error() string
Error implements the error interface.
func (*AggregatedValidationError) HasErrors ¶
func (e *AggregatedValidationError) HasErrors() bool
HasErrors returns true if there are any validation errors.
func (*AggregatedValidationError) ToError ¶
func (e *AggregatedValidationError) ToError() error
ToError returns nil if no errors, or the AggregatedValidationError itself.
type BackoffType ¶
type BackoffType string
BackoffType defines the backoff strategy for retries.
const ( // BackoffFixed uses a constant delay between retries. BackoffFixed BackoffType = "fixed" // BackoffLinear increases delay linearly (initialDelay * attempt). BackoffLinear BackoffType = "linear" // BackoffExponential doubles the delay with each retry. BackoffExponential BackoffType = "exponential" )
func (BackoffType) IsValid ¶
func (b BackoffType) IsValid() bool
IsValid returns true if the backoff type is valid.
func (BackoffType) OrDefault ¶
func (b BackoffType) OrDefault() BackoffType
OrDefault returns the backoff type or the default (BackoffFixed) if empty.
type BuildGraphOptions ¶
type BuildGraphOptions struct {
// SkipInputMaterialization skips input materialization (for validation-only use cases).
SkipInputMaterialization bool
}
BuildGraphOptions configures graph building behavior.
type ConfigInput ¶
type ConfigInput struct {
// DefaultTimeout is the default timeout per action execution
DefaultTimeout time.Duration
// GracePeriod is the cancellation grace period
GracePeriod time.Duration
// MaxConcurrency is the max concurrent actions (0 = unlimited)
MaxConcurrency int
}
ConfigInput holds the configuration values for action executor initialization. This mirrors config.ActionConfig but avoids circular dependencies.
type Context ¶
type Context struct {
// contains filtered or unexported fields
}
Context manages the __actions namespace during workflow execution. It provides thread-safe storage for action results and supports forEach iteration result aggregation.
func NewContext ¶
func NewContext() *Context
NewContext creates a new action context for workflow execution.
func (*Context) ActionCount ¶
ActionCount returns the number of actions with results.
func (*Context) AddIteration ¶
func (c *Context) AddIteration(actionName string, result *ForEachIterationResult)
AddIteration records a forEach iteration result. Results are stored in order by index.
func (*Context) AllActionNames ¶
AllActionNames returns all action names that have results.
func (*Context) Clone ¶
Clone creates a deep copy of the action context. Useful for testing or creating snapshots.
func (*Context) FinalizeForEach ¶
func (c *Context) FinalizeForEach(actionName string, inputs map[string]any) *ActionResult
FinalizeForEach aggregates forEach iteration results into a single ActionResult. This should be called after all iterations complete to create the combined result.
func (*Context) GetIterations ¶
func (c *Context) GetIterations(actionName string) []*ForEachIterationResult
GetIterations retrieves all iteration results for a forEach action.
func (*Context) GetNamespace ¶
GetNamespace returns the __actions map for CEL/template evaluation. The returned map contains action results in a format suitable for expression evaluation (e.g., __actions.build.results.exitCode).
func (*Context) GetResult ¶
func (c *Context) GetResult(name string) (*ActionResult, bool)
GetResult retrieves an action's result by name. Returns the result and true if found, nil and false otherwise.
func (*Context) MarkCancelled ¶
MarkCancelled marks an action as cancelled.
func (*Context) MarkFailed ¶
MarkFailed marks an action as failed with an error message.
func (*Context) MarkRunning ¶
MarkRunning marks an action as running with the current time.
func (*Context) MarkSkipped ¶
func (c *Context) MarkSkipped(name string, reason SkipReason)
MarkSkipped marks an action as skipped with a reason.
func (*Context) MarkStreamed ¶ added in v0.4.0
MarkStreamed marks an action as having streamed its output to the terminal.
func (*Context) MarkSucceeded ¶
MarkSucceeded marks an action as successfully completed.
func (*Context) MarkTimeout ¶
MarkTimeout marks an action as timed out.
func (*Context) SetResult ¶
func (c *Context) SetResult(name string, result *ActionResult)
SetResult stores an action's result in the context. This is called after an action completes (success, failure, or skip).
type DeferredValue ¶
type DeferredValue struct {
// OriginalExpr is the original CEL expression string (if expr-based).
OriginalExpr string `json:"originalExpr,omitempty" yaml:"originalExpr,omitempty" doc:"Original CEL expression"`
// OriginalTmpl is the original Go template string (if tmpl-based).
OriginalTmpl string `json:"originalTmpl,omitempty" yaml:"originalTmpl,omitempty" doc:"Original Go template"`
// Deferred indicates this value requires runtime evaluation.
Deferred bool `json:"deferred" yaml:"deferred" doc:"If true, value requires runtime evaluation"`
}
DeferredValue represents an expression that is preserved for runtime evaluation. This is used when a ValueRef references __actions, which cannot be resolved until the referenced action has completed during workflow execution.
func (*DeferredValue) Evaluate ¶
func (d *DeferredValue) Evaluate(ctx context.Context, resolverData, actionsData map[string]any) (any, error)
Evaluate resolves the deferred value using the provided resolver data and action results. The actionsData should contain the __actions namespace with completed action results.
func (*DeferredValue) IsDeferred ¶
func (d *DeferredValue) IsDeferred() bool
IsDeferred returns true if this value requires runtime evaluation.
type ErrorContext ¶
type ErrorContext struct {
// Message is the error message string.
Message string `json:"message"`
// Type categorizes the error source.
// Values: "http", "exec", "timeout", "validation", "unknown"
Type string `json:"type"`
// StatusCode is the HTTP status code (0 if not an HTTP error).
StatusCode int `json:"statusCode"`
// ExitCode is the process exit code (0 if not an exec error).
ExitCode int `json:"exitCode"`
// Attempt is the current attempt number (1-based).
// First attempt is 1, first retry is 2, etc.
Attempt int `json:"attempt"`
// MaxAttempts is the maximum attempts configured.
MaxAttempts int `json:"maxAttempts"`
}
ErrorContext provides error information for retryIf CEL expressions. It is exposed as __error in the CEL evaluation context.
func NewErrorContext ¶
func NewErrorContext(err error, attempt, maxAttempts int) *ErrorContext
NewErrorContext creates an ErrorContext from an error and attempt info. It inspects the error to determine the type, status code, and exit code.
func (*ErrorContext) ToMap ¶
func (e *ErrorContext) ToMap() map[string]any
ToMap converts ErrorContext to a map for CEL evaluation.
type ExecuteFunc ¶
ExecuteFunc is the function signature for action execution. It takes a context and returns the provider output and any error.
type ExecuteResult ¶
type ExecuteResult struct {
// Iterations contains results for each iteration
Iterations []*ForEachIterationResult `json:"iterations" yaml:"iterations" doc:"Results for each iteration"`
// TotalCount is the total number of iterations
TotalCount int `json:"totalCount" yaml:"totalCount" doc:"Total number of iterations"`
// SuccessCount is the number of successful iterations
SuccessCount int `json:"successCount" yaml:"successCount" doc:"Number of successful iterations"`
// FailureCount is the number of failed iterations
FailureCount int `json:"failureCount" yaml:"failureCount" doc:"Number of failed iterations"`
// AllSucceeded indicates if all iterations succeeded
AllSucceeded bool `json:"allSucceeded" yaml:"allSucceeded" doc:"Whether all iterations succeeded"`
// FirstError is the first error encountered (if any)
FirstError error `json:"-" yaml:"-"`
}
ExecuteResult contains the results of forEach execution.
func (*ExecuteResult) AggregatedResults ¶
func (r *ExecuteResult) AggregatedResults() []any
AggregatedResults returns all iteration results as a slice for __actions.name.results access.
type ExecutionResult ¶
type ExecutionResult struct {
// Actions contains results for all executed actions
Actions map[string]*ActionResult `json:"actions" yaml:"actions" doc:"Results for all actions"`
// FinalStatus is the overall execution status
FinalStatus ExecutionStatus `json:"finalStatus" yaml:"finalStatus" doc:"Overall execution status"`
// StartTime is when execution began
StartTime time.Time `json:"startTime" yaml:"startTime" doc:"Execution start time"`
// EndTime is when execution completed
EndTime time.Time `json:"endTime" yaml:"endTime" doc:"Execution end time"`
// FailedActions contains names of actions that failed
FailedActions []string `json:"failedActions,omitempty" yaml:"failedActions,omitempty" doc:"Names of failed actions"`
// SkippedActions contains names of actions that were skipped
SkippedActions []string `json:"skippedActions,omitempty" yaml:"skippedActions,omitempty" doc:"Names of skipped actions"`
}
ExecutionResult contains the final execution state.
func (*ExecutionResult) Duration ¶
func (r *ExecutionResult) Duration() time.Duration
Duration returns the total execution duration.
type ExecutionStatus ¶
type ExecutionStatus string
ExecutionStatus represents the overall execution status.
const ( // ExecutionSucceeded means all actions completed successfully. ExecutionSucceeded ExecutionStatus = "succeeded" // ExecutionFailed means one or more actions failed. ExecutionFailed ExecutionStatus = "failed" // ExecutionCancelled means execution was cancelled. ExecutionCancelled ExecutionStatus = "cancelled" // ExecutionPartialSuccess means some actions succeeded with onError:continue. ExecutionPartialSuccess ExecutionStatus = "partial-success" )
type Executor ¶
type Executor struct {
// contains filtered or unexported fields
}
Executor runs actions in dependency order with support for parallel execution, retry, timeout, and error handling.
func NewExecutor ¶
func NewExecutor(opts ...ExecutorOption) *Executor
NewExecutor creates a new action executor with the given options.
func (*Executor) Execute ¶
Execute runs the workflow actions in dependency order. It executes main actions first, then always runs finally actions regardless of failures.
func (*Executor) GetContext ¶
GetContext returns the action context for inspection.
type ExecutorOption ¶
type ExecutorOption func(*Executor)
ExecutorOption configures the executor.
func OptionsFromAppConfig ¶
func OptionsFromAppConfig(cfg ConfigInput) []ExecutorOption
OptionsFromAppConfig creates executor options from app configuration. CLI flags can override these defaults using the returned executor options.
Example:
cfg := action.ActionConfigInput{
DefaultTimeout: 5 * time.Minute,
GracePeriod: 30 * time.Second,
MaxConcurrency: 0,
}
opts := action.OptionsFromAppConfig(cfg)
executor := action.NewExecutor(opts...)
func WithDefaultTimeout ¶
func WithDefaultTimeout(d time.Duration) ExecutorOption
WithDefaultTimeout sets the default timeout for actions.
func WithGracePeriod ¶
func WithGracePeriod(d time.Duration) ExecutorOption
WithGracePeriod sets how long to wait for running actions during cancellation.
func WithIOStreams ¶ added in v0.4.0
func WithIOStreams(streams *provider.IOStreams) ExecutorOption
WithIOStreams sets the terminal IO streams for provider output streaming. When set, providers that support streaming (e.g., exec) can write output directly to the terminal in real-time. For parallel actions, each action gets a prefixed writer to attribute output clearly.
func WithMaxConcurrency ¶
func WithMaxConcurrency(n int) ExecutorOption
WithMaxConcurrency limits the number of parallel actions. Set to 0 for unlimited concurrency.
func WithProgressCallback ¶
func WithProgressCallback(callback ProgressCallback) ExecutorOption
WithProgressCallback sets the progress callback for execution events.
func WithRegistry ¶
func WithRegistry(registry RegistryInterface) ExecutorOption
WithRegistry sets the provider registry for the executor.
func WithResolverData ¶
func WithResolverData(data map[string]any) ExecutorOption
WithResolverData sets the resolver data for input resolution.
type ExpandedAction ¶
type ExpandedAction struct {
// Action is the original action definition.
*Action `json:",inline" yaml:",inline"`
// ExpandedName is the name for this expanded action.
// For forEach actions, this is "baseName[index]" (e.g., "deploy[0]").
// For regular actions, this matches the action's name.
ExpandedName string `json:"expandedName" yaml:"expandedName" doc:"Name for this expanded action" example:"deploy[0]"`
// MaterializedInputs contains inputs that were fully resolved during graph building.
// These do not reference __actions and can be used directly.
MaterializedInputs map[string]any `json:"materializedInputs,omitempty" yaml:"materializedInputs,omitempty" doc:"Resolved input values"`
// DeferredInputs contains inputs that reference __actions and must be resolved at runtime.
DeferredInputs map[string]*DeferredValue `json:"deferredInputs,omitempty" yaml:"deferredInputs,omitempty" doc:"Inputs requiring runtime resolution"`
// Section indicates which workflow section this action belongs to.
Section string `json:"section" yaml:"section" doc:"Workflow section (actions or finally)" example:"actions"`
// ForEachMetadata contains expansion information if this action was expanded from a forEach.
ForEachMetadata *ForEachExpansionMetadata `json:"forEachMetadata,omitempty" yaml:"forEachMetadata,omitempty" doc:"ForEach expansion info"`
// Dependencies contains the effective dependencies for this expanded action.
// For regular actions, this matches DependsOn plus any implicit dependencies from __actions references.
// For expanded forEach actions, this includes dependencies on all iterations of referenced forEach actions.
Dependencies []string `json:"dependencies" yaml:"dependencies" doc:"Effective dependencies for scheduling"`
}
ExpandedAction is an action with materialized inputs ready for execution. For forEach actions, each iteration becomes a separate ExpandedAction.
func (*ExpandedAction) GetExpandedName ¶
func (e *ExpandedAction) GetExpandedName() string
GetExpandedName returns the expanded action name. For forEach actions this is "baseName[index]", for regular actions it matches the original name.
func (*ExpandedAction) GetOriginalName ¶
func (e *ExpandedAction) GetOriginalName() string
GetOriginalName returns the original action name (before forEach expansion).
func (*ExpandedAction) HasDeferredInputs ¶
func (e *ExpandedAction) HasDeferredInputs() bool
HasDeferredInputs returns true if the action has any deferred inputs.
func (*ExpandedAction) IsForEachIteration ¶
func (e *ExpandedAction) IsForEachIteration() bool
IsForEachIteration returns true if this action is an expanded forEach iteration.
type ForEachExecuteFunc ¶
ForEachExecuteFunc is the function signature for executing a single forEach iteration. It receives the execution context, the current item, and the iteration index. Returns the provider output and any error.
type ForEachExecutor ¶
type ForEachExecutor struct {
// contains filtered or unexported fields
}
ForEachExecutor handles forEach iteration execution with concurrency control. It manages parallel execution of iterations while respecting concurrency limits and error handling policies.
func FromForEachClause ¶
func FromForEachClause(clause *spec.ForEachClause, progressCallback ProgressCallback) *ForEachExecutor
FromForEachClause creates a ForEachExecutor configured from a ForEachClause.
func NewForEachExecutor ¶
func NewForEachExecutor(opts ...ForEachExecutorOption) *ForEachExecutor
NewForEachExecutor creates a new ForEachExecutor with the given options.
func (*ForEachExecutor) Execute ¶
func (e *ForEachExecutor) Execute( ctx context.Context, actionName string, items []any, execute ForEachExecuteFunc, ) (*ExecuteResult, error)
Execute runs forEach iterations with concurrency control and error handling. Items is the array to iterate over, actionName is used for naming iterations.
type ForEachExecutorOption ¶
type ForEachExecutorOption func(*ForEachExecutor)
ForEachExecutorOption configures the ForEachExecutor.
func WithForEachConcurrency ¶
func WithForEachConcurrency(n int) ForEachExecutorOption
WithForEachConcurrency sets the concurrency limit for forEach execution. Set to 0 for unlimited concurrency.
func WithForEachOnError ¶
func WithForEachOnError(behavior spec.OnErrorBehavior) ForEachExecutorOption
WithForEachOnError sets the error handling behavior.
func WithForEachProgressCallback ¶
func WithForEachProgressCallback(callback ProgressCallback) ForEachExecutorOption
WithForEachProgressCallback sets the progress callback for forEach execution.
type ForEachExpansionMetadata ¶
type ForEachExpansionMetadata struct {
// ExpandedFrom is the original action name before forEach expansion.
ExpandedFrom string `json:"expandedFrom" yaml:"expandedFrom" doc:"Original action name" example:"deploy"`
// Index is the iteration index (0-based) within the forEach expansion.
Index int `json:"index" yaml:"index" doc:"Iteration index" example:"0"`
// Item is the current iteration item value.
Item any `json:"item,omitempty" yaml:"item,omitempty" doc:"Current iteration item"`
}
ForEachExpansionMetadata tracks forEach expansion information.
type ForEachIterationResult ¶
type ForEachIterationResult struct {
// Index is the 0-based iteration index.
Index int `json:"index" yaml:"index" doc:"Iteration index (0-based)"`
// Name is the expanded action name (e.g., "deploy[0]", "deploy[1]").
Name string `json:"name" yaml:"name" doc:"Expanded action name" maxLength:"150"`
// Results contains the output data from this iteration.
Results any `json:"results,omitempty" yaml:"results,omitempty" doc:"Iteration output data"`
// Status is the execution status of this iteration.
Status ActionStatus `json:"status" yaml:"status" doc:"Iteration execution status"`
// StartTime is when this iteration began.
StartTime *time.Time `json:"startTime,omitempty" yaml:"startTime,omitempty" doc:"Iteration start time"`
// EndTime is when this iteration completed.
EndTime *time.Time `json:"endTime,omitempty" yaml:"endTime,omitempty" doc:"Iteration end time"`
// Error contains the error message if this iteration failed.
Error string `json:"error,omitempty" yaml:"error,omitempty" doc:"Error message (if failed)"`
}
ForEachIterationResult represents the result of a single forEach iteration. When an action uses forEach, results are collected into an array of these.
func (*ForEachIterationResult) Duration ¶
func (r *ForEachIterationResult) Duration() time.Duration
Duration returns the iteration execution duration, or zero if not available.
type Graph ¶
type Graph struct {
// Actions is a map of all expanded actions keyed by their name.
// ForEach actions are expanded with indexed names like "deploy[0]", "deploy[1]".
Actions map[string]*ExpandedAction `json:"actions" yaml:"actions" doc:"All expanded actions"`
// ExecutionOrder contains phases of action names that can run in parallel.
// Phase 0 contains actions with no dependencies, phase 1 contains actions
// that depend only on phase 0 actions, and so on.
ExecutionOrder [][]string `json:"executionOrder" yaml:"executionOrder" doc:"Parallel execution phases for main actions"`
// FinallyOrder contains phases for the finally section.
// Finally actions have an implicit dependency on all main actions completing.
FinallyOrder [][]string `json:"finallyOrder,omitempty" yaml:"finallyOrder,omitempty" doc:"Parallel execution phases for finally actions"`
}
Graph represents the executable action dependency graph. It contains expanded actions with materialized inputs and execution order.
func BuildGraph ¶
func BuildGraph(ctx context.Context, w *Workflow, resolverData map[string]any, opts *BuildGraphOptions) (*Graph, error)
BuildGraph constructs the action dependency graph from a workflow. It expands forEach actions, materializes inputs (where possible), extracts dependencies, and computes execution phases.
func (*Graph) GetActionsByPhase ¶
func (g *Graph) GetActionsByPhase(phase int) []*ExpandedAction
GetActionsByPhase returns all actions in a specific execution phase.
func (*Graph) GetAllActionNames ¶
GetAllActionNames returns all action names in the graph including expanded forEach names.
func (*Graph) GetFinallyActionNames ¶
GetFinallyActionNames returns only the finally section action names.
func (*Graph) GetFinallyActionsByPhase ¶
func (g *Graph) GetFinallyActionsByPhase(phase int) []*ExpandedAction
GetFinallyActionsByPhase returns all finally actions in a specific execution phase.
func (*Graph) GetForEachIterations ¶
GetForEachIterations returns all expanded iteration names for a base action name. Returns nil if the action is not a forEach action or doesn't exist.
func (*Graph) GetMainActionNames ¶
GetMainActionNames returns only the main section action names.
func (*Graph) TotalFinallyPhases ¶
TotalFinallyPhases returns the total number of execution phases for finally actions.
func (*Graph) TotalPhases ¶
TotalPhases returns the total number of execution phases for main actions.
type GraphVisualization ¶
type GraphVisualization struct {
// Phases contains main action phases for visualization.
Phases []*VisualizationPhase `json:"phases" yaml:"phases"`
// FinallyPhases contains finally action phases.
FinallyPhases []*VisualizationPhase `json:"finallyPhases,omitempty" yaml:"finallyPhases,omitempty"`
// Edges represents dependencies between actions.
Edges []*VisualizationEdge `json:"edges" yaml:"edges"`
// Stats contains graph statistics.
Stats *VisualizationStats `json:"stats" yaml:"stats"`
}
GraphVisualization holds visualization data for rendering.
func BuildVisualization ¶
func BuildVisualization(graph *Graph) *GraphVisualization
BuildVisualization creates visualization data from a Graph.
func (*GraphVisualization) RenderASCII ¶
func (v *GraphVisualization) RenderASCII(w io.Writer) error
RenderASCII generates ASCII art representation of the action graph.
func (*GraphVisualization) RenderDOT ¶
func (v *GraphVisualization) RenderDOT(w io.Writer) error
RenderDOT generates GraphViz DOT format.
func (*GraphVisualization) RenderMermaid ¶
func (v *GraphVisualization) RenderMermaid(w io.Writer) error
RenderMermaid generates Mermaid diagram format.
type HTTPError ¶
HTTPError represents an HTTP error with a status code. Providers can return this error type to enable status code-based retry logic.
type NoOpProgressCallback ¶
type NoOpProgressCallback struct{}
NoOpProgressCallback is a progress callback that does nothing. Useful for testing or when progress tracking is not needed.
func (NoOpProgressCallback) OnActionCancelled ¶
func (NoOpProgressCallback) OnActionCancelled(_ string)
func (NoOpProgressCallback) OnActionComplete ¶
func (NoOpProgressCallback) OnActionComplete(_ string, _ any)
func (NoOpProgressCallback) OnActionFailed ¶
func (NoOpProgressCallback) OnActionFailed(_ string, _ error)
func (NoOpProgressCallback) OnActionSkipped ¶
func (NoOpProgressCallback) OnActionSkipped(_, _ string)
func (NoOpProgressCallback) OnActionStart ¶
func (NoOpProgressCallback) OnActionStart(_ string)
func (NoOpProgressCallback) OnActionTimeout ¶
func (NoOpProgressCallback) OnActionTimeout(_ string, _ time.Duration)
func (NoOpProgressCallback) OnFinallyComplete ¶
func (NoOpProgressCallback) OnFinallyComplete()
func (NoOpProgressCallback) OnFinallyStart ¶
func (NoOpProgressCallback) OnFinallyStart()
func (NoOpProgressCallback) OnForEachProgress ¶
func (NoOpProgressCallback) OnForEachProgress(_ string, _, _ int)
func (NoOpProgressCallback) OnPhaseComplete ¶
func (NoOpProgressCallback) OnPhaseComplete(_ int)
func (NoOpProgressCallback) OnPhaseStart ¶
func (NoOpProgressCallback) OnPhaseStart(_ int, _ []string)
func (NoOpProgressCallback) OnRetryAttempt ¶
func (NoOpProgressCallback) OnRetryAttempt(_ string, _, _ int, _ error)
type ProgressCallback ¶
type ProgressCallback interface {
// OnActionStart is called when an action begins execution.
OnActionStart(actionName string)
// OnActionComplete is called when an action completes successfully.
OnActionComplete(actionName string, results any)
// OnActionFailed is called when an action fails.
OnActionFailed(actionName string, err error)
// OnActionSkipped is called when an action is skipped.
OnActionSkipped(actionName, reason string)
// OnActionTimeout is called when an action times out.
OnActionTimeout(actionName string, timeout time.Duration)
// OnActionCancelled is called when an action is cancelled.
OnActionCancelled(actionName string)
// OnRetryAttempt is called before each retry attempt.
OnRetryAttempt(actionName string, attempt, maxAttempts int, err error)
// OnForEachProgress is called during forEach execution.
OnForEachProgress(actionName string, completed, total int)
// OnPhaseStart is called when a new execution phase begins.
OnPhaseStart(phase int, actionNames []string)
// OnPhaseComplete is called when an execution phase completes.
OnPhaseComplete(phase int)
// OnFinallyStart is called when the finally section begins.
OnFinallyStart()
// OnFinallyComplete is called when the finally section completes.
OnFinallyComplete()
}
ProgressCallback receives execution events for progress reporting.
type RegistryInterface ¶
type RegistryInterface interface {
// Get retrieves a provider by name.
Get(name string) (provider.Provider, bool)
// Has checks if a provider exists.
Has(name string) bool
}
RegistryInterface defines the provider registry operations needed for validation. This interface allows for mocking in tests.
type RenderOptions ¶
type RenderOptions struct {
// Format specifies the output format: "json" (default) or "yaml".
Format string
// IncludeTimestamp adds a generation timestamp to metadata.
IncludeTimestamp bool
// PrettyPrint enables indented output for readability.
PrettyPrint bool
}
RenderOptions configures rendering behavior.
func DefaultRenderOptions ¶
func DefaultRenderOptions() *RenderOptions
DefaultRenderOptions returns the default rendering options.
type RenderedAction ¶
type RenderedAction struct {
// Name is the action name (may be expanded with index for forEach).
Name string `json:"name" yaml:"name" doc:"Action name" maxLength:"150" example:"deploy[0]"`
// OriginalName is the action name before forEach expansion (if applicable).
OriginalName string `` /* 127-byte string literal not displayed */
// Description provides documentation for the action.
Description string `json:"description,omitempty" yaml:"description,omitempty" doc:"Human-readable description" maxLength:"500"`
// DisplayName is a human-friendly name for UI display.
DisplayName string `json:"displayName,omitempty" yaml:"displayName,omitempty" doc:"Display name for UI" maxLength:"100"`
// Sensitive indicates the action handles sensitive data.
Sensitive bool `json:"sensitive,omitempty" yaml:"sensitive,omitempty" doc:"If true, mask in logs"`
// Provider specifies which action provider to use.
Provider string `json:"provider" yaml:"provider" doc:"Provider name" maxLength:"100" example:"shell"`
// DependsOn lists action names that must complete first.
DependsOn []string `json:"dependsOn,omitempty" yaml:"dependsOn,omitempty" doc:"Dependency list" maxItems:"100"`
// When contains the condition for execution.
// Can be a boolean (already evaluated) or a DeferredValue (requires runtime evaluation).
When any `json:"when,omitempty" yaml:"when,omitempty" doc:"Execution condition (bool or deferred)"`
// OnError defines behavior when this action fails.
OnError string `json:"onError,omitempty" yaml:"onError,omitempty" doc:"Error handling behavior" example:"fail"`
// Timeout is the maximum execution duration as a string.
Timeout string `json:"timeout,omitempty" yaml:"timeout,omitempty" doc:"Max duration" example:"30s"`
// Retry contains retry configuration.
Retry *RenderedRetryConfig `json:"retry,omitempty" yaml:"retry,omitempty" doc:"Retry settings"`
// Inputs contains the action inputs.
// Values are either concrete (materialized) or DeferredValue structs.
Inputs map[string]any `json:"inputs" yaml:"inputs" doc:"Action inputs (may contain deferred values)"`
// Section indicates which workflow section this action belongs to.
Section string `json:"section" yaml:"section" doc:"Workflow section" example:"actions"`
// ForEach contains forEach metadata if this is an expanded iteration.
ForEach *RenderedForEachMetadata `json:"forEach,omitempty" yaml:"forEach,omitempty" doc:"ForEach expansion info"`
}
RenderedAction is a fully rendered action ready for execution.
type RenderedForEachMetadata ¶
type RenderedForEachMetadata struct {
// ExpandedFrom is the original action name before expansion.
ExpandedFrom string `json:"expandedFrom" yaml:"expandedFrom" doc:"Original action name" example:"deploy"`
// Index is the iteration index (0-based).
Index int `json:"index" yaml:"index" doc:"Iteration index" example:"0"`
// Item is the current iteration item value.
Item any `json:"item,omitempty" yaml:"item,omitempty" doc:"Iteration item value"`
// Concurrency is the concurrency limit from the original forEach clause.
Concurrency int `json:"concurrency,omitempty" yaml:"concurrency,omitempty" doc:"Concurrency limit (0=unlimited)"`
// OnError is the error handling behavior for forEach iterations.
OnError string `json:"onError,omitempty" yaml:"onError,omitempty" doc:"ForEach error handling" example:"fail"`
}
RenderedForEachMetadata tracks forEach expansion information in rendered output.
type RenderedGraph ¶
type RenderedGraph struct {
// APIVersion identifies the schema version.
APIVersion string `json:"apiVersion" yaml:"apiVersion" doc:"Schema version" example:"scafctl.oakwood-commons.github.io/v1alpha1"`
// Kind identifies the resource type.
Kind string `json:"kind" yaml:"kind" doc:"Resource kind" example:"ActionGraph"`
// Metadata contains graph-level metadata.
Metadata *RenderedMetadata `json:"metadata,omitempty" yaml:"metadata,omitempty" doc:"Graph metadata"`
// ExecutionOrder contains phases of action names that can run in parallel.
ExecutionOrder [][]string `json:"executionOrder" yaml:"executionOrder" doc:"Parallel execution phases for main actions"`
// FinallyOrder contains phases for the finally section.
FinallyOrder [][]string `json:"finallyOrder,omitempty" yaml:"finallyOrder,omitempty" doc:"Parallel execution phases for finally actions"`
// Actions is a map of all rendered actions keyed by their name.
Actions map[string]*RenderedAction `json:"actions" yaml:"actions" doc:"All actions in the graph"`
}
RenderedGraph is the executor-ready action graph output structure. This is the serializable form that can be consumed by external executors.
func RenderToStruct ¶
func RenderToStruct(graph *Graph, opts *RenderOptions) (*RenderedGraph, error)
RenderToStruct produces a RenderedGraph struct without serializing to bytes. This is useful for programmatic access to the rendered graph.
type RenderedMetadata ¶
type RenderedMetadata struct {
// GeneratedAt is the timestamp when the graph was rendered.
GeneratedAt string `json:"generatedAt,omitempty" yaml:"generatedAt,omitempty" doc:"Render timestamp" example:"2026-01-29T12:00:00Z"`
// TotalActions is the total number of actions in the graph.
TotalActions int `json:"totalActions" yaml:"totalActions" doc:"Total action count" example:"5"`
// TotalPhases is the total number of execution phases (main + finally).
TotalPhases int `json:"totalPhases" yaml:"totalPhases" doc:"Total phase count" example:"3"`
// HasFinally indicates if the graph has finally actions.
HasFinally bool `json:"hasFinally" yaml:"hasFinally" doc:"Whether finally section exists"`
// ForEachExpansions maps original action names to their expanded names.
ForEachExpansions map[string][]string `json:"forEachExpansions,omitempty" yaml:"forEachExpansions,omitempty" doc:"ForEach expansion mapping"`
}
RenderedMetadata contains graph-level metadata.
type RenderedRetryConfig ¶
type RenderedRetryConfig struct {
// MaxAttempts is the total number of execution attempts.
MaxAttempts int `json:"maxAttempts" yaml:"maxAttempts" doc:"Total attempts" minimum:"1" example:"3"`
// Backoff defines the delay strategy between retries.
Backoff string `json:"backoff,omitempty" yaml:"backoff,omitempty" doc:"Backoff strategy" example:"exponential"`
// InitialDelay is the delay before the first retry.
InitialDelay string `json:"initialDelay,omitempty" yaml:"initialDelay,omitempty" doc:"Initial delay" example:"1s"`
// MaxDelay caps the maximum delay between retries.
MaxDelay string `json:"maxDelay,omitempty" yaml:"maxDelay,omitempty" doc:"Max delay cap" example:"30s"`
}
RenderedRetryConfig is the serializable retry configuration.
type ResultSchemaMode ¶
type ResultSchemaMode string
ResultSchemaMode defines the validation behavior when result schema validation fails.
const ( // ResultSchemaModeError fails the action when schema validation fails (default). ResultSchemaModeError ResultSchemaMode = "error" // ResultSchemaModeWarn logs a warning and continues execution. ResultSchemaModeWarn ResultSchemaMode = "warn" // ResultSchemaModeIgnore skips schema validation entirely. ResultSchemaModeIgnore ResultSchemaMode = "ignore" )
func (ResultSchemaMode) IsValid ¶
func (m ResultSchemaMode) IsValid() bool
IsValid returns true if the result schema mode is valid.
func (ResultSchemaMode) OrDefault ¶
func (m ResultSchemaMode) OrDefault() ResultSchemaMode
OrDefault returns the mode or the default (ResultSchemaModeError) if empty.
type RetryCallback ¶
type RetryCallback interface {
// OnRetryAttempt is called before each retry attempt (not for the initial attempt).
// attempt is 1-indexed (first retry is attempt 2).
// err is the error from the previous attempt.
OnRetryAttempt(actionName string, attempt, maxAttempts int, err error)
}
RetryCallback receives retry events for progress reporting.
type RetryConfig ¶
type RetryConfig struct {
// MaxAttempts is the total number of execution attempts (including initial).
// Must be >= 1.
MaxAttempts int `json:"maxAttempts" yaml:"maxAttempts" doc:"Total execution attempts (min: 1)" minimum:"1" example:"3"`
// Backoff defines the delay strategy between retries.
// Default is "fixed".
Backoff BackoffType `json:"backoff,omitempty" yaml:"backoff,omitempty" doc:"Backoff strategy" example:"exponential" default:"fixed"`
// InitialDelay is the delay before the first retry.
// For exponential backoff, subsequent delays are multiplied by 2.
InitialDelay *duration.Duration `json:"initialDelay,omitempty" yaml:"initialDelay,omitempty" doc:"Delay before first retry" example:"1s"`
// MaxDelay caps the maximum delay between retries.
// Only meaningful for linear and exponential backoff.
MaxDelay *duration.Duration `json:"maxDelay,omitempty" yaml:"maxDelay,omitempty" doc:"Maximum delay between retries" example:"30s"`
// RetryIf is a CEL expression that determines whether a retry should occur.
// The expression has access to __error context with error details:
// - __error.message: Error message string
// - __error.type: Error type ("http", "exec", "timeout", "validation", "unknown")
// - __error.statusCode: HTTP status code (0 if not HTTP)
// - __error.exitCode: Process exit code (0 if not exec)
// - __error.attempt: Current attempt number (1-based)
// - __error.maxAttempts: Maximum configured attempts
// If not specified, all errors are retried (default behavior).
// If specified and evaluates to false, no retry occurs.
// Example: "${ __error.statusCode == 429 || __error.statusCode >= 500 }"
RetryIf *celexp.Expression `json:"retryIf,omitempty" yaml:"retryIf,omitempty" doc:"CEL expression to determine if retry should occur"`
}
RetryConfig defines automatic retry behavior for failed actions.
type RetryExecutor ¶
type RetryExecutor struct {
// contains filtered or unexported fields
}
RetryExecutor wraps action execution with retry logic and backoff strategies. It handles transient failures by retrying the action up to maxAttempts times with configurable delays between attempts.
func NewRetryExecutor ¶
func NewRetryExecutor(config *RetryConfig) *RetryExecutor
NewRetryExecutor creates a new retry executor with the given configuration. If config is nil, returns an executor that performs no retries (single attempt).
func (*RetryExecutor) CalculateDelay ¶
func (r *RetryExecutor) CalculateDelay(attempt int) time.Duration
CalculateDelay computes the delay before a retry attempt based on the backoff strategy. attempt is 1-indexed (first retry is attempt 2, since attempt 1 is the initial execution). Returns 0 for the first attempt or if no retry config is set.
func (*RetryExecutor) ExecuteWithRetry ¶
func (r *RetryExecutor) ExecuteWithRetry( ctx context.Context, actionName string, execute ExecuteFunc, callback RetryCallback, ) (*provider.Output, error)
ExecuteWithRetry runs an action with retry support. It executes the action up to maxAttempts times, with delays between retries based on the configured backoff strategy.
Parameters: - ctx: Context for cancellation and timeout - actionName: Name of the action (for callbacks) - execute: Function that performs the actual action execution - callback: Optional callback for retry events (can be nil)
Returns the output from a successful execution or the last error if all attempts fail.
func (*RetryExecutor) ExecuteWithRetryDetailed ¶
func (r *RetryExecutor) ExecuteWithRetryDetailed( ctx context.Context, actionName string, execute ExecuteFunc, callback RetryCallback, ) *RetryResult
ExecuteWithRetryDetailed runs an action with retry support and returns detailed results. This is useful for debugging and detailed progress reporting.
func (*RetryExecutor) MaxAttempts ¶
func (r *RetryExecutor) MaxAttempts() int
MaxAttempts returns the maximum number of execution attempts. Returns 1 if no config is set (no retries).
func (*RetryExecutor) ShouldRetry ¶
ShouldRetry determines if an execution should be retried based on the error and attempt number. Returns (shouldRetry, error). The error is non-nil if retryIf expression evaluation fails. Returns false if: - No retry config is set - Max attempts reached - Context was cancelled - The error is nil (success) - retryIf expression evaluates to false
func (*RetryExecutor) WithJitter ¶
func (r *RetryExecutor) WithJitter(fn func(time.Duration) time.Duration) *RetryExecutor
WithJitter sets a custom jitter function for testing. The jitter function receives the base delay and returns a modified delay.
type RetryResult ¶
type RetryResult struct {
// Output is the successful output (nil if all attempts failed)
Output *provider.Output
// Attempts is the total number of attempts made
Attempts int
// TotalDuration is the total time spent including delays
TotalDuration time.Duration
// FinalError is the error from the last attempt (nil if succeeded)
FinalError error
// AttemptErrors contains errors from each attempt
AttemptErrors []error
}
RetryResult contains information about a retry execution.
type SkipReason ¶
type SkipReason string
SkipReason indicates why an action was skipped.
const ( // SkipReasonCondition indicates the when condition evaluated to false. SkipReasonCondition SkipReason = "condition" // SkipReasonDependencyFailed indicates a required dependency failed. SkipReasonDependencyFailed SkipReason = "dependency-failed" )
type ValidationError ¶
type ValidationError struct {
// Section is the workflow section where the error occurred ("actions" or "finally").
Section string `json:"section,omitempty" yaml:"section,omitempty" doc:"Workflow section (actions or finally)" example:"actions"`
// ActionName is the name of the action with the validation error.
ActionName string `json:"actionName,omitempty" yaml:"actionName,omitempty" doc:"Action that failed validation" example:"deploy"`
// Field is the specific field that failed validation.
Field string `json:"field,omitempty" yaml:"field,omitempty" doc:"Field that failed validation" example:"dependsOn"`
// Message is the human-readable validation error message.
Message string `json:"message" yaml:"message" doc:"Validation failure message" maxLength:"500"`
}
ValidationError provides detailed validation failure information. It contains context about where the validation error occurred.
func (*ValidationError) Error ¶
func (e *ValidationError) Error() string
Error implements the error interface.
type VisualizationEdge ¶
type VisualizationEdge struct {
From string `json:"from" yaml:"from"`
To string `json:"to" yaml:"to"`
Label string `json:"label,omitempty" yaml:"label,omitempty"`
}
VisualizationEdge represents a dependency edge.
type VisualizationPhase ¶
type VisualizationPhase struct {
Phase int `json:"phase" yaml:"phase"`
Actions []string `json:"actions" yaml:"actions"`
Section string `json:"section" yaml:"section"` // "actions" or "finally"
}
VisualizationPhase represents a phase in the execution order.
type VisualizationStats ¶
type VisualizationStats struct {
TotalActions int `json:"totalActions" yaml:"totalActions"`
TotalPhases int `json:"totalPhases" yaml:"totalPhases"`
MaxParallelism int `json:"maxParallelism" yaml:"maxParallelism"`
AvgDependencies float64 `json:"avgDependencies" yaml:"avgDependencies"`
HasFinally bool `json:"hasFinally" yaml:"hasFinally"`
ForEachCount int `json:"forEachCount" yaml:"forEachCount"`
}
VisualizationStats contains graph statistics.
type Workflow ¶
type Workflow struct {
// Actions is a map of action definitions that execute based on their dependencies.
// Actions can depend on other actions and access their results via __actions.<name>.results.
Actions map[string]*Action `json:"actions,omitempty" yaml:"actions,omitempty" doc:"Action definitions keyed by name"`
// Finally is a map of actions that execute after all regular actions complete.
// Finally actions cannot use dependsOn to reference regular actions, but can
// access all regular action results. They have an implicit dependency on all regular actions.
Finally map[string]*Action `json:"finally,omitempty" yaml:"finally,omitempty" doc:"Cleanup/finalization actions that run after all regular actions"`
// ResultSchemaMode sets the default validation behavior for resultSchema across all actions.
// Individual actions can override this setting. Default is "error".
ResultSchemaMode ResultSchemaMode `` /* 143-byte string literal not displayed */
}
Workflow contains the action execution specification. It defines two sections: regular actions that execute based on dependencies, and finally actions that execute after all regular actions complete.