dryrun

package
v0.7.0 Latest Latest
Warning

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

Go to latest
Published: Apr 6, 2026 License: Apache-2.0 Imports: 7 Imported by: 0

README

dryrun — Structured WhatIf Report Generation

Package dryrun generates structured WhatIf reports for scafctl solutions, showing what a solution execution would do without performing any side effects.

Features

  • WhatIf messages — Each action includes a provider-generated description of what it would do with real resolved inputs (e.g., Would execute command "./deploy.sh" via bash in /app)
  • Real resolver data — Resolvers execute normally (they're side-effect-free), providing real data for accurate WhatIf messages
  • Action plan — Builds an execution-order action plan with phase assignments, WhatIf descriptions, deferred inputs, and dependencies
  • Verbose mode — Optionally includes MaterializedInputs for detailed inspection
  • Warnings — Collects issues like graph build failures
  • JSON/YAML-friendly — All types carry json and yaml struct tags for serialization

API

Types
// Report is the full structured WhatIf dry-run output.
type Report struct {
    DryRun       bool
    Solution     string
    Version      string
    HasWorkflow  bool
    ActionPlan   []WhatIfAction
    TotalActions int
    TotalPhases  int
    Warnings     []string
}

// WhatIfAction describes a single action in the WhatIf plan.
type WhatIfAction struct {
    Name               string
    Provider           string
    Description        string
    WhatIf             string            // Provider-generated description
    Phase              int
    Section            string            // "actions" or "finally"
    Dependencies       []string
    When               string
    MaterializedInputs map[string]any    // Only when Verbose is true
    DeferredInputs     map[string]string
}

// Options controls the dry-run generation.
type Options struct {
    Registry     *provider.Registry
    ResolverData map[string]any
    Verbose      bool
}
Functions
Generate(ctx context.Context, sol *solution.Solution, opts Options) (*Report, error)

Builds a structured WhatIf report from a solution and pre-executed resolver data.

Important: Callers must execute resolvers normally before calling Generate and pass the results via Options.ResolverData. Resolvers are side-effect-free, so they should run with real execution (not mocked). The function uses the real resolver data to generate accurate WhatIf messages by calling each provider's DescribeWhatIf method.

// 1. Execute resolvers normally (they're side-effect-free)
resolverData := executeResolvers(ctx, sol, params, registry)

// 2. Generate the WhatIf report
report, err := dryrun.Generate(ctx, sol, dryrun.Options{
    Registry:     registry,
    ResolverData: resolverData,
    Verbose:      false, // set true to include MaterializedInputs
})
if err != nil {
    return err
}

// 3. Use the report
fmt.Printf("Solution: %s (v%s)\n", report.Solution, report.Version)
fmt.Printf("Actions: %d across %d phases\n", report.TotalActions, report.TotalPhases)
for _, action := range report.ActionPlan {
    fmt.Printf("  What if: [%s] %s\n", action.Name, action.WhatIf)
}

Report Generation Flow

┌──────────────┐     ┌──────────────┐     ┌──────────────┐
│  Execute     │     │  dryrun      │     │   Report     │
│  Resolvers   │────>│  .Generate() │────>│   with       │
│  (real data) │     │              │     │   WhatIf     │
└──────────────┘     └──────┬───────┘     └──────────────┘
                            │
                     ┌──────┴───────┐
                     │ Build action │
                     │ graph, call  │
                     │ DescribeWhat │
                     │ If() per     │
                     │ action       │
                     └──────────────┘

CLI Usage

# WhatIf table output (default)
scafctl run solution -f ./my-solution.yaml --dry-run

# JSON output
scafctl run solution -f ./my-solution.yaml --dry-run -o json

# Verbose mode (includes MaterializedInputs)
scafctl run solution -f ./my-solution.yaml --dry-run --verbose

Testing

go test ./pkg/dryrun/... -v
go test ./pkg/dryrun/... -bench=.

Documentation

Overview

Package dryrun provides structured WhatIf report generation for scafctl solutions.

It coordinates resolver execution (real data, no mocking) and action graph building to produce a unified report showing what a solution execution would do without performing side effects. Each action includes a provider-generated WhatIf message describing the specific operation it would perform with the resolved inputs.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Options

type Options struct {
	// Registry provides provider descriptors for WhatIf message generation.
	Registry *provider.Registry `json:"-" yaml:"-"`
	// ResolverData is the pre-executed resolver data (from real resolver execution).
	// Callers should execute resolvers normally (they are side-effect-free) before
	// calling Generate and pass the results here.
	// If nil, the report will generate WhatIf messages without resolver context.
	ResolverData map[string]any `json:"-" yaml:"-"`
	// Verbose includes MaterializedInputs in the report when true.
	Verbose bool `json:"-" yaml:"-"`
}

Options controls the dry-run generation.

type Report

type Report struct {
	DryRun       bool           `json:"dryRun" yaml:"dryRun" doc:"Whether this is a dry-run report"`
	Solution     string         `json:"solution" yaml:"solution" doc:"Solution name" maxLength:"256" example:"my-solution"`
	Version      string         `json:"version,omitempty" yaml:"version,omitempty" doc:"Solution version" maxLength:"64" example:"1.0.0"`
	HasWorkflow  bool           `json:"hasWorkflow" yaml:"hasWorkflow" doc:"Whether the solution has a workflow"`
	ActionPlan   []WhatIfAction `` /* 133-byte string literal not displayed */
	TotalActions int            `json:"totalActions,omitempty" yaml:"totalActions,omitempty" doc:"Total number of planned actions" maximum:"1000" example:"5"`
	TotalPhases  int            `json:"totalPhases,omitempty" yaml:"totalPhases,omitempty" doc:"Total number of execution phases" maximum:"100" example:"3"`
	Warnings     []string       `json:"warnings,omitempty" yaml:"warnings,omitempty" doc:"Warnings about the dry-run" maxItems:"100"`
}

Report is the full structured WhatIf dry-run output.

func Generate

func Generate(ctx context.Context, sol *solution.Solution, opts Options) (*Report, error)

Generate builds a structured WhatIf dry-run report from a solution and pre-executed resolver data. Callers must execute resolvers (normally, not mocked) themselves and pass the data via Options.ResolverData. For each action, the provider's DescribeWhatIf is called with the materialized inputs to generate a context-specific WhatIf message.

type WhatIfAction added in v0.6.0

type WhatIfAction struct {
	Name        string `json:"name" yaml:"name" doc:"Action name" maxLength:"256" example:"deploy-service"`
	Provider    string `json:"provider" yaml:"provider" doc:"Provider name" maxLength:"128" example:"exec"`
	Description string `` /* 127-byte string literal not displayed */
	// WhatIf is the Go field name because it represents the provider's WhatIf
	// capability ("can this provider describe what it would do?"). The JSON/YAML
	// tag is "wouldDo" to give API consumers a clearer name for the response
	// value ("here's what it would do") vs the internal concept.
	WhatIf             string            `` /* 173-byte string literal not displayed */
	Phase              int               `json:"phase" yaml:"phase" doc:"Execution phase number" maximum:"100" example:"1"`
	Section            string            `json:"section" yaml:"section" doc:"Workflow section (actions or finally)" maxLength:"16" example:"actions"`
	Dependencies       []string          `json:"dependencies,omitempty" yaml:"dependencies,omitempty" doc:"Action dependencies" maxItems:"100"`
	CrossSectionRefs   []string          `` /* 152-byte string literal not displayed */
	When               string            `json:"when,omitempty" yaml:"when,omitempty" doc:"Conditional expression" maxLength:"2048" example:"_.enabled == true"`
	MaterializedInputs map[string]any    `` /* 128-byte string literal not displayed */
	DeferredInputs     map[string]string `json:"deferredInputs,omitempty" yaml:"deferredInputs,omitempty" doc:"Inputs deferred until runtime"`
}

WhatIfAction describes a single action in the WhatIf plan with a provider-generated description of what it would do.

Jump to

Keyboard shortcuts

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