action

package
v0.2.0 Latest Latest
Warning

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

Go to latest
Published: Feb 12, 2026 License: Apache-2.0 Imports: 22 Imported by: 0

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

View Source
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.

View Source
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

func CreateIterationName(baseName string, index int) string

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

func GetDeferredInputNames(values map[string]any) []string

GetDeferredInputNames returns the names of inputs that contain deferred values.

func GetFormat

func GetFormat(format string) (string, error)

GetFormat normalizes and validates the output format string.

func HasDeferredValues

func HasDeferredValues(values map[string]any) bool

HasDeferredValues checks if any values in the map are deferred.

func IsForEachIteration

func IsForEachIteration(name string) bool

IsForEachIteration checks if an action name represents a forEach iteration. Returns true if the name matches the pattern "baseName[index]".

func Materialize

func Materialize(ctx context.Context, v *spec.ValueRef, resolverData map[string]any) (any, error)

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

func ParseIterationName(name string) (baseName string, index int, ok bool)

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 `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)"`
}

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

func (c *Context) ActionCount() int

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

func (c *Context) AllActionNames() []string

AllActionNames returns all action names that have results.

func (*Context) Clone

func (c *Context) Clone() *Context

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

func (c *Context) GetNamespace() map[string]any

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) HasResult

func (c *Context) HasResult(name string) bool

HasResult checks if a result exists for the given action name.

func (*Context) MarkCancelled

func (c *Context) MarkCancelled(name string)

MarkCancelled marks an action as cancelled.

func (*Context) MarkFailed

func (c *Context) MarkFailed(name, errMsg string)

MarkFailed marks an action as failed with an error message.

func (*Context) MarkRunning

func (c *Context) MarkRunning(name string, inputs map[string]any)

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) MarkSucceeded

func (c *Context) MarkSucceeded(name string, results any)

MarkSucceeded marks an action as successfully completed.

func (*Context) MarkTimeout

func (c *Context) MarkTimeout(name string)

MarkTimeout marks an action as timed out.

func (*Context) Reset

func (c *Context) Reset()

Reset clears all stored results and iterations.

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 Duration

type Duration time.Duration

Duration is a wrapper around time.Duration that supports YAML/JSON marshaling.

func (Duration) AsDuration

func (d Duration) AsDuration() time.Duration

AsDuration returns the underlying time.Duration.

func (Duration) MarshalJSON

func (d Duration) MarshalJSON() ([]byte, error)

MarshalJSON implements json.Marshaler for Duration.

func (Duration) MarshalYAML

func (d Duration) MarshalYAML() (any, error)

MarshalYAML implements yaml.Marshaler for Duration.

func (Duration) String

func (d Duration) String() string

String returns the string representation of the duration.

func (*Duration) UnmarshalJSON

func (d *Duration) UnmarshalJSON(b []byte) error

UnmarshalJSON implements json.Unmarshaler for Duration.

func (*Duration) UnmarshalYAML

func (d *Duration) UnmarshalYAML(unmarshal func(any) error) error

UnmarshalYAML implements yaml.Unmarshaler for Duration.

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

type ExecuteFunc func(ctx context.Context) (*provider.Output, error)

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

func (e *Executor) Execute(ctx context.Context, w *Workflow) (*ExecutionResult, error)

Execute runs the workflow actions in dependency order. It executes main actions first, then always runs finally actions regardless of failures.

func (*Executor) GetContext

func (e *Executor) GetContext() *Context

GetContext returns the action context for inspection.

func (*Executor) Reset

func (e *Executor) Reset()

Reset clears the executor state for reuse.

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 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

type ForEachExecuteFunc func(ctx context.Context, item any, index int) (*provider.Output, error)

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

func (g *Graph) GetAllActionNames() []string

GetAllActionNames returns all action names in the graph including expanded forEach names.

func (*Graph) GetFinallyActionNames

func (g *Graph) GetFinallyActionNames() []string

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

func (g *Graph) GetForEachIterations(baseName string) []string

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

func (g *Graph) GetMainActionNames() []string

GetMainActionNames returns only the main section action names.

func (*Graph) TotalFinallyPhases

func (g *Graph) TotalFinallyPhases() int

TotalFinallyPhases returns the total number of execution phases for finally actions.

func (*Graph) TotalPhases

func (g *Graph) TotalPhases() int

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

type HTTPError struct {
	StatusCode int
	Message    string
}

HTTPError represents an HTTP error with a status code. Providers can return this error type to enable status code-based retry logic.

func (*HTTPError) Error

func (e *HTTPError) Error() string

Error implements the error interface.

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 `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 `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

func (r *RetryExecutor) ShouldRetry(ctx context.Context, err error, attempt int) (bool, error)

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.

Jump to

Keyboard shortcuts

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