Skip to content

Bug: CI hooks fire only once in --all mode, producing summary for last component only #2397

Description

@cfsb-jrose

Describe the Bug

Description

When running atmos terraform plan --all --stack <stack>, the CI summary hooks (after.terraform.plan) fire only once after all components have been processed, rather than once per component. This results in the GitHub step summary ($GITHUB_STEP_SUMMARY) containing output for only the last component in the dependency order, instead of per-component summaries with IaC change status badges.

Root Cause

The CI hooks are registered in the Cobra command layer (cmd/terraform/plan.go) via PostRunE, which fires a single time after RunE completes:

// cmd/terraform/plan.go
PostRunE: func(cmd *cobra.Command, args []string) error {
    return runHooksWithOutput(h.AfterTerraformPlan, cmd, args, capturedPlanOutput)
},

In --all mode, RunE calls ExecuteTerraformAll() → executeInDependencyOrder() → executeTerraformForNode() → ExecuteTerraform() for each component. The info struct is mutated by updateInfoFromNode() for each component, so by the time PostRunE fires:

  1. info.Component / info.Stack reflect only the last processed component
  2. capturedPlanOutput contains the combined stdout of all components (via the shared stdoutBuf), but the CI plugin's onAfterPlan handler parses it as if it belongs to a single component

Relevant code path:

  • cmd/terraform/plan.go:103 — single PostRunE call
  • internal/exec/terraform_executor.go:103 — updateInfoFromNode mutates shared info
  • internal/exec/terraform_executor.go:123 — executeNodeCommand calls ExecuteTerraform without any CI hook invocation
  • pkg/hooks/hooks.go:151 — RunCIHooks receives stale single-component context

Expected Behavior

When running atmos terraform plan --all --stack <stack> with CI enabled, each component should produce its own entry in $GITHUB_STEP_SUMMARY using the CI templates (e.g., plan.md). For example, with 5 components in the stack, the summary should contain 5 sections with per-component badges (PLAN-CREATE, PLAN-CHANGE, NO_CHANGE, etc.) and resource change details.

Actual Behavior

Only the last component in the dependency order gets a summary entry (or the combined output is misattributed to it). The other components' plan results are lost from the summary.

Steps to Reproduce

  1. Configure a stack with multiple terraform components that have depends_on relationships
  2. Enable CI in atmos.yaml:
    ci:
      enabled: true
      summary:
        enabled: true
      templates:
        base_path: "ci/templates"
        terraform:
          plan: "plan.md"
  3. Run in a GitHub Actions workflow:
    atmos terraform plan --all --stack my-stack --ci
  4. Check the GitHub job summary — only the last component has a summary entry

Suggested Fix

Fire CI hooks per-component inside executeTerraformForNode (or executeNodeCommand) rather than relying on the single PostRunE call. This requires:

  1. Detecting CI mode in executeNodeCommand
  2. Passing WithStdoutCapture / WithStderrCapture options to ExecuteTerraform per-component
  3. Calling RunCIHooks after each component completes with that component's captured output and correct info.Component / info.Stack
  4. Suppressing the PostRunE CI hook call when --all mode was used (to avoid double-firing for the last component)

Alternatively, ExecuteTerraformAll could accept a callback/hook interface to fire per-node completion events.

Screenshots

No response

Environment

  • Atmos version: v1.217.0
  • CI platform: GitHub Actions
  • Mode: atmos terraform plan --all --stack <stack> --ci

Additional Context

Related

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bug🐛 An issue with the system

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions