Skip to main content

98% Complexity Reduction in describe stacks

· 2 min read
nitrocode
Former Engineer @ Cloud Posse

ExecuteDescribeStacks was the most complex function in the entire Atmos codebase — cyclomatic complexity of 247 and cognitive complexity of 1252. We broke it apart.

What Changed

ExecuteDescribeStacks in internal/exec/describe_stacks.go was a 1,160-line monolith that repeated nearly identical component-processing logic four times — once for each component type (Terraform, Helmfile, Packer, Ansible). The duplication made it impossible to unit test individual behaviours and extremely difficult to reason about.

We extracted the shared logic into a new describe_stacks_component_processor.go file containing:

FunctionResponsibility
describeStacksProcessorImmutable config + mutable result map
processStackFileOrchestrates one stack file
processComponentTypeSectionIterates over all components of one type
processComponentEntryProcesses a single component (shared for all 4 types)
extractDescribeComponentSectionsExtracts vars, metadata, settings, env, auth, …
buildConfigAndStacksInfoBuilds the ConfigAndStacksInfo struct
resolveStackNameManifest name → template → pattern → filename
shouldFilterByStackClean filter predicate
ensureComponentEntryInMapCreates nested map paths safely
setAtmosComponentMetadataStamps atmos_component/stack/stack_file
resolveIncludeEmptyReads atmos.yaml IncludeEmpty setting
addSectionsToComponentEntryWrites filtered sections to output map
processComponentSectionTemplatesGo template processing
processComponentSectionYAMLFunctionsYAML function processing
applyTerraformMetadataInheritanceTerraform-specific metadata inheritance
hasStackExplicitComponentsDetects stacks with components
hasStackImportsDetects stacks with imports
filterEmptyFinalStacksPost-processing pruning
stackHasNonEmptyComponentsChecks for meaningful component content

Why This Matters

Before:

  • ExecuteDescribeStacks: cyclomatic complexity 247, cognitive complexity 1252
  • 1,160 lines of deeply nested, copy-pasted code
  • Practically untestable at a unit level

After:

  • ExecuteDescribeStacks orchestrator: cyclomatic complexity 10
  • Max complexity across all extracted functions: cyclomatic 20, cognitive 22 (processComponentEntry)
  • All pure helper functions covered at ~96% by unit tests (remaining uncovered lines are unreachable defensive type-assertion guards)

How to Use It

The public API is completely unchanged. ExecuteDescribeStacks accepts the same parameters and returns the same map[string]any. No migration is required.

New Unit Tests

80+ unit tests now cover every pure helper function at near-100%:

// Example: testing shouldFilterByStack in isolation
func TestShouldFilterByStack(t *testing.T) {
assert.False(t, shouldFilterByStack("", "stacks/prod.yaml", "prod")) // no filter
assert.False(t, shouldFilterByStack("prod", "stacks/prod.yaml", "prod")) // matches name
assert.True(t, shouldFilterByStack("dev", "stacks/prod.yaml", "prod")) // no match
}

Get Involved

We're continuing to reduce complexity across the codebase. If you spot a function with high complexity, open an issue or PR. Check the contributing guide to get started.