Dry-Run Tutorial#

This tutorial covers using --dry-run to preview what a solution execution would do without performing any side effects.

Overview#

Dry-run mode resolves all values and builds an action execution plan, but never executes actions. This gives you a complete picture of what would happen:

flowchart LR
  A["Solution<br/>(.yaml)"] --> B["Dry-Run Generator<br/>⚠️ No side effects!"] --> C["Report<br/>(resolvers, actions, phases)"]

When to Use Dry-Run#

Use CaseScenario
Pre-flight checkVerify all resolvers produce expected values before executing actions
Action plan reviewSee the execution order, phases, and dependencies before running
CI validationAssert resolver outputs in a pipeline without side effects
DebuggingUnderstand why a solution behaves unexpectedly by inspecting resolved values
DocumentationGenerate a report of what a solution does for review or audit

CLI Usage#

Dry-Run a Full Solution#

scafctl run solution -f solution.yaml --dry-run
scafctl run solution -f solution.yaml --dry-run

This resolves all values and shows the action plan without executing any actions.

Dry-Run with JSON Output#

scafctl run solution -f solution.yaml --dry-run -o json
scafctl run solution -f solution.yaml --dry-run -o json

Returns a structured JSON report with resolver values, action plan, phases, and warnings.

Dry-Run with Verbose Output#

scafctl run solution -f solution.yaml --dry-run --verbose
scafctl run solution -f solution.yaml --dry-run --verbose

Adds materialized inputs to each action in the report, showing exactly what values were resolved for each provider.

Example Walkthrough#

Step 1: Inspect the Example Solution#

cat examples/dryrun/basic-dryrun.yaml

This solution has four resolvers (greeting, target, port, endpoint) and two actions (greet, deploy).

Step 2: Run Dry-Run#

scafctl run solution -f examples/dryrun/basic-dryrun.yaml --dry-run
scafctl run solution -f examples/dryrun/basic-dryrun.yaml --dry-run

The output shows:

  • WhatIf messages — Each action’s provider-generated description of what it would do (e.g., Would execute command echo Hello via bash)
  • Action Plan — Execution order (greet in phase 1, deploy in phase 2 after greet)
  • No side effects — The echo commands are never executed

Step 3: JSON Output for Automation#

scafctl run solution -f examples/dryrun/basic-dryrun.yaml --dry-run -o json | jq .
scafctl run solution -f examples/dryrun/basic-dryrun.yaml --dry-run -o json | ConvertFrom-Json

The JSON report contains:

{
  "dryRun": true,
  "solution": "dryrun-demo",
  "version": "1.0.0",
  "hasWorkflow": true,
  "actionPlan": [
    {
      "name": "greet",
      "provider": "exec",
      "wouldDo": "Would execute command echo Hello, World! via bash",
      "phase": 1,
      "section": "actions"
    },
    {
      "name": "deploy",
      "provider": "exec",
      "wouldDo": "Would execute command ./deploy.sh via bash",
      "phase": 2,
      "section": "actions",
      "dependencies": ["greet"]
    }
  ],
  "totalActions": 2,
  "totalPhases": 2
}

Step 4: Conditional Actions#

scafctl run solution -f examples/dryrun/conditional-dryrun.yaml --dry-run -o json
scafctl run solution -f examples/dryrun/conditional-dryrun.yaml --dry-run -o json

This example shows how dry-run reports conditional (when) actions and finally blocks. The action plan includes the when expression so you can see which conditions will be evaluated at runtime.

Dry-Run Report Structure#

FieldDescription
dryRunAlways true
solutionSolution name from metadata
versionSolution version
hasWorkflowWhether the solution defines a workflow
actionPlanOrdered list of WhatIf actions with phase, provider, whatIf message, dependencies
totalActionsTotal number of actions
totalPhasesTotal execution phases
warningsIssues like graph build failures

WhatIf Action Fields#

FieldDescription
nameAction name
providerProvider name
wouldDoProvider-generated description of what this action would do
phaseExecution phase number
sectionWorkflow section (actions or finally)
descriptionAction description (if set)
dependenciesActions this depends on
whenConditional expression (if set)
materializedInputsResolved inputs (only with --verbose)
deferredInputsInputs deferred until runtime

Using with Snapshots#

Dry-run shows what would happen; snapshots capture what did happen. Combine them:

# Preview what will happen
scafctl run solution -f solution.yaml --dry-run -o json > plan.json

# Execute and capture the result
scafctl run resolver -f solution.yaml --snapshot --snapshot-file=actual.json

# Compare plan vs actual if needed
# Preview what will happen
scafctl run solution -f solution.yaml --dry-run -o json > plan.json

# Execute and capture the result
scafctl run resolver -f solution.yaml --snapshot --snapshot-file=actual.json

# Compare plan vs actual if needed

CI Pipeline Integration#

Use dry-run in CI to validate solutions without side effects:

# Verify all resolvers resolve successfully
output=$(scafctl run solution -f solution.yaml --dry-run -o json)
warnings=$(echo "$output" | jq '.warnings | length')

if [ "$warnings" -gt 0 ]; then
  echo "Dry-run reported warnings:"
  echo "$output" | jq '.warnings[]'
  exit 1
fi
# Verify all resolvers resolve successfully
$output = scafctl run solution -f solution.yaml --dry-run -o json
$parsed = $output | ConvertFrom-Json
$warnings = $parsed.warnings.Count

if ($warnings -gt 0) {
  Write-Output "Dry-run reported warnings:"
  $parsed.warnings
  exit 1
}

Working Directory Override#

Use --cwd (-C) to run a dry-run against a solution in a different directory:

# Dry-run a solution from another directory
scafctl --cwd /path/to/project dryrun -f solution.yaml

# Short form
scafctl -C /path/to/project dryrun -f solution.yaml -o json
# Dry-run a solution from another directory
scafctl --cwd /path/to/project dryrun -f solution.yaml

# Short form
scafctl -C /path/to/project dryrun -f solution.yaml -o json

All relative paths in the solution (file references, templates, etc.) resolve against the --cwd directory.

See Also#