Documentation
¶
Overview ¶
Package workflow implements the ssmx workflow DSL: parsing, validation, expression resolution, DAG execution, and shell step dispatch.
Index ¶
- func AlwaysTrueWarnings(steps map[string]*Step) []string
- func EvalBool(s string, ctx ExprContext) (bool, error)
- func Levels(steps map[string]*Step) ([][]string, error)
- func List() ([]string, error)
- func Resolve(s string, ctx ExprContext) (string, error)
- func ResolveWorkflow(run, runFile string, docParams map[string]string) (*Workflow, *SourceMeta, error)
- type Engine
- type ExprContext
- type FleetEngine
- type FleetRunSummary
- type Input
- type OnFailure
- type RunOptions
- type RunSummary
- type Secret
- type SourceKind
- type SourceMeta
- type Step
- type StepResult
- type StepSummary
- type TargetInfo
- type Targets
- type Workflow
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func AlwaysTrueWarnings ¶
AlwaysTrueWarnings returns human-readable warning messages for risky always: true step patterns. A warning is emitted for each step C that:
- depends directly on an always: true step A
- A has predecessors (A.Needs is non-empty)
- C does not explicitly list all of A's predecessors in its own needs
- C is not itself always: true
This pattern is risky because A runs regardless of whether its predecessors succeeded. If A succeeds after a predecessor failed, C will see A as satisfied and run even though the workflow is in a bad state.
func EvalBool ¶
func EvalBool(s string, ctx ExprContext) (bool, error)
EvalBool resolves all ${{ }} in s then evaluates the result as a boolean. Supported forms:
${{ inputs.flag }} truthy when resolved value is "true" or "1"
!${{ inputs.flag }} unary negation — inverts the inner result
${{ inputs.env }} == prod true when both sides are equal (string)
${{ inputs.env }} != prod true when both sides differ (string)
Compound expressions (&&, ||, parentheses) are not supported.
func Levels ¶
Levels returns groups of step names that can execute concurrently. Steps within the same group have no dependency on each other. All steps in a group must complete before the next group starts.
Uses Kahn's topological sort algorithm. Returns an error if any needs reference is undefined or a dependency cycle is detected. Returns nil, nil for empty input.
func List ¶
List returns all available workflow names, deduplicated with project-local taking precedence over personal on name collision.
func Resolve ¶
func Resolve(s string, ctx ExprContext) (string, error)
Resolve replaces all ${{ expr }} occurrences in s with their resolved string values. Returns an error if any expression references an unknown or unset field.
func ResolveWorkflow ¶ added in v0.2.1
func ResolveWorkflow(run, runFile string, docParams map[string]string) (*Workflow, *SourceMeta, error)
ResolveWorkflow resolves the active workflow from --run / --run-file flag values.
Resolution order:
- runFile non-empty → load from file (or stdin when "-")
- run starts with "doc:" → synthesize a single-step doc workflow; docParams are baked into Step.Params so callers must pass empty Inputs to RunOptions
- otherwise → discover by name via Load
Types ¶
type Engine ¶
type Engine struct {
// contains filtered or unexported fields
}
Engine executes workflows against a single target instance.
func New ¶
func New(cfg aws.Config, instanceID, name, privateIP, region, profile string, docAliases map[string]string) *Engine
New creates an Engine targeting instanceID.
func (*Engine) Run ¶
func (e *Engine) Run(ctx context.Context, wf *Workflow, opts RunOptions) (map[string]string, *RunSummary, error)
Run executes wf against the engine's target instance. It validates inputs, builds the DAG, and executes step levels concurrently. The workflow continues through all levels even on failure (to allow always: cleanup steps), then returns the first step error encountered. On success, the resolved workflow outputs are returned (empty map when wf.Outputs is not defined).
type ExprContext ¶
type ExprContext struct {
Inputs map[string]string
Secrets map[string]string // nil until fetched (Plan 2)
Env map[string]string
Steps map[string]*StepResult
Target TargetInfo
// CurrentStdout and CurrentExitCode are only valid when resolving
// outputs: expressions inside a running step.
CurrentStdout string
CurrentExitCode int
}
ExprContext holds all values available for ${{ }} expression resolution.
type FleetEngine ¶
type FleetEngine struct {
// contains filtered or unexported fields
}
FleetEngine runs a workflow concurrently against multiple EC2 instances. Each instance gets its own Engine; output is prefixed with the instance name so concurrent lines stay identifiable.
func NewFleetEngineWithConfig ¶
func NewFleetEngineWithConfig(cfg aws.Config, instances []awsclient.Instance, maxConcurrency int, region, profile string, docAliases map[string]string) *FleetEngine
NewFleetEngineWithConfig creates a FleetEngine for production use. Each per-instance Engine is created from the provided AWS config, region, and profile.
func (*FleetEngine) Run ¶
func (fe *FleetEngine) Run(ctx context.Context, wf *Workflow, opts RunOptions) (*FleetRunSummary, error)
Run executes wf against every instance in the fleet concurrently. Spinners are always disabled (NoSpinner=true) to prevent \r corruption. Output is prefixed with the instance name. A summary line is printed after all instances complete. Per-instance RunSummary values are always collected and returned in the FleetRunSummary regardless of opts.Stderr.
type FleetRunSummary ¶
type FleetRunSummary struct {
Workflow string `json:"workflow"`
Succeeded int `json:"succeeded"`
Failed int `json:"failed"`
Total int `json:"total"`
Instances []RunSummary `json:"instances"`
}
FleetRunSummary captures the aggregate outcome of a fleet workflow execution.
type Input ¶
type Input struct {
Type string `yaml:"type"` // "string", "int", "bool"
Required bool `yaml:"required,omitempty"`
Default any `yaml:"default,omitempty"`
Description string `yaml:"description,omitempty"`
}
Input declares a typed workflow parameter.
type OnFailure ¶
type OnFailure struct {
Workflow string `yaml:"workflow"`
With map[string]any `yaml:"with,omitempty"`
}
OnFailure specifies a rollback workflow to run if a step fails.
type RunOptions ¶
type RunOptions struct {
Inputs map[string]string // from --param key=value flags
DryRun bool
Stderr io.Writer // status output; defaults to os.Stderr
NoSpinner bool // disable animated spinner (e.g. for sub-workflow runs)
}
RunOptions configures a workflow execution.
type RunSummary ¶
type RunSummary struct {
Workflow string `json:"workflow"`
Instance string `json:"instance"`
Success bool `json:"success"`
Outputs map[string]string `json:"outputs,omitempty"`
Steps []StepSummary `json:"steps"`
Error string `json:"error,omitempty"`
}
RunSummary captures the outcome of a single workflow execution on one instance.
type Secret ¶
type Secret struct {
Name string `yaml:"name"`
SSM string `yaml:"ssm"`
Decrypt bool `yaml:"decrypt,omitempty"`
}
Secret declares an SSM Parameter Store reference.
type SourceKind ¶ added in v0.2.1
type SourceKind string
SourceKind identifies how a workflow was obtained.
const ( // SourceKindName is a workflow discovered by name from the search path. SourceKindName SourceKind = "name" // SourceKindFile is a workflow loaded from an explicit file path. SourceKindFile SourceKind = "file" // SourceKindStdin is a workflow read from stdin. SourceKindStdin SourceKind = "stdin" // SourceKindDoc is a workflow synthesized from an SSM document reference. SourceKindDoc SourceKind = "doc" )
type SourceMeta ¶ added in v0.2.1
type SourceMeta struct {
Kind SourceKind
Label string // human-readable label, e.g. "deploy", "/path/wf.yaml", "doc:AWS-RunPatchBaseline"
}
SourceMeta carries metadata about how a workflow was resolved. It is used for user-facing messages (errors, summaries, dry-run labels).
type Step ¶
type Step struct {
// Discriminated step kind — exactly one must be non-zero.
Shell string `yaml:"shell,omitempty"`
SSMDoc string `yaml:"ssm-doc,omitempty"`
Workflow string `yaml:"workflow,omitempty"`
Parallel map[string]*Step `yaml:"parallel,omitempty"`
// Shared execution fields.
Needs []string `yaml:"needs,omitempty"`
If string `yaml:"if,omitempty"`
Always bool `yaml:"always,omitempty"`
Timeout string `yaml:"timeout,omitempty"`
Env map[string]string `yaml:"env,omitempty"`
Outputs map[string]string `yaml:"outputs,omitempty"`
// ssm-doc specific.
Params map[string]string `yaml:"params,omitempty"`
// workflow-step specific.
With map[string]any `yaml:"with,omitempty"`
OnFailure *OnFailure `yaml:"on-failure,omitempty"`
}
Step is one unit of work within a workflow. Exactly one of Shell, SSMDoc, Workflow, or Parallel must be set.
type StepResult ¶
type StepResult struct {
Stdout string
Stderr string
ExitCode int
Success bool
Skipped bool
Outputs map[string]string
DocName string // resolved SSM document name (ssm-doc steps only)
DocAlias string // alias used, if any (ssm-doc steps only)
}
StepResult holds the outcome of a completed step.
type StepSummary ¶
type StepSummary struct {
Name string `json:"name"`
Success bool `json:"success"`
Skipped bool `json:"skipped"`
Exit int `json:"exit_code,omitempty"`
Stdout string `json:"stdout,omitempty"`
Stderr string `json:"stderr,omitempty"`
DocName string `json:"doc,omitempty"`
DocAlias string `json:"doc_alias,omitempty"`
}
StepSummary captures the outcome of a single step execution.
type TargetInfo ¶
TargetInfo holds per-instance metadata available as ${{ target.* }}.
type Targets ¶
type Targets struct {
Tags map[string]string `yaml:"tags,omitempty"`
InstanceIDs []string `yaml:"instance-ids,omitempty"`
MaxConcurrency int `yaml:"max-concurrency,omitempty"`
}
Targets defines default fleet targeting for a workflow.
type Workflow ¶
type Workflow struct {
Name string `yaml:"name"`
Description string `yaml:"description,omitempty"`
Version string `yaml:"version,omitempty"`
Targets *Targets `yaml:"targets,omitempty"`
Inputs map[string]*Input `yaml:"inputs,omitempty"`
Secrets []*Secret `yaml:"secrets,omitempty"`
Env map[string]string `yaml:"env,omitempty"`
Steps map[string]*Step `yaml:"steps"`
Outputs map[string]string `yaml:"outputs,omitempty"`
}
Workflow is the parsed form of a .ssmx/workflows/*.yaml file.
func Load ¶
Load finds and parses a workflow by name. Project-local (.ssmx/workflows/<name>.yaml) takes precedence over personal (~/.ssmx/workflows/<name>.yaml). Pass "-" as name to read from stdin.
func LoadFile ¶
LoadFile reads and parses a workflow from an explicit file path. Pass "-" to read from stdin — same as Load("-").
func SynthesizeDocWorkflow ¶ added in v0.2.1
SynthesizeDocWorkflow builds a single-step workflow from an SSM document reference. The docRef should be "doc:<name-or-alias>". docParams map directly to the step's ssm-doc params and are deep-copied.
The synthesized workflow has no declared inputs: parameter values are baked into Step.Params at synthesis time. Callers must pass empty Inputs to RunOptions to avoid ApplyInputs rejecting unknown keys.
func (*Workflow) ApplyInputs ¶
ApplyInputs validates that all required inputs are provided, applies defaults for omitted optional inputs, and returns the resolved input map.