Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Conversation

@aknysh
Copy link
Member

@aknysh aknysh commented Oct 11, 2025

what

  • Fix critical component inheritance regression where metadata.component was being overwritten during configuration inheritance
  • Restore correct default behavior where metadata.component defaults to the Atmos component name when not explicitly set
  • Prevent state file loss: Fix backend configuration to use correct workspace_key_prefix instead of inherited component names

why

  • PR Improve Atmos Auth #1602 introduced a regression in component processing that broke metadata.component handling
  • Critical Impact: Components using abstract component patterns were initializing new empty state files instead of finding existing state
    • When inheriting configuration via metadata.inherits, the system was inadvertently overwriting metadata.component with values from inherited components
    • Backend workspace_key_prefix ended up using the wrong component name (e.g., eks-service-defaults instead of eks-service)
    • This created new state at wrong S3 path, causing terraform plan to show full re-create of all resources
    • Could lead to resource duplication or apply failures due to conflicts
  • This caused errors like: invalid Terraform component: 'eks/n8n' points to the Terraform component 'helm-teleport-helper', but it does not exist

references

testing

  • Added comprehensive regression test in internal/exec/component_inheritance_test.go
    • Tests component that inherits configuration but doesn't set metadata.component
    • Verifies configuration inheritance (vars, settings) works correctly
    • Verifies metadata section is not inherited
    • Verifies component path defaults correctly to the Atmos component name
  • Added backend configuration test in internal/exec/abstract_component_backend_test.go
    • Critical test for backend state issue: Tests component with explicit metadata.component inheriting configuration from abstract component
    • Verifies metadata.component is preserved (not overwritten by inherited component's metadata.component)
    • Verifies backend workspace_key_prefix uses correct component path (e.g., eks-service not eks-service-defaults)
    • Verifies vars inheritance from abstract component works correctly
  • Created test fixtures in tests/fixtures/scenarios/:
    • component-inheritance-without-metadata-component/
    • abstract-component-backend/
  • All existing tests pass
  • Manual testing confirms the fix works correctly

impact

Before (1.194.0 - Broken)

# Abstract component
eks/service/defaults:
  metadata:
    type: abstract
    component: eks-service

# Concrete instance
eks/service/app1:
  metadata:
    component: eks-service
    inherits: [eks/service/defaults]  # Inherit configuration (vars, settings, etc.)

Problem: Processing metadata.inherits overwrote metadata.component

  • Backend ended up using workspace_key_prefix: eks-service-defaults (from inherited component)
  • Created new state at: s3://bucket/eks-service-defaults/...
  • Existing state at: s3://bucket/eks-service/... (not found)
  • Result: terraform plan showed full re-create of all resources ❌

After (This Fix)

Solution: metadata.component is preserved during configuration inheritance

  • Backend correctly uses workspace_key_prefix: eks-service (from explicit metadata.component)
  • Finds existing state at: s3://bucket/eks-service/...
  • Result: terraform plan shows correct incremental changes ✅

details

Key Concepts (Independent)

  1. metadata.component: Pointer to the physical terraform component directory in components/terraform/

    • Defaults to the Atmos component name if not specified
    • Determines the physical directory path for the component
    • Critical: Used to generate backend configuration (e.g., workspace_key_prefix)
    • Completely independent of configuration inheritance
  2. metadata.inherits: List of Atmos components to inherit configuration from (vars, settings, env, backend, etc.)

    • Purely for configuration merging - has nothing to do with component paths
    • The metadata section itself is NOT inherited from base components
    • Allows multiple inheritance for configuration merging
    • Completely independent of metadata.component and Atmos component names
  3. Atmos component name: The logical name of the component in the stack configuration

    • Used as default for metadata.component if not specified
    • Completely independent of configuration inheritance

The Bug

The regression in PR #1602 caused metadata.component to be inadvertently overwritten during configuration inheritance processing:

  1. Component eks/service/app1 has metadata.component: eks-service and metadata.inherits: [eks/service/defaults]
  2. System processes metadata.inherits to merge configuration (vars, settings, etc.) from eks/service/defaults
  3. BUG: During this processing, metadata.component: eks-service gets overwritten with the inherited component's metadata.component value
  4. Result: Component path becomes eks-service-defaults instead of eks-service

The Fix

Modified processMetadataInheritance() in stack_processor_process_stacks_helpers_inheritance.go to:

  • Track whether metadata.component was explicitly set on the current component
  • Process metadata.inherits to inherit vars, settings, backend, etc. (but NOT metadata)
  • Restore the explicitly-set metadata.component after processing inherits (prevents overwriting)
  • Default metadata.component to the Atmos component name when not explicitly set
  • This happens regardless of whether metadata.inherits exists or not

Code Changes

The fix ensures proper handling in three scenarios:

Scenario 1: Component without explicit metadata.component (Fixes #1609)

components:
  terraform:
    eks/n8n:  # Atmos component name
      metadata:
        inherits: [eks/helm-teleport-helper]  # Inherit configuration only
      vars:
        name: "n8n"

✅ Now works: metadata.component defaults to eks/n8n (Atmos component name)
❌ Before: metadata.component was overwritten during configuration inheritance, became helm-teleport-helper (component not found error)

Scenario 2: Component with explicit metadata.component + configuration inheritance (Fixes #1613)

components:
  terraform:
    eks/service/app1:
      metadata:
        component: eks-service  # Explicit - determines physical path
        inherits: [eks/service/defaults]  # Inherit configuration (vars, backend, etc.)

✅ Now works: metadata.component stays eks-service, backend uses correct workspace_key_prefix
❌ Before: metadata.component overwritten to eks-service-defaults during configuration inheritance, new empty state created

Scenario 3: Top-level component: attribute (Also affected by regression)

components:
  terraform:
    test/test-component-override:
      component: test/test-component  # Top-level attribute (not metadata.component)
      # ... configuration ...

✅ Now works: Top-level component: sets the component path, not overwritten by defaults
❌ Before: Default logic was overwriting top-level component inheritance

🤖 Generated with Claude Code

Summary by CodeRabbit

  • Bug Fixes

    • Component inheritance now relies solely on metadata.inherits and preserves top-level component attributes.
    • Default component path/name correctly resolves when metadata.component is absent.
    • Abstract-component backends inherit workspace_key_prefix and backend settings as expected.
    • Improved validation and error handling for metadata.inherits entries.
  • Tests

    • Added scenarios and tests covering abstract-component backends, inheritance without metadata.component, and a guard for certain mock failures.
  • Chores

    • Updated dependency versions.

This fixes a regression introduced in PR #1602 where components with
metadata.inherits but no explicit metadata.component were failing.

## Problem
When a component had:
- metadata.inherits: [base-component]
- NO metadata.component set

Atmos was incorrectly using the inherited component's metadata.component
value instead of defaulting to the component name itself.

## Solution
Modified processMetadataInheritance() to:
- Track whether metadata.component was explicitly set (not inherited)
- Process metadata.inherits to inherit configuration (vars, settings, etc.)
- Always default metadata.component to the component name when not explicitly set
- This happens regardless of whether metadata.inherits exists or not

Key insight: metadata.component is a pointer to the physical terraform
directory and is NOT related to metadata.inherits. The metadata section
itself is per-component and is NOT inherited.

## Changes
- internal/exec/stack_processor_process_stacks_helpers_inheritance.go:
  Fixed processMetadataInheritance to properly default metadata.component
- internal/exec/component_inheritance_test.go: Added regression test
- tests/fixtures/scenarios/component-inheritance-without-metadata-component/:
  Added test fixture

## Testing
- New regression test passes
- All existing describe component tests pass
- All stack processing tests pass
- Manual testing confirms fix works

Fixes #1609

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <[email protected]>
@github-actions github-actions bot added the size/m Medium size PR label Oct 11, 2025
@aknysh aknysh added the no-release Do not create a new release (wait for additional code changes) label Oct 11, 2025
aknysh and others added 2 commits October 10, 2025 23:28
This fixes a second regression from PR #1602 where explicitly-set
metadata.component values were being overwritten by values from
inherited abstract components.

## Problem
When a component explicitly sets metadata.component and inherits from
an abstract component:
```yaml
eks/service/app1:
  metadata:
    component: eks-service
    inherits:
      - eks/service/defaults  # abstract component
```

The explicitly-set metadata.component (eks-service) was being overwritten
by the abstract component's metadata.component value, causing:
- Wrong component path used
- Terraform looking for state in wrong location
- Potential resource duplication or conflicts

## Root Cause
In processMetadataInheritance(), after setting metadata.component explicitly,
processInheritedComponent() calls applyBaseComponentConfig() which
unconditionally overwrites result.BaseComponentName with the inherited value.

## Solution
Save the explicitly-set metadata.component value before processing inherits,
then restore it afterwards. This ensures:
- Explicit metadata.component values are never overwritten
- Backend workspace_key_prefix uses correct component name
- Components find their existing state files

## Changes
- internal/exec/stack_processor_process_stacks_helpers_inheritance.go:
  Added explicitBaseComponentName tracking and restoration after inherits
- internal/exec/abstract_component_backend_test.go: Added regression test
- tests/fixtures/scenarios/abstract-component-backend/: Added test fixture

## Testing
- New regression test passes
- All existing component inheritance tests pass
- All describe component tests pass

Fixes #1613

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <[email protected]>
@osterman
Copy link
Member

@aknysh please update the PR title to be more informative

@aknysh aknysh changed the title Fix Atmos regressions Fix component inheritance: restore default behavior for metadata.component Oct 12, 2025
@aknysh aknysh self-assigned this Oct 12, 2025
aknysh and others added 3 commits October 11, 2025 23:34
Fix the processMetadataInheritance() function to properly handle all three inheritance scenarios:
1. Top-level component: attribute sets BaseComponentName
2. metadata.component explicitly set preserves the value
3. metadata.inherits without metadata.component defaults to component name

Changes:
- Add conditional check to only set default BaseComponentName if not already set by top-level component inheritance
- Remove incorrect code that was adding current component to BaseComponents list
- BaseComponents should only contain components we inherit FROM, not the current component itself

This fixes the test failures where:
- TestProcessComponentInheritance was getting ["base-vpc", "derived-vpc"] instead of ["base-vpc"]
- TestProcessMetadataInheritance was getting ["mixin1", "mixin2", "derived"] instead of ["mixin1", "mixin2"]
- TestSpaceliftStackProcessor was getting wrong workspace_key_prefix values
- Component test/test-component-override was losing its top-level component: "test/test-component" value

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <[email protected]>
The previous fix didn't properly handle components with metadata.inherits but no metadata.component.
When processing inherits, applyBaseComponentConfig() would set result.BaseComponentName to the
inherited component name, and then our check would see it as already set and not default it.

This fix saves the original BaseComponentName (from top-level component inheritance) before
processing inherits, allowing us to distinguish between:
1. Value set by top-level component: attribute (should preserve)
2. Value set by metadata.inherits processing (should override with component name)

Fixes TestComponentInheritanceWithoutMetadataComponent which expected "derived-component"
but was getting "base-component".

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <[email protected]>
…paths

Update comments to clarify that metadata.inherits should NOT be used to determine
component paths or affect metadata.component. These are completely independent concepts:

- metadata.component: determines physical Terraform component directory path
- metadata.inherits: only for configuration inheritance (vars, settings, backend, etc.)
- Atmos component name: defaults for metadata.component when not explicitly set

The bug was that processing metadata.inherits inadvertently overwrote metadata.component
as a side effect of calling applyBaseComponentConfig(). The fix prevents this unwanted
overwriting while preserving the intended behavior of each mechanism.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <[email protected]>
@codecov
Copy link

codecov bot commented Oct 12, 2025

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 64.50%. Comparing base (09f27f2) to head (251d6bc).
⚠️ Report is 1 commits behind head on main.

Additional details and impacted files

Impacted file tree graph

@@            Coverage Diff             @@
##             main    #1614      +/-   ##
==========================================
+ Coverage   64.47%   64.50%   +0.03%     
==========================================
  Files         333      333              
  Lines       37281    37303      +22     
==========================================
+ Hits        24037    24064      +27     
+ Misses      11306    11296      -10     
- Partials     1938     1943       +5     
Flag Coverage Δ
unittests 64.50% <100.00%> (+0.03%) ⬆️

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

Files with missing lines Coverage Δ
...ck_processor_process_stacks_helpers_inheritance.go 94.23% <100.00%> (+0.94%) ⬆️

... and 5 files with indirect coverage changes

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

@aknysh aknysh added patch A minor, backward compatible change and removed no-release Do not create a new release (wait for additional code changes) labels Oct 12, 2025
@aknysh aknysh marked this pull request as ready for review October 12, 2025 19:32
@aknysh aknysh requested review from a team as code owners October 12, 2025 19:32
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Oct 12, 2025

📝 Walkthrough

Walkthrough

Processes metadata.inherits independently of metadata.component, preserves/restores explicit metadata.component, adds helpers to apply inherited configs, and updates fixtures and tests for abstract-component backend and inheritance without metadata.component. Also bumps a few Go module versions.

Changes

Cohort / File(s) Summary
Deps
go.mod
Bumps yq/v4 → v4.48.1, golang.org/x/crypto → v0.43.0, golang.org/x/net → v0.46.0; updates indirects.
Inheritance processing
internal/exec/stack_processor_process_stacks_helpers_inheritance.go
Reworks processMetadataInheritance to rely only on metadata.inherits, track whether metadata.component was explicit, save/restore top-level BaseComponentName, determine BaseComponentName after inherits, validate inherits entries, and add processInheritedComponent + apply flow.
Exec tests
internal/exec/abstract_component_backend_test.go, internal/exec/component_inheritance_test.go, internal/exec/terraform_affected_test.go
Adds tests validating abstract-component backend workspace_key_prefix, inheritance when metadata.component is omitted, and a test guard/skip for mock-failure in TestGetAffectedComponents.
Fixtures: abstract-component-backend
tests/fixtures/scenarios/abstract-component-backend/...
Adds scenario with atmos.yaml, stacks/tenant1-dev.yaml, catalog stacks/catalog/eks-service-defaults.yaml (abstract component), and module components/terraform/eks-service/main.tf.
Fixtures: inheritance w/o metadata.component
tests/fixtures/scenarios/component-inheritance-without-metadata-component/...
Adds atmos.yaml, stacks/base.yaml, stacks/test.yaml, and terraform modules components/terraform/base-component/main.tf and components/terraform/derived-component/main.tf to exercise inheritance without metadata.component.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  participant CLI as Caller
  participant SP as StackProcessor
  participant IP as processInheritedComponent
  participant AC as applyBaseComponentConfig

  CLI->>SP: processMetadataInheritance(component)
  Note right of SP: Save top-level BaseComponentName\nDetect explicit metadata.component
  SP->>SP: Validate metadata.inherits type
  loop per inherited entry
    SP->>IP: processInheritedComponent(entry)
    IP-->>SP: returned inherited config
    SP->>AC: applyBaseComponentConfig(inherited config)
    AC-->>SP: merge into component
  end
  SP->>SP: Determine BaseComponentName (explicit → top-level → default)
  SP->>SP: Restore explicit metadata.component if preserved
  SP-->>CLI: finalized component (vars, metadata, backend)
  Note over CLI,SP: workspace_key_prefix & component path derived from final BaseComponentName
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Suggested reviewers

  • osterman

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Out of Scope Changes Check ⚠️ Warning The pull request includes dependency version bumps in go.mod and an unrelated guard addition in terraform_affected_test.go, neither of which pertain to the objectives of restoring metadata.component behavior or fixing backend prefix resolution as described in the linked issues. Please extract the dependency updates and the test guard change in terraform_affected_test.go into separate commits or a different pull request so that this one remains focused on the component inheritance fix, facilitating a clearer and more targeted review.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title Check ✅ Passed The pull request title accurately and succinctly describes the core change by stating it fixes component inheritance and restores the default behavior for metadata.component, directly reflecting the main purpose of the changeset.
Linked Issues Check ✅ Passed The code changes update processMetadataInheritance to track and restore explicit metadata.component settings, default metadata.component to the Atmos component name when omitted, and adjust backend prefix derivation, accompanied by new tests and fixtures that validate these behaviors; these updates directly address the objectives of issues #1613 and #1609 concerning backend workspace_key_prefix correction and component resolution when metadata.component is omitted.
Docstring Coverage ✅ Passed No functions found in the changes. Docstring coverage check skipped.
✨ Finishing touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch fixes-2

📜 Recent review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 18d0333 and 251d6bc.

📒 Files selected for processing (2)
  • tests/fixtures/scenarios/abstract-component-backend/atmos.yaml (1 hunks)
  • tests/fixtures/scenarios/component-inheritance-without-metadata-component/atmos.yaml (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • tests/fixtures/scenarios/abstract-component-backend/atmos.yaml
  • tests/fixtures/scenarios/component-inheritance-without-metadata-component/atmos.yaml
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (5)
  • GitHub Check: Build (ubuntu-latest, linux)
  • GitHub Check: Build (windows-latest, windows)
  • GitHub Check: Analyze (go)
  • GitHub Check: Lint (golangci)
  • GitHub Check: Summary

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
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: 0

🧹 Nitpick comments (2)
tests/fixtures/scenarios/abstract-component-backend/components/terraform/eks-service/main.tf (1)

1-15: Fixture looks good; optional: add descriptions/validation to inputs.

Helps readability and prevents empty strings in tests.

tests/fixtures/scenarios/component-inheritance-without-metadata-component/components/terraform/base-component/main.tf (1)

1-11: Looks correct; consider brief var descriptions.

Keeps fixtures self‑documenting without changing behavior.

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 09f27f2 and 9f176b7.

⛔ Files ignored due to path filters (1)
  • go.sum is excluded by !**/*.sum
📒 Files selected for processing (13)
  • go.mod (2 hunks)
  • internal/exec/abstract_component_backend_test.go (1 hunks)
  • internal/exec/component_inheritance_test.go (1 hunks)
  • internal/exec/stack_processor_process_stacks_helpers_inheritance.go (2 hunks)
  • tests/fixtures/scenarios/abstract-component-backend/atmos.yaml (1 hunks)
  • tests/fixtures/scenarios/abstract-component-backend/components/terraform/eks-service/main.tf (1 hunks)
  • tests/fixtures/scenarios/abstract-component-backend/stacks/catalog/eks-service-defaults.yaml (1 hunks)
  • tests/fixtures/scenarios/abstract-component-backend/stacks/tenant1-dev.yaml (1 hunks)
  • tests/fixtures/scenarios/component-inheritance-without-metadata-component/atmos.yaml (1 hunks)
  • tests/fixtures/scenarios/component-inheritance-without-metadata-component/components/terraform/base-component/main.tf (1 hunks)
  • tests/fixtures/scenarios/component-inheritance-without-metadata-component/components/terraform/derived-component/main.tf (1 hunks)
  • tests/fixtures/scenarios/component-inheritance-without-metadata-component/stacks/base.yaml (1 hunks)
  • tests/fixtures/scenarios/component-inheritance-without-metadata-component/stacks/test.yaml (1 hunks)
🧰 Additional context used
📓 Path-based instructions (5)
tests/**

📄 CodeRabbit inference engine (CLAUDE.md)

Integration tests should use fixtures under tests/test-cases/ and follow precondition-based skipping helpers.

Files:

  • tests/fixtures/scenarios/abstract-component-backend/components/terraform/eks-service/main.tf
  • tests/fixtures/scenarios/abstract-component-backend/stacks/tenant1-dev.yaml
  • tests/fixtures/scenarios/component-inheritance-without-metadata-component/stacks/base.yaml
  • tests/fixtures/scenarios/component-inheritance-without-metadata-component/components/terraform/derived-component/main.tf
  • tests/fixtures/scenarios/component-inheritance-without-metadata-component/stacks/test.yaml
  • tests/fixtures/scenarios/abstract-component-backend/atmos.yaml
  • tests/fixtures/scenarios/component-inheritance-without-metadata-component/components/terraform/base-component/main.tf
  • tests/fixtures/scenarios/component-inheritance-without-metadata-component/atmos.yaml
  • tests/fixtures/scenarios/abstract-component-backend/stacks/catalog/eks-service-defaults.yaml
go.{mod,sum}

📄 CodeRabbit inference engine (.cursor/rules/atmos-rules.mdc)

go.{mod,sum}: Manage dependencies with Go modules
Keep dependencies up to date

Files:

  • go.mod
**/*_test.go

📄 CodeRabbit inference engine (.cursor/rules/atmos-rules.mdc)

**/*_test.go: Every new feature must include comprehensive unit tests
Test both happy paths and error conditions
Use table-driven tests for multiple scenarios

**/*_test.go: Write unit tests as table-driven tests focused on behavior; prefer high coverage for pkg/ and internal/exec/; comments must end with periods.
Use t.Skipf with a reason instead of t.Skip; never skip without a reason.
Test files must mirror implementation file names (e.g., aws_ssm_store_test.go pairs with aws_ssm_store.go).

Files:

  • internal/exec/abstract_component_backend_test.go
  • internal/exec/component_inheritance_test.go
**/*.go

📄 CodeRabbit inference engine (.cursor/rules/atmos-rules.mdc)

**/*.go: All code must pass golangci-lint checks
Follow Go error handling idioms and use meaningful error messages
Wrap errors with context using fmt.Errorf("context: %w", err)
Consider custom error types for domain-specific errors
Follow standard Go coding style; run gofmt and goimports
Use snake_case for environment variables
Document complex logic with inline comments

**/*.go: All comments must end with periods across all Go code (godot linter enforced).
Organize imports into three groups (stdlib, 3rd-party, Atmos) separated by blank lines and sorted alphabetically within groups; preserve existing aliases.
Add defer perf.Track(<atmosConfig|nil>, ".")() at the start of all public and critical private functions, followed by a blank line.
All errors must be wrapped using static errors from errors/errors.go; prefer errors.Join for multiple errors, fmt.Errorf with %w for context, and check with errors.Is; never use dynamic errors directly.
Use utils.PrintfMarkdown() to render embedded markdown examples for CLI help output.
Co-locate unit tests with implementation files; integration tests reside under tests/.
Distinguish UI output from logging: UI prompts/status/errors to stderr; data/results to stdout; logging for system/debug info only with structured fields.
Most text UI must go to stderr; only data/results to stdout. Prefer utils.PrintfMessageToTUI for UI messages.
Bind all environment variables with viper.BindEnv(); every env var must have an ATMOS_ alternative binding.
Favor cross-platform code: prefer SDKs over external binaries, use filepath/os/runtime, and handle OS-specific differences or use build tags.
For non-standard execution paths, capture telemetry using telemetry.CaptureCmd or telemetry.CaptureCmdString without collecting user data.
Search for existing methods and utilities (internal/exec, pkg/) before implementing new functionality; prefer reuse/refactoring over duplication.

Files:

  • internal/exec/abstract_component_backend_test.go
  • internal/exec/stack_processor_process_stacks_helpers_inheritance.go
  • internal/exec/component_inheritance_test.go
**/!(*_test).go

📄 CodeRabbit inference engine (.cursor/rules/atmos-rules.mdc)

Document all exported functions, types, and methods with Go doc comments

Files:

  • internal/exec/stack_processor_process_stacks_helpers_inheritance.go
🧠 Learnings (4)
📚 Learning: 2025-09-23T02:30:42.362Z
Learnt from: CR
PR: cloudposse/atmos#0
File: .cursor/rules/atmos-rules.mdc:0-0
Timestamp: 2025-09-23T02:30:42.362Z
Learning: Applies to go.{mod,sum} : Keep dependencies up to date

Applied to files:

  • go.mod
📚 Learning: 2025-09-23T02:30:42.362Z
Learnt from: CR
PR: cloudposse/atmos#0
File: .cursor/rules/atmos-rules.mdc:0-0
Timestamp: 2025-09-23T02:30:42.362Z
Learning: Applies to go.{mod,sum} : Manage dependencies with Go modules

Applied to files:

  • go.mod
📚 Learning: 2025-10-11T23:25:09.201Z
Learnt from: CR
PR: cloudposse/atmos#0
File: CLAUDE.md:0-0
Timestamp: 2025-10-11T23:25:09.201Z
Learning: Applies to internal/exec/stack_processor_utils.go : Place core stack processing utilities in internal/exec/stack_processor_utils.go and test multiple inheritance scenarios.

Applied to files:

  • internal/exec/stack_processor_process_stacks_helpers_inheritance.go
  • internal/exec/component_inheritance_test.go
📚 Learning: 2024-11-25T17:17:15.703Z
Learnt from: RoseSecurity
PR: cloudposse/atmos#797
File: pkg/list/atmos.yaml:213-214
Timestamp: 2024-11-25T17:17:15.703Z
Learning: The file `pkg/list/atmos.yaml` is primarily intended for testing purposes.

Applied to files:

  • tests/fixtures/scenarios/component-inheritance-without-metadata-component/atmos.yaml
🧬 Code graph analysis (1)
internal/exec/stack_processor_process_stacks_helpers_inheritance.go (2)
pkg/config/const.go (2)
  • ComponentSectionName (67-67)
  • InheritsSectionName (93-93)
errors/errors.go (2)
  • ErrInvalidComponentMetadataComponent (146-146)
  • ErrInvalidComponentMetadataInherits (148-148)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (7)
  • GitHub Check: Analyze (go)
  • GitHub Check: Lint (golangci)
  • GitHub Check: Analyze (go)
  • GitHub Check: Lint (golangci)
  • GitHub Check: Acceptance Tests (macos-latest, macos)
  • GitHub Check: Acceptance Tests (ubuntu-latest, linux)
  • GitHub Check: Summary
🔇 Additional comments (20)
tests/fixtures/scenarios/component-inheritance-without-metadata-component/stacks/base.yaml (1)

1-7: LGTM for base defaults.

Types align with Terraform vars; good foundation for inheritance.

tests/fixtures/scenarios/abstract-component-backend/atmos.yaml (1)

1-16: Scenario scaffold reads well.

Matches test intent; backend flags consistent for abstract-component tests.

tests/fixtures/scenarios/abstract-component-backend/stacks/tenant1-dev.yaml (1)

1-18: Correctly preserves explicit metadata.component and inherits defaults.

This should drive workspace_key_prefix to eks-service as intended. Please confirm your new test asserts that backend prefix equals eks-service, not eks-service-defaults.

tests/fixtures/scenarios/abstract-component-backend/stacks/catalog/eks-service-defaults.yaml (1)

1-14: Abstract defaults look consistent.

Setting type: abstract and workspace_key_prefix: eks-service aligns with the fix.

tests/fixtures/scenarios/component-inheritance-without-metadata-component/stacks/test.yaml (1)

1-17: Good coverage for “no metadata.component” path.

Expectations align with restored defaulting to the Atmos component name.

tests/fixtures/scenarios/component-inheritance-without-metadata-component/atmos.yaml (1)

1-16: Fixture LGTM.

Settings are sane for this scenario; auto_generate_backend_file true is fine for tests.

tests/fixtures/scenarios/component-inheritance-without-metadata-component/components/terraform/derived-component/main.tf (1)

1-15: LGTM!

Clean test fixture. The variable declarations are straightforward and support the inheritance test scenarios effectively.

internal/exec/abstract_component_backend_test.go (3)

14-26: Solid test structure.

The directory navigation with cleanup pattern is correct. Using t.Cleanup ensures the working directory is restored even if the test fails.


47-61: Critical regression check is clear and well-documented.

The comments explicitly call out what should happen (workspace_key_prefix from metadata.component) vs. the regression (using abstract component name). This makes the test intent crystal clear.


63-88: Thorough verification of inheritance behavior.

Good coverage of the inheritance chain, vars propagation, and metadata preservation. These assertions confirm that configuration is inherited while component identity remains distinct.

internal/exec/component_inheritance_test.go (3)

11-32: Test setup follows established patterns.

Consistent with the abstract component backend test. The directory navigation and cleanup are correct.


41-55: Verifies default component path behavior.

The key assertion at lines 47-50 confirms that when metadata.component is absent, the component path defaults to the component name. This validates the fix for issue #1609.


57-73: Metadata scope verification is valuable.

The comment at lines 57-58 clarifies an important invariant: metadata is per-component and not inherited. The assertions confirm this behavior.

internal/exec/stack_processor_process_stacks_helpers_inheritance.go (4)

88-110: State tracking for explicit metadata.component is clear.

The logic correctly distinguishes between an explicitly set metadata.component (which should be preserved) and values that may be overwritten during inheritance processing. The comments explain the intent well.


112-131: Restoration logic handles the inheritance override correctly.

The key fix is here: after processing metadata.inherits (which calls applyBaseComponentConfig and overwrites BaseComponentName), you restore the explicit metadata.component if it was set. This prevents inherited component names from leaking into the concrete component's identity.


133-145: Default logic covers all cases systematically.

The three-tier fallback is sound:

  1. Use explicit metadata.component (handled earlier)
  2. Use top-level component attribute (restored from saved value)
  3. Default to Atmos component name

This ensures correct behavior whether the user specifies component identity explicitly or relies on defaults.


150-190: Helper function improves readability.

Extracting the per-inherited-component processing into processInheritedComponent makes the loop at lines 121-125 cleaner. The validation and error handling here are thorough.

go.mod (3)

3-3: Go version 1.24.8: confirm toolchain/CI availability

Ensure CI/build images and local dev toolchains have Go 1.24.8 (or a matching toolchain directive) to avoid module resolution quirks.

As per coding guidelines


379-383: ```shell
grep -E '^go [0-9]+' -n go.mod


---

`67-67`: **Verify yq/v4 module bump**: no direct Go imports detected; confirm this version bump applies (e.g., in CI/scripts) and that `go.sum` is updated and tidy.

</blockquote></details>

</blockquote></details>

</details>

<!-- This is an auto-generated comment by CodeRabbit for review status -->

coderabbitai[bot]
coderabbitai bot previously approved these changes Oct 12, 2025
Add check to skip test when gomonkey mocking fails and the real function
gets called with an invalid repository path, returning an unexpected error.

The test "empty_affected_list" was flaky because:
1. It mocks ExecuteDescribeAffectedWithTargetRepoPath to return empty list
2. When mock fails (platform/compiler dependent), real function is called
3. Real function tries to access fake path "/path/to/repo"
4. Returns error "invalid repository path"
5. Test fails with: "Received unexpected error: invalid repository path"

Now the test properly detects this scenario and skips with a helpful message
instead of failing intermittently.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <[email protected]>
coderabbitai[bot]
coderabbitai bot previously approved these changes Oct 12, 2025
@aknysh aknysh requested a review from osterman October 12, 2025 20:23
osterman
osterman previously approved these changes Oct 12, 2025
@aknysh aknysh dismissed stale reviews from osterman and coderabbitai[bot] via 251d6bc October 12, 2025 22:34
@aknysh aknysh requested a review from osterman October 12, 2025 22:34
@aknysh aknysh merged commit e289fee into main Oct 13, 2025
52 checks passed
@aknysh aknysh deleted the fixes-2 branch October 13, 2025 00:17
@github-actions
Copy link

These changes were released in v1.194.1-rc.0.

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

3 participants