Skip to content

fix(ci): fire CI hooks per-component in apply --all mode (#2475)#2477

Merged
Andriy Knysh (aknysh) merged 3 commits into
cloudposse:mainfrom
thejrose1984:bugfix/2475/atmos-ci
May 22, 2026
Merged

fix(ci): fire CI hooks per-component in apply --all mode (#2475)#2477
Andriy Knysh (aknysh) merged 3 commits into
cloudposse:mainfrom
thejrose1984:bugfix/2475/atmos-ci

Conversation

@thejrose1984
Copy link
Copy Markdown
Contributor

@thejrose1984 thejrose1984 commented May 22, 2026

Extends the per-component CI hook pattern from PR #2430 (plan --all) to apply --all, so each component produces its own CI summary entry instead of a single misattributed entry for the last component.

what

  • Update apply --all to fire per-component CI hooks.
  • Preserve per-component CI reporting semantics used by plan --all.

why

  • Prevent CI summaries from being misattributed to only the last component.
  • Ensure each component has its own hook and status entry in CI pipelines.

references

Summary by CodeRabbit

  • Bug Fixes

    • Prevented duplicate CI hook firing during multi-component Terraform apply runs.
    • Reset per-run state at apply start so deferred and post-run hooks observe consistent values.
    • Suppressed post-run hook execution for multi-component apply to avoid double execution.
  • Tests

    • Added tests covering CI hook handling and post-run suppression in multi-component apply scenarios.

Review Change Stack

@thejrose1984 thejrose1984 requested a review from a team as a code owner May 22, 2026 02:25
@atmos-pro
Copy link
Copy Markdown
Contributor

atmos-pro Bot commented May 22, 2026

Tip

Atmos Pro  

No affected stacks workflow was detected for this pull request.
If this is expected, no action is needed.
Learn More.

@github-actions github-actions Bot added the size/m Medium size PR label May 22, 2026
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 22, 2026

📝 Walkthrough

Walkthrough

Resets per-run state at apply start, suppresses global deferred/PostRunE hooks during multi-component (--all) runs, and adds per-component CI-hook invocation for Terraform apply; tests cover wrapper invocation, PostRunE suppression, and exit-code forwarding.

Changes

Multi-component apply CI hooks

Layer / File(s) Summary
Global hook suppression for multi-component runs
cmd/terraform/apply.go
Per-run state resets capturedApplyOutput and wasMultiComponentExecution at RunE start. Deferred error-hook invocation is conditioned on runErr != nil && !wasMultiComponentExecution. PostRunE returns nil immediately when wasMultiComponentExecution is true.
Per-component apply hook implementation and wiring
cmd/terraform/utils.go
Adds runCIHooksForApplyComponent to initialize CLI config and call h.RunCIHooks with AfterTerraformApply, passing stripped component output and derived exit code. terraformRunWithOptions sets info.PerComponentHook to this helper for apply subcommands in multi-component mode.
Apply component hook test coverage
cmd/terraform/utils_hooks_test.go
Adds tests: TestRunCIHooksForApplyComponent_DemoStacks, TestApplyPostRunE_SuppressedWhenMultiComponent, and TestRunCIHooksForApplyComponent_ExitCodeForwarding to validate wrapper invocation, PostRunE suppression, and exit-code forwarding across success and error paths.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related issues

Possibly related PRs

  • cloudposse/atmos#2430: Establishes the multi-component CI-hook sentinel pattern with wasMultiComponentExecution and per-component hook wiring that this PR extends from plan to apply mode.
  • cloudposse/atmos#2382: Introduces CI hook options and exit-code forwarding that the new apply hook handler relies on.

Suggested labels

patch

Suggested reviewers

  • aknysh
  • goruha
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely describes the main change: extending per-component CI hook firing to apply --all mode, matching the PR's core objective.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@cmd/terraform/utils_hooks_test.go`:
- Around line 184-196: The test builds a command via newHookTestCmd() which
creates a command with Use: "plan", but the test invokes applyCmd.PostRunE,
causing a mismatch; update the test so the command identity matches apply:
either create a new helper/newHookTestCmd that accepts a use-name and call
newHookTestCmd("apply"), or set cmd.Use = "apply" on the returned command before
calling applyCmd.PostRunE(cmd, ...), ensuring newHookTestCmd(),
applyCmd.PostRunE, and the cmd variable reflect the "apply" command identity.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 1955e1b9-f0a4-4dba-88fa-dc88cc33c577

📥 Commits

Reviewing files that changed from the base of the PR and between 357464e and 3387ad4.

📒 Files selected for processing (3)
  • cmd/terraform/apply.go
  • cmd/terraform/utils.go
  • cmd/terraform/utils_hooks_test.go

Comment thread cmd/terraform/utils_hooks_test.go
thejrose1984 added a commit to thejrose1984/atmos that referenced this pull request May 22, 2026
Addresses CodeRabbit review on PR cloudposse#2477: newHookTestCmd() created a
command with Use:"plan" but the test calls applyCmd.PostRunE, causing
ProcessCommandLineArgs to see the wrong subcommand name in the
non-suppressed path.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
thejrose1984 added a commit to thejrose1984/atmos that referenced this pull request May 22, 2026
Same fix as PR cloudposse#2477: newHookTestCmd() hardcodes Use:"plan" but the
test calls deployCmd.PostRunE, causing ProcessCommandLineArgs to see
the wrong subcommand name in the non-suppressed path.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
thejrose1984 and others added 2 commits May 21, 2026 23:28
…2475)

Extends the per-component hook pattern from PR cloudposse#2430 (plan --all) to
apply --all so each component produces its own CI summary entry instead
of a single misattributed entry for the last component.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Addresses CodeRabbit review on PR cloudposse#2477: newHookTestCmd() created a
command with Use:"plan" but the test calls applyCmd.PostRunE, causing
ProcessCommandLineArgs to see the wrong subcommand name in the
non-suppressed path.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@thejrose1984 thejrose1984 force-pushed the bugfix/2475/atmos-ci branch from 1984411 to a7781e8 Compare May 22, 2026 03:28
thejrose1984 added a commit to thejrose1984/atmos that referenced this pull request May 22, 2026
Same fix as PR cloudposse#2477: newHookTestCmd() hardcodes Use:"plan" but the
test calls deployCmd.PostRunE, causing ProcessCommandLineArgs to see
the wrong subcommand name in the non-suppressed path.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
cmd/terraform/utils_hooks_test.go (1)

156-198: ⚡ Quick win

Initialize cmd.NewTestKit(t) in these new cmd tests.

Please add cmd.NewTestKit(t) at the start of each new test here so command/root state cleanup is consistent with repo test conventions.

As per coding guidelines "cmd/**/*_test.go: ALWAYS use cmd.NewTestKit(t) for cmd tests to auto-clean RootCmd state (flags, args)."

Also applies to: 203-232

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@cmd/terraform/utils_hooks_test.go` around lines 156 - 198, The tests
TestRunCIHooksForApplyComponent_DemoStacks and
TestApplyPostRunE_SuppressedWhenMultiComponent need to call cmd.NewTestKit(t) at
the start to ensure RootCmd state is reset between tests; add a
cmd.NewTestKit(t) invocation as the first statement in each of these test
functions (before t.Chdir and before creating cmd via newHookTestCmd()), so
command/root flags and args are auto-cleaned for tests that exercise
newHookTestCmd(), applyCmd.PostRunE and the wasMultiComponentExecution logic.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@cmd/terraform/utils_hooks_test.go`:
- Around line 156-198: The tests TestRunCIHooksForApplyComponent_DemoStacks and
TestApplyPostRunE_SuppressedWhenMultiComponent need to call cmd.NewTestKit(t) at
the start to ensure RootCmd state is reset between tests; add a
cmd.NewTestKit(t) invocation as the first statement in each of these test
functions (before t.Chdir and before creating cmd via newHookTestCmd()), so
command/root flags and args are auto-cleaned for tests that exercise
newHookTestCmd(), applyCmd.PostRunE and the wasMultiComponentExecution logic.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 6a640242-3b5c-49cf-81a5-712501a1d528

📥 Commits

Reviewing files that changed from the base of the PR and between 1984411 and a7781e8.

📒 Files selected for processing (3)
  • cmd/terraform/apply.go
  • cmd/terraform/utils.go
  • cmd/terraform/utils_hooks_test.go

@codecov
Copy link
Copy Markdown

codecov Bot commented May 22, 2026

Codecov Report

❌ Patch coverage is 64.00000% with 9 lines in your changes missing coverage. Please review.
✅ Project coverage is 78.24%. Comparing base (a0cd286) to head (f621d07).

Files with missing lines Patch % Lines
cmd/terraform/utils.go 61.90% 6 Missing and 2 partials ⚠️
cmd/terraform/apply.go 75.00% 0 Missing and 1 partial ⚠️

❌ Your patch check has failed because the patch coverage (64.00%) is below the target coverage (80.00%). You can increase the patch coverage or adjust the target coverage.

Additional details and impacted files

Impacted file tree graph

@@            Coverage Diff             @@
##             main    #2477      +/-   ##
==========================================
+ Coverage   78.21%   78.24%   +0.03%     
==========================================
  Files        1119     1119              
  Lines      106243   106266      +23     
==========================================
+ Hits        83095    83148      +53     
+ Misses      18509    18483      -26     
+ Partials     4639     4635       -4     
Flag Coverage Δ
unittests 78.24% <64.00%> (+0.03%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

Files with missing lines Coverage Δ
cmd/terraform/apply.go 78.18% <75.00%> (+0.82%) ⬆️
cmd/terraform/utils.go 55.45% <61.90%> (+0.41%) ⬆️

... and 10 files with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

thejrose1984 added a commit to thejrose1984/atmos that referenced this pull request May 22, 2026
Same fix as PR cloudposse#2477: newHookTestCmd() hardcodes Use:"plan" but the
test calls deployCmd.PostRunE, causing ProcessCommandLineArgs to see
the wrong subcommand name in the non-suppressed path.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@thejrose1984
Copy link
Copy Markdown
Contributor Author

Status summary for maintainers

Code state: CodeRabbit APPROVED at the current HEAD f621d070. Full CI matrix has already run — Tests, Build (linux/macos/windows), Acceptance Tests, CodeQL, golangci-lint, Hadolint, and all [mock-*]/[validate] jobs pass.

What's blocking merge:

  1. autofix (atmos.ci) failure — fork-PR infrastructure limitation. The autofix steps (gofumpt, pre-commit whitespace, NOTICE generation, HCL fmt, README regen) all ran successfully. The Commit fixes via Atmos Pro step then failed because Atmos Pro cannot push back to the fork branch. I verified locally with gofumpt/goimports/trailing-whitespace that no actual Go-source changes are needed. maintainerCanModify is true on this PR, so a maintainer can push the autofix changes (if any) directly, or this check needs to be excluded from required status checks for fork PRs.
  2. Missing patch semver label. PR Semver Labels fails because no semver label is set, and I lack AddLabelsToLabelable permission. This is a bug fix (issue Bug: CI hooks fire only once in --all mode, producing summary for last component only #2475) so patch is appropriate.
  3. Human review. Branch protection requires a maintainer review beyond CodeRabbit's bot approval.

Re: the inline nitpick about cmd.NewTestKit(t) — I responded above explaining why it doesn't apply in cmd/terraform (TestKit is in package cmd, not exported across subpackages; CodeRabbit's own prior learning from #1808 confirms this).

@aknysh Andriy Knysh (aknysh) added the patch A minor, backward compatible change label May 22, 2026
Copy link
Copy Markdown
Member

@aknysh Andriy Knysh (aknysh) left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thanks thejrose1984

@aknysh Andriy Knysh (aknysh) merged commit 06a3104 into cloudposse:main May 22, 2026
63 of 65 checks passed
@atmos-pro
Copy link
Copy Markdown
Contributor

atmos-pro Bot commented May 22, 2026

Note

Atmos Pro  

Waiting for your GitHub Actions workflow to upload affected stacks.
Learn More.

@thejrose1984 thejrose1984 deleted the bugfix/2475/atmos-ci branch May 22, 2026 13:44
@github-actions
Copy link
Copy Markdown

These changes were released in v1.220.0-rc.1.

Andriy Knysh (aknysh) added a commit that referenced this pull request May 23, 2026
* fix(ci): fire CI hooks per-component in deploy --all mode (#2476)

Extends the per-component hook pattern from PR #2430 (plan --all) and
#2475 (apply --all) to deploy --all so each component produces its own
CI summary entry instead of a single misattributed entry for the last
component.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* test: clarify exit code 2 label in deploy hook forwarding test

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* test: use deploy command identity in PostRunE suppression test

Same fix as PR #2477: newHookTestCmd() hardcodes Use:"plan" but the
test calls deployCmd.PostRunE, causing ProcessCommandLineArgs to see
the wrong subcommand name in the non-suppressed path.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* test(deploy): add RunE defer-guard regression test

Convert runHooksOnErrorWithOutput to a package-level var so tests can stub it,
and add TestDeployRunE_DeferGuard covering all four branches of the deploy.go
RunE defer-guard contract: non-nil error must fire the global hook only when
wasMultiComponentExecution is false, and nil error must never fire it.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix(ci): repair broken merge from main and refactor tests

The previous merge from main left the branch unbuildable:
- cmd/terraform/utils.go was missing a closing brace on the deploy
  PerComponentHook branch, producing a Go syntax error
- cmd/terraform/utils_hooks_test.go had deploy and apply test bodies
  interleaved with overlapping function declarations and orphaned
  statements

Reconstruct the test file to host both the deploy tests (this PR) and
the apply tests (brought in from main via #2475), and address open
CodeRabbit nitpicks at the same time:

- Add a compile-time sentinel for schema.ConfigAndStacksInfo so a
  field rename surfaces as a build failure
- Convert plan/deploy/apply demo-stacks tests and the deploy RunE
  defer-guard scenarios to table-driven subtests
- Document why cmd.NewTestKit(t) cannot be used here (circular
  import between cmd/terraform and cmd, same workaround the workdir
  tests use)

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* refactor: narrow test changes to deploy scope and fix comment

Code review follow-ups:

- Restore the linear style of plan/apply demo-stacks tests to match
  main; these tests came in via merge and aren't part of this PR's
  scope. Only the deploy demo-stacks test and the deploy RunE
  defer-guard scenarios are refactored to table-driven subtests, per
  the CodeRabbit nitpicks for this PR.
- Update the per-component hook wiring comment in utils.go to read
  "plan, deploy, and apply" now that all three branches are wired.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

---------

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-authored-by: Andriy Knysh <aknysh@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

patch A minor, backward compatible change size/m Medium size PR

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants