workflow

package
v0.2.1 Latest Latest
Warning

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

Go to latest
Published: Apr 22, 2026 License: MIT Imports: 16 Imported by: 0

Documentation

Overview

Package workflow implements the ssmx workflow DSL: parsing, validation, expression resolution, DAG execution, and shell step dispatch.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func AlwaysTrueWarnings

func AlwaysTrueWarnings(steps map[string]*Step) []string

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

func Levels(steps map[string]*Step) ([][]string, error)

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

func List() ([]string, error)

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:

  1. runFile non-empty → load from file (or stdin when "-")
  2. run starts with "doc:" → synthesize a single-step doc workflow; docParams are baked into Step.Params so callers must pass empty Inputs to RunOptions
  3. 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.

func (*Step) Kind

func (s *Step) Kind() string

Kind returns the kind field name that is set ("shell", "ssm-doc", "workflow", "parallel"), or "" if no kind is 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

type TargetInfo struct {
	Name       string
	InstanceID string
	PrivateIP  string
}

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

func Load(name string) (*Workflow, error)

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

func LoadFile(path string) (*Workflow, error)

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

func SynthesizeDocWorkflow(docRef string, docParams map[string]string) *Workflow

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

func (wf *Workflow) ApplyInputs(provided map[string]string) (map[string]string, error)

ApplyInputs validates that all required inputs are provided, applies defaults for omitted optional inputs, and returns the resolved input map.

func (*Workflow) Validate

func (wf *Workflow) Validate() error

Validate checks that the workflow is structurally valid: each step has exactly one kind field set.

Jump to

Keyboard shortcuts

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