Skip to content

Conversation

@osterman
Copy link
Member

@osterman osterman commented Nov 22, 2025

what

Feature Implementation:

  • Add metadata inheritance from base components with deep-merge semantics (enabled by default via stacks.inherit.metadata)
  • Add metadata.name as a stable logical component identity for workspace key prefixes
  • Update workspace key generation precedence: explicit backend prefix → metadata.name → component identity → component path
  • Expose new inherit field in atmos describe config output

Bug Fixes:

  • Exclude metadata.type: abstract from inheritance to prevent abstract components from becoming deployable
  • Apply metadata inheritance in ExecuteDescribeStacks to ensure inherited metadata fields (like terraform_workspace) are resolved when describing stacks
  • Handle precedence conflicts: explicit terraform_workspace takes precedence over inherited/imported patterns

Documentation:

  • Document metadata.name convention: first-level component folder relative to component base path
  • Eliminate manual workspace_key_prefix patterns across version management documentation
  • Update all design patterns (folder-based versioning, git flow, release tracks, strict pinning) to use catalog inheritance with metadata.name
  • Add PRDs for metadata inheritance and workspace key prefixes
  • Improve version management best practices to promote inherited metadata.name over manual settings

Tests:

  • Add comprehensive test coverage for metadata inheritance scenarios
  • Add tests for workspace key generation with metadata.name
  • Add regression test for metadata.type: abstract exclusion
  • Update snapshots for new stacks.inherit field in describe config output

why

Feature Justification:

  • Metadata inheritance eliminates repetition across component hierarchies by allowing base components to define shared metadata (workspace configuration, Spacelift settings, etc.)
  • metadata.name provides a stable, predictable workspace key that doesn't change when component paths are refactored
  • Default-enabled inheritance with deep-merge semantics ensures components automatically inherit metadata while allowing explicit overrides

Bug Justification:

  • Without excluding metadata.type: abstract, abstract base components could become deployable when inherited, breaking the abstract component pattern
  • ExecuteDescribeStacks was only merging YAML imports but not applying component inheritance, causing inherited metadata fields to be ignored
  • Pattern/template metadata from imports/inheritance could override explicit workspace values due to precedence order in BuildTerraformWorkspace

Documentation Justification:

  • The metadata.name feature was implemented but documentation still showed old manual workspace_key_prefix patterns, creating confusion and encouraging error-prone workarounds
  • Creates a clear, consistent convention: metadata.name = top-level component folder
  • Makes documentation DRY by showing catalog patterns that inherit the stable key

references

Summary by CodeRabbit

  • New Features

    • Metadata now inherits from base components by default with deep-merge semantics.
    • Added metadata.name as a stable logical component identity for stable workspace keys.
  • Behavior / Bug Fixes

    • Workspace key generation priority: explicit backend prefix → metadata.name → component identity/path.
    • metadata.inherits and abstract-typed metadata are not inherited; component values win on conflict.
    • Describe/preview flows reflect merged metadata for workspace keys.
  • Configuration

    • stacks.inherit.metadata option to disable metadata inheritance (enabled by default).
  • Documentation

    • New docs, migration guidance, examples, and blog posts.
  • Tests

    • Expanded tests covering inheritance, merging, and workspace-key scenarios.

✏️ Tip: You can customize this high-level summary in your review settings.

osterman and others added 6 commits November 21, 2025 08:40
Introduces a design proposal for making metadata fields inheritable
from base components, solving the versioned component state management
problem.

Key changes:
- New `stacks.inherit.metadata` configuration option (default: true)
- All metadata fields inherit except `metadata.inherits`
- New `metadata.name` field for logical component identity
- Updated workspace_key_prefix auto-generation to use metadata.name

This enables DRY patterns for versioned components where the logical
identity (for state keys) can be defined once in a base component
and inherited by all derived components.

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

Co-Authored-By: Claude <[email protected]>
Introduces a design proposal for using metadata.name as the logical
component identity in workspace_key_prefix auto-generation.

Key points:
- New metadata.name field represents logical component identity
- Priority: explicit config > metadata.name > metadata.component > Atmos name
- Fully backwards compatible - falls back to current behavior if not set
- Solves versioned component state stability problem
- Works with metadata inheritance for DRY configuration

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

Co-Authored-By: Claude <[email protected]>
🤖 Generated with [Claude Code](https://claude.com/claude-code)

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

This implements the metadata inheritance feature and workspace_key_prefix
calculation improvements:

- Add `stacks.inherit.metadata` configuration option (default: true)
- Make metadata inheritable from base components (except `metadata.inherits`)
- Add `metadata.name` field for logical component identity
- Update workspace_key_prefix auto-generation priority:
  1. Explicit backend config
  2. metadata.name (new)
  3. metadata.component
  4. Atmos component name

This enables versioned component patterns where state remains stable across
version upgrades (e.g., vpc/v1 -> vpc/v2) when using metadata.name.

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

Co-Authored-By: Claude <[email protected]>
- Add metadata to list of inherited sections in inheritance docs
- Document stacks.inherit.metadata configuration option
- Update folder-based versioning to use metadata.name pattern
- Remove incorrect settings.workspace_key_prefix examples
- Add blog posts for metadata inheritance and stable workspace keys

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

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

- Add explicit convention that metadata.name should use top-level component folder
- Document convention in blog post and version management docs
- Replace manual workspace_key_prefix patterns with inherited metadata.name in:
  - git-flow-branches-as-channels.mdx (catalog inheritance pattern)
  - release-tracks-channels.mdx (both track organization approaches)
  - terraform-workspace.mdx (add recommended section before advanced)
  - version-management/index.mdx (best practices)
  - continuous-version-deployment.mdx (planned divergence examples)
  - strict-version-pinning.mdx (catalog pattern for versioned components)
  - folder-based-versioning.mdx (convention callout)

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

Co-Authored-By: Claude <[email protected]>
@osterman osterman requested a review from a team as a code owner November 22, 2025 13:28
@github-actions github-actions bot added the size/xl Extra large size PR label Nov 22, 2025
@mergify
Copy link

mergify bot commented Nov 22, 2025

Warning

This PR exceeds the recommended limit of 1,000 lines.

Large PRs are difficult to review and may be rejected due to their size.

Please verify that this PR does not address multiple issues.
Consider refactoring it into smaller, more focused PRs to facilitate a smoother review process.

@github-actions
Copy link

github-actions bot commented Nov 22, 2025

Dependency Review

✅ No vulnerabilities or license issues found.

Scanned Files

None

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Nov 22, 2025

📝 Walkthrough

Walkthrough

Adds default-on metadata inheritance (opt-out via stacks.inherit.metadata), introduces metadata.name for stable logical component identity, deep-merges base and component metadata (component wins; excludes metadata.inherits and metadata.type: abstract), and threads merged metadata into Terraform backend defaulting to prioritize metadata.name for workspace key/prefix generation.

Changes

Cohort / File(s) Summary
Schema & config types
pkg/schema/schema.go
Add StacksInherit + Stacks.Inherit and IsMetadataInheritanceEnabled(); add BaseComponentMetadata to base component config.
Public JSON schema
pkg/datafetcher/schema/stacks/stack-config/1.0.json
Add metadata.name property; update custom description to reflect inheritance when enabled.
Component/result helpers
internal/exec/stack_processor_process_stacks_helpers.go, internal/exec/stack_processor_process_stacks_helpers_inheritance.go
Add BaseComponentMetadata map[string]any to ComponentProcessorResult; propagate base metadata in inheritance initialization/application.
Metadata merge & inheritance
internal/exec/stack_processor_merge.go, internal/exec/stack_processor_utils.go, internal/exec/metadata_inheritance_test.go
Implement metadata inheritance merging (filter metadata.inherits, exclude type: abstract), deep-merge semantics, and tests covering name inheritance, abstract exclusion, non-inheritance of inherits, toggle, nested merges, and upgrade scenarios.
Backend processing — thread metadata
internal/exec/stack_processor_backend.go, internal/exec/stack_processor_backend_test.go
Thread merged metadata via componentMetadata in terraformBackendConfig; update S3/GCS/Azure default functions to accept metadata; compute workspace key/prefix priority: explicit backend > metadata.name > metadata.component > Atmos component name; add tests (precedence, slash normalization).
Describe / processing path
internal/exec/describe_stacks.go
Merge base metadata into component metadata during describe/processing when inheritance enabled; ensure explicit terraform_workspace overrides inherited templates/patterns.
Docs — core, CLI, patterns & blog
website docs & blog (multiple website/.../*.mdx)
Document metadata inheritance rules and exceptions, recommend metadata.name for stable workspace keys, add catalog-based examples, migration guidance, and update backend/workspace docs and CLI guidance.
Design patterns / examples
website/docs/design-patterns/version-management/*.mdx, stacks/catalog/*.yaml, updated stack examples
Introduce catalog base components and examples using inheritance-driven stable workspace keys (use metadata.name instead of embedding versions).
Snapshots / CLI output
tests/snapshots/TestCLICommands_atmos_describe_config.stdout.golden
Add new inherit object in stacks config snapshot (schema surface).

Sequence Diagram(s)

sequenceDiagram
    autonumber
    participant SP as StackProcessor
    participant Base as BaseConfigLoader
    participant Merge as MetadataMerge
    participant Backend as BackendDefaults
    participant Out as Output/Describe

    SP->>Base: load base & component configs
    SP->>SP: check stacks.inherit.metadata (default: true)
    alt inheritance enabled
        SP->>Merge: mergeMetadata(baseMetadata, componentMetadata)
        Merge->>Merge: filter base (exclude inherits / type: abstract)
        Merge->>Merge: deep-merge, overlay component (component wins)
        Merge-->>SP: finalComponentMetadata
    else inheritance disabled
        SP-->>SP: finalComponentMetadata = componentMetadata
    end
    SP->>Out: write finalComponentMetadata into component map
    SP->>Backend: processTerraformBackend(finalComponentMetadata)
    Backend->>Backend: compute workspace key/prefix:
    Backend->>Backend: 1) explicit backend value?
    alt explicit present
        Backend-->>Out: use explicit
    else
        Backend->>Backend: 2) metadata.name?
        alt metadata.name present
            Backend-->>Out: use metadata.name (slashes -> -)
        else
            Backend->>Backend: 3) metadata.component?
            alt metadata.component present
                Backend-->>Out: use metadata.component (slashes -> -)
            else
                Backend-->>Out: use Atmos component name
            end
        end
    end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~50 minutes

  • Focus review areas:
    • Metadata merging logic and exclusion rules in internal/exec/stack_processor_merge.go and internal/exec/stack_processor_utils.go.
    • Backend default functions and updated call sites/signatures in internal/exec/stack_processor_backend.go.
    • Tests in internal/exec/* covering priority, edge cases (nil/empty metadata, slash normalization), and metadata.type/metadata.inherits behavior.
    • Schema/JSON changes alignment with Go types in pkg/schema and pkg/datafetcher/schema/.../1.0.json.

Possibly related PRs

Suggested labels

major

Suggested reviewers

  • aknysh
  • kevcube
  • goruha

Pre-merge checks and finishing touches

✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately captures the main feature: metadata inheritance and metadata.name for workspace key prefix calculation—the core runtime changes in this PR.
Docstring Coverage ✅ Passed Docstring coverage is 90.00% which is sufficient. The required threshold is 80.00%.
✨ Finishing touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch osterman/metadata-inheritance-prd

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

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
website/docs/design-patterns/version-management/continuous-version-deployment.mdx (1)

236-244: Please drop the old workspace_key_prefix guidance

The example still tells readers to set settings.workspace_key_prefix, which is the manual pattern this PR is retiring. To stay consistent, show the stable identity via metadata.name (or inherit from the catalog base) and remove the explicit prefix override. That keeps the doc aligned with the new metadata.name convention.

     vpc:
       metadata:
-        component: vpc-experiment  # Pin dev to experiment
-      settings:
-        workspace_key_prefix: "vpc"  # Keep stable across experiments
+        name: vpc  # Stable identity across experiments
+        component: vpc-experiment  # Pin dev to experiment
🧹 Nitpick comments (3)
pkg/schema/schema.go (1)

438-445: Stacks inheritance surface and default metadata behavior are well-shaped

The Stacks.Inherit struct plus StacksInherit.IsMetadataInheritanceEnabled() giving a default of true lines up cleanly with the docs (“enabled by default, opt-out via atmos.yaml”) and keeps the config surface explicit while preserving sane zero-values.

If you ever want extra nil-safety, you could switch the receiver to a value to allow var s *StacksInherit callers without risking a panic:

-func (s *StacksInherit) IsMetadataInheritanceEnabled() bool {
-	if s.Metadata == nil {
+func (s StacksInherit) IsMetadataInheritanceEnabled() bool {
+	if s.Metadata == nil {
 		return true
 	}
-	return *s.Metadata
+	return *s.Metadata
}

Also applies to: 447-462

docs/prd/metadata-inheritance.md (2)

26-26: Minor wording simplification.

The phrase "each component must define" is slightly redundant since ownership is implied. Consider: "each component must explicitly define its own metadata" → "metadata cannot be inherited from base components."


352-352: Add missing punctuation.

Line 352 (the Exclude metadata.inherits... bullet) is missing a period at the end of the paragraph following the code block.

Apply this minor fix:

-   - Exclude `metadata.inherits` from being inherited
+   - Exclude `metadata.inherits` from being inherited.
📜 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 77768f5 and 186d45b.

📒 Files selected for processing (20)
  • docs/prd/metadata-inheritance.md (1 hunks)
  • docs/prd/workspace-key-prefixes.md (1 hunks)
  • internal/exec/stack_processor_backend.go (4 hunks)
  • internal/exec/stack_processor_backend_test.go (2 hunks)
  • internal/exec/stack_processor_merge.go (3 hunks)
  • internal/exec/stack_processor_process_stacks_helpers.go (1 hunks)
  • internal/exec/stack_processor_process_stacks_helpers_inheritance.go (2 hunks)
  • internal/exec/stack_processor_utils.go (1 hunks)
  • pkg/datafetcher/schema/stacks/stack-config/1.0.json (2 hunks)
  • pkg/schema/schema.go (2 hunks)
  • website/blog/2025-11-21-metadata-inheritance.mdx (1 hunks)
  • website/blog/2025-11-21-metadata-name-workspace-keys.mdx (1 hunks)
  • website/docs/cli/commands/terraform/terraform-workspace.mdx (1 hunks)
  • website/docs/core-concepts/stacks/inheritance/inheritance.mdx (3 hunks)
  • website/docs/design-patterns/version-management/continuous-version-deployment.mdx (2 hunks)
  • website/docs/design-patterns/version-management/folder-based-versioning.mdx (6 hunks)
  • website/docs/design-patterns/version-management/git-flow-branches-as-channels.mdx (3 hunks)
  • website/docs/design-patterns/version-management/index.mdx (1 hunks)
  • website/docs/design-patterns/version-management/release-tracks-channels.mdx (2 hunks)
  • website/docs/design-patterns/version-management/strict-version-pinning.mdx (1 hunks)
🧰 Additional context used
🧠 Learnings (14)
📓 Common learnings
Learnt from: Listener430
Repo: cloudposse/atmos PR: 934
File: tests/fixtures/scenarios/docs-generate/README.md.gotmpl:99-118
Timestamp: 2025-01-25T03:51:57.689Z
Learning: For the cloudposse/atmos repository, changes to template contents should be handled in dedicated PRs and are typically considered out of scope for PRs focused on other objectives.
📚 Learning: 2025-09-29T02:20:11.636Z
Learnt from: aknysh
Repo: cloudposse/atmos PR: 1540
File: internal/exec/validate_component.go:117-118
Timestamp: 2025-09-29T02:20:11.636Z
Learning: The ValidateComponent function in internal/exec/validate_component.go had its componentSection parameter type refined from `any` to `map[string]any` without adding new parameters. This is a type safety improvement, not a signature change requiring call site updates.

Applied to files:

  • internal/exec/stack_processor_process_stacks_helpers.go
  • internal/exec/stack_processor_backend.go
  • internal/exec/stack_processor_process_stacks_helpers_inheritance.go
  • internal/exec/stack_processor_merge.go
📚 Learning: 2025-10-08T06:48:07.499Z
Learnt from: aknysh
Repo: cloudposse/atmos PR: 1602
File: internal/exec/stack_processor_utils.go:968-1003
Timestamp: 2025-10-08T06:48:07.499Z
Learning: The `FindComponentDependenciesLegacy` function in `internal/exec/stack_processor_utils.go` is legacy code that is not actively used and is kept only for backward compatibility purposes.

Applied to files:

  • internal/exec/stack_processor_process_stacks_helpers.go
  • internal/exec/stack_processor_backend.go
  • internal/exec/stack_processor_utils.go
  • internal/exec/stack_processor_merge.go
📚 Learning: 2024-12-08T14:26:16.972Z
Learnt from: pkbhowmick
Repo: cloudposse/atmos PR: 828
File: pkg/schema/schema.go:98-100
Timestamp: 2024-12-08T14:26:16.972Z
Learning: The `ListConfig` columns array in the `Components` struct can be empty.

Applied to files:

  • internal/exec/stack_processor_process_stacks_helpers.go
📚 Learning: 2024-11-02T15:35:09.958Z
Learnt from: aknysh
Repo: cloudposse/atmos PR: 759
File: internal/exec/terraform.go:366-368
Timestamp: 2024-11-02T15:35:09.958Z
Learning: In `internal/exec/terraform.go`, the workspace cleaning code under both the general execution path and within the `case "init":` block is intentionally duplicated because the code execution paths are different. The `.terraform/environment` file should be deleted before executing `terraform init` in both scenarios to ensure a clean state.

Applied to files:

  • website/docs/cli/commands/terraform/terraform-workspace.mdx
  • website/docs/design-patterns/version-management/folder-based-versioning.mdx
📚 Learning: 2024-12-03T03:49:30.395Z
Learnt from: aknysh
Repo: cloudposse/atmos PR: 810
File: website/docs/core-concepts/stacks/yaml-functions/terraform.output.mdx:104-110
Timestamp: 2024-12-03T03:49:30.395Z
Learning: In the documentation for `!terraform.output`, warnings about template variable availability are already covered in other sections, so no need to suggest adding them here.

Applied to files:

  • website/docs/cli/commands/terraform/terraform-workspace.mdx
📚 Learning: 2025-08-29T20:57:35.423Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 1433
File: cmd/theme_list.go:33-36
Timestamp: 2025-08-29T20:57:35.423Z
Learning: In the Atmos codebase, avoid using viper.SetEnvPrefix("ATMOS") with viper.AutomaticEnv() because canonical environment variable names are not exclusive to Atmos and could cause conflicts. Instead, use selective environment variable binding through the setEnv function in pkg/config/load.go with bindEnv(v, "config.key", "ENV_VAR_NAME") for specific environment variables.

Applied to files:

  • website/docs/cli/commands/terraform/terraform-workspace.mdx
📚 Learning: 2024-12-01T00:33:20.298Z
Learnt from: aknysh
Repo: cloudposse/atmos PR: 810
File: examples/tests/stacks/catalog/terraform/template-functions-test2/defaults.yaml:28-32
Timestamp: 2024-12-01T00:33:20.298Z
Learning: In `examples/tests/stacks/catalog/terraform/template-functions-test2/defaults.yaml`, `!exec atmos terraform output` is used in examples to demonstrate its usage, even though `!terraform.output` is the recommended approach according to the documentation.

Applied to files:

  • website/docs/cli/commands/terraform/terraform-workspace.mdx
  • website/docs/design-patterns/version-management/release-tracks-channels.mdx
📚 Learning: 2025-10-07T00:25:16.333Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 1498
File: website/src/components/Screengrabs/atmos-terraform-metadata--help.html:25-55
Timestamp: 2025-10-07T00:25:16.333Z
Learning: In Atmos CLI, subcommands inherit flags from their parent commands via Cobra's command inheritance. For example, `atmos terraform metadata --help` shows `--affected` and related flags inherited from the parent `terraform` command (defined in cmd/terraform.go), even though the metadata subcommand doesn't explicitly define these flags. This is expected Cobra behavior and auto-generated help screengrabs accurately reflect this inheritance.

Applied to files:

  • website/blog/2025-11-21-metadata-inheritance.mdx
  • docs/prd/metadata-inheritance.md
  • internal/exec/stack_processor_utils.go
  • website/docs/core-concepts/stacks/inheritance/inheritance.mdx
📚 Learning: 2025-11-10T23:23:39.771Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 1686
File: toolchain/registry/aqua/aqua_test.go:417-442
Timestamp: 2025-11-10T23:23:39.771Z
Learning: In Atmos toolchain AquaRegistry, tests should not hit real GitHub. Use the options pattern via WithGitHubBaseURL to inject an httptest server URL and make GetLatestVersion/GetAvailableVersions deterministic.

Applied to files:

  • internal/exec/stack_processor_backend_test.go
📚 Learning: 2025-11-08T19:56:18.660Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 1697
File: internal/exec/oci_utils.go:0-0
Timestamp: 2025-11-08T19:56:18.660Z
Learning: In the Atmos codebase, when a function receives an `*schema.AtmosConfiguration` parameter, it should read configuration values from `atmosConfig.Settings` fields rather than using direct `os.Getenv()` or `viper.GetString()` calls. The Atmos pattern is: viper.BindEnv in cmd/root.go binds environment variables → Viper unmarshals into atmosConfig.Settings via mapstructure → business logic reads from the Settings struct. This provides centralized config management, respects precedence, and enables testability. Example: `atmosConfig.Settings.AtmosGithubToken` instead of `os.Getenv("ATMOS_GITHUB_TOKEN")` in functions like `getGHCRAuth` in internal/exec/oci_utils.go.

Applied to files:

  • internal/exec/stack_processor_backend.go
📚 Learning: 2025-10-13T18:13:54.020Z
Learnt from: aknysh
Repo: cloudposse/atmos PR: 1622
File: pkg/perf/perf.go:140-184
Timestamp: 2025-10-13T18:13:54.020Z
Learning: In pkg/perf/perf.go, the `trackWithSimpleStack` function intentionally skips ownership checks at call stack depth > 1 to avoid expensive `getGoroutineID()` calls on every nested function. This is a performance optimization for the common single-goroutine execution case (most Atmos commands), accepting the rare edge case of potential metric corruption if multi-goroutine execution occurs at depth > 1. The ~19× performance improvement justifies this trade-off.

Applied to files:

  • internal/exec/stack_processor_utils.go
📚 Learning: 2024-11-13T21:37:07.852Z
Learnt from: Cerebrovinny
Repo: cloudposse/atmos PR: 764
File: internal/exec/describe_stacks.go:289-295
Timestamp: 2024-11-13T21:37:07.852Z
Learning: In the `internal/exec/describe_stacks.go` file of the `atmos` project written in Go, avoid extracting the stack name handling logic into a helper function within the `ExecuteDescribeStacks` method, even if the logic appears duplicated.

Applied to files:

  • internal/exec/stack_processor_utils.go
📚 Learning: 2024-12-07T16:16:13.038Z
Learnt from: Listener430
Repo: cloudposse/atmos PR: 825
File: internal/exec/helmfile_generate_varfile.go:28-31
Timestamp: 2024-12-07T16:16:13.038Z
Learning: In `internal/exec/helmfile_generate_varfile.go`, the `--help` command (`./atmos helmfile generate varfile --help`) works correctly without requiring stack configurations, and the only change needed was to make `ProcessCommandLineArgs` exportable by capitalizing its name.

Applied to files:

  • internal/exec/stack_processor_utils.go
🧬 Code graph analysis (3)
internal/exec/stack_processor_backend_test.go (1)
pkg/schema/schema.go (1)
  • AtmosConfiguration (53-94)
internal/exec/stack_processor_utils.go (3)
pkg/schema/schema.go (1)
  • Stacks (438-445)
pkg/config/const.go (1)
  • InheritsSectionName (102-102)
pkg/merge/merge.go (1)
  • Merge (389-427)
internal/exec/stack_processor_merge.go (3)
pkg/schema/schema.go (1)
  • Stacks (438-445)
pkg/merge/merge.go (1)
  • Merge (389-427)
pkg/config/const.go (1)
  • MetadataSectionName (75-75)
🪛 GitHub Actions: Website Preview Build
website/blog/2025-11-21-metadata-name-workspace-keys.mdx

[error] 1-1: Build failed: Docusaurus reported broken links during locale en build. Broken link: /changelog/metadata-name-workspace-keys -> /blog/metadata-inheritance. Command: 'npm run build:site' (exit code 1).

website/docs/cli/commands/terraform/terraform-workspace.mdx

[error] 1-1: Build failed: Docusaurus reported broken links during locale en build. Broken link: /changelog/metadata-name-workspace-keys -> /blog/metadata-inheritance. Command: 'npm run build:site' (exit code 1).

website/docs/design-patterns/version-management/continuous-version-deployment.mdx

[error] 1-1: Build failed: Docusaurus reported broken links during locale en build. Broken link: /changelog/metadata-name-workspace-keys -> /blog/metadata-inheritance. Command: 'npm run build:site' (exit code 1).

website/blog/2025-11-21-metadata-inheritance.mdx

[error] 1-1: Build failed: Docusaurus reported broken links during locale en build. Broken link: /changelog/metadata-name-workspace-keys -> /blog/metadata-inheritance. Command: 'npm run build:site' (exit code 1).

website/docs/design-patterns/version-management/folder-based-versioning.mdx

[error] 1-1: Build failed: Docusaurus reported broken links during locale en build. Broken link: /changelog/metadata-name-workspace-keys -> /blog/metadata-inheritance. Command: 'npm run build:site' (exit code 1).

website/docs/design-patterns/version-management/index.mdx

[error] 1-1: Build failed: Docusaurus reported broken links during locale en build. Broken link: /changelog/metadata-name-workspace-keys -> /blog/metadata-inheritance. Command: 'npm run build:site' (exit code 1).

website/docs/design-patterns/version-management/git-flow-branches-as-channels.mdx

[error] 1-1: Build failed: Docusaurus reported broken links during locale en build. Broken link: /changelog/metadata-name-workspace-keys -> /blog/metadata-inheritance. Command: 'npm run build:site' (exit code 1).

website/docs/core-concepts/stacks/inheritance/inheritance.mdx

[error] 1-1: Build failed: Docusaurus reported broken links during locale en build. Broken link: /changelog/metadata-name-workspace-keys -> /blog/metadata-inheritance. Command: 'npm run build:site' (exit code 1).

website/docs/design-patterns/version-management/strict-version-pinning.mdx

[error] 1-1: Build failed: Docusaurus reported broken links during locale en build. Broken link: /changelog/metadata-name-workspace-keys -> /blog/metadata-inheritance. Command: 'npm run build:site' (exit code 1).

website/docs/design-patterns/version-management/release-tracks-channels.mdx

[error] 1-1: Build failed: Docusaurus reported broken links during locale en build. Broken link: /changelog/metadata-name-workspace-keys -> /blog/metadata-inheritance. Command: 'npm run build:site' (exit code 1).

🪛 LanguageTool
docs/prd/workspace-key-prefixes.md

[typographical] ~66-~66: Consider using a typographic opening quote here.
Context: ...e metadata-inheritance.md) - Represents "what this component IS" vs "where its co...

(EN_QUOTES)


[typographical] ~66-~66: Consider using a typographic close quote here.
Context: ...md) - Represents "what this component IS" vs "where its code lives" ### Updated ...

(EN_QUOTES)


[typographical] ~66-~66: Consider using a typographic opening quote here.
Context: ... Represents "what this component IS" vs "where its code lives" ### Updated Calcu...

(EN_QUOTES)


[typographical] ~66-~66: Consider using a typographic close quote here.
Context: ...s component IS" vs "where its code lives" ### Updated Calculation Logic **New p...

(EN_QUOTES)


[style] ~246-~246: Three successive sentences begin with the same word. Consider rewording the sentence or use a thesaurus to find a synonym.
Context: ...endDefaults()similarly forprefix. Update setAzureBackendKey()similarly fork...

(ENGLISH_WORD_REPEAT_BEGINNING_RULE)

website/docs/design-patterns/version-management/git-flow-branches-as-channels.mdx

[typographical] ~192-~192: Consider using a typographic opening quote here.
Context: ...erits name: vpc → workspace_key_prefix: "vpc" vars: name: "dev-use1...

(EN_QUOTES)


[typographical] ~192-~192: Consider using a typographic close quote here.
Context: ...s name: vpc → workspace_key_prefix: "vpc" vars: name: "dev-use1-vpc...

(EN_QUOTES)


[typographical] ~232-~232: Consider using a typographic opening quote here.
Context: ...erits name: vpc → workspace_key_prefix: "vpc" vars: name: "prod-use...

(EN_QUOTES)


[typographical] ~232-~232: Consider using a typographic close quote here.
Context: ...s name: vpc → workspace_key_prefix: "vpc" vars: name: "prod-use1-vp...

(EN_QUOTES)

docs/prd/metadata-inheritance.md

[style] ~26-~26: Since ownership is already implied, this phrasing may be redundant.
Context: ...d entirely - each component must define its own metadata. ### Problems This Causes ##...

(PRP_OWN)


[grammar] ~352-~352: Please add a punctuation mark at the end of paragraph.
Context: ... Exclude metadata.inherits from being inherited 2. Modify `internal/exec/stack_process...

(PUNCTUATION_PARAGRAPH_END)

website/docs/design-patterns/version-management/strict-version-pinning.mdx

[typographical] ~128-~128: Consider using a typographic opening quote here.
Context: ...erits name: vpc → workspace_key_prefix: "vpc" vars: name: "prod-vpc...

(EN_QUOTES)


[typographical] ~128-~128: Consider using a typographic close quote here.
Context: ...s name: vpc → workspace_key_prefix: "vpc" vars: name: "prod-vpc" ...

(EN_QUOTES)


[typographical] ~130-~130: Consider using a typographic opening quote here.
Context: ...prefix: "vpc" vars: name: "prod-vpc" cidr_block: "10.0.0.0/...

(EN_QUOTES)


[typographical] ~130-~130: Consider using a typographic close quote here.
Context: ...vpc" vars: name: "prod-vpc" cidr_block: "10.0.0.0/16" ``` <...

(EN_QUOTES)


[typographical] ~131-~131: Consider using a typographic opening quote here.
Context: ... name: "prod-vpc" cidr_block: "10.0.0.0/16" ``` ### 2. Maintai...

(EN_QUOTES)


[typographical] ~131-~131: Consider using a typographic close quote here.
Context: ...od-vpc" cidr_block: "10.0.0.0/16" ``` ### 2. Maintain Stable Wor...

(EN_QUOTES)

⏰ Context from checks skipped due to timeout of 900000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: Acceptance Tests (windows)
  • GitHub Check: Summary
🔇 Additional comments (24)
pkg/datafetcher/schema/stacks/stack-config/1.0.json (1)

506-509: metadata.name field and updated custom docs look consistent with inheritance behavior

Adding metadata.name as a logical identity for workspace key generation and clarifying that metadata.custom inherits when stacks.inherit.metadata is enabled matches the new stacks inheritance model and is backwards compatible (optional field, no new required keys).

Also applies to: 550-551

pkg/schema/schema.go (1)

836-851: BaseComponentMetadata field nicely completes the base component config shape

Adding BaseComponentMetadata alongside vars/settings/env/auth/providers/hooks keeps the base-component surface symmetric with ComponentProcessorResult and gives you a clear slot to carry inherited metadata through the pipeline.

website/blog/2025-11-21-metadata-name-workspace-keys.mdx (1)

1-60: Post reads well; please re-check the /blog/metadata-inheritance link against the preview build

The explanation and examples around using metadata.name as the stable top-level folder identity are clear and match the new convention. Given the reported Docusaurus error about /blog/metadata-inheritance, once this and the companion post are in place, please re-run the website build to confirm that link is now resolved (and adjust any changelog entry if it still points at a mismatched path).

website/blog/2025-11-21-metadata-inheritance.mdx (1)

1-61: Nice concise overview of metadata inheritance; verify it clears the previously broken link

The before/after YAML makes the behavior change obvious, and the config snippet for disabling stacks.inherit.metadata aligns with the new StacksInherit API. Since the build previously reported /blog/metadata-inheritance as missing, this file should fix that; please rerun the site build to confirm the broken-link check is now clean.

internal/exec/stack_processor_process_stacks_helpers.go (1)

48-86: Adding BaseComponentMetadata to ComponentProcessorResult is consistent with the new metadata flow

Threading BaseComponentMetadata through ComponentProcessorResult matches the schema-side BaseComponentConfig change and gives inheritance helpers a proper place to stash merged base metadata without affecting existing fields.

internal/exec/stack_processor_process_stacks_helpers_inheritance.go (2)

18-29: Wiring BaseComponentMetadata alongside other base maps looks consistent

Initializing result.BaseComponentMetadata with the same capacity hint as vars/settings/env/auth keeps the pattern consistent and avoids nil-map edge cases when later merging.


193-203: Propagating BaseComponentMetadata out of BaseComponentConfig is the right place

Assigning result.BaseComponentMetadata = baseComponentConfig.BaseComponentMetadata here mirrors how other base sections are surfaced and keeps all inheritance-derived data flowing through the same struct.

website/docs/core-concepts/stacks/inheritance/inheritance.mdx (1)

49-73: Metadata inheritance docs read clearly and match the new behavior

The “What Gets Inherited” table plus the :::info Metadata Inheritance block do a nice job of spelling out that metadata is inherited while excluding metadata.inherits, and the small wording tweaks in the Single/Multiple/Multilevel sections keep the story consistent without overloading the reader. The stacks.inherit.metadata: false example is also a helpful escape hatch for older stacks.

Also applies to: 81-83, 251-253, 394-395

website/docs/design-patterns/version-management/index.mdx (1)

231-256: Best-practice shift to metadata.name for stable keys is coherent

Using metadata.name as the stable identity and keeping version info in metadata.component while flagging versioned workspace_key_prefix patterns as WRONG lines up well with the new backend behavior and should make upgrades much less brittle. The example YAML and cross-link to folder-based versioning are tight and actionable.

website/docs/cli/commands/terraform/terraform-workspace.mdx (1)

55-85: Nice, this puts the simple metadata.name pattern before the advanced templating

The catalog + prod stack example makes it obvious how metadata.name drives a stable workspace_key_prefix without extra config, and parking the Go-template workspace_key_prefix under an “Advanced” heading keeps that escape hatch available without encouraging it as the default. This matches the backend semantics you’re testing around metadata.name.

Also, CI is currently failing on a Docusaurus broken link: /changelog/metadata-name-workspace-keys -> /blog/metadata-inheritance. It doesn’t appear in this file, but you’ll want to update or remove that link elsewhere before merging.

Also applies to: 87-98

internal/exec/stack_processor_merge.go (1)

136-152: Metadata inheritance merge and wiring into backend look solid

Using finalComponentMetadata as the merge of base + component metadata (with component last) matches the documented “component wins” behavior, and threading that same merged map into both the public Metadata section and terraformBackendConfig.componentMetadata keeps backend defaults (e.g., metadata.name-based workspace prefixes) aligned with what users see in the processed stack. The conditional on IsMetadataInheritanceEnabled() plus a non-empty base map keeps the fast path cheap.

Also applies to: 161-163, 169-180

internal/exec/stack_processor_backend_test.go (1)

14-28: Good coverage for metadata.name-driven workspace key behavior

Adding componentMetadata to the test matrix and asserting priority/fallback rules across S3/GCS/Azure (incl. slash normalization, explicit workspace_key_prefix precedence, and empty/absent name cases) gives strong confidence that the new backend logic matches the documented semantics. Normalizing nil metadata to an empty map in the test harness is also a nice touch to keep the call shape predictable.

Also applies to: 235-347, 354-366

website/docs/design-patterns/version-management/folder-based-versioning.mdx (4)

103-165: Catalog inheritance pattern is well-documented and clear.

The introduction of the catalog-based base component with metadata.name effectively demonstrates how to stabilize workspace keys across version changes. The YAML structure is correct, and the inheritance pattern using metadata.inherits is properly explained.


208-216: Metadata.name convention clearly established.

The tip section effectively communicates the convention that metadata.name should use the top-level component folder name. The examples make the pattern predictable and easy to follow.


272-303: Rollback strategy leverages catalog inheritance well.

The section correctly shows how updating the base catalog component automatically propagates to all derived components. The zero-downtime rollback explanation is valuable context.


1-400: Review comment is inaccurate—the file doesn't contain the cited broken link.

The search found no /blog/metadata-inheritance links in the reviewed file folder-based-versioning.mdx. The link actually exists in the blog post website/blog/2025-11-21-metadata-name-workspace-keys.mdx (line 18), and that link target is valid—the destination blog post website/blog/2025-11-21-metadata-inheritance.mdx exists. No action needed on the file under review.

Likely an incorrect or invalid review comment.

website/docs/design-patterns/version-management/release-tracks-channels.mdx (3)

112-127: Catalog base definitions establish clear metadata inheritance pattern across both track organizations.

Both "Tracks Per Component" and "Track-First Organization" approaches properly define base catalog components with metadata.name for logical identity. This makes the pattern consistent regardless of folder organization choice.

Also applies to: 218-233


129-153: Stack-level component inheritance correctly leverages catalog metadata.

Both production stack examples show proper usage of metadata.inherits to pull from base defaults, with clear comments explaining that workspace_key_prefix is inherited from metadata.name. This reinforces the pattern established in file 1.

Also applies to: 235-259


1-300: The review comment references non-existent broken links.

After comprehensive search across the codebase, the link /changelog/metadata-name-workspace-keys/blog/metadata-inheritance does not exist in either release-tracks-channels.mdx or folder-based-versioning.mdx.

The only occurrence of /blog/metadata-inheritance exists in a separate blog post file (website/blog/2025-11-21-metadata-name-workspace-keys.mdx), where it is a valid link. The files cited in the review contain no such broken link pattern.

All verified internal links in both documentation files are properly formed and reference valid paths.

Likely an incorrect or invalid review comment.

docs/prd/metadata-inheritance.md (5)

1-120: PRD effectively articulates the problem and proposed solution.

The problem statement clearly explains why metadata inheritance is needed: preventing silent state loss during component version upgrades and enabling DRY metadata patterns. The proposed solution with stacks.inherit.metadata configuration and the new metadata.name field is well-reasoned and backward-compatible.


121-165: Workspace key priority logic is clear and well-documented.

The four-level priority (explicit prefix > metadata.name > metadata.component > Atmos name) is sensible and gives users appropriate control. The convention of setting metadata.name to the top-level folder name makes the pattern predictable.


166-282: Use cases comprehensively cover real-world scenarios.

All four use cases—versioned components, release tracks, governance patterns, and multi-instance components—demonstrate practical value of the feature. The examples are clear and properly annotated with expected outcomes.


283-324: Breaking change analysis is thorough and honest.

The assessment that breakage risk is low (because metadata wasn't previously inherited) is sound. Providing both a config-level opt-out and field-level overrides gives users adequate migration paths.


325-392: Implementation plan provides clear direction for backend team.

Schema changes, processing updates, and JSON schema modifications are all specified. The plan correctly identifies the three key processing areas: stack utilities, merge logic, and backend defaults.

coderabbitai[bot]
coderabbitai bot previously approved these changes Nov 22, 2025
@osterman osterman added the minor New features that do not break anything label Nov 22, 2025
…ession

Fix regression in `atmos list instances` where all component instances were
being filtered out due to inheriting `metadata.type: abstract` from base
components.

## Changes

**Code fixes:**
- Exclude `metadata.type: abstract` from metadata inheritance in stack_processor_utils.go
- Abstract is a base component designation that should not propagate to child components
- Other metadata.type values (e.g., 'real', custom types) continue to be inherited
- Update code comments to clarify both 'inherits' and 'type: abstract' exclusions

**Documentation updates:**
- Update metadata-inheritance.md PRD to document the exclusion
- Update inheritance.mdx website docs with clear explanation
- Clarify that child components inheriting from abstract components are concrete implementations

## Test Results

- TestCLICommands/atmos_list_instances - PASS
- TestCLICommands/atmos_list_instances_no_tty - PASS
- All internal/exec tests - PASS
- Abstract component tests - PASS

## Impact

- atmos list instances now correctly returns all non-abstract component instances
- Base abstract components retain metadata.type: abstract
- Child components do not inherit the abstract type designation
- Other metadata fields continue to be inherited as designed

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

Co-Authored-By: Claude <[email protected]>
Add extensive unit tests for metadata.name inheritance and metadata.type: abstract exclusion.

## What Changed

- Added `internal/exec/metadata_inheritance_test.go` with 653 lines of comprehensive tests
- Fixed broken changelog link in metadata-name-workspace-keys blog post

## Test Coverage Added

### 6 Major Test Functions (24+ test cases):

1. **TestMetadataNameInheritance** - Verifies metadata.name inheritance from base components and usage in workspace_key_prefix calculation
2. **TestMetadataTypeAbstractExclusion** - Confirms metadata.type: abstract is NOT inherited (prevents child components from becoming abstract)
3. **TestMetadataInheritsNotInherited** - Validates metadata.inherits is not inherited (it's the meta-property)
4. **TestMetadataInheritanceConfiguration** - Tests stacks.inherit.metadata flag (enabled/disabled)
5. **TestMetadataDeepMerge** - Verifies deep merging of nested metadata fields
6. **TestVersionedComponentUpgrade** - Validates PRIMARY use case from PRD (stable state paths across version upgrades)

## Coverage Improvement

**Before**: ~40% coverage
- Backend configuration with metadata.name tested
- Abstract component handling tested
- Missing: inheritance behavior, configuration flags, PRD use cases

**After**: ~75-85% coverage (estimated)
- All critical functionality tested
- Edge cases covered
- Primary use case validated
- Configuration flags tested

## Test Results

All tests PASS:
- 24 new test cases added
- All existing tests still pass (no regressions)
- Website builds successfully

## Why This Matters

The PR implemented metadata inheritance and metadata.name features but was missing critical test coverage for:
- metadata.name inheritance from base components
- metadata.type: abstract exclusion (commit af24538)
- stacks.inherit.metadata configuration flag
- Versioned component upgrade scenario (primary PRD use case)

These tests ensure the feature works as documented and prevents regressions.

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

Co-Authored-By: Claude <[email protected]>
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 (1)
internal/exec/metadata_inheritance_test.go (1)

587-617: Test helper accuracy concern: filterBaseMetadata differs from production code.

The test helper filterBaseMetadata (lines 603-617) filters metadata fields before merging, but the production code in stack_processor_merge.go (lines 136-152) comments that filtering is "already excluded during collection" - which happens in stack_processor_utils.go (lines 1724-1748).

However, your test helper implements the filtering correctly and matches the production logic in stack_processor_utils.go. The test approach is valid.

Minor suggestion: Add a comment explaining that this helper replicates the filtering logic from processBaseComponentConfigInternal in stack_processor_utils.go for testing purposes, to make the relationship explicit.

Apply this diff to clarify the helper's purpose:

-// filterBaseMetadata filters base metadata to exclude 'inherits' and 'type: abstract'.
+// filterBaseMetadata filters base metadata to exclude 'inherits' and 'type: abstract'.
+// This replicates the filtering logic from processBaseComponentConfigInternal in stack_processor_utils.go.
 func filterBaseMetadata(baseMetadata map[string]any) map[string]any {
📜 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 186d45b and 0a365e0.

📒 Files selected for processing (6)
  • docs/prd/metadata-inheritance.md (1 hunks)
  • internal/exec/metadata_inheritance_test.go (1 hunks)
  • internal/exec/stack_processor_merge.go (3 hunks)
  • internal/exec/stack_processor_utils.go (1 hunks)
  • website/blog/2025-11-21-metadata-name-workspace-keys.mdx (1 hunks)
  • website/docs/core-concepts/stacks/inheritance/inheritance.mdx (3 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • website/blog/2025-11-21-metadata-name-workspace-keys.mdx
  • website/docs/core-concepts/stacks/inheritance/inheritance.mdx
🧰 Additional context used
🧠 Learnings (12)
📓 Common learnings
Learnt from: Listener430
Repo: cloudposse/atmos PR: 934
File: tests/fixtures/scenarios/docs-generate/README.md.gotmpl:99-118
Timestamp: 2025-01-25T03:51:57.689Z
Learning: For the cloudposse/atmos repository, changes to template contents should be handled in dedicated PRs and are typically considered out of scope for PRs focused on other objectives.
📚 Learning: 2025-09-29T02:20:11.636Z
Learnt from: aknysh
Repo: cloudposse/atmos PR: 1540
File: internal/exec/validate_component.go:117-118
Timestamp: 2025-09-29T02:20:11.636Z
Learning: The ValidateComponent function in internal/exec/validate_component.go had its componentSection parameter type refined from `any` to `map[string]any` without adding new parameters. This is a type safety improvement, not a signature change requiring call site updates.

Applied to files:

  • internal/exec/stack_processor_merge.go
  • internal/exec/stack_processor_utils.go
  • internal/exec/metadata_inheritance_test.go
📚 Learning: 2025-10-07T00:25:16.333Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 1498
File: website/src/components/Screengrabs/atmos-terraform-metadata--help.html:25-55
Timestamp: 2025-10-07T00:25:16.333Z
Learning: In Atmos CLI, subcommands inherit flags from their parent commands via Cobra's command inheritance. For example, `atmos terraform metadata --help` shows `--affected` and related flags inherited from the parent `terraform` command (defined in cmd/terraform.go), even though the metadata subcommand doesn't explicitly define these flags. This is expected Cobra behavior and auto-generated help screengrabs accurately reflect this inheritance.

Applied to files:

  • docs/prd/metadata-inheritance.md
📚 Learning: 2025-10-08T06:48:07.499Z
Learnt from: aknysh
Repo: cloudposse/atmos PR: 1602
File: internal/exec/stack_processor_utils.go:968-1003
Timestamp: 2025-10-08T06:48:07.499Z
Learning: The `FindComponentDependenciesLegacy` function in `internal/exec/stack_processor_utils.go` is legacy code that is not actively used and is kept only for backward compatibility purposes.

Applied to files:

  • internal/exec/stack_processor_utils.go
📚 Learning: 2024-11-19T23:00:45.899Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 795
File: internal/exec/stack_processor_utils.go:378-386
Timestamp: 2024-11-19T23:00:45.899Z
Learning: In the `ProcessYAMLConfigFile` function within `internal/exec/stack_processor_utils.go`, directory traversal in stack imports is acceptable and should not be restricted.

Applied to files:

  • internal/exec/stack_processor_utils.go
📚 Learning: 2025-10-13T18:13:54.020Z
Learnt from: aknysh
Repo: cloudposse/atmos PR: 1622
File: pkg/perf/perf.go:140-184
Timestamp: 2025-10-13T18:13:54.020Z
Learning: In pkg/perf/perf.go, the `trackWithSimpleStack` function intentionally skips ownership checks at call stack depth > 1 to avoid expensive `getGoroutineID()` calls on every nested function. This is a performance optimization for the common single-goroutine execution case (most Atmos commands), accepting the rare edge case of potential metric corruption if multi-goroutine execution occurs at depth > 1. The ~19× performance improvement justifies this trade-off.

Applied to files:

  • internal/exec/stack_processor_utils.go
📚 Learning: 2024-10-20T00:41:57.135Z
Learnt from: haitham911
Repo: cloudposse/atmos PR: 731
File: internal/exec/validate_stacks.go:93-98
Timestamp: 2024-10-20T00:41:57.135Z
Learning: When downloading schema files in `internal/exec/validate_stacks.go`, use a consistent temporary file name to overwrite the file each time and avoid creating multiple temporary files.

Applied to files:

  • internal/exec/metadata_inheritance_test.go
📚 Learning: 2024-12-07T16:19:01.683Z
Learnt from: aknysh
Repo: cloudposse/atmos PR: 825
File: internal/exec/terraform.go:30-30
Timestamp: 2024-12-07T16:19:01.683Z
Learning: In `internal/exec/terraform.go`, skipping stack validation when help flags are present is not necessary.

Applied to files:

  • internal/exec/metadata_inheritance_test.go
📚 Learning: 2024-11-02T15:35:09.958Z
Learnt from: aknysh
Repo: cloudposse/atmos PR: 759
File: internal/exec/terraform.go:366-368
Timestamp: 2024-11-02T15:35:09.958Z
Learning: In `internal/exec/terraform.go`, the workspace cleaning code under both the general execution path and within the `case "init":` block is intentionally duplicated because the code execution paths are different. The `.terraform/environment` file should be deleted before executing `terraform init` in both scenarios to ensure a clean state.

Applied to files:

  • internal/exec/metadata_inheritance_test.go
📚 Learning: 2024-12-07T16:16:13.038Z
Learnt from: Listener430
Repo: cloudposse/atmos PR: 825
File: internal/exec/helmfile_generate_varfile.go:28-31
Timestamp: 2024-12-07T16:16:13.038Z
Learning: In `internal/exec/helmfile_generate_varfile.go`, the `--help` command (`./atmos helmfile generate varfile --help`) works correctly without requiring stack configurations, and the only change needed was to make `ProcessCommandLineArgs` exportable by capitalizing its name.

Applied to files:

  • internal/exec/metadata_inheritance_test.go
📚 Learning: 2024-11-13T21:37:07.852Z
Learnt from: Cerebrovinny
Repo: cloudposse/atmos PR: 764
File: internal/exec/describe_stacks.go:289-295
Timestamp: 2024-11-13T21:37:07.852Z
Learning: In the `internal/exec/describe_stacks.go` file of the `atmos` project written in Go, avoid extracting the stack name handling logic into a helper function within the `ExecuteDescribeStacks` method, even if the logic appears duplicated.

Applied to files:

  • internal/exec/metadata_inheritance_test.go
📚 Learning: 2025-11-11T03:47:45.878Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 1686
File: toolchain/add_test.go:67-77
Timestamp: 2025-11-11T03:47:45.878Z
Learning: In the cloudposse/atmos codebase, tests should prefer t.Setenv for environment variable setup/teardown instead of os.Setenv/Unsetenv to ensure test-scoped isolation.

Applied to files:

  • internal/exec/metadata_inheritance_test.go
🧬 Code graph analysis (3)
internal/exec/stack_processor_merge.go (3)
pkg/schema/schema.go (1)
  • Stacks (438-445)
pkg/merge/merge.go (1)
  • Merge (389-427)
pkg/config/const.go (1)
  • MetadataSectionName (75-75)
internal/exec/stack_processor_utils.go (3)
pkg/schema/schema.go (1)
  • Stacks (438-445)
pkg/config/const.go (1)
  • InheritsSectionName (102-102)
pkg/merge/merge.go (1)
  • Merge (389-427)
internal/exec/metadata_inheritance_test.go (3)
pkg/schema/schema.go (2)
  • Stacks (438-445)
  • StacksInherit (448-453)
internal/exec/stack_processor_process_stacks_helpers.go (1)
  • ComponentProcessorResult (48-86)
pkg/config/const.go (1)
  • InheritsSectionName (102-102)
🪛 LanguageTool
docs/prd/metadata-inheritance.md

[style] ~26-~26: Since ownership is already implied, this phrasing may be redundant.
Context: ...d entirely - each component must define its own metadata. ### Problems This Causes ##...

(PRP_OWN)


[grammar] ~354-~354: Please add a punctuation mark at the end of paragraph.
Context: ... Exclude metadata.inherits from being inherited 2. Modify `internal/exec/stack_process...

(PUNCTUATION_PARAGRAPH_END)

⏰ Context from checks skipped due to timeout of 900000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (4)
  • GitHub Check: Acceptance Tests (windows)
  • GitHub Check: Acceptance Tests (macos)
  • GitHub Check: Acceptance Tests (linux)
  • GitHub Check: Summary
🔇 Additional comments (7)
internal/exec/stack_processor_merge.go (1)

136-152: LGTM! Metadata inheritance implementation follows established patterns.

The metadata merging logic correctly:

  • Gates on IsMetadataInheritanceEnabled() for opt-out behavior
  • Follows the same merge order as other sections (base → component, component wins)
  • Passes the final merged metadata to backend processing

One clarification: The comment states that inherits and type: abstract are "already excluded during collection." Verify this happens in the base component processing path (lines 1724-1748 in stack_processor_utils.go), where the filtering actually occurs. The comment is accurate but refers to logic in a different file.

docs/prd/metadata-inheritance.md (2)

103-122: LGTM! Inheritance behavior is clearly documented.

The inheritance table and special exclusions section accurately reflect the implementation:

  • metadata.inherits is excluded (it's the meta-property defining inheritance)
  • metadata.type: abstract is excluded (base component designation)
  • Other fields are inherited and can be overridden

This matches the filtering logic in internal/exec/stack_processor_utils.go lines 1730-1741.


143-167: Documentation accurately reflects implementation—no changes needed.

The priority order in the PRD matches the backend processing logic exactly. The explicit backend.s3.workspace_key_prefix is checked first (line 87); if present and non-empty, the block is skipped entirely, preserving the user override. The fallback chain then follows: metadata.name (line 90), metadata.component (line 92), then the Atmos component name default (line 88). This same pattern is consistently applied to S3, GCS, and Azure backends.

internal/exec/stack_processor_utils.go (1)

1724-1748: LGTM! Base component metadata filtering and merging is correct.

The implementation properly:

  • Filters out metadata.inherits (line 1732) - the meta-property defining inheritance
  • Excludes type: abstract (lines 1736-1740) - base component designation
  • Merges the filtered base metadata with accumulated BaseComponentMetadata
  • Gates the entire block on IsMetadataInheritanceEnabled()

This filtering happens during base component processing, which is what the comment in stack_processor_merge.go refers to when it says "already excluded during collection."

One edge case to consider: If a base component has type: "concrete" (or any non-abstract type), it will be inherited. Is this intentional? Based on the PRD (lines 109, 250-260 in metadata-inheritance.md), this appears correct - only type: abstract should be excluded.

internal/exec/metadata_inheritance_test.go (3)

15-204: LGTM! Comprehensive test coverage for metadata.name inheritance.

The test suite covers critical scenarios:

  • Basic inheritance from base components
  • Component override of inherited values
  • Versioned components (the primary use case)
  • Inheritance disabled via configuration flag
  • Slash normalization in metadata.name
  • Empty/missing name handling
  • Multiple component instances with different names

Each test verifies both the metadata merging and the downstream effect on workspace_key_prefix calculation by calling the actual processTerraformBackend function, providing good integration coverage.


208-335: LGTM! Type exclusion logic is thoroughly tested.

The tests correctly verify:

  • type: abstract is excluded from inheritance (lines 221-232)
  • Other type values like real-component ARE inherited (lines 249-260)
  • Component can explicitly override inherited type (lines 262-274)
  • Other metadata fields are still inherited when type is excluded (lines 322-332)

This matches the PRD specification (lines 109, 119-122 in metadata-inheritance.md) that only type: abstract is excluded as a special case.


619-643: Simplified merge helper is adequate for tests.

The simpleMerge helper uses a recursive approach for deep merging maps (lines 631-637), which is simpler than the production pkg/merge.Merge that handles list merge strategies and other complexities.

For unit testing metadata inheritance, this simplified version is sufficient since metadata typically contains nested maps rather than complex list structures. The comment on line 620 appropriately notes this difference.

coderabbitai[bot]
coderabbitai bot previously approved these changes Nov 23, 2025
The `atmos describe config` output now includes the `stacks.inherit` field,
which was added as part of the metadata inheritance feature. This field
controls whether metadata is inherited from base components.

This is an expected change in the configuration schema and output format.

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

Co-Authored-By: Claude <[email protected]>
coderabbitai[bot]
coderabbitai bot previously approved these changes Nov 23, 2025
…e resolution

Apply metadata inheritance when processing stacks in ExecuteDescribeStacks to ensure inherited metadata fields like terraform_workspace are correctly resolved.

Previously, ExecuteDescribeStacks only merged YAML imports via FindStacksMap but did not apply component inheritance, causing components with metadata.inherits to ignore inherited metadata fields.

Changes:
- Call ProcessBaseComponentConfig to resolve inheritance chains for each component
- Merge base component metadata with component's own metadata (component overrides base)
- Remove terraform_workspace_pattern/template when explicit terraform_workspace exists to ensure explicit values take precedence over inherited/imported patterns

Fixes TestDescribeStacksWithFilter7 which expects test/test-component-override-3 to inherit terraform_workspace from its inheritance chain.

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

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

codecov bot commented Nov 23, 2025

Codecov Report

❌ Patch coverage is 88.37209% with 10 lines in your changes missing coverage. Please review.
✅ Project coverage is 72.03%. Comparing base (6e39488) to head (8a0987e).
⚠️ Report is 2 commits behind head on main.

Files with missing lines Patch % Lines
internal/exec/describe_stacks.go 85.36% 3 Missing and 3 partials ⚠️
internal/exec/stack_processor_merge.go 83.33% 1 Missing and 1 partial ⚠️
internal/exec/stack_processor_utils.go 84.61% 1 Missing and 1 partial ⚠️
Additional details and impacted files

Impacted file tree graph

@@            Coverage Diff             @@
##             main    #1812      +/-   ##
==========================================
+ Coverage   71.98%   72.03%   +0.04%     
==========================================
  Files         471      471              
  Lines       45222    45299      +77     
==========================================
+ Hits        32555    32631      +76     
+ Misses      10071    10067       -4     
- Partials     2596     2601       +5     
Flag Coverage Δ
unittests 72.03% <88.37%> (+0.04%) ⬆️

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

Files with missing lines Coverage Δ
internal/exec/stack_processor_backend.go 85.84% <100.00%> (+0.79%) ⬆️
...nal/exec/stack_processor_process_stacks_helpers.go 73.33% <ø> (ø)
...ck_processor_process_stacks_helpers_inheritance.go 94.95% <100.00%> (+0.08%) ⬆️
pkg/schema/schema.go 88.46% <100.00%> (+0.46%) ⬆️
internal/exec/stack_processor_merge.go 84.43% <83.33%> (-0.19%) ⬇️
internal/exec/stack_processor_utils.go 80.04% <84.61%> (+0.70%) ⬆️
internal/exec/describe_stacks.go 72.85% <85.36%> (+0.94%) ⬆️

... and 4 files with indirect coverage changes

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

coderabbitai[bot]
coderabbitai bot previously approved these changes Nov 23, 2025
@osterman osterman changed the title docs: Document metadata.name convention for stable workspace keys feat: Add metadata inheritance and metadata.name for workspace key prefix Nov 24, 2025
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: 1

📜 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 a2ade6c and 8ecc480.

📒 Files selected for processing (5)
  • pkg/schema/schema.go (2 hunks)
  • tests/snapshots/TestCLICommands_atmos_describe_config.stdout.golden (1 hunks)
  • website/blog/2025-11-21-metadata-name-workspace-keys.mdx (1 hunks)
  • website/docs/core-concepts/components/terraform/backends.mdx (1 hunks)
  • website/docs/core-concepts/components/terraform/workspaces.mdx (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • pkg/schema/schema.go
🧰 Additional context used
📓 Path-based instructions (2)
website/**

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

website/**: Update website documentation in the website/ directory when adding new features, ensure consistency between CLI help text and website documentation, and follow the website's documentation structure and style
Keep website code in the website/ directory, follow the existing website architecture and style, and test website changes locally before committing
Keep CLI documentation and website documentation in sync and document new features on the website with examples and use cases

Files:

  • website/docs/core-concepts/components/terraform/backends.mdx
  • website/docs/core-concepts/components/terraform/workspaces.mdx
  • website/blog/2025-11-21-metadata-name-workspace-keys.mdx
website/blog/**/*.mdx

📄 CodeRabbit inference engine (CLAUDE.md)

PRs labeled minor/major MUST include blog post at website/blog/YYYY-MM-DD-feature-name.mdx with YAML front matter, after intro, tags (feature/enhancement/bugfix/contributors), and author (committer's GitHub username).

Files:

  • website/blog/2025-11-21-metadata-name-workspace-keys.mdx
🧠 Learnings (6)
📚 Learning: 2025-10-07T00:25:16.333Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 1498
File: website/src/components/Screengrabs/atmos-terraform-metadata--help.html:25-55
Timestamp: 2025-10-07T00:25:16.333Z
Learning: In Atmos CLI, subcommands inherit flags from their parent commands via Cobra's command inheritance. For example, `atmos terraform metadata --help` shows `--affected` and related flags inherited from the parent `terraform` command (defined in cmd/terraform.go), even though the metadata subcommand doesn't explicitly define these flags. This is expected Cobra behavior and auto-generated help screengrabs accurately reflect this inheritance.

Applied to files:

  • website/docs/core-concepts/components/terraform/backends.mdx
  • tests/snapshots/TestCLICommands_atmos_describe_config.stdout.golden
📚 Learning: 2025-08-29T20:57:35.423Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 1433
File: cmd/theme_list.go:33-36
Timestamp: 2025-08-29T20:57:35.423Z
Learning: In the Atmos codebase, avoid using viper.SetEnvPrefix("ATMOS") with viper.AutomaticEnv() because canonical environment variable names are not exclusive to Atmos and could cause conflicts. Instead, use selective environment variable binding through the setEnv function in pkg/config/load.go with bindEnv(v, "config.key", "ENV_VAR_NAME") for specific environment variables.

Applied to files:

  • website/docs/core-concepts/components/terraform/backends.mdx
📚 Learning: 2025-01-19T15:49:15.593Z
Learnt from: samtholiya
Repo: cloudposse/atmos PR: 955
File: tests/snapshots/TestCLICommands_atmos_validate_editorconfig_--help.stdout.golden:0-0
Timestamp: 2025-01-19T15:49:15.593Z
Learning: In future commits, the help text for Atmos CLI commands should be limited to only show component and stack parameters for commands that actually use them. This applies to the example usage section in command help text.

Applied to files:

  • website/docs/core-concepts/components/terraform/backends.mdx
📚 Learning: 2024-12-01T00:33:20.298Z
Learnt from: aknysh
Repo: cloudposse/atmos PR: 810
File: examples/tests/stacks/catalog/terraform/template-functions-test2/defaults.yaml:28-32
Timestamp: 2024-12-01T00:33:20.298Z
Learning: In `examples/tests/stacks/catalog/terraform/template-functions-test2/defaults.yaml`, `!exec atmos terraform output` is used in examples to demonstrate its usage, even though `!terraform.output` is the recommended approach according to the documentation.

Applied to files:

  • website/docs/core-concepts/components/terraform/backends.mdx
📚 Learning: 2025-03-18T12:26:25.329Z
Learnt from: Listener430
Repo: cloudposse/atmos PR: 1149
File: tests/snapshots/TestCLICommands_atmos_vendor_pull_ssh.stderr.golden:7-7
Timestamp: 2025-03-18T12:26:25.329Z
Learning: In the Atmos project, typos or inconsistencies in test snapshot files (such as "terrafrom" instead of "terraform") may be intentional as they capture the exact output of commands and should not be flagged as issues requiring correction.

Applied to files:

  • website/docs/core-concepts/components/terraform/backends.mdx
  • tests/snapshots/TestCLICommands_atmos_describe_config.stdout.golden
📚 Learning: 2024-11-02T15:35:09.958Z
Learnt from: aknysh
Repo: cloudposse/atmos PR: 759
File: internal/exec/terraform.go:366-368
Timestamp: 2024-11-02T15:35:09.958Z
Learning: In `internal/exec/terraform.go`, the workspace cleaning code under both the general execution path and within the `case "init":` block is intentionally duplicated because the code execution paths are different. The `.terraform/environment` file should be deleted before executing `terraform init` in both scenarios to ensure a clean state.

Applied to files:

  • website/docs/core-concepts/components/terraform/workspaces.mdx
🪛 LanguageTool
website/blog/2025-11-21-metadata-name-workspace-keys.mdx

[grammar] ~30-~30: Please add a punctuation mark at the end of paragraph.
Context: ...name - Easy to forget when creating new components ## The Solution metadata.name provi...

(PUNCTUATION_PARAGRAPH_END)

⏰ Context from checks skipped due to timeout of 900000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (4)
  • GitHub Check: Acceptance Tests (windows)
  • GitHub Check: Acceptance Tests (linux)
  • GitHub Check: Acceptance Tests (macos)
  • GitHub Check: Summary
🔇 Additional comments (5)
tests/snapshots/TestCLICommands_atmos_describe_config.stdout.golden (1)

46-46: Snapshot correctly reflects the new inherit field.

The addition of the inherit field to the stacks config output is spot-on. The empty object representation is appropriate here—default inheritance behavior is computed at runtime rather than serialized in the config output, consistent with other fields in this snapshot.

website/blog/2025-11-21-metadata-name-workspace-keys.mdx (1)

1-76: Blog post meets all content guidelines.

YAML frontmatter is complete (slug, title, authors, tags), <!--truncate--> is correctly placed, and the post clearly explains the problem, solution, and convention for metadata.name. The progression from motivation through concrete examples to a convention table is well-structured.

website/docs/core-concepts/components/terraform/backends.mdx (2)

176-195: Auto-generation priority and metadata.name usage are clearly documented.

Lines 176–182 correctly specify the three-step priority (metadata.namemetadata.component → component name) with slash-to-dash normalization. The tip (lines 184–195) reinforces this with a practical versioned-component example. The cross-reference to Terraform Workspaces documentation helps users understand how metadata.name connects workspace generation to state paths.


155-175: Update context: workspace_key_prefix auto-generation.

Line 155 notes workspace_key_prefix is "optional," and lines 176–182 explain auto-generation. This clarifies intent well—no explicit setting required if you rely on defaults. Good progression from manual example (lines 157–174) to auto-generation explanation.

website/docs/core-concepts/components/terraform/workspaces.mdx (1)

194-240: Duplication claim is unsubstantiated—section appears only once in the file.

The grep verification confirms there is exactly one instance of "How Workspaces Relate to State Paths" in the workspaces.mdx file. The new content is clean, clearly explains the two-level S3 state hierarchy, documents the auto-generation priority (explicit backend → metadata.namemetadata.component → component name), and provides a practical YAML example for versioned components. The cross-reference to backends documentation supports discoverability.

coderabbitai[bot]
coderabbitai bot previously approved these changes Nov 27, 2025
…ace_template

Fixed confusing workspace_key_prefix examples and added comprehensive
documentation for the workspace configuration system.

**Changes:**

1. **Fixed confusing backend examples** (configure-terraform-backend.mdx, backends.mdx)
   - Replaced placeholder text with realistic values
   - Changed from: `workspace_key_prefix = "<component name, e.g. vpc>"`
   - Changed to: `workspace_key_prefix = "vpc"  # Or any stable identifier`

2. **Added comprehensive workspace_key_prefix documentation** (vendor-manifest.mdx)
   - Priority order table showing 4-level calculation
   - Recommended approach using metadata.name (NEW feature)
   - Alternative explicit override approach
   - Legacy manual workaround (pre-metadata.name)
   - Clear "Result:" comments showing effective calculated values

3. **Documented terraform_workspace_template** (workspaces.mdx)
   - Previously undocumented feature with full Go template support
   - Priority order: template > pattern > workspace > auto-generated
   - Usage examples with Sprig functions
   - When to use guide (templates vs patterns vs static)

4. **Added workspace NAME vs KEY PREFIX clarification** (workspaces.mdx)
   - Note box distinguishing the two independent concepts
   - Workspace NAME: controlled by terraform_workspace_template/pattern/workspace
   - Workspace KEY PREFIX: controlled by metadata.name or explicit backend config
   - State path diagram showing both parts: {workspace_key_prefix}/{workspace}/terraform.tfstate

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

Co-Authored-By: Claude <[email protected]>
osterman and others added 2 commits November 28, 2025 13:51
Added links to official HashiCorp Terraform documentation for workspace
and workspace_key_prefix concepts to clarify these are Terraform features,
not Atmos inventions.

**Changes:**

- Added link to Terraform workspaces documentation
- Added link to S3 backend workspace_key_prefix parameter documentation
- Clarified these are "Terraform concepts" in the note box
- Added references to official docs in vendor-manifest.mdx

**References:**
- https://developer.hashicorp.com/terraform/cli/workspaces
- https://developer.hashicorp.com/terraform/language/state/workspaces
- https://developer.hashicorp.com/terraform/language/backend/s3

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

Co-Authored-By: Claude <[email protected]>
Replaced "Advanced:" heading with PillBox component to match design
pattern documentation style.

**Changes:**
- Import PillBox component
- Replace "### Advanced: Using Go Templates" with "### Using Go Templates" + PillBox
- Consistent with design patterns documentation style

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

Co-Authored-By: Claude <[email protected]>
osterman and others added 2 commits November 28, 2025 13:57
Changed "Workspace NAME vs Workspace KEY PREFIX" to "Workspace Name vs
Workspace Key Prefix" for better readability. All-caps style is harder
to read and less professional.

**Changes:**
- Note box title: "NAME" → "Name", "KEY PREFIX" → "Key Prefix"
- Bullet points: "Workspace NAME" → "Workspace name", "Workspace KEY PREFIX" → "Workspace key prefix"
- Maintained bold emphasis on the terms

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

Co-Authored-By: Claude <[email protected]>
Changed to proper title case:
- "Workspace name" → "Workspace Name"
- "Workspace key prefix" → "Workspace Key Prefix"

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

Co-Authored-By: Claude <[email protected]>
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: 2

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
website/docs/quick-start/advanced/configure-terraform-backend.mdx (1)

195-218: Update documentation to include metadata.name in workspace key precedence.

The current documentation explains that without workspace_key_prefix, the component name is used automatically with slashes replaced by dashes, but doesn't mention the new metadata.name feature introduced in this PR. Update this section to document the new workspace key precedence and recommend metadata.name as the stable, logical component identity for workspace keys.

Consider restructuring this section to explain the workspace key generation order:

  1. Explicit backend.s3.workspace_key_prefix (highest priority)
  2. metadata.name (recommended stable identity—new in this PR)
  3. Component identity (metadata.component)
  4. Component path/name (fallback, auto-normalized slashes to dashes)

Add an example showing how to use metadata.name for workspace key stability, similar to how versioned components can benefit from this approach.

🧹 Nitpick comments (4)
website/docs/quick-start/advanced/configure-terraform-backend.mdx (3)

139-139: Clarify the preferred approach for stable workspace identifiers.

The documentation currently guides users to set explicit workspace_key_prefix values or rely on the component name (with slashes replaced by dashes), but this PR introduces metadata.name as the preferred stable identifier for workspace keys. Update the comment to mention metadata.name as the recommended approach in the new workspace key precedence order: explicit backend prefix → metadata.name → component identity → component path.

-      workspace_key_prefix = "vpc"  # Or any stable identifier for your component
+      workspace_key_prefix = "vpc"  # Or better: use metadata.name for stable identity

320-322: Clarify automatic workspace_key_prefix generation now includes metadata.name.

This paragraph states that Atmos will "automatically add workspace_key_prefix for the component," but doesn't explain the new role of metadata.name in this automatic generation. Clarify that metadata.name (when defined) is now the preferred identifier used during this automatic process, as part of the new precedence order.


388-392: Consider showing metadata.name as an alternative approach in multi-instance examples.

These examples demonstrate explicit workspace_key_prefix configuration for multiple component instances (vpc/1 and vpc/2). With the new metadata.name feature, these could be simplified by defining metadata.name at a base component level, reducing duplication and improving maintainability. Consider adding an example showing how metadata.name can serve as a stable identity across both instances.

Also applies to: 407-410

docs/prd/workspace-key-prefixes.md (1)

244-247: Streamline parallel sentence structure to improve readability.

Three consecutive sentences open with "Update", which creates mechanical repetition. While this emphasizes the parallel changes needed across backend implementations, the effect is slightly awkward.

 Update `setS3BackendDefaults()` similarly for `prefix`.
 
-Update `setGCSBackendDefaults()` similarly for `prefix`.
+Apply the same changes to `setGCSBackendDefaults()` for the `prefix` field.

-Update `setAzureBackendKey()` similarly for `key`.
+Do likewise for `setAzureBackendKey()` to handle the `key` field.

Alternatively, consolidate into a list format for clearer parallelism:

-Update `setS3BackendDefaults()` similarly for `prefix`.
-
-Update `setGCSBackendDefaults()` similarly for `prefix`.
-
-Update `setAzureBackendKey()` similarly for `key`.
+Update backend default functions similarly:
+- `setS3BackendDefaults()` for `prefix`
+- `setGCSBackendDefaults()` for `prefix`
+- `setAzureBackendKey()` for `key`
📜 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 8ecc480 and 387a68d.

📒 Files selected for processing (7)
  • docs/prd/metadata-inheritance.md (1 hunks)
  • docs/prd/workspace-key-prefixes.md (1 hunks)
  • website/blog/2025-11-21-metadata-name-workspace-keys.mdx (1 hunks)
  • website/docs/core-concepts/components/terraform/backends.mdx (2 hunks)
  • website/docs/core-concepts/components/terraform/workspaces.mdx (2 hunks)
  • website/docs/core-concepts/vendor/vendor-manifest.mdx (1 hunks)
  • website/docs/quick-start/advanced/configure-terraform-backend.mdx (1 hunks)
✅ Files skipped from review due to trivial changes (1)
  • website/blog/2025-11-21-metadata-name-workspace-keys.mdx
🚧 Files skipped from review as they are similar to previous changes (1)
  • website/docs/core-concepts/components/terraform/backends.mdx
🧰 Additional context used
📓 Path-based instructions (2)
website/**

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

website/**: Update website documentation in the website/ directory when adding new features, ensure consistency between CLI help text and website documentation, and follow the website's documentation structure and style
Keep website code in the website/ directory, follow the existing website architecture and style, and test website changes locally before committing
Keep CLI documentation and website documentation in sync and document new features on the website with examples and use cases

Files:

  • website/docs/quick-start/advanced/configure-terraform-backend.mdx
  • website/docs/core-concepts/components/terraform/workspaces.mdx
  • website/docs/core-concepts/vendor/vendor-manifest.mdx
docs/prd/**/*.md

📄 CodeRabbit inference engine (CLAUDE.md)

Create PRD documentation in docs/prd/ using kebab-case filenames (e.g., command-registry-pattern.md, error-handling-strategy.md).

Files:

  • docs/prd/metadata-inheritance.md
  • docs/prd/workspace-key-prefixes.md
🧠 Learnings (12)
📚 Learning: 2024-11-02T15:35:09.958Z
Learnt from: aknysh
Repo: cloudposse/atmos PR: 759
File: internal/exec/terraform.go:366-368
Timestamp: 2024-11-02T15:35:09.958Z
Learning: In `internal/exec/terraform.go`, the workspace cleaning code under both the general execution path and within the `case "init":` block is intentionally duplicated because the code execution paths are different. The `.terraform/environment` file should be deleted before executing `terraform init` in both scenarios to ensure a clean state.

Applied to files:

  • website/docs/quick-start/advanced/configure-terraform-backend.mdx
  • website/docs/core-concepts/components/terraform/workspaces.mdx
📚 Learning: 2025-03-18T12:26:25.329Z
Learnt from: Listener430
Repo: cloudposse/atmos PR: 1149
File: tests/snapshots/TestCLICommands_atmos_vendor_pull_ssh.stderr.golden:7-7
Timestamp: 2025-03-18T12:26:25.329Z
Learning: In the Atmos project, typos or inconsistencies in test snapshot files (such as "terrafrom" instead of "terraform") may be intentional as they capture the exact output of commands and should not be flagged as issues requiring correction.

Applied to files:

  • website/docs/quick-start/advanced/configure-terraform-backend.mdx
📚 Learning: 2025-04-25T20:54:19.701Z
Learnt from: mcalhoun
Repo: cloudposse/atmos PR: 963
File: website/docs/core-concepts/projects/configuration/stores.mdx:286-286
Timestamp: 2025-04-25T20:54:19.701Z
Learning: For the AWS SSM Parameter Store implementation in Atmos, support for `read_role_arn` and `write_role_arn` options is essential to enable cross-account access, allowing users to run operations like `terraform plan` in multiple accounts while accessing values across keystores. Azure Key Vault would need similar capabilities for cross-tenant/subscription authentication.

Applied to files:

  • website/docs/quick-start/advanced/configure-terraform-backend.mdx
📚 Learning: 2025-09-10T21:17:55.273Z
Learnt from: samtholiya
Repo: cloudposse/atmos PR: 1466
File: toolchain/http_client_test.go:3-10
Timestamp: 2025-09-10T21:17:55.273Z
Learning: In the cloudposse/atmos repository, imports should never be changed as per samtholiya's coding guidelines.

Applied to files:

  • website/docs/core-concepts/vendor/vendor-manifest.mdx
📚 Learning: 2025-01-25T03:51:57.689Z
Learnt from: Listener430
Repo: cloudposse/atmos PR: 934
File: tests/fixtures/scenarios/docs-generate/README.md.gotmpl:99-118
Timestamp: 2025-01-25T03:51:57.689Z
Learning: For the cloudposse/atmos repository, changes to template contents should be handled in dedicated PRs and are typically considered out of scope for PRs focused on other objectives.

Applied to files:

  • website/docs/core-concepts/vendor/vendor-manifest.mdx
📚 Learning: 2025-07-05T20:59:02.914Z
Learnt from: aknysh
Repo: cloudposse/atmos PR: 1363
File: internal/exec/template_utils.go:18-18
Timestamp: 2025-07-05T20:59:02.914Z
Learning: In the Atmos project, gomplate v4 is imported with a blank import (`_ "github.com/hairyhenderson/gomplate/v4"`) alongside v3 imports to resolve AWS SDK version conflicts. V3 uses older AWS SDK versions that conflict with newer AWS modules used by Atmos. A full migration to v4 requires extensive refactoring due to API changes and should be handled in a separate PR.

Applied to files:

  • website/docs/core-concepts/vendor/vendor-manifest.mdx
📚 Learning: 2025-11-01T20:24:29.557Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 1714
File: NOTICE:0-0
Timestamp: 2025-11-01T20:24:29.557Z
Learning: In the cloudposse/atmos repository, the NOTICE file is programmatically generated and should not be manually edited. Issues with dependency license URLs in NOTICE will be resolved when upstream package metadata is corrected.

Applied to files:

  • website/docs/core-concepts/vendor/vendor-manifest.mdx
📚 Learning: 2025-08-29T20:57:35.423Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 1433
File: cmd/theme_list.go:33-36
Timestamp: 2025-08-29T20:57:35.423Z
Learning: In the Atmos codebase, avoid using viper.SetEnvPrefix("ATMOS") with viper.AutomaticEnv() because canonical environment variable names are not exclusive to Atmos and could cause conflicts. Instead, use selective environment variable binding through the setEnv function in pkg/config/load.go with bindEnv(v, "config.key", "ENV_VAR_NAME") for specific environment variables.

Applied to files:

  • website/docs/core-concepts/vendor/vendor-manifest.mdx
📚 Learning: 2024-10-31T01:22:09.586Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 737
File: examples/demo-vendoring/vendor.d/vendor1.yaml:10-11
Timestamp: 2024-10-31T01:22:09.586Z
Learning: In `examples/demo-vendoring/vendor.d/vendor1.yaml`, when specifying the source for the `ipinfo` component, it's acceptable to use `main` as the version reference if pinning to a specific version is not practical.

Applied to files:

  • website/docs/core-concepts/vendor/vendor-manifest.mdx
📚 Learning: 2025-11-08T19:56:18.660Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 1697
File: internal/exec/oci_utils.go:0-0
Timestamp: 2025-11-08T19:56:18.660Z
Learning: In the Atmos codebase, when a function receives an `*schema.AtmosConfiguration` parameter, it should read configuration values from `atmosConfig.Settings` fields rather than using direct `os.Getenv()` or `viper.GetString()` calls. The Atmos pattern is: viper.BindEnv in cmd/root.go binds environment variables → Viper unmarshals into atmosConfig.Settings via mapstructure → business logic reads from the Settings struct. This provides centralized config management, respects precedence, and enables testability. Example: `atmosConfig.Settings.AtmosGithubToken` instead of `os.Getenv("ATMOS_GITHUB_TOKEN")` in functions like `getGHCRAuth` in internal/exec/oci_utils.go.

Applied to files:

  • website/docs/core-concepts/vendor/vendor-manifest.mdx
📚 Learning: 2024-10-27T16:59:26.187Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 729
File: internal/exec/help.go:48-51
Timestamp: 2024-10-27T16:59:26.187Z
Learning: In the Atmos CLI help messages, when providing examples that include the version number, use the actual version variable (e.g., `version.Version`) instead of placeholders like `<version>`.

Applied to files:

  • website/docs/core-concepts/vendor/vendor-manifest.mdx
📚 Learning: 2025-10-07T00:25:16.333Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 1498
File: website/src/components/Screengrabs/atmos-terraform-metadata--help.html:25-55
Timestamp: 2025-10-07T00:25:16.333Z
Learning: In Atmos CLI, subcommands inherit flags from their parent commands via Cobra's command inheritance. For example, `atmos terraform metadata --help` shows `--affected` and related flags inherited from the parent `terraform` command (defined in cmd/terraform.go), even though the metadata subcommand doesn't explicitly define these flags. This is expected Cobra behavior and auto-generated help screengrabs accurately reflect this inheritance.

Applied to files:

  • docs/prd/metadata-inheritance.md
🪛 LanguageTool
website/docs/core-concepts/components/terraform/workspaces.mdx

[typographical] ~234-~234: In American English, use a period after an abbreviation.
Context: ... behavior :::tip When to Use Templates vs Patterns - **Use `terraform_workspace_t...

(MISSING_PERIOD_AFTER_ABBREVIATION)


[grammar] ~239-~239: Please add a punctuation mark at the end of paragraph.
Context: ...g/Gomplate functions - Complex naming rules - **Use terraform_workspace_pattern*...

(PUNCTUATION_PARAGRAPH_END)


[typographical] ~260-~260: In American English, use a period after an abbreviation.
Context: ...orm.tfstate ``` :::note Workspace Name vs Workspace Key Prefix These are two sepa...

(MISSING_PERIOD_AFTER_ABBREVIATION)

docs/prd/metadata-inheritance.md

[style] ~26-~26: Since ownership is already implied, this phrasing may be redundant.
Context: ...d entirely - each component must define its own metadata. ### Problems This Causes ##...

(PRP_OWN)


[grammar] ~354-~354: Please add a punctuation mark at the end of paragraph.
Context: ... Exclude metadata.inherits from being inherited 2. Modify `internal/exec/stack_process...

(PUNCTUATION_PARAGRAPH_END)

docs/prd/workspace-key-prefixes.md

[typographical] ~66-~66: Consider using a typographic opening quote here.
Context: ...e metadata-inheritance.md) - Represents "what this component IS" vs "where its co...

(EN_QUOTES)


[typographical] ~66-~66: Consider using a typographic close quote here.
Context: ...md) - Represents "what this component IS" vs "where its code lives" ### Updated ...

(EN_QUOTES)


[typographical] ~66-~66: Consider using a typographic opening quote here.
Context: ... Represents "what this component IS" vs "where its code lives" ### Updated Calcu...

(EN_QUOTES)


[typographical] ~66-~66: Consider using a typographic close quote here.
Context: ...s component IS" vs "where its code lives" ### Updated Calculation Logic **New p...

(EN_QUOTES)


[style] ~246-~246: Three successive sentences begin with the same word. Consider rewording the sentence or use a thesaurus to find a synonym.
Context: ...endDefaults()similarly forprefix. Update setAzureBackendKey()similarly fork...

(ENGLISH_WORD_REPEAT_BEGINNING_RULE)

⏰ Context from checks skipped due to timeout of 900000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: Acceptance Tests (windows)
  • GitHub Check: Summary
🔇 Additional comments (12)
docs/prd/metadata-inheritance.md (3)

73-121: Clear and comprehensive inheritance specification.

The inheritance behavior table and special-case definitions (lines 107-121) effectively communicate which metadata fields propagate and why metadata.type: abstract is excluded. This directly supports the PR objective of preventing abstract components from becoming deployable through inheritance.


140-166: Workspace key precedence logic is well-documented and aligns with implementation intent.

The four-level priority order (explicit backend prefix → metadata.name → metadata.component → component name) matches the PR objectives. The pseudocode at lines 153-159 provides clarity for implementers.


285-325: Breaking change assessment is prudent and migration path is practical.

The low-risk evaluation correctly identifies that most existing codebases don't populate metadata in abstract base components, and the override mechanism provides an escape hatch. The two migration strategies (disable inheritance or override specific fields) are straightforward for users encountering unexpected behavior.

docs/prd/workspace-key-prefixes.md (4)

69-101: Priority order and pseudocode are precise and implementable.

The table at lines 71–77 and the accompanying pseudocode (lines 81–101) clearly define the four-level priority with explicit handling for each case. This directly implements the PR objective for workspace key precedence and ensures explicit backend configuration always wins (priority 1).


113-202: Use cases effectively demonstrate practical value and backwards compatibility.

Five scenarios span real problems (versioned components, release tracks, multiple instances) and reassure users that existing configurations without metadata.name continue working unchanged. Use Case 5 (lines 204–218) is particularly valuable for adoption confidence.


327-372: Migration guidance balances pragmatism with safety.

The distinction between new projects (straightforward adoption) and existing projects (careful consideration of state location) shows appropriate caution. The three-step migration path (lines 350–372) with state-preservation alternatives gives users agency over their transition.


382-384: Cross-reference to metadata inheritance establishes clear dependency.

The dependency note correctly identifies that for metadata.name to be inherited from base components, the metadata inheritance feature must be enabled. This ensures users understand the interaction between the two features.

website/docs/core-concepts/components/terraform/workspaces.mdx (4)

260-276: Fix punctuation in note about Workspace Name vs Workspace Key Prefix.

Line 260: ":::note Workspace Name vs Workspace Key Prefix" needs a period after the abbreviation "vs" in American English.

Apply this diff:

-:::note Workspace Name vs Workspace Key Prefix
+:::note Workspace Name vs. Workspace Key Prefix

318-320: Good addition of Terraform Backends reference.

The new reference link complements the workspace documentation and provides readers with guidance on backend configuration.


195-313: Overall: Strong documentation aligned with PR objectives.

The new sections effectively document metadata.name as a stable workspace key identity and provide comprehensive guidance on workspace naming strategies (Go templates, patterns, and static values). The content complements the backend documentation and includes practical examples.

Minor punctuation issues flagged above should be addressed. Beyond that, the documentation achieves the PR goal of explaining metadata.name-driven stability and improving workspace configuration clarity.

As a follow-up, ensure that:

  1. The automatic Terraform workspace calculation and default stack name behavior still accurately reflects the current implementation after metadata inheritance changes
  2. The workspace_key_prefix priority order (explicit backend → metadata.name → component identity → component path) is consistently applied across all backend types in the implementation

281-313: Documentation accurately reflects implementation—workspace_key_prefix priority is consistent across all backends.

Verification confirms that the documented priority order (explicit backend → metadata.name → metadata.component → Atmos component name) is correctly and consistently implemented:

  • S3 backend (setS3BackendDefaults): Uses workspace_key_prefix with documented priority
  • GCS backend (setGCSBackendDefaults): Uses prefix with same priority order
  • Azure backend (setAzureBackendKey): Uses key with same priority order

All three implementations follow the exact priority sequence described in lines 281-289, and the practical example showing how metadata.name prevents version information from leaking into state paths is accurate.

website/docs/core-concepts/vendor/vendor-manifest.mdx (1)

555-624: Documentation is technically accurate and well-structured; no corrections needed.

The verification confirms that the workspace key prefix guidance in lines 553-624 is correct and properly implemented:

Priority table verified: The four-level priority (explicit backend config → metadata.name → metadata.component → component name) exactly matches the implementation in internal/exec/stack_processor_backend.go

YAML examples verified: All examples align with actual test cases in stack_processor_backend_test.go, including the automatic slash-to-dash conversion (e.g., network/vpcnetwork-vpc)

Backend coverage verified: S3, GCS, and Azure backends all follow identical priority logic with the same documentation pattern

Contextual placement verified: The section follows logically from the "Vendoring Multiple Versions" section and precedes "Vendoring from OCI Registries"

Documentation style verified: Code blocks, YAML formatting, and admonitions (tip block, important note) are consistent with the website's established patterns

The section effectively demonstrates why metadata.name solves the state migration problem when upgrading component versions, with clear before/after comparisons. The legacy section appropriately documents the prior manual workaround approach.

The optional cross-reference suggestion from the review (linking to metadata inheritance documentation) would be a nice-to-have but is not necessary for documentation completeness—users can search for metadata-related topics independently.

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

🧹 Nitpick comments (4)
docs/prd/metadata-inheritance.md (2)

26-26: Minor: Phrasing could be tightened.

Line 26 says "each component must define its own metadata" — the subject is implied by context. Consider: "...only that metadata is excluded entirely from inheritance" (removes "each component must define its own").


329-370: Implementation section is detailed and references real code paths.

Schema changes (lines 329–345), stack processor changes (lines 351–363), and JSON schema updates (lines 365–369) are concrete and point to actual files. This is helpful for reviewers tracking implementation.

One note: Line 354 is missing a period at the end of the "Exclude metadata.inherits..." item. Add punctuation:

-   - Exclude `metadata.inherits` from being inherited
+   - Exclude `metadata.inherits` from being inherited.
website/docs/core-concepts/components/terraform/workspaces.mdx (1)

195-233: New section on Go templates is well-structured and timely.

The "Using Go Templates for Workspace Names" section (lines 195–232) effectively bridges simple patterns and advanced templating. The priority order (terraform_workspace_template > pattern > terraform_workspace > auto-generated) is clear and matches the PRD. The tip (lines 234–247) helps users choose the right tool.

Minor: Line 234 should read "Use terraform_workspace_template..." with a period after the closing backtick. Similarly, line 239 and line 245 need periods at the end of list items for consistency.

docs/prd/workspace-key-prefixes.md (1)

220-283: Implementation section is concrete and actionable.

Lines 224–242 show the updated setS3BackendDefaults() function with metadata parameter. Signature change (lines 249–259) is clear. Schema changes (lines 265–282) specify JSON schema addition for metadata.name. Function signature updates to setGCSBackendDefaults() and setAzureBackendKey() are mentioned (lines 245–247).

One note: Line 246 has three successive sentences beginning with "Update": "Update setGCSBackendDefaults() similarly..." and "Update setAzureBackendKey() similarly...". Consider varying sentence structure:

-Update `setGCSBackendDefaults()` similarly for `prefix`.
+Apply the same logic to `setGCSBackendDefaults()` for `prefix`.

-Update `setAzureBackendKey()` similarly for `key`.
+Apply the same logic to `setAzureBackendKey()` for `key`.

This is minor but improves readability.

📜 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 8ecc480 and 387a68d.

📒 Files selected for processing (7)
  • docs/prd/metadata-inheritance.md (1 hunks)
  • docs/prd/workspace-key-prefixes.md (1 hunks)
  • website/blog/2025-11-21-metadata-name-workspace-keys.mdx (1 hunks)
  • website/docs/core-concepts/components/terraform/backends.mdx (2 hunks)
  • website/docs/core-concepts/components/terraform/workspaces.mdx (2 hunks)
  • website/docs/core-concepts/vendor/vendor-manifest.mdx (1 hunks)
  • website/docs/quick-start/advanced/configure-terraform-backend.mdx (1 hunks)
✅ Files skipped from review due to trivial changes (1)
  • website/docs/quick-start/advanced/configure-terraform-backend.mdx
🚧 Files skipped from review as they are similar to previous changes (2)
  • website/docs/core-concepts/components/terraform/backends.mdx
  • website/blog/2025-11-21-metadata-name-workspace-keys.mdx
🧰 Additional context used
📓 Path-based instructions (2)
website/**

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

website/**: Update website documentation in the website/ directory when adding new features, ensure consistency between CLI help text and website documentation, and follow the website's documentation structure and style
Keep website code in the website/ directory, follow the existing website architecture and style, and test website changes locally before committing
Keep CLI documentation and website documentation in sync and document new features on the website with examples and use cases

Files:

  • website/docs/core-concepts/components/terraform/workspaces.mdx
  • website/docs/core-concepts/vendor/vendor-manifest.mdx
docs/prd/**/*.md

📄 CodeRabbit inference engine (CLAUDE.md)

Create PRD documentation in docs/prd/ using kebab-case filenames (e.g., command-registry-pattern.md, error-handling-strategy.md).

Files:

  • docs/prd/workspace-key-prefixes.md
  • docs/prd/metadata-inheritance.md
🧠 Learnings (9)
📚 Learning: 2024-11-02T15:35:09.958Z
Learnt from: aknysh
Repo: cloudposse/atmos PR: 759
File: internal/exec/terraform.go:366-368
Timestamp: 2024-11-02T15:35:09.958Z
Learning: In `internal/exec/terraform.go`, the workspace cleaning code under both the general execution path and within the `case "init":` block is intentionally duplicated because the code execution paths are different. The `.terraform/environment` file should be deleted before executing `terraform init` in both scenarios to ensure a clean state.

Applied to files:

  • website/docs/core-concepts/components/terraform/workspaces.mdx
📚 Learning: 2025-01-25T03:51:57.689Z
Learnt from: Listener430
Repo: cloudposse/atmos PR: 934
File: tests/fixtures/scenarios/docs-generate/README.md.gotmpl:99-118
Timestamp: 2025-01-25T03:51:57.689Z
Learning: For the cloudposse/atmos repository, changes to template contents should be handled in dedicated PRs and are typically considered out of scope for PRs focused on other objectives.

Applied to files:

  • website/docs/core-concepts/components/terraform/workspaces.mdx
📚 Learning: 2025-07-05T20:59:02.914Z
Learnt from: aknysh
Repo: cloudposse/atmos PR: 1363
File: internal/exec/template_utils.go:18-18
Timestamp: 2025-07-05T20:59:02.914Z
Learning: In the Atmos project, gomplate v4 is imported with a blank import (`_ "github.com/hairyhenderson/gomplate/v4"`) alongside v3 imports to resolve AWS SDK version conflicts. V3 uses older AWS SDK versions that conflict with newer AWS modules used by Atmos. A full migration to v4 requires extensive refactoring due to API changes and should be handled in a separate PR.

Applied to files:

  • website/docs/core-concepts/vendor/vendor-manifest.mdx
📚 Learning: 2025-08-29T20:57:35.423Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 1433
File: cmd/theme_list.go:33-36
Timestamp: 2025-08-29T20:57:35.423Z
Learning: In the Atmos codebase, avoid using viper.SetEnvPrefix("ATMOS") with viper.AutomaticEnv() because canonical environment variable names are not exclusive to Atmos and could cause conflicts. Instead, use selective environment variable binding through the setEnv function in pkg/config/load.go with bindEnv(v, "config.key", "ENV_VAR_NAME") for specific environment variables.

Applied to files:

  • website/docs/core-concepts/vendor/vendor-manifest.mdx
📚 Learning: 2024-10-31T01:22:09.586Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 737
File: examples/demo-vendoring/vendor.d/vendor1.yaml:10-11
Timestamp: 2024-10-31T01:22:09.586Z
Learning: In `examples/demo-vendoring/vendor.d/vendor1.yaml`, when specifying the source for the `ipinfo` component, it's acceptable to use `main` as the version reference if pinning to a specific version is not practical.

Applied to files:

  • website/docs/core-concepts/vendor/vendor-manifest.mdx
📚 Learning: 2025-11-08T19:56:18.660Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 1697
File: internal/exec/oci_utils.go:0-0
Timestamp: 2025-11-08T19:56:18.660Z
Learning: In the Atmos codebase, when a function receives an `*schema.AtmosConfiguration` parameter, it should read configuration values from `atmosConfig.Settings` fields rather than using direct `os.Getenv()` or `viper.GetString()` calls. The Atmos pattern is: viper.BindEnv in cmd/root.go binds environment variables → Viper unmarshals into atmosConfig.Settings via mapstructure → business logic reads from the Settings struct. This provides centralized config management, respects precedence, and enables testability. Example: `atmosConfig.Settings.AtmosGithubToken` instead of `os.Getenv("ATMOS_GITHUB_TOKEN")` in functions like `getGHCRAuth` in internal/exec/oci_utils.go.

Applied to files:

  • website/docs/core-concepts/vendor/vendor-manifest.mdx
📚 Learning: 2024-10-27T16:59:26.187Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 729
File: internal/exec/help.go:48-51
Timestamp: 2024-10-27T16:59:26.187Z
Learning: In the Atmos CLI help messages, when providing examples that include the version number, use the actual version variable (e.g., `version.Version`) instead of placeholders like `<version>`.

Applied to files:

  • website/docs/core-concepts/vendor/vendor-manifest.mdx
📚 Learning: 2024-11-23T00:13:22.004Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 801
File: examples/quick-start-advanced/Dockerfile:9-9
Timestamp: 2024-11-23T00:13:22.004Z
Learning: When updating the `ATMOS_VERSION` in Dockerfiles, the team prefers to pin to the next future version when the PR merges, even if the version is not yet released.

Applied to files:

  • website/docs/core-concepts/vendor/vendor-manifest.mdx
📚 Learning: 2025-10-07T00:25:16.333Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 1498
File: website/src/components/Screengrabs/atmos-terraform-metadata--help.html:25-55
Timestamp: 2025-10-07T00:25:16.333Z
Learning: In Atmos CLI, subcommands inherit flags from their parent commands via Cobra's command inheritance. For example, `atmos terraform metadata --help` shows `--affected` and related flags inherited from the parent `terraform` command (defined in cmd/terraform.go), even though the metadata subcommand doesn't explicitly define these flags. This is expected Cobra behavior and auto-generated help screengrabs accurately reflect this inheritance.

Applied to files:

  • docs/prd/metadata-inheritance.md
🪛 LanguageTool
website/docs/core-concepts/components/terraform/workspaces.mdx

[typographical] ~234-~234: In American English, use a period after an abbreviation.
Context: ... behavior :::tip When to Use Templates vs Patterns - **Use `terraform_workspace_t...

(MISSING_PERIOD_AFTER_ABBREVIATION)


[grammar] ~239-~239: Please add a punctuation mark at the end of paragraph.
Context: ...g/Gomplate functions - Complex naming rules - **Use terraform_workspace_pattern*...

(PUNCTUATION_PARAGRAPH_END)


[typographical] ~260-~260: In American English, use a period after an abbreviation.
Context: ...orm.tfstate ``` :::note Workspace Name vs Workspace Key Prefix These are two sepa...

(MISSING_PERIOD_AFTER_ABBREVIATION)

docs/prd/workspace-key-prefixes.md

[typographical] ~66-~66: Consider using a typographic opening quote here.
Context: ...e metadata-inheritance.md) - Represents "what this component IS" vs "where its co...

(EN_QUOTES)


[typographical] ~66-~66: Consider using a typographic close quote here.
Context: ...md) - Represents "what this component IS" vs "where its code lives" ### Updated ...

(EN_QUOTES)


[typographical] ~66-~66: Consider using a typographic opening quote here.
Context: ... Represents "what this component IS" vs "where its code lives" ### Updated Calcu...

(EN_QUOTES)


[typographical] ~66-~66: Consider using a typographic close quote here.
Context: ...s component IS" vs "where its code lives" ### Updated Calculation Logic **New p...

(EN_QUOTES)


[style] ~246-~246: Three successive sentences begin with the same word. Consider rewording the sentence or use a thesaurus to find a synonym.
Context: ...endDefaults()similarly forprefix. Update setAzureBackendKey()similarly fork...

(ENGLISH_WORD_REPEAT_BEGINNING_RULE)

docs/prd/metadata-inheritance.md

[style] ~26-~26: Since ownership is already implied, this phrasing may be redundant.
Context: ...d entirely - each component must define its own metadata. ### Problems This Causes ##...

(PRP_OWN)


[grammar] ~354-~354: Please add a punctuation mark at the end of paragraph.
Context: ... Exclude metadata.inherits from being inherited 2. Modify `internal/exec/stack_process...

(PUNCTUATION_PARAGRAPH_END)

🪛 markdownlint-cli2 (0.18.1)
docs/prd/workspace-key-prefixes.md

5-5: Emphasis used instead of a heading

(MD036, no-emphasis-as-heading)

docs/prd/metadata-inheritance.md

5-5: Emphasis used instead of a heading

(MD036, no-emphasis-as-heading)

⏰ Context from checks skipped due to timeout of 900000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Summary
🔇 Additional comments (12)
website/docs/core-concepts/vendor/vendor-manifest.mdx (2)

553-591: Excellent addition—priority order and problem explanation are clear.

The new section effectively educates users on metadata.name as the stable identity for versioned components. The priority table and YAML examples clearly show the problem (version-leaking into state paths) and the recommended solution. The callout at line 586 reinforces why this matters.

Minor suggestion: The phrase "When you upgrade to vpc/2.0.0, workspace_key_prefix STAYS vpc" (line 582) could be slightly clearer by saying "...the value of workspace_key_prefix remains vpc" to avoid ambiguity about what "STAYS" refers to.


592-625: Good coverage of alternatives and legacy patterns.

The explicit override (592–606) and legacy workaround sections (608–622) provide clear migration paths. The distinction between the three approaches is helpful.

Note at line 626–628 correctly flags non-S3 backends but could link to the backend-specific documentation if available (e.g., GCS prefix or Azure key) for completeness.

docs/prd/metadata-inheritance.md (3)

103-121: Inheritance behavior table is clear and well-motivated.

The table correctly documents which fields inherit and which don't. The special treatment of metadata.type: abstract (marked as partial, with justification) and metadata.inherits (excluded) aligns with the problem statement and prevents abstract components from being inherited as deployable. Good.


168-284: Use cases are practical and cover key patterns.

The four use cases (versioned components, release tracks, governance, multiple instances) effectively illustrate the feature's value. Each example shows both the base component definition and derived usage, making the inheritance flow clear.


285-326: Breaking change assessment is realistic and provides migration path.

The analysis correctly identifies low risk (most users don't set metadata in abstract base components, derived components can override). The migration path (disable via stacks.inherit.metadata: false or override specific fields) is practical. Good risk communication.

website/docs/core-concepts/components/terraform/workspaces.mdx (2)

249-276: "How Workspaces Relate to State Paths" section adds essential clarity.

This section (lines 249–276) explains the two-level hierarchy (workspace_key_prefix + workspace) and explicitly distinguishes the two concepts. This is a critical mental model for users and was previously missing. The :::note callout (lines 260–276) is especially valuable for preventing confusion.

The ASCII diagram at lines 253–258 clearly shows the S3 path structure.


281-313: workspace_key_prefix auto-generation guidance is accurate and practical.

Priority order (lines 285–288) and the example (lines 294–309) correctly show how metadata.name provides stable state paths across version upgrades. The connection to the design-patterns doc (line 312) is helpful for users implementing versioned components.

docs/prd/workspace-key-prefixes.md (5)

68-101: Priority logic and pseudocode are clear and implementable.

The priority order (explicit backend > metadata.name > metadata.component > Atmos component name) is consistent across all docs. The pseudocode (lines 82–100) clearly shows the logic and fallback behavior. Good implementation guidance.


103-111: Backward compatibility claim is well-justified.

Lines 103–111 correctly argue that metadata.name is optional and falls back gracefully to current behavior. No breaking change. Clear statement.


113-219: Use cases are comprehensive and realistic.

Five use cases (versioned folders, release tracks, inheritance, multiple instances, no-metadata) cover real patterns. Each includes concrete YAML examples. Use Case 5 (lines 204–218) explicitly addresses backward compatibility by showing configs without metadata.name still work. Good coverage.


312-373: Migration guide is practical and well-differentiated.

Lines 312–373 separate guidance for new projects (start with metadata.name) vs existing projects (two scenarios: with/without explicit workspace_key_prefix). The scenario with existing versioned state (lines 348–372) correctly warns that adding metadata.name without careful planning could "lose" the existing state if the name doesn't match the current key. Good risk communication.


374-390: Success criteria and dependencies are clear.

Lines 374–390 establish measurable success criteria (5 items) and explicitly note dependency on metadata-inheritance.md feature. Good closure for a comprehensive PRD.

osterman and others added 2 commits November 28, 2025 18:34
Fixed missing terminal punctuation and standardized formatting:

**docs/prd/metadata-inheritance.md:**
- Added period to end of bullet "Exclude metadata.inherits from being inherited"

**website/docs/core-concepts/components/terraform/workspaces.mdx:**
- Changed "When to Use Templates vs Patterns" → "When to Use Templates vs. Patterns"
- Added periods to end of bullets under terraform_workspace_pattern
- Added period to end of bullet under terraform_workspace

**Note:** docs/prd/metadata-inheritance.md and docs/prd/workspace-key-prefixes.md
already have proper heading structure with "## Status" followed by "**Implemented**"
on the next line, which is correct Markdown format.

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

Co-Authored-By: Claude <[email protected]>
coderabbitai[bot]
coderabbitai bot previously approved these changes Nov 29, 2025
Focus on user pain points (governance at scale) rather than technical details.

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

Co-Authored-By: Claude <[email protected]>
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

♻️ Duplicate comments (1)
docs/prd/metadata-inheritance.md (1)

3-5: Use heading instead of emphasis for Status section.

Line 5 uses **Implemented** (bold), which violates markdownlint MD036. Per coding guidelines for docs/prd/**/*.md, use a proper Markdown heading to maintain visual hierarchy and enable proper documentation indexing.

 ## Status
 
-**Implemented**
+### Implemented
🧹 Nitpick comments (2)
website/docs/core-concepts/components/terraform/workspaces.mdx (2)

234-247: Minor: Fix punctuation consistency and reduce repetition in "When to Use" section.

The section introduces three use cases but repeats "when you need" across all three bullets (lines 235, 241, 245). Additionally, line 239 ("Complex naming rules") lacks the ending period that the other bullets have.

Apply this diff for consistency:

 :::tip When to Use Templates vs. Patterns
-- **Use `terraform_workspace_template`** when you need:
+- **Use `terraform_workspace_template`** for:
   - String manipulation (upper/lower case, substring, etc.)
   - Conditional logic
   - Access to Sprig/Gomplate functions
-  - Complex naming rules
+  - Complex naming rules.
 
-- **Use `terraform_workspace_pattern`** when you need:
+- **Use `terraform_workspace_pattern`** for:
   - Simple token replacement with context variables.
   - Straightforward naming patterns.
 
-- **Use `terraform_workspace`** when you need:
+- **Use `terraform_workspace`** for:
   - A fixed, static workspace name.

This removes the repetitive phrase and adds the missing period to the "Complex naming rules" bullet.


260-260: Minor: Add period after abbreviation in note title.

Line 260 title should use "vs." (with period) to follow American English conventions.

-:::note Workspace Name vs Workspace Key Prefix
+:::note Workspace Name vs. Workspace Key Prefix
📜 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 387a68d and 8a0987e.

📒 Files selected for processing (3)
  • docs/prd/metadata-inheritance.md (1 hunks)
  • website/blog/2025-11-21-metadata-inheritance.mdx (1 hunks)
  • website/docs/core-concepts/components/terraform/workspaces.mdx (2 hunks)
🧰 Additional context used
📓 Path-based instructions (3)
website/**

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

website/**: Update website documentation in the website/ directory when adding new features, ensure consistency between CLI help text and website documentation, and follow the website's documentation structure and style
Keep website code in the website/ directory, follow the existing website architecture and style, and test website changes locally before committing
Keep CLI documentation and website documentation in sync and document new features on the website with examples and use cases

Files:

  • website/docs/core-concepts/components/terraform/workspaces.mdx
  • website/blog/2025-11-21-metadata-inheritance.mdx
website/blog/**/*.mdx

📄 CodeRabbit inference engine (CLAUDE.md)

PRs labeled minor/major MUST include blog post at website/blog/YYYY-MM-DD-feature-name.mdx with YAML front matter, after intro, tags (feature/enhancement/bugfix/contributors), and author (committer's GitHub username).

Files:

  • website/blog/2025-11-21-metadata-inheritance.mdx
docs/prd/**/*.md

📄 CodeRabbit inference engine (CLAUDE.md)

Create PRD documentation in docs/prd/ using kebab-case filenames (e.g., command-registry-pattern.md, error-handling-strategy.md).

Files:

  • docs/prd/metadata-inheritance.md
🧠 Learnings (5)
📚 Learning: 2024-11-02T15:35:09.958Z
Learnt from: aknysh
Repo: cloudposse/atmos PR: 759
File: internal/exec/terraform.go:366-368
Timestamp: 2024-11-02T15:35:09.958Z
Learning: In `internal/exec/terraform.go`, the workspace cleaning code under both the general execution path and within the `case "init":` block is intentionally duplicated because the code execution paths are different. The `.terraform/environment` file should be deleted before executing `terraform init` in both scenarios to ensure a clean state.

Applied to files:

  • website/docs/core-concepts/components/terraform/workspaces.mdx
📚 Learning: 2025-01-25T03:51:57.689Z
Learnt from: Listener430
Repo: cloudposse/atmos PR: 934
File: tests/fixtures/scenarios/docs-generate/README.md.gotmpl:99-118
Timestamp: 2025-01-25T03:51:57.689Z
Learning: For the cloudposse/atmos repository, changes to template contents should be handled in dedicated PRs and are typically considered out of scope for PRs focused on other objectives.

Applied to files:

  • website/docs/core-concepts/components/terraform/workspaces.mdx
📚 Learning: 2025-03-18T12:26:25.329Z
Learnt from: Listener430
Repo: cloudposse/atmos PR: 1149
File: tests/snapshots/TestCLICommands_atmos_vendor_pull_ssh.stderr.golden:7-7
Timestamp: 2025-03-18T12:26:25.329Z
Learning: In the Atmos project, typos or inconsistencies in test snapshot files (such as "terrafrom" instead of "terraform") may be intentional as they capture the exact output of commands and should not be flagged as issues requiring correction.

Applied to files:

  • website/docs/core-concepts/components/terraform/workspaces.mdx
📚 Learning: 2025-11-24T17:35:20.297Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-24T17:35:20.297Z
Learning: Applies to website/blog/**/*.mdx : PRs labeled minor/major MUST include blog post at website/blog/YYYY-MM-DD-feature-name.mdx with YAML front matter, <!--truncate--> after intro, tags (feature/enhancement/bugfix/contributors), and author (committer's GitHub username).

Applied to files:

  • website/blog/2025-11-21-metadata-inheritance.mdx
📚 Learning: 2025-10-07T00:25:16.333Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 1498
File: website/src/components/Screengrabs/atmos-terraform-metadata--help.html:25-55
Timestamp: 2025-10-07T00:25:16.333Z
Learning: In Atmos CLI, subcommands inherit flags from their parent commands via Cobra's command inheritance. For example, `atmos terraform metadata --help` shows `--affected` and related flags inherited from the parent `terraform` command (defined in cmd/terraform.go), even though the metadata subcommand doesn't explicitly define these flags. This is expected Cobra behavior and auto-generated help screengrabs accurately reflect this inheritance.

Applied to files:

  • website/blog/2025-11-21-metadata-inheritance.mdx
  • docs/prd/metadata-inheritance.md
🪛 LanguageTool
website/docs/core-concepts/components/terraform/workspaces.mdx

[grammar] ~239-~239: Please add a punctuation mark at the end of paragraph.
Context: ...g/Gomplate functions - Complex naming rules - **Use terraform_workspace_pattern*...

(PUNCTUATION_PARAGRAPH_END)


[style] ~241-~241: This word has been used in one of the immediately preceding sentences. Using a synonym could make your text more interesting to read, unless the repetition is intentional.
Context: ...terraform_workspace_pattern`** when you need: - Simple token replacement with cont...

(EN_REPEATEDWORDS_NEED)


[style] ~245-~245: This word has been used in one of the immediately preceding sentences. Using a synonym could make your text more interesting to read, unless the repetition is intentional.
Context: ... Use terraform_workspace when you need: - A fixed, static workspace name. ::...

(EN_REPEATEDWORDS_NEED)


[typographical] ~260-~260: In American English, use a period after an abbreviation.
Context: ...orm.tfstate ``` :::note Workspace Name vs Workspace Key Prefix These are two sepa...

(MISSING_PERIOD_AFTER_ABBREVIATION)

docs/prd/metadata-inheritance.md

[style] ~26-~26: Since ownership is already implied, this phrasing may be redundant.
Context: ...d entirely - each component must define its own metadata. ### Problems This Causes ##...

(PRP_OWN)

🪛 markdownlint-cli2 (0.18.1)
docs/prd/metadata-inheritance.md

5-5: Emphasis used instead of a heading

(MD036, no-emphasis-as-heading)

⏰ Context from checks skipped due to timeout of 900000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (4)
  • GitHub Check: Acceptance Tests (macos)
  • GitHub Check: Acceptance Tests (linux)
  • GitHub Check: Acceptance Tests (windows)
  • GitHub Check: Summary
🔇 Additional comments (4)
website/blog/2025-11-21-metadata-inheritance.mdx (1)

1-70: Blog post meets all coding guidelines.

YAML frontmatter, filename format, author attribution, tags, and truncate delimiter all align with website/blog/**/*.mdx requirements. The narrative structure (problem → solution → configuration) is clear and the YAML examples effectively illustrate the feature.

website/docs/core-concepts/components/terraform/workspaces.mdx (3)

11-11: Import addition approved.

The PillBox component import aligns with its usage on line 197 for the "Advanced" label.


195-227: Excellent documentation of metadata.name and workspace key generation.

The new sections thoroughly document the Go template workflow, priority order for workspace configuration, and the metadata.name-driven auto-generation of workspace_key_prefix. The versioned component example (lines 294-303) effectively illustrates how metadata.name prevents version information from leaking into state paths—directly supporting the PR's key feature.

Also applies to: 228-232, 281-314


1-373: Documentation structure and style compliant.

The changes follow the existing website documentation patterns with proper use of MDX components (File, Terminal, PillBox), consistent formatting, and clear section organization. The content depth and examples are appropriate for the feature scope.

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

Labels

minor New features that do not break anything size/xl Extra large size PR

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants