Skip to content

Conversation

@osterman
Copy link
Member

@osterman osterman commented Dec 20, 2025

Summary

  • Implement shell completion for semantic-typed flags and arguments (component/stack types)
  • Add interactive prompting for missing required semantic-typed values
  • Support custom component types in shell completions

What Changed

  • New custom component type provider system (pkg/component/custom)
  • Shell completion for semantic-typed arguments and flags in custom commands
  • Interactive prompting for missing required semantic-typed values
  • Extended command schema to support semantic types and components
  • Comprehensive test coverage for completion and prompting functionality

Why This Matters

This feature enables custom commands to provide superior developer experience through:

  • Tab completion for component and stack arguments/flags
  • Interactive prompts for required semantic-typed values
  • Support for custom component types beyond built-in types

References

🤖 Generated with Claude Code

Summary by CodeRabbit

Release Notes

  • New Features

    • Support for custom component types beyond built-in Terraform, Helmfile, and Packer.
    • Enhanced CLI shell completion for component and stack selection.
    • Interactive prompting for missing semantic-typed arguments and flags.
    • Template variable access to component configuration data.
  • Documentation

    • Added comprehensive guides for defining and using custom component types.
    • Added example scripts demonstrating custom component workflows.
    • Updated schema definitions to support custom components.

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

@osterman osterman requested review from a team as code owners December 20, 2025 07:37
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Dec 20, 2025

Warning

Rate limit exceeded

@osterman has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 24 minutes and 7 seconds before requesting another review.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

📥 Commits

Reviewing files that changed from the base of the PR and between 24fe365 and 49c190f.

📒 Files selected for processing (21)
  • cmd/cmd_semantic_completion.go
  • cmd/cmd_semantic_completion_test.go
  • cmd/cmd_utils.go
  • cmd/cmd_utils_test.go
  • errors/errors.go
  • examples/custom-components/README.md
  • examples/custom-components/atmos.yaml
  • examples/custom-components/components/script/deploy-app/deploy.sh
  • examples/custom-components/stacks/catalog/script/deploy-app.yaml
  • examples/custom-components/stacks/deploy/dev.yaml
  • internal/exec/describe_component.go
  • internal/exec/describe_component_test.go
  • internal/exec/stack_processor_process_stacks.go
  • internal/exec/stack_processor_process_stacks_test.go
  • internal/exec/vendor_utils.go
  • pkg/component/custom/provider.go
  • pkg/component/custom/provider_test.go
  • pkg/component/registry.go
  • pkg/component/registry_test.go
  • pkg/schema/command.go
  • tests/fixtures/schemas/atmos/atmos-manifest/1.0/atmos-manifest.json
📝 Walkthrough

Walkthrough

Adds support for custom component types and semantic CLI completion: new provider/registry APIs, command schema extensions, semantic-driven shell completion and interactive prompting, stack/component processing updates, schema and docs, plus example custom-component assets and tests.

Changes

Cohort / File(s) Summary
Semantic completion
cmd/cmd_semantic_completion.go, cmd/cmd_semantic_completion_test.go
New semantic completion and interactive prompting (PromptConfig, DefaultPromptConfig, completion & prompt helpers, perf tracking) with comprehensive tests and graceful-degradation paths.
Custom command integration
cmd/cmd_utils.go, cmd/cmd_utils_test.go
Wire semantic completions into custom command creation, add findTypedValue and processCustomComponentType to resolve/expose component config; tests for command processing and typed-value extraction.
Custom component provider
pkg/component/custom/provider.go, pkg/component/custom/provider_test.go
New dynamic Provider implementation (ListComponents, EnsureRegistered, metadata methods), no-op exec/artifact hooks, and unit tests.
Component registry
pkg/component/registry.go, pkg/component/registry_test.go
Adds ListAllComponents(ctx, componentType, stacksMap) to aggregate/deduplicate components across stacks with graceful degradation; tests updated for per-stack listing and errors.
CLI schema/types
pkg/schema/command.go
New CommandArgument, CommandFlag (SemanticType), CommandEnv, CommandComponent types and added Command.Component field for custom component declarations.
Describe component flow
internal/exec/describe_component.go, internal/exec/describe_component_test.go
Propagate explicit ComponentType through describe flows, add per-type processing helpers, and add tests for filtering, file output, and imports extraction.
Stack processing
internal/exec/stack_processor_process_stacks.go, internal/exec/stack_processor_process_stacks_test.go
Add processing for custom component types: merge vars/settings/env, inject metadata, include custom types in allComponents; tests for happy path, filters, and custom type behavior.
Error sentinels
errors/errors.go
Add ErrCustomComponentTypeRegistration, ErrComponentArgumentNotFound, ErrStackArgumentNotFound.
Manifest schema (core & website)
tests/fixtures/schemas/.../atmos-manifest.json, website/static/schemas/.../atmos-manifest.json
Add custom_components and custom_component_manifest definitions and wire additionalProperties to allow custom component types alongside built-ins.
Examples
examples/custom-components/README.md, examples/custom-components/atmos.yaml, examples/custom-components/components/script/..., examples/custom-components/stacks/...
New example demonstrating a "script" custom component type: docs, config, deploy script, and stack files.
Docs / Blog / Roadmap
website/blog/2025-12-20-custom-component-types.mdx, website/docs/cli/configuration/commands.mdx, website/src/data/roadmap.js
New blog and CLI docs (duplicated section in commands.mdx), and roadmap milestone updates referencing PR/changelog.
Vendor utilities
internal/exec/vendor_utils.go
Minor path-normalization simplifications (removed ToSlash conversions).

Sequence Diagram(s)

sequenceDiagram
    autonumber
    participant U as User/CLI
    participant Cmd as Command Handler
    participant Reg as Component Registry
    participant Prov as Custom Provider
    participant Prompt as Prompt (PromptConfig)
    participant Exec as Executor

    U->>Cmd: invoke custom command (missing semantic values)
    Cmd->>Reg: Load stacks map & request components for type
    Reg->>Prov: ListComponents(stackConfig)
    Prov-->>Reg: component lists
    Reg-->>Cmd: aggregated components

    opt missing semantic args/flags
        Cmd->>Prompt: promptForSemanticValues
        Prompt->>Reg: request available components/stacks
        Reg->>Prov: ListComponents per-stack
        Prov-->>Reg: component names
        Reg-->>Prompt: aggregated options
        Prompt->>U: interactive selection
        U-->>Prompt: selected values
        Prompt-->>Cmd: resolved values
    end

    Cmd->>Exec: execute command with resolved component/stack
    Exec-->>U: command output/result
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

Suggested reviewers

  • aknysh
  • Gowiem

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 45.16% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately describes the main feature: adding support for custom component types in custom commands, which aligns with the primary objective of this PR.
Linked Issues check ✅ Passed The PR addresses core requirements from all three linked issues: custom component type recognition and listing (#1787), semantic-type completion for dynamic values (#438), and framework for external inputs via command arguments (#444).
Out of Scope Changes check ✅ Passed All changes are within scope: custom component infrastructure, semantic completion/prompting, schema updates, provider registration, command processing, and comprehensive tests supporting the three linked issues.
✨ Finishing touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feature/dev-3755-custom-component-types

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.

@github-actions github-actions bot added the size/xl Extra large size PR label Dec 20, 2025
@mergify
Copy link

mergify bot commented Dec 20, 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 Dec 20, 2025

Dependency Review

✅ No vulnerabilities or license issues found.

Scanned Files

None

@codecov
Copy link

codecov bot commented Dec 20, 2025

Codecov Report

❌ Patch coverage is 74.19355% with 72 lines in your changes missing coverage. Please review.
✅ Project coverage is 74.55%. Comparing base (c5d0f3b) to head (844dc35).
⚠️ Report is 12 commits behind head on main.

Files with missing lines Patch % Lines
cmd/cmd_utils.go 35.00% 24 Missing and 2 partials ⚠️
cmd/cmd_semantic_completion.go 80.34% 19 Missing and 4 partials ⚠️
internal/exec/stack_processor_process_stacks.go 60.00% 10 Missing and 8 partials ⚠️
internal/exec/describe_component.go 25.00% 2 Missing and 1 partial ⚠️
pkg/component/custom/provider.go 96.07% 1 Missing and 1 partial ⚠️

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

Additional details and impacted files

Impacted file tree graph

@@            Coverage Diff             @@
##             main    #1904      +/-   ##
==========================================
+ Coverage   74.49%   74.55%   +0.06%     
==========================================
  Files         777      779       +2     
  Lines       71044    71319     +275     
==========================================
+ Hits        52925    53173     +248     
- Misses      14653    14661       +8     
- Partials     3466     3485      +19     
Flag Coverage Δ
unittests 74.55% <74.19%> (+0.06%) ⬆️

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

Files with missing lines Coverage Δ
errors/errors.go 100.00% <ø> (ø)
internal/exec/vendor_utils.go 60.37% <100.00%> (+0.18%) ⬆️
pkg/component/registry.go 100.00% <100.00%> (ø)
pkg/component/custom/provider.go 96.07% <96.07%> (ø)
internal/exec/describe_component.go 77.85% <25.00%> (+8.80%) ⬆️
internal/exec/stack_processor_process_stacks.go 83.37% <60.00%> (-2.80%) ⬇️
cmd/cmd_semantic_completion.go 80.34% <80.34%> (ø)
cmd/cmd_utils.go 54.79% <35.00%> (-0.97%) ⬇️

... and 5 files with indirect coverage changes

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

@osterman osterman changed the title feat: Add semantic type completion and interactive prompting for custom commands feat: Add custom component types for custom commands Dec 21, 2025
@osterman osterman added the minor New features that do not break anything label Dec 21, 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

Caution

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

⚠️ Outside diff range comments (1)
internal/exec/describe_component.go (1)

399-405: ComponentTypeSectionName is set regardless of error.

Line 403 sets result.ComponentSection[cfg.ComponentTypeSectionName] before checking if err is nil. If ProcessStacks fails, this may modify a partially-initialized or error-state result.

🔎 Suggested fix
 func tryProcessWithComponentType(params *componentTypeProcessParams) (schema.ConfigAndStacksInfo, error) {
 	params.configAndStacksInfo.ComponentType = params.componentType
 	result, err := ProcessStacks(params.atmosConfig, params.configAndStacksInfo, true, params.processTemplates, params.processYamlFunctions, params.skip, params.authManager)
+	if err != nil {
+		return result, err
+	}
 	result.ComponentSection[cfg.ComponentTypeSectionName] = params.componentType
-	return result, err
+	return result, nil
 }
🧹 Nitpick comments (6)
examples/custom-components/README.md (2)

11-24: Add language identifier to directory tree code block.

The fenced code block at line 11 should include a language identifier to satisfy markdown linting (MD040). For a directory tree, use text as the language.

-```
+```text
 examples/custom-components/

40-46: Add language identifier to output code block.

The fenced code block at line 40 should include a language identifier to satisfy markdown linting (MD040). For command output, use text as the language.

-   ```
+   ```text
    Component: deploy-app
pkg/config/load.go (1)

684-689: Good modernization of error handling.

The switch from type switch to errors.As correctly handles wrapped errors and follows Go 1.13+ patterns.

For consistency, consider updating the remaining type switches in this file to use errors.As:

  • Line 495-500 in readSystemConfig
  • Line 520-525 in readHomeConfigWithProvider
  • Line 701-706 in readAtmosConfigCli
🔎 Example refactor for readSystemConfig
 		err := mergeConfig(v, configFilePath, CliConfigFileName, false)
-		switch err.(type) {
-		case viper.ConfigFileNotFoundError:
+		if err != nil {
+			var configFileNotFoundError viper.ConfigFileNotFoundError
+			if errors.As(err, &configFileNotFoundError) {
+				return nil
+			}
+			return err
+		}
-			return nil
-		default:
-			return err
-		}
internal/exec/stack_processor_process_stacks_test.go (2)

327-745: Tests verify non-error completion but not output correctness.

All validateResult callbacks only assert result != nil. This confirms the function doesn't error, but doesn't verify the actual merging behavior or output structure. Consider adding assertions for at least a few key scenarios:

validateResult: func(t *testing.T, result map[string]any) {
    assert.NotNil(t, result)
    components, ok := result[cfg.ComponentsSectionName].(map[string]any)
    assert.True(t, ok, "components section should exist")
    // verify expected structure
}

As per coding guidelines: "Test behavior, not implementation."


747-801: Filter tests confirm no errors but don't verify filtering behavior.

Same observation - these tests don't verify that the filter actually excludes the expected component types from the result. Consider adding assertions that check the filtered output only contains the expected component type.

cmd/cmd_utils.go (1)

1308-1353: Consider returning early with a more specific error when component/stack lookup yields empty values.

The findTypedValue calls at lines 1321 and 1327 could return empty strings if the argument/flag exists but its value is empty (not just when the typed param isn't found). This might lead to confusing errors downstream.

🔎 Potential improvement for empty value handling
 	// Find component name from argument/flag with type: component.
 	componentName := findTypedValue(commandConfig, argumentsData, flagsData, "component")
 	if componentName == "" {
-		errUtils.CheckErrorPrintAndExit(errUtils.ErrComponentArgumentNotFound, "", "")
+		errUtils.CheckErrorPrintAndExit(
+			errUtils.ErrComponentArgumentNotFound,
+			"Missing component",
+			"Ensure an argument or flag with type 'component' is defined and has a value",
+		)
 	}
📜 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 5538ee0 and e379365.

📒 Files selected for processing (24)
  • cmd/cmd_semantic_completion.go
  • cmd/cmd_semantic_completion_test.go
  • cmd/cmd_utils.go
  • cmd/cmd_utils_test.go
  • errors/errors.go
  • examples/custom-components/README.md
  • examples/custom-components/atmos.yaml
  • examples/custom-components/components/script/deploy-app/deploy.sh
  • examples/custom-components/stacks/catalog/script/deploy-app.yaml
  • examples/custom-components/stacks/deploy/dev.yaml
  • internal/exec/describe_component.go
  • internal/exec/describe_component_test.go
  • internal/exec/stack_processor_process_stacks.go
  • internal/exec/stack_processor_process_stacks_test.go
  • pkg/component/custom/provider.go
  • pkg/component/custom/provider_test.go
  • pkg/component/registry.go
  • pkg/component/registry_test.go
  • pkg/config/load.go
  • pkg/schema/command.go
  • tests/fixtures/schemas/atmos/atmos-manifest/1.0/atmos-manifest.json
  • website/blog/2025-12-20-custom-component-types.mdx
  • website/docs/cli/configuration/commands.mdx
  • website/static/schemas/atmos/atmos-manifest/1.0/atmos-manifest.json
🧰 Additional context used
📓 Path-based instructions (6)
**/*.go

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

**/*.go: Use Viper for managing configuration, environment variables, and flags in CLI commands
Use interfaces for external dependencies to facilitate mocking and consider using testify/mock for creating mock implementations
All code must pass golangci-lint checks
Follow Go's error handling idioms: use meaningful error messages, wrap errors with context using fmt.Errorf("context: %w", err), and consider using custom error types for domain-specific errors
Follow standard Go coding style: use gofmt and goimports to format code, prefer short descriptive variable names, use kebab-case for command-line flags, and snake_case for environment variables
Document all exported functions, types, and methods following Go's documentation conventions
Document complex logic with inline comments in Go code
Support configuration via files, environment variables, and flags following the precedence order: flags > environment variables > config file > defaults
Provide clear error messages to users, include troubleshooting hints when appropriate, and log detailed errors for debugging

**/*.go: NEVER use fmt.Fprintf(os.Stdout/Stderr) or fmt.Println(); use data.* or ui.* functions instead
All comments must end with periods (enforced by godot linter)
Organize imports in three groups separated by blank lines, sorted alphabetically: 1) Go stdlib, 2) 3rd-party (NOT cloudposse/atmos), 3) Atmos packages; maintain aliases: cfg, log, u, errUtils
Add defer perf.Track(atmosConfig, "pkg.FuncName")() + blank line to all public functions for performance tracking; use nil if no atmosConfig param
All errors MUST be wrapped using static errors defined in errors/errors.go; use errors.Join for combining multiple errors; use fmt.Errorf with %w for adding string context; use error builder for complex errors; use errors.Is() for error checking; NEVER use dynamic errors directly
Use go.uber.org/mock/mockgen with //go:generate directives for mock generation; never create manual mocks
Keep files small...

Files:

  • internal/exec/describe_component_test.go
  • cmd/cmd_semantic_completion_test.go
  • errors/errors.go
  • pkg/component/registry.go
  • cmd/cmd_semantic_completion.go
  • pkg/component/custom/provider_test.go
  • internal/exec/describe_component.go
  • cmd/cmd_utils.go
  • cmd/cmd_utils_test.go
  • pkg/config/load.go
  • pkg/component/custom/provider.go
  • internal/exec/stack_processor_process_stacks.go
  • pkg/component/registry_test.go
  • pkg/schema/command.go
  • internal/exec/stack_processor_process_stacks_test.go
**/*_test.go

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

**/*_test.go: Every new feature must include comprehensive unit tests targeting >80% code coverage for all packages
Use table-driven tests for testing multiple scenarios in Go
Include integration tests for command flows and test CLI end-to-end when possible with test fixtures

**/*_test.go: Prefer unit tests with mocks over integration tests; use interfaces + dependency injection for testability; generate mocks with go.uber.org/mock/mockgen; use table-driven tests; target >80% coverage
Test behavior, not implementation; never test stub functions; avoid tautological tests; make code testable via DI; no coverage theater; remove always-skipped tests; use errors.Is() for error checking

Files:

  • internal/exec/describe_component_test.go
  • cmd/cmd_semantic_completion_test.go
  • pkg/component/custom/provider_test.go
  • cmd/cmd_utils_test.go
  • pkg/component/registry_test.go
  • internal/exec/stack_processor_process_stacks_test.go
cmd/**/*.go

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

cmd/**/*.go: Use Cobra's recommended command structure with a root command and subcommands, implementing each command in a separate file under cmd/ directory
Provide comprehensive help text for all commands and flags, include examples in command help, and follow Go's documentation conventions in Cobra command definitions
Provide meaningful feedback to users and include progress indicators for long-running operations in CLI commands

cmd/**/*.go: Commands MUST use flags.NewStandardParser() for command-specific flags; NEVER call viper.BindEnv() or viper.BindPFlag() directly (Forbidigo enforces this); see cmd/version/version.go for reference
Embed CLI examples from cmd/markdown/*_usage.md using //go:embed; render with utils.PrintfMarkdown()

Files:

  • cmd/cmd_semantic_completion_test.go
  • cmd/cmd_semantic_completion.go
  • cmd/cmd_utils.go
  • cmd/cmd_utils_test.go
cmd/**/*_test.go

📄 CodeRabbit inference engine (CLAUDE.md)

ALWAYS use cmd.NewTestKit(t) for cmd tests to auto-clean RootCmd state (flags, args)

Files:

  • cmd/cmd_semantic_completion_test.go
  • cmd/cmd_utils_test.go
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/blog/2025-12-20-custom-component-types.mdx
  • website/static/schemas/atmos/atmos-manifest/1.0/atmos-manifest.json
  • website/docs/cli/configuration/commands.mdx
website/blog/**/*.mdx

📄 CodeRabbit inference engine (CLAUDE.md)

website/blog/**/*.mdx: Follow PR template (what/why/references); PRs labeled minor/major MUST include blog post at website/blog/YYYY-MM-DD-feature-name.mdx with YAML front matter, after intro, and only tags from website/blog/tags.yml
Blog posts MUST use only tags defined in website/blog/tags.yml and authors defined in website/blog/authors.yml; valid tags are: feature, enhancement, bugfix, dx, breaking-change, security, documentation, deprecation, core; never invent new tags

Files:

  • website/blog/2025-12-20-custom-component-types.mdx
🧠 Learnings (65)
📚 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/describe_component_test.go
  • errors/errors.go
  • pkg/component/registry.go
  • cmd/cmd_semantic_completion.go
  • internal/exec/describe_component.go
  • cmd/cmd_utils.go
  • pkg/component/custom/provider.go
  • internal/exec/stack_processor_process_stacks.go
  • pkg/component/registry_test.go
  • pkg/schema/command.go
  • internal/exec/stack_processor_process_stacks_test.go
📚 Learning: 2025-11-24T17:35:37.209Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: .cursor/rules/atmos-rules.mdc:0-0
Timestamp: 2025-11-24T17:35:37.209Z
Learning: Applies to **/*_test.go : Include integration tests for command flows and test CLI end-to-end when possible with test fixtures

Applied to files:

  • internal/exec/describe_component_test.go
  • cmd/cmd_semantic_completion_test.go
  • pkg/component/custom/provider_test.go
  • cmd/cmd_utils_test.go
  • internal/exec/stack_processor_process_stacks_test.go
📚 Learning: 2025-12-16T18:20:55.630Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-16T18:20:55.630Z
Learning: Applies to **/*_test.go : Test behavior, not implementation; never test stub functions; avoid tautological tests; make code testable via DI; no coverage theater; remove always-skipped tests; use errors.Is() for error checking

Applied to files:

  • internal/exec/describe_component_test.go
  • cmd/cmd_semantic_completion_test.go
  • cmd/cmd_utils_test.go
  • pkg/component/registry_test.go
  • internal/exec/stack_processor_process_stacks_test.go
📚 Learning: 2025-11-24T17:35:37.209Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: .cursor/rules/atmos-rules.mdc:0-0
Timestamp: 2025-11-24T17:35:37.209Z
Learning: Applies to **/*_test.go : Every new feature must include comprehensive unit tests targeting >80% code coverage for all packages

Applied to files:

  • internal/exec/describe_component_test.go
  • cmd/cmd_semantic_completion_test.go
  • pkg/component/custom/provider_test.go
  • internal/exec/stack_processor_process_stacks_test.go
📚 Learning: 2025-12-17T20:55:47.884Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 1874
File: internal/exec/describe_affected_utils_test.go:436-468
Timestamp: 2025-12-17T20:55:47.884Z
Learning: In the Atmos codebase, there are two different paths for the `locked` flag: (1) filtering logic in `internal/exec/component_utils.go` (`isComponentLocked()`) reads from `componentSection["metadata"]["locked"]` to determine which components to include/exclude, and (2) extraction/rendering logic in `pkg/list/extract/affected.go` reads from `settings.metadata.locked` to display the locked status in output. Tests for filtering behavior should use `metadata.locked`.

Applied to files:

  • internal/exec/describe_component_test.go
  • internal/exec/stack_processor_process_stacks_test.go
📚 Learning: 2025-12-16T18:20:55.630Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-16T18:20:55.630Z
Learning: Applies to **/*_test.go : Prefer unit tests with mocks over integration tests; use interfaces + dependency injection for testability; generate mocks with go.uber.org/mock/mockgen; use table-driven tests; target >80% coverage

Applied to files:

  • internal/exec/describe_component_test.go
  • cmd/cmd_semantic_completion_test.go
  • pkg/component/custom/provider_test.go
📚 Learning: 2025-11-24T17:35:37.209Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: .cursor/rules/atmos-rules.mdc:0-0
Timestamp: 2025-11-24T17:35:37.209Z
Learning: Applies to **/*_test.go : Use table-driven tests for testing multiple scenarios in Go

Applied to files:

  • internal/exec/describe_component_test.go
  • cmd/cmd_utils_test.go
  • internal/exec/stack_processor_process_stacks_test.go
📚 Learning: 2025-05-23T19:51:47.091Z
Learnt from: samtholiya
Repo: cloudposse/atmos PR: 1255
File: cmd/describe_affected_test.go:15-15
Timestamp: 2025-05-23T19:51:47.091Z
Learning: The atmos codebase has a custom extension to *testing.T that provides a Chdir method, allowing test functions to call t.Chdir() to change working directories during tests. This is used consistently across test files in the codebase.

Applied to files:

  • internal/exec/describe_component_test.go
📚 Learning: 2025-12-21T04:10:29.030Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 1891
File: internal/exec/describe_affected.go:468-468
Timestamp: 2025-12-21T04:10:29.030Z
Learning: In Go, package-level declarations (constants, variables, types, and functions) are visible to all files in the same package without imports. During reviews in cloudposse/atmos (and similar Go codebases), before suggesting to declare a new identifier, first check if it already exists in another file of the same package. If it exists, you can avoid adding a new declaration; if not, proceed with a proper package-level declaration. 

Applied to files:

  • internal/exec/describe_component_test.go
  • cmd/cmd_semantic_completion_test.go
  • errors/errors.go
  • pkg/component/registry.go
  • cmd/cmd_semantic_completion.go
  • pkg/component/custom/provider_test.go
  • internal/exec/describe_component.go
  • cmd/cmd_utils.go
  • cmd/cmd_utils_test.go
  • pkg/config/load.go
  • pkg/component/custom/provider.go
  • internal/exec/stack_processor_process_stacks.go
  • pkg/component/registry_test.go
  • pkg/schema/command.go
  • internal/exec/stack_processor_process_stacks_test.go
📚 Learning: 2025-11-24T17:35:37.209Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: .cursor/rules/atmos-rules.mdc:0-0
Timestamp: 2025-11-24T17:35:37.209Z
Learning: Applies to cmd/**/*.go : Provide comprehensive help text for all commands and flags, include examples in command help, and follow Go's documentation conventions in Cobra command definitions

Applied to files:

  • cmd/cmd_semantic_completion_test.go
  • cmd/cmd_semantic_completion.go
  • cmd/cmd_utils.go
  • cmd/cmd_utils_test.go
  • pkg/schema/command.go
📚 Learning: 2025-12-10T18:32:43.260Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 1808
File: cmd/terraform/backend/backend_delete_test.go:9-23
Timestamp: 2025-12-10T18:32:43.260Z
Learning: In cmd subpackages, tests should avoid using NewTestKit(t) unless tests actually interact with RootCmd (e.g., execute commands via RootCmd or modify RootCmd state). For structural tests that only verify command structure/flags without touching RootCmd, TestKit cleanup is unnecessary.

Applied to files:

  • cmd/cmd_semantic_completion_test.go
  • cmd/cmd_utils_test.go
📚 Learning: 2025-12-16T18:20:55.630Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-16T18:20:55.630Z
Learning: Applies to **/*.go : Keep files small and focused (<600 lines); one cmd/impl per file; co-locate tests; never use //revive:disable:file-length-limit

Applied to files:

  • cmd/cmd_semantic_completion_test.go
📚 Learning: 2025-02-18T13:18:53.146Z
Learnt from: samtholiya
Repo: cloudposse/atmos PR: 1068
File: cmd/vendor_pull.go:31-31
Timestamp: 2025-02-18T13:18:53.146Z
Learning: Error checking is not required for cobra.Command.RegisterFlagCompletionFunc calls as these are static configurations done at init time.

Applied to files:

  • cmd/cmd_semantic_completion_test.go
  • cmd/cmd_semantic_completion.go
  • cmd/cmd_utils.go
📚 Learning: 2025-11-24T17:35:37.209Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: .cursor/rules/atmos-rules.mdc:0-0
Timestamp: 2025-11-24T17:35:37.209Z
Learning: Applies to cmd/**/*.go : Use Cobra's recommended command structure with a root command and subcommands, implementing each command in a separate file under `cmd/` directory

Applied to files:

  • cmd/cmd_semantic_completion_test.go
  • cmd/cmd_utils_test.go
  • pkg/schema/command.go
📚 Learning: 2025-12-16T18:20:55.630Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-16T18:20:55.630Z
Learning: Applies to cmd/**/*_test.go : ALWAYS use cmd.NewTestKit(t) for cmd tests to auto-clean RootCmd state (flags, args)

Applied to files:

  • cmd/cmd_semantic_completion_test.go
  • cmd/cmd_utils_test.go
📚 Learning: 2025-02-09T14:38:53.443Z
Learnt from: samtholiya
Repo: cloudposse/atmos PR: 992
File: cmd/cmd_utils.go:0-0
Timestamp: 2025-02-09T14:38:53.443Z
Learning: Error handling for RegisterFlagCompletionFunc in AddStackCompletion is not required as the errors are non-critical for tab completion functionality.

Applied to files:

  • cmd/cmd_semantic_completion_test.go
  • cmd/cmd_semantic_completion.go
📚 Learning: 2025-02-07T19:21:38.028Z
Learnt from: samtholiya
Repo: cloudposse/atmos PR: 992
File: cmd/vendor_pull.go:31-31
Timestamp: 2025-02-07T19:21:38.028Z
Learning: The cobra.Command.RegisterFlagCompletionFunc method (as of cobra v1.8.1) never returns an error. It only initializes an internal map and stores the completion function, always returning nil. Error handling for this method call is unnecessary.

Applied to files:

  • cmd/cmd_semantic_completion_test.go
  • cmd/cmd_semantic_completion.go
  • cmd/cmd_utils.go
📚 Learning: 2025-02-07T19:21:38.028Z
Learnt from: samtholiya
Repo: cloudposse/atmos PR: 992
File: cmd/vendor_pull.go:31-31
Timestamp: 2025-02-07T19:21:38.028Z
Learning: The cobra.Command.RegisterFlagCompletionFunc method never returns an error as it simply stores the completion function in an internal map. Error handling for this method call is unnecessary.

Applied to files:

  • cmd/cmd_semantic_completion_test.go
  • cmd/cmd_semantic_completion.go
  • cmd/cmd_utils.go
📚 Learning: 2024-12-05T22:33:40.955Z
Learnt from: aknysh
Repo: cloudposse/atmos PR: 820
File: cmd/list_components.go:53-54
Timestamp: 2024-12-05T22:33:40.955Z
Learning: In the Atmos CLI Go codebase, using `u.LogErrorAndExit` within completion functions is acceptable because it logs the error and exits the command execution.

Applied to files:

  • cmd/cmd_semantic_completion_test.go
  • cmd/cmd_semantic_completion.go
📚 Learning: 2025-12-13T03:21:35.786Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 1813
File: cmd/terraform/shell.go:28-73
Timestamp: 2025-12-13T03:21:35.786Z
Learning: In Atmos, when calling cfg.InitCliConfig, you must first populate the schema.ConfigAndStacksInfo struct with global flag values using flags.ParseGlobalFlags(cmd, v) rather than passing an empty struct. The LoadConfig function (pkg/config/load.go) reads config selection fields (AtmosConfigFilesFromArg, AtmosConfigDirsFromArg, BasePath, ProfilesFromArg) directly from the ConfigAndStacksInfo struct, NOT from Viper. Passing an empty struct causes config selection flags (--base-path, --config, --config-path, --profile) to be silently ignored. Correct pattern: parse flags → populate struct → call InitCliConfig. See cmd/terraform/plan_diff.go for reference implementation.

Applied to files:

  • cmd/cmd_semantic_completion_test.go
  • cmd/cmd_semantic_completion.go
  • cmd/cmd_utils.go
  • pkg/config/load.go
  • internal/exec/stack_processor_process_stacks_test.go
📚 Learning: 2024-11-16T17:30:52.893Z
Learnt from: pkbhowmick
Repo: cloudposse/atmos PR: 786
File: internal/exec/shell_utils.go:159-162
Timestamp: 2024-11-16T17:30:52.893Z
Learning: For the `atmos terraform shell` command in `internal/exec/shell_utils.go`, input validation for the custom shell prompt is not required, as users will use this as a CLI tool and any issues will impact themselves.

Applied to files:

  • cmd/cmd_semantic_completion_test.go
  • cmd/cmd_semantic_completion.go
  • cmd/cmd_utils.go
📚 Learning: 2025-01-09T22:27:25.538Z
Learnt from: samtholiya
Repo: cloudposse/atmos PR: 914
File: cmd/validate_stacks.go:20-23
Timestamp: 2025-01-09T22:27:25.538Z
Learning: The validate commands in Atmos can have different help handling implementations. Specifically, validate_component.go and validate_stacks.go are designed to handle help requests differently, with validate_stacks.go including positional argument checks while validate_component.go does not.

Applied to files:

  • cmd/cmd_semantic_completion_test.go
  • cmd/cmd_semantic_completion.go
  • cmd/cmd_utils.go
  • examples/custom-components/README.md
  • examples/custom-components/atmos.yaml
  • website/docs/cli/configuration/commands.mdx
  • internal/exec/stack_processor_process_stacks_test.go
📚 Learning: 2025-12-13T04:37:40.435Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 1686
File: cmd/toolchain/get.go:23-40
Timestamp: 2025-12-13T04:37:40.435Z
Learning: In Go CLI command files using Cobra, constrain the subcommand to accept at most one positional argument (MaximumNArgs(1)) so it supports both listing all items (zero args) and fetching a specific item (one arg). Define and parse flags with a standard parser (e.g., flags.NewStandardParser()) and avoid binding flags to Viper (no viper.BindEnv/BindPFlag). This promotes explicit argument handling and predictable flag behavior across command files.

Applied to files:

  • cmd/cmd_semantic_completion_test.go
  • cmd/cmd_semantic_completion.go
  • cmd/cmd_utils.go
  • cmd/cmd_utils_test.go
📚 Learning: 2025-12-13T06:10:13.688Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 1686
File: errors/errors.go:184-203
Timestamp: 2025-12-13T06:10:13.688Z
Learning: cloudposse/atmos: For toolchain work, duplicate/unused error sentinels in errors/errors.go should be cleaned up in a separate refactor PR and not block feature PRs; canonical toolchain sentinels live under toolchain/registry with re-exports in toolchain/errors.go.

Applied to files:

  • errors/errors.go
📚 Learning: 2025-12-16T18:20:55.630Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-16T18:20:55.630Z
Learning: Applies to website/docs/cli/commands/**/*.mdx : All CLI commands/flags need Docusaurus documentation in website/docs/cli/commands/ with specific structure: frontmatter, Intro component, Screengrab component, Usage section, Arguments/Flags using <dl><dt>/<dd>, and Examples section

Applied to files:

  • website/blog/2025-12-20-custom-component-types.mdx
  • website/docs/cli/configuration/commands.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/blog/2025-12-20-custom-component-types.mdx
  • examples/custom-components/README.md
  • examples/custom-components/atmos.yaml
  • website/docs/cli/configuration/commands.mdx
📚 Learning: 2025-10-10T23:51:36.597Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 1599
File: internal/exec/terraform.go:394-402
Timestamp: 2025-10-10T23:51:36.597Z
Learning: In Atmos (internal/exec/terraform.go), when adding OpenTofu-specific flags like `--var-file` for `init`, do not gate them based on command name (e.g., checking if `info.Command == "tofu"` or `info.Command == "opentofu"`) because command names don't reliably indicate the actual binary being executed (symlinks, aliases). Instead, document the OpenTofu requirement in code comments and documentation, trusting users who enable the feature (e.g., `PassVars`) to ensure their terraform command points to an OpenTofu binary.

Applied to files:

  • website/blog/2025-12-20-custom-component-types.mdx
  • cmd/cmd_utils.go
📚 Learning: 2025-09-13T16:39:20.007Z
Learnt from: samtholiya
Repo: cloudposse/atmos PR: 1466
File: cmd/markdown/atmos_toolchain_aliases.md:2-4
Timestamp: 2025-09-13T16:39:20.007Z
Learning: In the cloudposse/atmos repository, CLI documentation files in cmd/markdown/ follow a specific format that uses " $ atmos command" (with leading space and dollar sign prompt) in code blocks. This is the established project convention and should not be changed to comply with standard markdownlint rules MD040 and MD014.

Applied to files:

  • website/blog/2025-12-20-custom-component-types.mdx
  • examples/custom-components/README.md
  • examples/custom-components/atmos.yaml
  • website/docs/cli/configuration/commands.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-12-20-custom-component-types.mdx
  • cmd/cmd_utils.go
  • examples/custom-components/README.md
📚 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:

  • cmd/cmd_semantic_completion.go
  • cmd/cmd_utils.go
  • internal/exec/stack_processor_process_stacks.go
  • internal/exec/stack_processor_process_stacks_test.go
📚 Learning: 2025-11-24T17:35:37.209Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: .cursor/rules/atmos-rules.mdc:0-0
Timestamp: 2025-11-24T17:35:37.209Z
Learning: Applies to cmd/**/*.go : Provide meaningful feedback to users and include progress indicators for long-running operations in CLI commands

Applied to files:

  • cmd/cmd_semantic_completion.go
📚 Learning: 2025-01-09T22:37:01.004Z
Learnt from: samtholiya
Repo: cloudposse/atmos PR: 914
File: cmd/terraform_commands.go:260-265
Timestamp: 2025-01-09T22:37:01.004Z
Learning: In the terraform commands implementation (cmd/terraform_commands.go), the direct use of `os.Args[2:]` for argument handling is intentionally preserved to avoid extensive refactoring. While it could be improved to use cobra's argument parsing, such changes should be handled in a dedicated PR to maintain focus and minimize risk.

Applied to files:

  • cmd/cmd_utils.go
📚 Learning: 2025-06-23T02:14:30.937Z
Learnt from: aknysh
Repo: cloudposse/atmos PR: 1327
File: cmd/terraform.go:111-117
Timestamp: 2025-06-23T02:14:30.937Z
Learning: In cmd/terraform.go, flags for the DescribeAffected function are added dynamically at runtime when info.Affected is true. This is intentional to avoid exposing internal flags like "file", "format", "verbose", "include-spacelift-admin-stacks", "include-settings", and "upload" in the terraform command interface, while still providing them for the shared DescribeAffected function used by both `atmos describe affected` and `atmos terraform apply --affected`.

Applied to files:

  • cmd/cmd_utils.go
📚 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:

  • cmd/cmd_utils.go
📚 Learning: 2025-12-16T18:20:55.630Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-16T18:20:55.630Z
Learning: Applies to **/*.go : Organize imports in three groups separated by blank lines, sorted alphabetically: 1) Go stdlib, 2) 3rd-party (NOT cloudposse/atmos), 3) Atmos packages; maintain aliases: cfg, log, u, errUtils

Applied to files:

  • cmd/cmd_utils.go
📚 Learning: 2024-12-11T18:40:12.808Z
Learnt from: Listener430
Repo: cloudposse/atmos PR: 844
File: cmd/helmfile.go:37-37
Timestamp: 2024-12-11T18:40:12.808Z
Learning: In the atmos project, `cliConfig` is initialized within the `cmd` package in `root.go` and can be used in other command files.

Applied to files:

  • cmd/cmd_utils.go
  • pkg/config/load.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:

  • cmd/cmd_utils.go
  • pkg/config/load.go
  • internal/exec/stack_processor_process_stacks_test.go
📚 Learning: 2025-05-30T03:21:37.197Z
Learnt from: aknysh
Repo: cloudposse/atmos PR: 1274
File: go.mod:63-63
Timestamp: 2025-05-30T03:21:37.197Z
Learning: The redis dependency (github.com/redis/go-redis/v9) in the atmos project is only used in tests, not in production code.

Applied to files:

  • cmd/cmd_utils.go
📚 Learning: 2025-12-16T18:20:55.630Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-16T18:20:55.630Z
Learning: Applies to **/*.go : Add `defer perf.Track(atmosConfig, "pkg.FuncName")()` + blank line to all public functions for performance tracking; use nil if no atmosConfig param

Applied to files:

  • cmd/cmd_utils.go
📚 Learning: 2025-12-16T18:20:55.630Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-16T18:20:55.630Z
Learning: Applies to **/*.go : Use ATMOS_ prefix for environment variables with viper.BindEnv("ATMOS_VAR", "ATMOS_VAR", "FALLBACK")

Applied to files:

  • cmd/cmd_utils.go
  • pkg/config/load.go
📚 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:

  • cmd/cmd_utils.go
  • pkg/config/load.go
📚 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:

  • cmd/cmd_utils.go
  • examples/custom-components/atmos.yaml
📚 Learning: 2025-12-13T04:37:25.223Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 1686
File: cmd/root.go:0-0
Timestamp: 2025-12-13T04:37:25.223Z
Learning: In Atmos cmd/root.go Execute(), after cfg.InitCliConfig, we must call both toolchainCmd.SetAtmosConfig(&atmosConfig) and toolchain.SetAtmosConfig(&atmosConfig) so the CLI wrapper and the toolchain package receive configuration; missing either can cause nil-pointer panics in toolchain path resolution.

Applied to files:

  • cmd/cmd_utils.go
  • pkg/config/load.go
📚 Learning: 2024-10-20T13:06:20.839Z
Learnt from: haitham911
Repo: cloudposse/atmos PR: 736
File: pkg/utils/file_utils.go:177-194
Timestamp: 2024-10-20T13:06:20.839Z
Learning: In `pkg/utils/file_utils.go`, the `SearchConfigFile` function should focus on returning the file path and an `exists` boolean without returning an error.

Applied to files:

  • pkg/config/load.go
📚 Learning: 2025-04-23T15:02:50.246Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 1202
File: pkg/utils/yaml_func_exec.go:104-104
Timestamp: 2025-04-23T15:02:50.246Z
Learning: In the Atmos codebase, direct calls to `os.Getenv` should be avoided. Instead, use `viper.BindEnv` for environment variable access. This provides a consistent approach to configuration management across the codebase.

Applied to files:

  • pkg/config/load.go
📚 Learning: 2025-04-10T20:48:22.687Z
Learnt from: samtholiya
Repo: cloudposse/atmos PR: 1147
File: pkg/config/load.go:0-0
Timestamp: 2025-04-10T20:48:22.687Z
Learning: In the `bindEnv` function in `pkg/config/load.go`, panic is used deliberately instead of returning errors because errors from `BindEnv` would only occur due to developer mistakes. Using panic helps with early detection of these developer errors during initialization.

Applied to files:

  • pkg/config/load.go
📚 Learning: 2024-10-23T21:36:40.262Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 740
File: cmd/cmd_utils.go:340-359
Timestamp: 2024-10-23T21:36:40.262Z
Learning: In the Go codebase for Atmos, when reviewing functions like `checkAtmosConfig` in `cmd/cmd_utils.go`, avoid suggesting refactoring to return errors instead of calling `os.Exit` if such changes would significantly increase the scope due to the need to update multiple call sites.

Applied to files:

  • pkg/config/load.go
📚 Learning: 2025-11-24T17:35:37.209Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: .cursor/rules/atmos-rules.mdc:0-0
Timestamp: 2025-11-24T17:35:37.209Z
Learning: Applies to **/*.go : Use Viper for managing configuration, environment variables, and flags in CLI commands

Applied to files:

  • pkg/config/load.go
📚 Learning: 2024-10-20T13:12:46.499Z
Learnt from: haitham911
Repo: cloudposse/atmos PR: 736
File: pkg/config/const.go:6-6
Timestamp: 2024-10-20T13:12:46.499Z
Learning: In `cmd/cmd_utils.go`, it's acceptable to have hardcoded references to `atmos.yaml` in logs, and it's not necessary to update them to use the `CliConfigFileName` constant.

Applied to files:

  • pkg/config/load.go
📚 Learning: 2025-09-23T04:43:31.857Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 1430
File: pkg/config/config.go:98-107
Timestamp: 2025-09-23T04:43:31.857Z
Learning: In the Atmos codebase, NO_PAGER environment variable handling is intentionally kept as direct os.Getenv() access in pkg/config/config.go rather than using Viper binding, because adding no_pager to the config file would be confusing for users. This is an acknowledged exception to the normal Viper binding pattern for environment variables.

Applied to files:

  • pkg/config/load.go
📚 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:

  • examples/custom-components/README.md
📚 Learning: 2024-11-25T17:17:15.703Z
Learnt from: RoseSecurity
Repo: cloudposse/atmos PR: 797
File: pkg/list/atmos.yaml:213-214
Timestamp: 2024-11-25T17:17:15.703Z
Learning: The file `pkg/list/atmos.yaml` is primarily intended for testing purposes.

Applied to files:

  • examples/custom-components/atmos.yaml
📚 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:

  • examples/custom-components/atmos.yaml
📚 Learning: 2025-09-24T20:45:40.401Z
Learnt from: Benbentwo
Repo: cloudposse/atmos PR: 1475
File: tests/fixtures/scenarios/atmos-auth/stacks/deploy/nonprod.yaml:3-4
Timestamp: 2025-09-24T20:45:40.401Z
Learning: In Atmos stack files, the correct syntax for importing other stack files is `import:` (singular), not `imports:` (plural). All stack files in the Atmos codebase consistently use `import:` followed by a list of paths to import.

Applied to files:

  • examples/custom-components/atmos.yaml
📚 Learning: 2025-01-25T15:21:40.413Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 808
File: examples/demo-atmos-cli-imports/atmos.yaml:8-8
Timestamp: 2025-01-25T15:21:40.413Z
Learning: In Atmos, when a directory is specified for configuration loading (e.g., in the `import` section of atmos.yaml), all files within that directory should be treated as Atmos configurations. Do not suggest restricting file extensions in directory-based glob patterns.

Applied to files:

  • examples/custom-components/atmos.yaml
📚 Learning: 2024-12-12T15:17:45.245Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 808
File: examples/demo-atmos.d/atmos.d/tools/helmfile.yml:10-10
Timestamp: 2024-12-12T15:17:45.245Z
Learning: In `examples/demo-atmos.d/atmos.d/tools/helmfile.yml`, when suggesting changes to `kubeconfig_path`, ensure that the values use valid Go template syntax.

Applied to files:

  • examples/custom-components/atmos.yaml
📚 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_process_stacks.go
  • internal/exec/stack_processor_process_stacks_test.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.go
  • internal/exec/stack_processor_process_stacks_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/stack_processor_process_stacks.go
  • internal/exec/stack_processor_process_stacks_test.go
📚 Learning: 2025-05-22T15:42:10.906Z
Learnt from: aknysh
Repo: cloudposse/atmos PR: 1261
File: internal/exec/utils.go:639-640
Timestamp: 2025-05-22T15:42:10.906Z
Learning: In the Atmos codebase, when appending slices with `args := append(configAndStacksInfo.CliArgs, configAndStacksInfo.AdditionalArgsAndFlags...)`, it's intentional that the result is not stored back in the original slice. This pattern is used when the merged result serves a different purpose than the original slices, such as when creating a filtered version for component section assignments.

Applied to files:

  • internal/exec/stack_processor_process_stacks.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:

  • pkg/component/registry_test.go
📚 Learning: 2025-11-24T17:35:37.209Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: .cursor/rules/atmos-rules.mdc:0-0
Timestamp: 2025-11-24T17:35:37.209Z
Learning: Applies to website/** : Keep CLI documentation and website documentation in sync and document new features on the website with examples and use cases

Applied to files:

  • website/docs/cli/configuration/commands.mdx
📚 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/stack_processor_process_stacks_test.go
📚 Learning: 2025-12-16T18:20:55.630Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-16T18:20:55.630Z
Learning: New configs support Go templating with FuncMap() from internal/exec/template_funcs.go

Applied to files:

  • internal/exec/stack_processor_process_stacks_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/stack_processor_process_stacks_test.go
🧬 Code graph analysis (11)
internal/exec/describe_component_test.go (1)
internal/exec/describe_component.go (1)
  • FilterAbstractComponents (567-595)
pkg/component/registry.go (3)
pkg/schema/schema.go (1)
  • Context (525-540)
pkg/perf/perf.go (1)
  • Track (121-138)
errors/errors.go (1)
  • ErrComponentProviderNotFound (293-293)
cmd/cmd_semantic_completion.go (5)
pkg/config/config.go (1)
  • InitCliConfig (28-67)
pkg/schema/command.go (1)
  • Command (6-19)
pkg/component/registry.go (1)
  • ListAllComponents (157-186)
cmd/cmd_utils.go (1)
  • StackFlagCompletion (1067-1124)
pkg/flags/types.go (1)
  • CompletionFunc (21-21)
pkg/component/custom/provider_test.go (3)
pkg/component/provider.go (1)
  • ExecutionContext (48-59)
pkg/schema/schema.go (1)
  • AtmosConfiguration (54-99)
pkg/component/registry.go (1)
  • GetProvider (52-60)
internal/exec/describe_component.go (1)
pkg/auth/hooks.go (1)
  • AuthManager (23-23)
cmd/cmd_utils_test.go (2)
pkg/schema/command.go (3)
  • CommandFlag (33-44)
  • CommandComponent (55-61)
  • CommandArgument (22-30)
pkg/schema/schema.go (1)
  • AtmosConfiguration (54-99)
pkg/config/load.go (1)
pkg/logger/log.go (1)
  • Debug (24-26)
pkg/component/custom/provider.go (4)
pkg/perf/perf.go (1)
  • Track (121-138)
pkg/component/provider.go (1)
  • ExecutionContext (48-59)
errors/errors.go (2)
  • ErrComponentTypeEmpty (295-295)
  • ErrCustomComponentTypeRegistration (309-309)
pkg/component/registry.go (2)
  • GetProvider (52-60)
  • Register (31-48)
internal/exec/stack_processor_process_stacks.go (1)
pkg/config/const.go (7)
  • TerraformComponentType (57-57)
  • HelmfileComponentType (58-58)
  • PackerComponentType (59-59)
  • VarsSectionName (69-69)
  • SettingsSectionName (70-70)
  • EnvSectionName (72-72)
  • ComponentTypeSectionName (95-95)
pkg/component/registry_test.go (2)
errors/errors.go (1)
  • ErrComponentProviderNotFound (293-293)
pkg/component/registry.go (3)
  • Reset (133-140)
  • Register (31-48)
  • ListAllComponents (157-186)
internal/exec/stack_processor_process_stacks_test.go (2)
pkg/config/const.go (19)
  • VarsSectionName (69-69)
  • SettingsSectionName (70-70)
  • EnvSectionName (72-72)
  • TerraformSectionName (81-81)
  • CommandSectionName (80-80)
  • HelmfileSectionName (82-82)
  • PackerSectionName (83-83)
  • NameSectionName (65-65)
  • BackendTypeSectionName (74-74)
  • BackendSectionName (73-73)
  • RemoteStateBackendTypeSectionName (76-76)
  • RemoteStateBackendSectionName (75-75)
  • ProvidersSectionName (67-67)
  • HooksSectionName (68-68)
  • AuthSectionName (86-86)
  • ComponentsSectionName (79-79)
  • TerraformComponentType (57-57)
  • HelmfileComponentType (58-58)
  • PackerComponentType (59-59)
internal/exec/stack_processor_process_stacks.go (1)
  • ProcessStackConfig (28-603)
🪛 LanguageTool
website/blog/2025-12-20-custom-component-types.mdx

[style] ~11-~11: Since ownership is already implied, this phrasing may be redundant.
Context: ...- Atmos custom commands can now define their own component types beyond terraform, `he...

(PRP_OWN)


[style] ~23-~23: Since ownership is already implied, this phrasing may be redundant.
Context: ...tom Component Types Now you can define your own component types directly in custom comm...

(PRP_OWN)


[grammar] ~77-~77: Use a hyphen to join words.
Context: ... data type (string, bool). ### Full Stack Inheritance Custom components inh...

(QB_NEW_EN_HYPHEN)

website/docs/cli/configuration/commands.mdx

[style] ~637-~637: Since ownership is already implied, this phrasing may be redundant.
Context: ...onent Types Custom commands can define their own component types beyond the built-in `te...

(PRP_OWN)


[typographical] ~733-~733: Consider using typographic quotation marks here.
Context: ...ponent_type }}| Component type (e.g., "script") | |{{ .Component.atmos_stack }}` | S...

(EN_QUOTES)


[typographical] ~745-~745: Consider using typographic quotation marks here.
Context: ...uired.** The component type name (e.g., "script", "ansible", "manifest") | | base_path...

(EN_QUOTES)


[typographical] ~745-~745: Consider using a typographic opening quote here.
Context: ...he component type name (e.g., "script", "ansible", "manifest") | | base_path | ...

(EN_QUOTES)


[typographical] ~745-~745: Consider using a typographic close quote here.
Context: ...nent type name (e.g., "script", "ansible", "manifest") | | base_path | Optional...

(EN_QUOTES)


[typographical] ~745-~745: Consider using typographic quotation marks here.
Context: ...t type name (e.g., "script", "ansible", "manifest") | | base_path | Optional. Base direc...

(EN_QUOTES)

🪛 markdownlint-cli2 (0.18.1)
examples/custom-components/README.md

11-11: Fenced code blocks should have a language specified

(MD040, fenced-code-language)


40-40: Fenced code blocks should have a language specified

(MD040, fenced-code-language)

⏰ 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). (3)
  • GitHub Check: Acceptance Tests (macos)
  • GitHub Check: Acceptance Tests (windows)
  • GitHub Check: Summary

coderabbitai[bot]
coderabbitai bot previously approved these changes Dec 22, 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: 2

🧹 Nitpick comments (2)
internal/exec/stack_processor_process_stacks.go (1)

552-588: Consider using the merge library for consistency.

Custom component merge logic manually iterates over maps rather than using m.Merge() (used elsewhere in this function at lines 174, 186, 198, 212, etc.). This bypasses the atmosConfig merge strategy settings and creates inconsistent behavior between built-in and custom component types.

🔎 Refactor to use m.Merge for consistency
-			// Merge global vars into component vars.
-			componentVars := map[string]any{}
-			for k, v := range globalVarsSection {
-				componentVars[k] = v
-			}
-			if vars, ok := componentMap[cfg.VarsSectionName].(map[string]any); ok {
-				for k, v := range vars {
-					componentVars[k] = v
-				}
-			}
-			componentMap[cfg.VarsSectionName] = componentVars
+			// Merge global vars into component vars.
+			componentVars := map[string]any{}
+			if vars, ok := componentMap[cfg.VarsSectionName].(map[string]any); ok {
+				componentVars = vars
+			}
+			mergedVars, err := m.Merge(atmosConfig, []map[string]any{globalVarsSection, componentVars})
+			if err != nil {
+				return nil, err
+			}
+			componentMap[cfg.VarsSectionName] = mergedVars

Apply similar changes for settings and env merges.

internal/exec/stack_processor_process_stacks_test.go (1)

327-745: Strengthen test assertions beyond NotNil checks.

Most test cases only verify assert.NotNil(result), which doesn't validate the actual behavior of ProcessStackConfig. This approach doesn't catch bugs in merging logic, missing fields, or incorrect values.

Consider adding assertions that verify actual configuration values, especially for the comprehensive test at lines 628-721:

 			validateResult: func(t *testing.T, result map[string]any) {
 				assert.NotNil(t, result)
+				// Verify stack name override is preserved
+				assert.Equal(t, "comprehensive-stack", result[cfg.NameSectionName])
+				// Verify components section exists and has expected types
+				components := result[cfg.ComponentsSectionName].(map[string]any)
+				assert.Contains(t, components, cfg.TerraformComponentType)
+				assert.Contains(t, components, cfg.HelmfileComponentType)
+				assert.Contains(t, components, cfg.PackerComponentType)
 			},

As per coding guidelines, tests should verify behavior rather than just check for non-nil results.

📜 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 e379365 and b192e9b.

📒 Files selected for processing (3)
  • internal/exec/stack_processor_process_stacks.go
  • internal/exec/stack_processor_process_stacks_test.go
  • internal/exec/vendor_utils.go
🧰 Additional context used
📓 Path-based instructions (2)
**/*.go

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

**/*.go: Use Viper for managing configuration, environment variables, and flags in CLI commands
Use interfaces for external dependencies to facilitate mocking and consider using testify/mock for creating mock implementations
All code must pass golangci-lint checks
Follow Go's error handling idioms: use meaningful error messages, wrap errors with context using fmt.Errorf("context: %w", err), and consider using custom error types for domain-specific errors
Follow standard Go coding style: use gofmt and goimports to format code, prefer short descriptive variable names, use kebab-case for command-line flags, and snake_case for environment variables
Document all exported functions, types, and methods following Go's documentation conventions
Document complex logic with inline comments in Go code
Support configuration via files, environment variables, and flags following the precedence order: flags > environment variables > config file > defaults
Provide clear error messages to users, include troubleshooting hints when appropriate, and log detailed errors for debugging

**/*.go: NEVER use fmt.Fprintf(os.Stdout/Stderr) or fmt.Println(); use data.* or ui.* functions instead
All comments must end with periods (enforced by godot linter)
Organize imports in three groups separated by blank lines, sorted alphabetically: 1) Go stdlib, 2) 3rd-party (NOT cloudposse/atmos), 3) Atmos packages; maintain aliases: cfg, log, u, errUtils
Add defer perf.Track(atmosConfig, "pkg.FuncName")() + blank line to all public functions for performance tracking; use nil if no atmosConfig param
All errors MUST be wrapped using static errors defined in errors/errors.go; use errors.Join for combining multiple errors; use fmt.Errorf with %w for adding string context; use error builder for complex errors; use errors.Is() for error checking; NEVER use dynamic errors directly
Use go.uber.org/mock/mockgen with //go:generate directives for mock generation; never create manual mocks
Keep files small...

Files:

  • internal/exec/stack_processor_process_stacks.go
  • internal/exec/vendor_utils.go
  • internal/exec/stack_processor_process_stacks_test.go
**/*_test.go

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

**/*_test.go: Every new feature must include comprehensive unit tests targeting >80% code coverage for all packages
Use table-driven tests for testing multiple scenarios in Go
Include integration tests for command flows and test CLI end-to-end when possible with test fixtures

**/*_test.go: Prefer unit tests with mocks over integration tests; use interfaces + dependency injection for testability; generate mocks with go.uber.org/mock/mockgen; use table-driven tests; target >80% coverage
Test behavior, not implementation; never test stub functions; avoid tautological tests; make code testable via DI; no coverage theater; remove always-skipped tests; use errors.Is() for error checking

Files:

  • internal/exec/stack_processor_process_stacks_test.go
🧠 Learnings (23)
📓 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.go
  • internal/exec/stack_processor_process_stacks_test.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_process_stacks.go
  • internal/exec/vendor_utils.go
  • internal/exec/stack_processor_process_stacks_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/stack_processor_process_stacks.go
  • internal/exec/stack_processor_process_stacks_test.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.go
  • internal/exec/stack_processor_process_stacks_test.go
📚 Learning: 2025-06-23T02:14:30.937Z
Learnt from: aknysh
Repo: cloudposse/atmos PR: 1327
File: cmd/terraform.go:111-117
Timestamp: 2025-06-23T02:14:30.937Z
Learning: In cmd/terraform.go, flags for the DescribeAffected function are added dynamically at runtime when info.Affected is true. This is intentional to avoid exposing internal flags like "file", "format", "verbose", "include-spacelift-admin-stacks", "include-settings", and "upload" in the terraform command interface, while still providing them for the shared DescribeAffected function used by both `atmos describe affected` and `atmos terraform apply --affected`.

Applied to files:

  • internal/exec/stack_processor_process_stacks.go
📚 Learning: 2025-05-22T15:42:10.906Z
Learnt from: aknysh
Repo: cloudposse/atmos PR: 1261
File: internal/exec/utils.go:639-640
Timestamp: 2025-05-22T15:42:10.906Z
Learning: In the Atmos codebase, when appending slices with `args := append(configAndStacksInfo.CliArgs, configAndStacksInfo.AdditionalArgsAndFlags...)`, it's intentional that the result is not stored back in the original slice. This pattern is used when the merged result serves a different purpose than the original slices, such as when creating a filtered version for component section assignments.

Applied to files:

  • internal/exec/stack_processor_process_stacks.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/stack_processor_process_stacks.go
  • internal/exec/stack_processor_process_stacks_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/stack_processor_process_stacks.go
  • internal/exec/stack_processor_process_stacks_test.go
📚 Learning: 2025-12-13T03:21:35.786Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 1813
File: cmd/terraform/shell.go:28-73
Timestamp: 2025-12-13T03:21:35.786Z
Learning: In Atmos, when calling cfg.InitCliConfig, you must first populate the schema.ConfigAndStacksInfo struct with global flag values using flags.ParseGlobalFlags(cmd, v) rather than passing an empty struct. The LoadConfig function (pkg/config/load.go) reads config selection fields (AtmosConfigFilesFromArg, AtmosConfigDirsFromArg, BasePath, ProfilesFromArg) directly from the ConfigAndStacksInfo struct, NOT from Viper. Passing an empty struct causes config selection flags (--base-path, --config, --config-path, --profile) to be silently ignored. Correct pattern: parse flags → populate struct → call InitCliConfig. See cmd/terraform/plan_diff.go for reference implementation.

Applied to files:

  • internal/exec/stack_processor_process_stacks.go
  • internal/exec/stack_processor_process_stacks_test.go
📚 Learning: 2025-12-17T20:55:47.884Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 1874
File: internal/exec/describe_affected_utils_test.go:436-468
Timestamp: 2025-12-17T20:55:47.884Z
Learning: In the Atmos codebase, there are two different paths for the `locked` flag: (1) filtering logic in `internal/exec/component_utils.go` (`isComponentLocked()`) reads from `componentSection["metadata"]["locked"]` to determine which components to include/exclude, and (2) extraction/rendering logic in `pkg/list/extract/affected.go` reads from `settings.metadata.locked` to display the locked status in output. Tests for filtering behavior should use `metadata.locked`.

Applied to files:

  • internal/exec/stack_processor_process_stacks.go
  • internal/exec/stack_processor_process_stacks_test.go
📚 Learning: 2025-10-10T23:51:36.597Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 1599
File: internal/exec/terraform.go:394-402
Timestamp: 2025-10-10T23:51:36.597Z
Learning: In Atmos (internal/exec/terraform.go), when adding OpenTofu-specific flags like `--var-file` for `init`, do not gate them based on command name (e.g., checking if `info.Command == "tofu"` or `info.Command == "opentofu"`) because command names don't reliably indicate the actual binary being executed (symlinks, aliases). Instead, document the OpenTofu requirement in code comments and documentation, trusting users who enable the feature (e.g., `PassVars`) to ensure their terraform command points to an OpenTofu binary.

Applied to files:

  • internal/exec/stack_processor_process_stacks.go
📚 Learning: 2025-12-21T04:10:29.030Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 1891
File: internal/exec/describe_affected.go:468-468
Timestamp: 2025-12-21T04:10:29.030Z
Learning: In Go, package-level declarations (constants, variables, types, and functions) are visible to all files in the same package without imports. During reviews in cloudposse/atmos (and similar Go codebases), before suggesting to declare a new identifier, first check if it already exists in another file of the same package. If it exists, you can avoid adding a new declaration; if not, proceed with a proper package-level declaration. 

Applied to files:

  • internal/exec/stack_processor_process_stacks.go
  • internal/exec/vendor_utils.go
  • internal/exec/stack_processor_process_stacks_test.go
📚 Learning: 2024-10-22T23:00:20.627Z
Learnt from: Cerebrovinny
Repo: cloudposse/atmos PR: 737
File: internal/exec/vendor_utils.go:131-141
Timestamp: 2024-10-22T23:00:20.627Z
Learning: In the `ReadAndProcessVendorConfigFile` function in `internal/exec/vendor_utils.go`, the existence of the vendor config file is already checked, so additional file existence checks may be unnecessary.

Applied to files:

  • internal/exec/vendor_utils.go
📚 Learning: 2024-10-31T07:09:31.983Z
Learnt from: Cerebrovinny
Repo: cloudposse/atmos PR: 737
File: internal/exec/vendor_utils.go:181-182
Timestamp: 2024-10-31T07:09:31.983Z
Learning: In `internal/exec/vendor_utils.go`, the variables `mergedSources` and `mergedImports` are declared and used later in the code. Do not suggest removing them as unused variables.

Applied to files:

  • internal/exec/vendor_utils.go
📚 Learning: 2025-03-21T16:14:35.272Z
Learnt from: Listener430
Repo: cloudposse/atmos PR: 984
File: internal/exec/vendor_model.go:0-0
Timestamp: 2025-03-21T16:14:35.272Z
Learning: The function `copyToTarget` is being replaced with `copyToTargetWithPatterns` to support enhanced glob pattern matching for vendoring, but is temporarily kept for reference until the new implementation is fully confirmed.

Applied to files:

  • internal/exec/vendor_utils.go
📚 Learning: 2024-10-28T01:51:30.811Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 727
File: internal/exec/terraform_clean.go:329-332
Timestamp: 2024-10-28T01:51:30.811Z
Learning: In the Atmos Go code, when deleting directories or handling file paths (e.g., in `terraform_clean.go`), always resolve the absolute path using `filepath.Abs` and use the logger `u.LogWarning` for logging messages instead of using `fmt.Printf`.

Applied to files:

  • internal/exec/vendor_utils.go
📚 Learning: 2025-12-16T18:20:55.630Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-16T18:20:55.630Z
Learning: Applies to **/*.go : Code must be Linux/macOS/Windows compatible; use SDKs over binaries; use filepath.Join() instead of hardcoded path separators

Applied to files:

  • internal/exec/vendor_utils.go
📚 Learning: 2025-11-24T17:35:37.209Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: .cursor/rules/atmos-rules.mdc:0-0
Timestamp: 2025-11-24T17:35:37.209Z
Learning: Applies to **/*_test.go : Include integration tests for command flows and test CLI end-to-end when possible with test fixtures

Applied to files:

  • internal/exec/stack_processor_process_stacks_test.go
📚 Learning: 2025-12-16T18:20:55.630Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-16T18:20:55.630Z
Learning: Applies to **/*_test.go : Test behavior, not implementation; never test stub functions; avoid tautological tests; make code testable via DI; no coverage theater; remove always-skipped tests; use errors.Is() for error checking

Applied to files:

  • internal/exec/stack_processor_process_stacks_test.go
📚 Learning: 2025-11-24T17:35:37.209Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: .cursor/rules/atmos-rules.mdc:0-0
Timestamp: 2025-11-24T17:35:37.209Z
Learning: Applies to **/*_test.go : Every new feature must include comprehensive unit tests targeting >80% code coverage for all packages

Applied to files:

  • internal/exec/stack_processor_process_stacks_test.go
📚 Learning: 2025-12-16T18:20:55.630Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-16T18:20:55.630Z
Learning: New configs support Go templating with FuncMap() from internal/exec/template_funcs.go

Applied to files:

  • internal/exec/stack_processor_process_stacks_test.go
📚 Learning: 2025-01-09T22:27:25.538Z
Learnt from: samtholiya
Repo: cloudposse/atmos PR: 914
File: cmd/validate_stacks.go:20-23
Timestamp: 2025-01-09T22:27:25.538Z
Learning: The validate commands in Atmos can have different help handling implementations. Specifically, validate_component.go and validate_stacks.go are designed to handle help requests differently, with validate_stacks.go including positional argument checks while validate_component.go does not.

Applied to files:

  • internal/exec/stack_processor_process_stacks_test.go
🧬 Code graph analysis (3)
internal/exec/stack_processor_process_stacks.go (1)
pkg/config/const.go (7)
  • TerraformComponentType (57-57)
  • HelmfileComponentType (58-58)
  • PackerComponentType (59-59)
  • VarsSectionName (69-69)
  • SettingsSectionName (70-70)
  • EnvSectionName (72-72)
  • ComponentTypeSectionName (95-95)
internal/exec/vendor_utils.go (1)
pkg/utils/file_utils.go (1)
  • JoinPathAndValidate (178-199)
internal/exec/stack_processor_process_stacks_test.go (3)
pkg/schema/schema.go (1)
  • AtmosConfiguration (54-99)
pkg/config/const.go (19)
  • VarsSectionName (69-69)
  • SettingsSectionName (70-70)
  • EnvSectionName (72-72)
  • TerraformSectionName (81-81)
  • CommandSectionName (80-80)
  • HelmfileSectionName (82-82)
  • PackerSectionName (83-83)
  • NameSectionName (65-65)
  • BackendTypeSectionName (74-74)
  • BackendSectionName (73-73)
  • RemoteStateBackendTypeSectionName (76-76)
  • RemoteStateBackendSectionName (75-75)
  • ProvidersSectionName (67-67)
  • HooksSectionName (68-68)
  • AuthSectionName (86-86)
  • ComponentsSectionName (79-79)
  • TerraformComponentType (57-57)
  • HelmfileComponentType (58-58)
  • PackerComponentType (59-59)
internal/exec/stack_processor_process_stacks.go (1)
  • ProcessStackConfig (28-607)
⏰ 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). (3)
  • GitHub Check: Acceptance Tests (macos)
  • GitHub Check: Acceptance Tests (windows)
  • GitHub Check: Summary
🔇 Additional comments (2)
internal/exec/vendor_utils.go (2)

362-362: Cross-platform path handling looks good.

Using filepath.Join without ToSlash is the correct approach for Windows compatibility. This aligns with the coding guidelines requiring cross-platform path handling.


537-537: Path validation correctly handles cross-platform compatibility.

Using JoinPathAndValidate without prior ToSlash normalization is correct. The function internally handles platform-specific path resolution and validates existence appropriately.

coderabbitai[bot]
coderabbitai bot previously approved these changes Dec 22, 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: 0

🧹 Nitpick comments (5)
internal/exec/stack_processor_process_stacks.go (2)

540-543: Silent skip when custom type section is not a map.

When components.(map[string]any) fails, the code continues silently. If a user misconfigures a custom component type section (e.g., script: "invalid"), this won't surface an error. Consider returning an error similar to the built-in type handling.

🔎 Suggested fix
 		componentsMap, ok := components.(map[string]any)
 		if !ok {
-			continue
+			return nil, fmt.Errorf("%w: custom component type '%s' must be a map, got %T in stack '%s'",
+				errUtils.ErrInvalidComponentsSection, componentType, components, stackName)
 		}

552-588: Manual merge differs from built-in types.

The custom component processing uses manual map iteration for merging vars/settings/env. Built-in types use m.Merge() which may handle edge cases like deep merging differently. This could lead to subtle behavioral differences.

If consistency with built-in types is desired, consider using m.Merge() here too.

internal/exec/stack_processor_process_stacks_test.go (3)

346-732: Consider adding content validation to happy path tests.

Most test cases only verify result != nil. While this confirms no errors, it doesn't validate that the config was actually processed correctly. For example, the "config with stack-level name override" test could verify the name appears in the result.

That said, the focus here is verifying no panics/errors across various configs. If behavior verification is the goal, the current approach is fine.


758-812: Filter test doesn't verify exclusion.

The test runs with different filters but only asserts result != nil. It doesn't verify that:

  • When filtering for terraform, helmfile/packer sections are empty
  • When filtering for helmfile, terraform/packer sections are empty

Consider adding assertions that verify excluded types aren't processed.

🔎 Suggested enhancement
 		t.Run(tt.name, func(t *testing.T) {
 			result, err := ProcessStackConfig(
 				// ... params ...
 			)
 			require.NoError(t, err)
 			assert.NotNil(t, result)
+
+			components := result[cfg.ComponentsSectionName].(map[string]any)
+			if tt.componentTypeFilter != "" {
+				// Verify only the filtered type is present
+				for _, compType := range []string{cfg.TerraformComponentType, cfg.HelmfileComponentType, cfg.PackerComponentType} {
+					section := components[compType].(map[string]any)
+					if compType == tt.componentTypeFilter {
+						// Filtered type should exist (even if empty in this test)
+						assert.NotNil(t, section)
+					}
+				}
+			}
 		})

882-886: Missing assertion for filtered-out terraform.

When tt.expectTerraform is false (line 854), the test doesn't assert terraform is actually excluded. The else branch is missing.

🔎 Suggested fix
 			// Check terraform components.
 			terraformSection, hasTerraform := components[cfg.TerraformComponentType].(map[string]any)
 			if tt.expectTerraform {
 				assert.True(t, hasTerraform && len(terraformSection) > 0, "terraform components should be present")
+			} else {
+				assert.True(t, !hasTerraform || len(terraformSection) == 0, "terraform components should NOT be present when filtered")
 			}
📜 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 b192e9b and 1f7e23b.

📒 Files selected for processing (2)
  • internal/exec/stack_processor_process_stacks.go
  • internal/exec/stack_processor_process_stacks_test.go
🧰 Additional context used
📓 Path-based instructions (2)
**/*.go

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

**/*.go: Use Viper for managing configuration, environment variables, and flags in CLI commands
Use interfaces for external dependencies to facilitate mocking and consider using testify/mock for creating mock implementations
All code must pass golangci-lint checks
Follow Go's error handling idioms: use meaningful error messages, wrap errors with context using fmt.Errorf("context: %w", err), and consider using custom error types for domain-specific errors
Follow standard Go coding style: use gofmt and goimports to format code, prefer short descriptive variable names, use kebab-case for command-line flags, and snake_case for environment variables
Document all exported functions, types, and methods following Go's documentation conventions
Document complex logic with inline comments in Go code
Support configuration via files, environment variables, and flags following the precedence order: flags > environment variables > config file > defaults
Provide clear error messages to users, include troubleshooting hints when appropriate, and log detailed errors for debugging

**/*.go: NEVER use fmt.Fprintf(os.Stdout/Stderr) or fmt.Println(); use data.* or ui.* functions instead
All comments must end with periods (enforced by godot linter)
Organize imports in three groups separated by blank lines, sorted alphabetically: 1) Go stdlib, 2) 3rd-party (NOT cloudposse/atmos), 3) Atmos packages; maintain aliases: cfg, log, u, errUtils
Add defer perf.Track(atmosConfig, "pkg.FuncName")() + blank line to all public functions for performance tracking; use nil if no atmosConfig param
All errors MUST be wrapped using static errors defined in errors/errors.go; use errors.Join for combining multiple errors; use fmt.Errorf with %w for adding string context; use error builder for complex errors; use errors.Is() for error checking; NEVER use dynamic errors directly
Use go.uber.org/mock/mockgen with //go:generate directives for mock generation; never create manual mocks
Keep files small...

Files:

  • internal/exec/stack_processor_process_stacks.go
  • internal/exec/stack_processor_process_stacks_test.go
**/*_test.go

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

**/*_test.go: Every new feature must include comprehensive unit tests targeting >80% code coverage for all packages
Use table-driven tests for testing multiple scenarios in Go
Include integration tests for command flows and test CLI end-to-end when possible with test fixtures

**/*_test.go: Prefer unit tests with mocks over integration tests; use interfaces + dependency injection for testability; generate mocks with go.uber.org/mock/mockgen; use table-driven tests; target >80% coverage
Test behavior, not implementation; never test stub functions; avoid tautological tests; make code testable via DI; no coverage theater; remove always-skipped tests; use errors.Is() for error checking

Files:

  • internal/exec/stack_processor_process_stacks_test.go
🧠 Learnings (25)
📓 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.go
  • internal/exec/stack_processor_process_stacks_test.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_process_stacks.go
  • internal/exec/stack_processor_process_stacks_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/stack_processor_process_stacks.go
  • internal/exec/stack_processor_process_stacks_test.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.go
  • internal/exec/stack_processor_process_stacks_test.go
📚 Learning: 2025-06-23T02:14:30.937Z
Learnt from: aknysh
Repo: cloudposse/atmos PR: 1327
File: cmd/terraform.go:111-117
Timestamp: 2025-06-23T02:14:30.937Z
Learning: In cmd/terraform.go, flags for the DescribeAffected function are added dynamically at runtime when info.Affected is true. This is intentional to avoid exposing internal flags like "file", "format", "verbose", "include-spacelift-admin-stacks", "include-settings", and "upload" in the terraform command interface, while still providing them for the shared DescribeAffected function used by both `atmos describe affected` and `atmos terraform apply --affected`.

Applied to files:

  • internal/exec/stack_processor_process_stacks.go
📚 Learning: 2025-05-22T15:42:10.906Z
Learnt from: aknysh
Repo: cloudposse/atmos PR: 1261
File: internal/exec/utils.go:639-640
Timestamp: 2025-05-22T15:42:10.906Z
Learning: In the Atmos codebase, when appending slices with `args := append(configAndStacksInfo.CliArgs, configAndStacksInfo.AdditionalArgsAndFlags...)`, it's intentional that the result is not stored back in the original slice. This pattern is used when the merged result serves a different purpose than the original slices, such as when creating a filtered version for component section assignments.

Applied to files:

  • internal/exec/stack_processor_process_stacks.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_process_stacks.go
  • internal/exec/stack_processor_process_stacks_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/stack_processor_process_stacks.go
  • internal/exec/stack_processor_process_stacks_test.go
📚 Learning: 2025-12-17T20:55:47.884Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 1874
File: internal/exec/describe_affected_utils_test.go:436-468
Timestamp: 2025-12-17T20:55:47.884Z
Learning: In the Atmos codebase, there are two different paths for the `locked` flag: (1) filtering logic in `internal/exec/component_utils.go` (`isComponentLocked()`) reads from `componentSection["metadata"]["locked"]` to determine which components to include/exclude, and (2) extraction/rendering logic in `pkg/list/extract/affected.go` reads from `settings.metadata.locked` to display the locked status in output. Tests for filtering behavior should use `metadata.locked`.

Applied to files:

  • internal/exec/stack_processor_process_stacks.go
  • internal/exec/stack_processor_process_stacks_test.go
📚 Learning: 2025-10-10T23:51:36.597Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 1599
File: internal/exec/terraform.go:394-402
Timestamp: 2025-10-10T23:51:36.597Z
Learning: In Atmos (internal/exec/terraform.go), when adding OpenTofu-specific flags like `--var-file` for `init`, do not gate them based on command name (e.g., checking if `info.Command == "tofu"` or `info.Command == "opentofu"`) because command names don't reliably indicate the actual binary being executed (symlinks, aliases). Instead, document the OpenTofu requirement in code comments and documentation, trusting users who enable the feature (e.g., `PassVars`) to ensure their terraform command points to an OpenTofu binary.

Applied to files:

  • internal/exec/stack_processor_process_stacks.go
📚 Learning: 2025-01-07T20:38:09.618Z
Learnt from: samtholiya
Repo: cloudposse/atmos PR: 896
File: cmd/editor_config.go:37-40
Timestamp: 2025-01-07T20:38:09.618Z
Learning: Error handling suggestion for `cmd.Help()` in `cmd/editor_config.go` was deferred as the code is planned for future modifications.

Applied to files:

  • internal/exec/stack_processor_process_stacks.go
📚 Learning: 2025-01-25T04:01:58.095Z
Learnt from: Listener430
Repo: cloudposse/atmos PR: 934
File: internal/exec/docs_generate.go:98-101
Timestamp: 2025-01-25T04:01:58.095Z
Learning: In the `generateSingleReadme` function of the docs generation feature (internal/exec/docs_generate.go), errors from `fetchAndParseYAML` should be logged and skipped rather than causing early returns. This is by design to process all inputs and collect all errors, instead of failing fast on the first error.

Applied to files:

  • internal/exec/stack_processor_process_stacks.go
📚 Learning: 2024-11-12T03:16:02.910Z
Learnt from: aknysh
Repo: cloudposse/atmos PR: 775
File: internal/exec/template_funcs_component.go:157-159
Timestamp: 2024-11-12T03:16:02.910Z
Learning: In the Go code for `componentFunc` in `internal/exec/template_funcs_component.go`, the function `cleanTerraformWorkspace` does not return errors, and it's acceptable if the file does not exist. Therefore, error handling for `cleanTerraformWorkspace` is not needed.

Applied to files:

  • internal/exec/stack_processor_process_stacks.go
📚 Learning: 2024-10-23T21:36:40.262Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 740
File: cmd/cmd_utils.go:340-359
Timestamp: 2024-10-23T21:36:40.262Z
Learning: In the Go codebase for Atmos, when reviewing functions like `checkAtmosConfig` in `cmd/cmd_utils.go`, avoid suggesting refactoring to return errors instead of calling `os.Exit` if such changes would significantly increase the scope due to the need to update multiple call sites.

Applied to files:

  • internal/exec/stack_processor_process_stacks.go
📚 Learning: 2024-12-02T21:26:32.337Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 808
File: pkg/config/config.go:478-483
Timestamp: 2024-12-02T21:26:32.337Z
Learning: In the 'atmos' project, when reviewing Go code like `pkg/config/config.go`, avoid suggesting file size checks after downloading remote configs if such checks aren't implemented elsewhere in the codebase.

Applied to files:

  • internal/exec/stack_processor_process_stacks.go
📚 Learning: 2025-04-04T02:03:23.676Z
Learnt from: aknysh
Repo: cloudposse/atmos PR: 1185
File: internal/exec/yaml_func_store.go:26-26
Timestamp: 2025-04-04T02:03:23.676Z
Learning: The Atmos codebase currently uses `log.Fatal` for error handling in multiple places. The maintainers are aware this isn't an ideal pattern (should only be used in main() or init() functions) and plan to address it comprehensively in a separate PR. CodeRabbit should not flag these issues or push for immediate changes until that refactoring is complete.

Applied to files:

  • internal/exec/stack_processor_process_stacks.go
📚 Learning: 2025-12-21T04:10:29.030Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 1891
File: internal/exec/describe_affected.go:468-468
Timestamp: 2025-12-21T04:10:29.030Z
Learning: In Go, package-level declarations (constants, variables, types, and functions) are visible to all files in the same package without imports. During reviews in cloudposse/atmos (and similar Go codebases), before suggesting to declare a new identifier, first check if it already exists in another file of the same package. If it exists, you can avoid adding a new declaration; if not, proceed with a proper package-level declaration. 

Applied to files:

  • internal/exec/stack_processor_process_stacks.go
  • internal/exec/stack_processor_process_stacks_test.go
📚 Learning: 2025-12-16T18:20:55.630Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-16T18:20:55.630Z
Learning: Applies to **/*_test.go : Test behavior, not implementation; never test stub functions; avoid tautological tests; make code testable via DI; no coverage theater; remove always-skipped tests; use errors.Is() for error checking

Applied to files:

  • internal/exec/stack_processor_process_stacks_test.go
📚 Learning: 2025-11-24T17:35:37.209Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: .cursor/rules/atmos-rules.mdc:0-0
Timestamp: 2025-11-24T17:35:37.209Z
Learning: Applies to **/*_test.go : Include integration tests for command flows and test CLI end-to-end when possible with test fixtures

Applied to files:

  • internal/exec/stack_processor_process_stacks_test.go
📚 Learning: 2025-12-16T18:20:55.630Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-16T18:20:55.630Z
Learning: New configs support Go templating with FuncMap() from internal/exec/template_funcs.go

Applied to files:

  • internal/exec/stack_processor_process_stacks_test.go
📚 Learning: 2025-11-24T17:35:37.209Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: .cursor/rules/atmos-rules.mdc:0-0
Timestamp: 2025-11-24T17:35:37.209Z
Learning: Applies to **/*_test.go : Every new feature must include comprehensive unit tests targeting >80% code coverage for all packages

Applied to files:

  • internal/exec/stack_processor_process_stacks_test.go
📚 Learning: 2025-11-24T17:35:37.209Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: .cursor/rules/atmos-rules.mdc:0-0
Timestamp: 2025-11-24T17:35:37.209Z
Learning: Applies to **/*_test.go : Use table-driven tests for testing multiple scenarios in Go

Applied to files:

  • internal/exec/stack_processor_process_stacks_test.go
📚 Learning: 2025-12-13T03:21:35.786Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 1813
File: cmd/terraform/shell.go:28-73
Timestamp: 2025-12-13T03:21:35.786Z
Learning: In Atmos, when calling cfg.InitCliConfig, you must first populate the schema.ConfigAndStacksInfo struct with global flag values using flags.ParseGlobalFlags(cmd, v) rather than passing an empty struct. The LoadConfig function (pkg/config/load.go) reads config selection fields (AtmosConfigFilesFromArg, AtmosConfigDirsFromArg, BasePath, ProfilesFromArg) directly from the ConfigAndStacksInfo struct, NOT from Viper. Passing an empty struct causes config selection flags (--base-path, --config, --config-path, --profile) to be silently ignored. Correct pattern: parse flags → populate struct → call InitCliConfig. See cmd/terraform/plan_diff.go for reference implementation.

Applied to files:

  • internal/exec/stack_processor_process_stacks_test.go
📚 Learning: 2025-01-09T22:27:25.538Z
Learnt from: samtholiya
Repo: cloudposse/atmos PR: 914
File: cmd/validate_stacks.go:20-23
Timestamp: 2025-01-09T22:27:25.538Z
Learning: The validate commands in Atmos can have different help handling implementations. Specifically, validate_component.go and validate_stacks.go are designed to handle help requests differently, with validate_stacks.go including positional argument checks while validate_component.go does not.

Applied to files:

  • internal/exec/stack_processor_process_stacks_test.go
🧬 Code graph analysis (2)
internal/exec/stack_processor_process_stacks.go (2)
pkg/config/const.go (7)
  • TerraformComponentType (57-57)
  • HelmfileComponentType (58-58)
  • PackerComponentType (59-59)
  • VarsSectionName (69-69)
  • SettingsSectionName (70-70)
  • EnvSectionName (72-72)
  • ComponentTypeSectionName (95-95)
errors/errors.go (1)
  • ErrInvalidComponentMapType (226-226)
internal/exec/stack_processor_process_stacks_test.go (3)
pkg/config/const.go (20)
  • ComponentsSectionName (79-79)
  • VarsSectionName (69-69)
  • SettingsSectionName (70-70)
  • EnvSectionName (72-72)
  • TerraformSectionName (81-81)
  • CommandSectionName (80-80)
  • HelmfileSectionName (82-82)
  • PackerSectionName (83-83)
  • NameSectionName (65-65)
  • BackendTypeSectionName (74-74)
  • BackendSectionName (73-73)
  • RemoteStateBackendTypeSectionName (76-76)
  • RemoteStateBackendSectionName (75-75)
  • ProvidersSectionName (67-67)
  • HooksSectionName (68-68)
  • AuthSectionName (86-86)
  • TerraformComponentType (57-57)
  • HelmfileComponentType (58-58)
  • PackerComponentType (59-59)
  • ComponentTypeSectionName (95-95)
errors/errors.go (1)
  • ErrInvalidComponentMapType (226-226)
internal/exec/stack_processor_process_stacks.go (1)
  • ProcessStackConfig (28-607)
⏰ 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 (3)
internal/exec/stack_processor_process_stacks.go (1)

523-595: Implementation looks solid overall.

The custom component processing:

  • Correctly skips built-in types
  • Respects the componentTypeFilter parameter
  • Returns errors for invalid component configs
  • Injects required metadata for template access

Good work addressing the previous review feedback.

internal/exec/stack_processor_process_stacks_test.go (2)

302-312: Good coverage for the new error path.

This test case validates that invalid custom component configs (non-map values) properly return ErrInvalidComponentMapType. Uses errors.Is() as per guidelines.


814-906: Solid test coverage for custom component types.

This test properly validates:

  • Filtering behavior for custom vs built-in types
  • Metadata injection (component and component_type)
  • Vars preservation after merging

Good table-driven structure. The assertions address the previous review feedback.

@osterman osterman force-pushed the feature/dev-3755-custom-component-types branch from 1f7e23b to ce5b81f Compare December 26, 2025 13:56
@github-actions
Copy link

Warning

Release Documentation Required

This PR is labeled minor or major and requires documentation updates:

  • Changelog entry
  • Roadmap update - Update website/src/data/roadmap.js with the new milestone

Alternatively: If this change doesn't require release documentation, remove the minor or major label.

@mergify
Copy link

mergify bot commented Jan 1, 2026

💥 This pull request now has conflicts. Could you fix it @osterman? 🙏

@mergify mergify bot added the conflict This PR has conflicts label Jan 1, 2026
@osterman osterman force-pushed the feature/dev-3755-custom-component-types branch from 537d638 to 1e1afec Compare January 1, 2026 19:38
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 (5)
examples/custom-components/README.md (1)

1-61: Good documentation for the new feature.

The README clearly explains the custom component types workflow. Consider adding language identifiers to the fenced code blocks on lines 11 and 40 for consistency—text works well for directory structures and sample output.

pkg/component/custom/provider_test.go (2)

134-147: EnsureRegistered idempotency test is valuable.

Verifying that re-registration succeeds silently is important for the "ensure" pattern. Consider calling component.Reset() at the start of this test to guarantee isolation from prior test state.

🔎 Optional: Add Reset for test isolation
 func TestEnsureRegistered(t *testing.T) {
+	component.Reset()
+
 	// Test registering a new type.
 	err := EnsureRegistered("test-custom-type", "components/test-custom-type")

149-152: Consider using errors.Is for precise error checking.

Per coding guidelines, errors.Is() is preferred for error checking in tests.

🔎 Optional fix
 func TestEnsureRegistered_EmptyType(t *testing.T) {
 	err := EnsureRegistered("", "components/empty")
-	assert.Error(t, err)
+	assert.ErrorIs(t, err, errUtils.ErrComponentTypeEmpty)
 }

You'd need to import errUtils "github.com/cloudposse/atmos/errors".

pkg/component/custom/provider.go (1)

32-44: Consider if perf.Track overhead is warranted for trivial getters.

Per coding guidelines, perf.Track should be omitted for trivial getters/setters. GetType and GetGroup are simple field returns. Removing the tracking would reduce overhead.

🔎 Optional: Remove perf tracking from trivial getters
 // GetType returns the component type identifier.
 func (p *Provider) GetType() string {
-	defer perf.Track(nil, "custom.GetType")()
-
 	return p.typeName
 }

 // GetGroup returns the component group for categorization.
 func (p *Provider) GetGroup() string {
-	defer perf.Track(nil, "custom.GetGroup")()
-
 	return "Custom"
 }
cmd/cmd_semantic_completion_test.go (1)

487-504: Basic smoke test for customComponentCompletion.

This test verifies the function returns a valid closure and handles config load failures gracefully. Consider adding a test that uses a mock or fixture to verify successful completion behavior.

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 1f7e23b and 1e1afec.

📒 Files selected for processing (19)
  • cmd/cmd_semantic_completion.go
  • cmd/cmd_semantic_completion_test.go
  • cmd/cmd_utils.go
  • cmd/cmd_utils_test.go
  • errors/errors.go
  • examples/custom-components/README.md
  • examples/custom-components/atmos.yaml
  • examples/custom-components/components/script/deploy-app/deploy.sh
  • examples/custom-components/stacks/catalog/script/deploy-app.yaml
  • examples/custom-components/stacks/deploy/dev.yaml
  • internal/exec/describe_component.go
  • internal/exec/describe_component_test.go
  • internal/exec/stack_processor_process_stacks.go
  • internal/exec/stack_processor_process_stacks_test.go
  • internal/exec/vendor_utils.go
  • pkg/component/custom/provider.go
  • pkg/component/custom/provider_test.go
  • pkg/component/registry.go
  • pkg/component/registry_test.go
🚧 Files skipped from review as they are similar to previous changes (6)
  • examples/custom-components/stacks/deploy/dev.yaml
  • errors/errors.go
  • pkg/component/registry.go
  • cmd/cmd_utils_test.go
  • examples/custom-components/atmos.yaml
  • internal/exec/describe_component_test.go
🧰 Additional context used
📓 Path-based instructions (5)
**/*.go

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

**/*.go: Use Viper for managing configuration, environment variables, and flags in CLI commands
Use interfaces for external dependencies to facilitate mocking and consider using testify/mock for creating mock implementations
All code must pass golangci-lint checks
Follow Go's error handling idioms: use meaningful error messages, wrap errors with context using fmt.Errorf("context: %w", err), and consider using custom error types for domain-specific errors
Follow standard Go coding style: use gofmt and goimports to format code, prefer short descriptive variable names, use kebab-case for command-line flags, and snake_case for environment variables
Document all exported functions, types, and methods following Go's documentation conventions
Document complex logic with inline comments in Go code
Support configuration via files, environment variables, and flags following the precedence order: flags > environment variables > config file > defaults
Provide clear error messages to users, include troubleshooting hints when appropriate, and log detailed errors for debugging

**/*.go: All comments must end with periods (enforced by godot linter)
Never delete existing comments without a very strong reason; preserve helpful comments explaining why/how/what/where, and update comments to match code when refactoring
Organize imports in three groups separated by blank lines, sorted alphabetically: (1) Go stdlib, (2) 3rd-party (NOT cloudposse/atmos), (3) Atmos packages. Maintain aliases: cfg, log, u, errUtils
Use flags.NewStandardParser() for command-specific flags; NEVER call viper.BindEnv() or viper.BindPFlag() directly (enforced by Forbidigo)
All errors MUST be wrapped using static errors defined in errors/errors.go; use errors.Join for combining multiple errors, fmt.Errorf with %w for adding string context, error builder for complex errors, and errors.Is() for error checking. Never use dynamic errors directly
Define interfaces for all major funct...

Files:

  • pkg/component/custom/provider_test.go
  • internal/exec/vendor_utils.go
  • pkg/component/custom/provider.go
  • pkg/component/registry_test.go
  • internal/exec/stack_processor_process_stacks.go
  • cmd/cmd_utils.go
  • internal/exec/describe_component.go
  • internal/exec/stack_processor_process_stacks_test.go
  • cmd/cmd_semantic_completion.go
  • cmd/cmd_semantic_completion_test.go
**/*_test.go

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

**/*_test.go: Every new feature must include comprehensive unit tests targeting >80% code coverage for all packages
Use table-driven tests for testing multiple scenarios in Go
Include integration tests for command flows and test CLI end-to-end when possible with test fixtures

**/*_test.go: Use cmd.NewTestKit(t) for cmd tests to auto-clean RootCmd state (flags, args)
Test behavior, not implementation; never test stub functions; avoid tautological tests; use errors.Is() for error checking; remove always-skipped tests
Prefer unit tests with mocks over integration tests; use interfaces and dependency injection for testability; use table-driven tests for comprehensive coverage; target >80% coverage; skip tests gracefully with helpers from tests/test_preconditions.go
Never manually edit golden snapshot files under tests/test-cases/ or tests/testdata/; always use -regenerate-snapshots flag. Never use pipe redirection when running tests as it breaks TTY detection

Files:

  • pkg/component/custom/provider_test.go
  • pkg/component/registry_test.go
  • internal/exec/stack_processor_process_stacks_test.go
  • cmd/cmd_semantic_completion_test.go
pkg/**/*.go

📄 CodeRabbit inference engine (CLAUDE.md)

pkg/**/*.go: Add defer perf.Track(atmosConfig, "pkg.FuncName")() + blank line to all public functions, except trivial getters/setters, command constructors, simple factory functions, and functions that only delegate to another tracked function. Use nil if no atmosConfig param
Avoid adding new functions to pkg/utils/; create purpose-built packages for new functionality (e.g., pkg/store/, pkg/git/, pkg/pro/, pkg/filesystem/)

Files:

  • pkg/component/custom/provider_test.go
  • pkg/component/custom/provider.go
  • pkg/component/registry_test.go
internal/exec/**/*.go

📄 CodeRabbit inference engine (CLAUDE.md)

New templates should support Go templating with FuncMap() from internal/exec/template_funcs.go

Files:

  • internal/exec/vendor_utils.go
  • internal/exec/stack_processor_process_stacks.go
  • internal/exec/describe_component.go
  • internal/exec/stack_processor_process_stacks_test.go
cmd/**/*.go

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

cmd/**/*.go: Use Cobra's recommended command structure with a root command and subcommands, implementing each command in a separate file under cmd/ directory
Provide comprehensive help text for all commands and flags, include examples in command help, and follow Go's documentation conventions in Cobra command definitions
Provide meaningful feedback to users and include progress indicators for long-running operations in CLI commands

cmd/**/*.go: Add defer perf.Track(atmosConfig, "pkg.FuncName")() + blank line to all public functions, except trivial getters/setters, command constructors, simple factory functions, and functions that only delegate to another tracked function
Commands MUST use the command registry pattern via CommandProvider interface; see docs/prd/command-registry-pattern.md and cmd/internal/registry.go
Embed examples from cmd/markdown/*_usage.md using //go:embed and render with utils.PrintfMarkdown()

Files:

  • cmd/cmd_utils.go
  • cmd/cmd_semantic_completion.go
  • cmd/cmd_semantic_completion_test.go
🧠 Learnings (61)
📓 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.
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.
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-01T18:25:25.942Z
Learning: Stack pipeline: Load atmos.yaml → process imports/inheritance → apply overrides → render templates → generate config. Templates use Go templates + Gomplate with `atmos.Component()`, `!terraform.state`, `!terraform.output`, store integration
Learnt from: osterman
Repo: cloudposse/atmos PR: 727
File: internal/exec/terraform.go:114-118
Timestamp: 2024-10-21T17:51:53.976Z
Learning: When `atmos terraform clean --everything` is used without specifying a component and without the `--force` flag, prompt the user for confirmation before deleting all components. Use the `--force` flag to skip the confirmation prompt.
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.
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-01T18:25:25.942Z
Learning: When adding new CLI command: (1) Create `cmd/[command]/` with CommandProvider interface, (2) Add blank import to `cmd/root.go`, (3) Implement in `internal/exec/mycommand.go`, (4) Add tests and Docusaurus docs in `website/docs/cli/commands/`, (5) Build website: `cd website && npm run build`. See `docs/developing-atmos-commands.md` and `docs/prd/command-registry-pattern.md`
Learnt from: samtholiya
Repo: cloudposse/atmos PR: 914
File: cmd/validate_stacks.go:20-23
Timestamp: 2025-01-09T22:27:25.538Z
Learning: The validate commands in Atmos can have different help handling implementations. Specifically, validate_component.go and validate_stacks.go are designed to handle help requests differently, with validate_stacks.go including positional argument checks while validate_component.go does not.
Learnt from: RoseSecurity
Repo: cloudposse/atmos PR: 1448
File: cmd/ansible.go:26-28
Timestamp: 2025-09-05T14:57:37.360Z
Learning: The Atmos codebase uses a consistent pattern for commands that delegate to external tools: `PersistentFlags().Bool("", false, doubleDashHint)` where doubleDashHint provides help text about using double dashes to separate Atmos options from native command arguments. This pattern is used across terraform, packer, helmfile, atlantis, aws, and ansible commands.
Learnt from: samtholiya
Repo: cloudposse/atmos PR: 1466
File: cmd/markdown/atmos_toolchain_aliases.md:2-4
Timestamp: 2025-09-13T16:39:20.007Z
Learning: In the cloudposse/atmos repository, CLI documentation files in cmd/markdown/ follow a specific format that uses " $ atmos command" (with leading space and dollar sign prompt) in code blocks. This is the established project convention and should not be changed to comply with standard markdownlint rules MD040 and MD014.
📚 Learning: 2025-11-24T17:35:37.209Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: .cursor/rules/atmos-rules.mdc:0-0
Timestamp: 2025-11-24T17:35:37.209Z
Learning: Applies to **/*_test.go : Every new feature must include comprehensive unit tests targeting >80% code coverage for all packages

Applied to files:

  • pkg/component/custom/provider_test.go
  • internal/exec/stack_processor_process_stacks_test.go
  • cmd/cmd_semantic_completion_test.go
📚 Learning: 2026-01-01T18:25:25.942Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-01T18:25:25.942Z
Learning: Applies to **/*_test.go : Prefer unit tests with mocks over integration tests; use interfaces and dependency injection for testability; use table-driven tests for comprehensive coverage; target >80% coverage; skip tests gracefully with helpers from `tests/test_preconditions.go`

Applied to files:

  • pkg/component/custom/provider_test.go
📚 Learning: 2025-11-24T17:35:37.209Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: .cursor/rules/atmos-rules.mdc:0-0
Timestamp: 2025-11-24T17:35:37.209Z
Learning: Applies to **/*_test.go : Include integration tests for command flows and test CLI end-to-end when possible with test fixtures

Applied to files:

  • pkg/component/custom/provider_test.go
  • internal/exec/stack_processor_process_stacks_test.go
  • cmd/cmd_semantic_completion_test.go
📚 Learning: 2025-12-21T04:10:29.030Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 1891
File: internal/exec/describe_affected.go:468-468
Timestamp: 2025-12-21T04:10:29.030Z
Learning: In Go, package-level declarations (constants, variables, types, and functions) are visible to all files in the same package without imports. During reviews in cloudposse/atmos (and similar Go codebases), before suggesting to declare a new identifier, first check if it already exists in another file of the same package. If it exists, you can avoid adding a new declaration; if not, proceed with a proper package-level declaration. 

Applied to files:

  • pkg/component/custom/provider_test.go
  • internal/exec/vendor_utils.go
  • pkg/component/custom/provider.go
  • pkg/component/registry_test.go
  • internal/exec/stack_processor_process_stacks.go
  • cmd/cmd_utils.go
  • internal/exec/describe_component.go
  • internal/exec/stack_processor_process_stacks_test.go
  • cmd/cmd_semantic_completion.go
  • cmd/cmd_semantic_completion_test.go
📚 Learning: 2024-10-22T23:00:20.627Z
Learnt from: Cerebrovinny
Repo: cloudposse/atmos PR: 737
File: internal/exec/vendor_utils.go:131-141
Timestamp: 2024-10-22T23:00:20.627Z
Learning: In the `ReadAndProcessVendorConfigFile` function in `internal/exec/vendor_utils.go`, the existence of the vendor config file is already checked, so additional file existence checks may be unnecessary.

Applied to files:

  • internal/exec/vendor_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/vendor_utils.go
  • internal/exec/stack_processor_process_stacks.go
  • internal/exec/stack_processor_process_stacks_test.go
📚 Learning: 2024-10-28T01:51:30.811Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 727
File: internal/exec/terraform_clean.go:329-332
Timestamp: 2024-10-28T01:51:30.811Z
Learning: In the Atmos Go code, when deleting directories or handling file paths (e.g., in `terraform_clean.go`), always resolve the absolute path using `filepath.Abs` and use the logger `u.LogWarning` for logging messages instead of using `fmt.Printf`.

Applied to files:

  • internal/exec/vendor_utils.go
📚 Learning: 2024-12-02T21:26:32.337Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 808
File: pkg/config/config.go:478-483
Timestamp: 2024-12-02T21:26:32.337Z
Learning: In the 'atmos' project, when reviewing Go code like `pkg/config/config.go`, avoid suggesting file size checks after downloading remote configs if such checks aren't implemented elsewhere in the codebase.

Applied to files:

  • internal/exec/vendor_utils.go
  • internal/exec/stack_processor_process_stacks.go
📚 Learning: 2025-03-21T16:14:35.272Z
Learnt from: Listener430
Repo: cloudposse/atmos PR: 984
File: internal/exec/vendor_model.go:0-0
Timestamp: 2025-03-21T16:14:35.272Z
Learning: The function `copyToTarget` is being replaced with `copyToTargetWithPatterns` to support enhanced glob pattern matching for vendoring, but is temporarily kept for reference until the new implementation is fully confirmed.

Applied to files:

  • internal/exec/vendor_utils.go
📚 Learning: 2024-10-31T07:09:31.983Z
Learnt from: Cerebrovinny
Repo: cloudposse/atmos PR: 737
File: internal/exec/vendor_utils.go:181-182
Timestamp: 2024-10-31T07:09:31.983Z
Learning: In `internal/exec/vendor_utils.go`, the variables `mergedSources` and `mergedImports` are declared and used later in the code. Do not suggest removing them as unused variables.

Applied to files:

  • internal/exec/vendor_utils.go
📚 Learning: 2026-01-01T18:25:25.942Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-01T18:25:25.942Z
Learning: Applies to **/*.go : Use cross-platform compatible code: Linux/macOS/Windows compatible, use SDKs over binaries, use `filepath.Join()` instead of hardcoded path separators

Applied to files:

  • internal/exec/vendor_utils.go
📚 Learning: 2026-01-01T18:25:25.942Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-01T18:25:25.942Z
Learning: Applies to cmd/**/*.go : Commands MUST use the command registry pattern via `CommandProvider` interface; see `docs/prd/command-registry-pattern.md` and `cmd/internal/registry.go`

Applied to files:

  • pkg/component/custom/provider.go
  • cmd/cmd_utils.go
  • cmd/cmd_semantic_completion_test.go
📚 Learning: 2026-01-01T18:25:25.942Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-01T18:25:25.942Z
Learning: Use Registry Pattern for extensibility; existing implementations include Command Registry (`cmd/internal/registry.go` with `CommandProvider` interface) and Store Registry (`pkg/store/registry.go` with multi-provider implementations)

Applied to files:

  • pkg/component/custom/provider.go
📚 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:

  • pkg/component/registry_test.go
  • internal/exec/stack_processor_process_stacks.go
  • cmd/cmd_utils.go
  • internal/exec/describe_component.go
  • internal/exec/stack_processor_process_stacks_test.go
  • cmd/cmd_semantic_completion.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:

  • pkg/component/registry_test.go
📚 Learning: 2026-01-01T18:25:25.942Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-01T18:25:25.942Z
Learning: Stack pipeline: Load atmos.yaml → process imports/inheritance → apply overrides → render templates → generate config. Templates use Go templates + Gomplate with `atmos.Component()`, `!terraform.state`, `!terraform.output`, store integration

Applied to files:

  • internal/exec/stack_processor_process_stacks.go
  • cmd/cmd_utils.go
  • internal/exec/describe_component.go
  • internal/exec/stack_processor_process_stacks_test.go
  • examples/custom-components/README.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_process_stacks.go
  • internal/exec/stack_processor_process_stacks_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/stack_processor_process_stacks.go
  • cmd/cmd_utils.go
  • internal/exec/stack_processor_process_stacks_test.go
  • cmd/cmd_semantic_completion.go
📚 Learning: 2025-05-22T15:42:10.906Z
Learnt from: aknysh
Repo: cloudposse/atmos PR: 1261
File: internal/exec/utils.go:639-640
Timestamp: 2025-05-22T15:42:10.906Z
Learning: In the Atmos codebase, when appending slices with `args := append(configAndStacksInfo.CliArgs, configAndStacksInfo.AdditionalArgsAndFlags...)`, it's intentional that the result is not stored back in the original slice. This pattern is used when the merged result serves a different purpose than the original slices, such as when creating a filtered version for component section assignments.

Applied to files:

  • internal/exec/stack_processor_process_stacks.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_process_stacks.go
  • internal/exec/stack_processor_process_stacks_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/stack_processor_process_stacks.go
  • internal/exec/stack_processor_process_stacks_test.go
📚 Learning: 2025-12-17T20:55:47.884Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 1874
File: internal/exec/describe_affected_utils_test.go:436-468
Timestamp: 2025-12-17T20:55:47.884Z
Learning: In the Atmos codebase, there are two different paths for the `locked` flag: (1) filtering logic in `internal/exec/component_utils.go` (`isComponentLocked()`) reads from `componentSection["metadata"]["locked"]` to determine which components to include/exclude, and (2) extraction/rendering logic in `pkg/list/extract/affected.go` reads from `settings.metadata.locked` to display the locked status in output. Tests for filtering behavior should use `metadata.locked`.

Applied to files:

  • internal/exec/stack_processor_process_stacks.go
  • internal/exec/stack_processor_process_stacks_test.go
📚 Learning: 2025-01-07T20:38:09.618Z
Learnt from: samtholiya
Repo: cloudposse/atmos PR: 896
File: cmd/editor_config.go:37-40
Timestamp: 2025-01-07T20:38:09.618Z
Learning: Error handling suggestion for `cmd.Help()` in `cmd/editor_config.go` was deferred as the code is planned for future modifications.

Applied to files:

  • internal/exec/stack_processor_process_stacks.go
📚 Learning: 2025-01-25T04:01:58.095Z
Learnt from: Listener430
Repo: cloudposse/atmos PR: 934
File: internal/exec/docs_generate.go:98-101
Timestamp: 2025-01-25T04:01:58.095Z
Learning: In the `generateSingleReadme` function of the docs generation feature (internal/exec/docs_generate.go), errors from `fetchAndParseYAML` should be logged and skipped rather than causing early returns. This is by design to process all inputs and collect all errors, instead of failing fast on the first error.

Applied to files:

  • internal/exec/stack_processor_process_stacks.go
📚 Learning: 2024-11-12T03:16:02.910Z
Learnt from: aknysh
Repo: cloudposse/atmos PR: 775
File: internal/exec/template_funcs_component.go:157-159
Timestamp: 2024-11-12T03:16:02.910Z
Learning: In the Go code for `componentFunc` in `internal/exec/template_funcs_component.go`, the function `cleanTerraformWorkspace` does not return errors, and it's acceptable if the file does not exist. Therefore, error handling for `cleanTerraformWorkspace` is not needed.

Applied to files:

  • internal/exec/stack_processor_process_stacks.go
📚 Learning: 2024-10-23T21:36:40.262Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 740
File: cmd/cmd_utils.go:340-359
Timestamp: 2024-10-23T21:36:40.262Z
Learning: In the Go codebase for Atmos, when reviewing functions like `checkAtmosConfig` in `cmd/cmd_utils.go`, avoid suggesting refactoring to return errors instead of calling `os.Exit` if such changes would significantly increase the scope due to the need to update multiple call sites.

Applied to files:

  • internal/exec/stack_processor_process_stacks.go
📚 Learning: 2025-04-04T02:03:23.676Z
Learnt from: aknysh
Repo: cloudposse/atmos PR: 1185
File: internal/exec/yaml_func_store.go:26-26
Timestamp: 2025-04-04T02:03:23.676Z
Learning: The Atmos codebase currently uses `log.Fatal` for error handling in multiple places. The maintainers are aware this isn't an ideal pattern (should only be used in main() or init() functions) and plan to address it comprehensively in a separate PR. CodeRabbit should not flag these issues or push for immediate changes until that refactoring is complete.

Applied to files:

  • internal/exec/stack_processor_process_stacks.go
📚 Learning: 2025-11-24T17:35:37.209Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: .cursor/rules/atmos-rules.mdc:0-0
Timestamp: 2025-11-24T17:35:37.209Z
Learning: Applies to cmd/**/*.go : Provide comprehensive help text for all commands and flags, include examples in command help, and follow Go's documentation conventions in Cobra command definitions

Applied to files:

  • cmd/cmd_utils.go
  • cmd/cmd_semantic_completion.go
  • cmd/cmd_semantic_completion_test.go
📚 Learning: 2025-11-24T17:35:37.209Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: .cursor/rules/atmos-rules.mdc:0-0
Timestamp: 2025-11-24T17:35:37.209Z
Learning: Applies to cmd/**/*.go : Use Cobra's recommended command structure with a root command and subcommands, implementing each command in a separate file under `cmd/` directory

Applied to files:

  • cmd/cmd_utils.go
  • cmd/cmd_semantic_completion_test.go
📚 Learning: 2026-01-01T18:25:25.942Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-01T18:25:25.942Z
Learning: When adding new CLI command: (1) Create `cmd/[command]/` with CommandProvider interface, (2) Add blank import to `cmd/root.go`, (3) Implement in `internal/exec/mycommand.go`, (4) Add tests and Docusaurus docs in `website/docs/cli/commands/`, (5) Build website: `cd website && npm run build`. See `docs/developing-atmos-commands.md` and `docs/prd/command-registry-pattern.md`

Applied to files:

  • cmd/cmd_utils.go
  • examples/custom-components/README.md
📚 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:

  • cmd/cmd_utils.go
📚 Learning: 2026-01-01T18:25:25.942Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-01T18:25:25.942Z
Learning: Configuration loading precedence: CLI flags → ENV vars → config files → defaults (use Viper). Environment variables require ATMOS_ prefix via `viper.BindEnv("ATMOS_VAR", ...)`

Applied to files:

  • cmd/cmd_utils.go
📚 Learning: 2024-12-11T18:40:12.808Z
Learnt from: Listener430
Repo: cloudposse/atmos PR: 844
File: cmd/helmfile.go:37-37
Timestamp: 2024-12-11T18:40:12.808Z
Learning: In the atmos project, `cliConfig` is initialized within the `cmd` package in `root.go` and can be used in other command files.

Applied to files:

  • cmd/cmd_utils.go
📚 Learning: 2026-01-01T18:25:25.942Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-01T18:25:25.942Z
Learning: Applies to **/*.go : Organize imports in three groups separated by blank lines, sorted alphabetically: (1) Go stdlib, (2) 3rd-party (NOT cloudposse/atmos), (3) Atmos packages. Maintain aliases: `cfg`, `log`, `u`, `errUtils`

Applied to files:

  • cmd/cmd_utils.go
📚 Learning: 2026-01-01T18:25:25.942Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-01T18:25:25.942Z
Learning: Applies to pkg/**/*.go : Add `defer perf.Track(atmosConfig, "pkg.FuncName")()` + blank line to all public functions, except trivial getters/setters, command constructors, simple factory functions, and functions that only delegate to another tracked function. Use `nil` if no atmosConfig param

Applied to files:

  • cmd/cmd_utils.go
📚 Learning: 2025-05-30T03:21:37.197Z
Learnt from: aknysh
Repo: cloudposse/atmos PR: 1274
File: go.mod:63-63
Timestamp: 2025-05-30T03:21:37.197Z
Learning: The redis dependency (github.com/redis/go-redis/v9) in the atmos project is only used in tests, not in production code.

Applied to files:

  • cmd/cmd_utils.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:

  • cmd/cmd_utils.go
📚 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:

  • cmd/cmd_utils.go
📚 Learning: 2025-02-18T13:18:53.146Z
Learnt from: samtholiya
Repo: cloudposse/atmos PR: 1068
File: cmd/vendor_pull.go:31-31
Timestamp: 2025-02-18T13:18:53.146Z
Learning: Error checking is not required for cobra.Command.RegisterFlagCompletionFunc calls as these are static configurations done at init time.

Applied to files:

  • cmd/cmd_utils.go
  • cmd/cmd_semantic_completion.go
  • cmd/cmd_semantic_completion_test.go
📚 Learning: 2025-02-07T19:21:38.028Z
Learnt from: samtholiya
Repo: cloudposse/atmos PR: 992
File: cmd/vendor_pull.go:31-31
Timestamp: 2025-02-07T19:21:38.028Z
Learning: The cobra.Command.RegisterFlagCompletionFunc method (as of cobra v1.8.1) never returns an error. It only initializes an internal map and stores the completion function, always returning nil. Error handling for this method call is unnecessary.

Applied to files:

  • cmd/cmd_utils.go
  • cmd/cmd_semantic_completion.go
  • cmd/cmd_semantic_completion_test.go
📚 Learning: 2025-02-07T19:21:38.028Z
Learnt from: samtholiya
Repo: cloudposse/atmos PR: 992
File: cmd/vendor_pull.go:31-31
Timestamp: 2025-02-07T19:21:38.028Z
Learning: The cobra.Command.RegisterFlagCompletionFunc method never returns an error as it simply stores the completion function in an internal map. Error handling for this method call is unnecessary.

Applied to files:

  • cmd/cmd_utils.go
  • cmd/cmd_semantic_completion.go
  • cmd/cmd_semantic_completion_test.go
📚 Learning: 2025-12-13T03:21:35.786Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 1813
File: cmd/terraform/shell.go:28-73
Timestamp: 2025-12-13T03:21:35.786Z
Learning: In Atmos, when calling cfg.InitCliConfig, you must first populate the schema.ConfigAndStacksInfo struct with global flag values using flags.ParseGlobalFlags(cmd, v) rather than passing an empty struct. The LoadConfig function (pkg/config/load.go) reads config selection fields (AtmosConfigFilesFromArg, AtmosConfigDirsFromArg, BasePath, ProfilesFromArg) directly from the ConfigAndStacksInfo struct, NOT from Viper. Passing an empty struct causes config selection flags (--base-path, --config, --config-path, --profile) to be silently ignored. Correct pattern: parse flags → populate struct → call InitCliConfig. See cmd/terraform/plan_diff.go for reference implementation.

Applied to files:

  • cmd/cmd_utils.go
  • internal/exec/stack_processor_process_stacks_test.go
  • cmd/cmd_semantic_completion.go
  • cmd/cmd_semantic_completion_test.go
📚 Learning: 2025-01-09T22:27:25.538Z
Learnt from: samtholiya
Repo: cloudposse/atmos PR: 914
File: cmd/validate_stacks.go:20-23
Timestamp: 2025-01-09T22:27:25.538Z
Learning: The validate commands in Atmos can have different help handling implementations. Specifically, validate_component.go and validate_stacks.go are designed to handle help requests differently, with validate_stacks.go including positional argument checks while validate_component.go does not.

Applied to files:

  • cmd/cmd_utils.go
  • internal/exec/stack_processor_process_stacks_test.go
  • cmd/cmd_semantic_completion.go
  • cmd/cmd_semantic_completion_test.go
  • examples/custom-components/README.md
📚 Learning: 2025-12-13T04:37:25.223Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 1686
File: cmd/root.go:0-0
Timestamp: 2025-12-13T04:37:25.223Z
Learning: In Atmos cmd/root.go Execute(), after cfg.InitCliConfig, we must call both toolchainCmd.SetAtmosConfig(&atmosConfig) and toolchain.SetAtmosConfig(&atmosConfig) so the CLI wrapper and the toolchain package receive configuration; missing either can cause nil-pointer panics in toolchain path resolution.

Applied to files:

  • cmd/cmd_utils.go
📚 Learning: 2024-11-16T17:30:52.893Z
Learnt from: pkbhowmick
Repo: cloudposse/atmos PR: 786
File: internal/exec/shell_utils.go:159-162
Timestamp: 2024-11-16T17:30:52.893Z
Learning: For the `atmos terraform shell` command in `internal/exec/shell_utils.go`, input validation for the custom shell prompt is not required, as users will use this as a CLI tool and any issues will impact themselves.

Applied to files:

  • cmd/cmd_utils.go
  • cmd/cmd_semantic_completion.go
  • cmd/cmd_semantic_completion_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:

  • cmd/cmd_utils.go
  • examples/custom-components/README.md
📚 Learning: 2025-12-13T04:37:40.435Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 1686
File: cmd/toolchain/get.go:23-40
Timestamp: 2025-12-13T04:37:40.435Z
Learning: In Go CLI command files using Cobra, constrain the subcommand to accept at most one positional argument (MaximumNArgs(1)) so it supports both listing all items (zero args) and fetching a specific item (one arg). Define and parse flags with a standard parser (e.g., flags.NewStandardParser()) and avoid binding flags to Viper (no viper.BindEnv/BindPFlag). This promotes explicit argument handling and predictable flag behavior across command files.

Applied to files:

  • cmd/cmd_utils.go
  • cmd/cmd_semantic_completion.go
  • cmd/cmd_semantic_completion_test.go
📚 Learning: 2026-01-01T18:25:25.942Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-01T18:25:25.942Z
Learning: Applies to internal/exec/**/*.go : New templates should support Go templating with `FuncMap()` from `internal/exec/template_funcs.go`

Applied to files:

  • internal/exec/stack_processor_process_stacks_test.go
📚 Learning: 2026-01-01T18:25:25.942Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-01T18:25:25.942Z
Learning: Applies to **/*_test.go : Test behavior, not implementation; never test stub functions; avoid tautological tests; use `errors.Is()` for error checking; remove always-skipped tests

Applied to files:

  • internal/exec/stack_processor_process_stacks_test.go
📚 Learning: 2025-11-24T17:35:37.209Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: .cursor/rules/atmos-rules.mdc:0-0
Timestamp: 2025-11-24T17:35:37.209Z
Learning: Applies to **/*_test.go : Use table-driven tests for testing multiple scenarios in Go

Applied to files:

  • internal/exec/stack_processor_process_stacks_test.go
📚 Learning: 2025-02-09T14:38:53.443Z
Learnt from: samtholiya
Repo: cloudposse/atmos PR: 992
File: cmd/cmd_utils.go:0-0
Timestamp: 2025-02-09T14:38:53.443Z
Learning: Error handling for RegisterFlagCompletionFunc in AddStackCompletion is not required as the errors are non-critical for tab completion functionality.

Applied to files:

  • cmd/cmd_semantic_completion.go
  • cmd/cmd_semantic_completion_test.go
📚 Learning: 2025-11-24T17:35:37.209Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: .cursor/rules/atmos-rules.mdc:0-0
Timestamp: 2025-11-24T17:35:37.209Z
Learning: Applies to cmd/**/*.go : Provide meaningful feedback to users and include progress indicators for long-running operations in CLI commands

Applied to files:

  • cmd/cmd_semantic_completion.go
  • cmd/cmd_semantic_completion_test.go
📚 Learning: 2024-12-05T22:33:40.955Z
Learnt from: aknysh
Repo: cloudposse/atmos PR: 820
File: cmd/list_components.go:53-54
Timestamp: 2024-12-05T22:33:40.955Z
Learning: In the Atmos CLI Go codebase, using `u.LogErrorAndExit` within completion functions is acceptable because it logs the error and exits the command execution.

Applied to files:

  • cmd/cmd_semantic_completion.go
  • cmd/cmd_semantic_completion_test.go
📚 Learning: 2026-01-01T18:25:25.942Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-01T18:25:25.942Z
Learning: Applies to **/*.go : Keep files focused and small (<600 lines); use one cmd/impl per file; co-locate tests; never use `//revive:disable:file-length-limit`

Applied to files:

  • cmd/cmd_semantic_completion_test.go
📚 Learning: 2025-12-10T18:32:43.260Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 1808
File: cmd/terraform/backend/backend_delete_test.go:9-23
Timestamp: 2025-12-10T18:32:43.260Z
Learning: In cmd subpackages, tests should avoid using NewTestKit(t) unless tests actually interact with RootCmd (e.g., execute commands via RootCmd or modify RootCmd state). For structural tests that only verify command structure/flags without touching RootCmd, TestKit cleanup is unnecessary.

Applied to files:

  • cmd/cmd_semantic_completion_test.go
📚 Learning: 2026-01-01T18:25:25.942Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-01T18:25:25.942Z
Learning: Applies to **/*_test.go : Use `cmd.NewTestKit(t)` for cmd tests to auto-clean RootCmd state (flags, args)

Applied to files:

  • cmd/cmd_semantic_completion_test.go
📚 Learning: 2025-11-24T17:35:37.209Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: .cursor/rules/atmos-rules.mdc:0-0
Timestamp: 2025-11-24T17:35:37.209Z
Learning: Applies to README.md : Update README.md with new commands and features

Applied to files:

  • examples/custom-components/README.md
📚 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:

  • examples/custom-components/README.md
📚 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:

  • examples/custom-components/README.md
📚 Learning: 2025-09-13T16:39:20.007Z
Learnt from: samtholiya
Repo: cloudposse/atmos PR: 1466
File: cmd/markdown/atmos_toolchain_aliases.md:2-4
Timestamp: 2025-09-13T16:39:20.007Z
Learning: In the cloudposse/atmos repository, CLI documentation files in cmd/markdown/ follow a specific format that uses " $ atmos command" (with leading space and dollar sign prompt) in code blocks. This is the established project convention and should not be changed to comply with standard markdownlint rules MD040 and MD014.

Applied to files:

  • examples/custom-components/README.md
🧬 Code graph analysis (7)
pkg/component/custom/provider_test.go (2)
pkg/component/custom/provider.go (2)
  • NewProvider (23-30)
  • EnsureRegistered (117-136)
pkg/component/registry.go (1)
  • GetProvider (52-60)
internal/exec/vendor_utils.go (1)
pkg/utils/file_utils.go (1)
  • JoinPathAndValidate (178-199)
internal/exec/stack_processor_process_stacks.go (2)
pkg/config/const.go (7)
  • TerraformComponentType (57-57)
  • HelmfileComponentType (58-58)
  • PackerComponentType (59-59)
  • VarsSectionName (69-69)
  • SettingsSectionName (70-70)
  • EnvSectionName (72-72)
  • ComponentTypeSectionName (98-98)
errors/errors.go (1)
  • ErrInvalidComponentMapType (252-252)
cmd/cmd_utils.go (4)
pkg/schema/command.go (1)
  • Command (6-21)
errors/errors.go (2)
  • ErrComponentArgumentNotFound (339-339)
  • ErrStackArgumentNotFound (340-340)
pkg/component/custom/provider.go (1)
  • EnsureRegistered (117-136)
internal/exec/describe_component.go (2)
  • ExecuteDescribeComponent (214-231)
  • ExecuteDescribeComponentParams (203-211)
internal/exec/stack_processor_process_stacks_test.go (3)
pkg/config/const.go (11)
  • SettingsSectionName (70-70)
  • EnvSectionName (72-72)
  • TerraformSectionName (83-83)
  • CommandSectionName (82-82)
  • HelmfileSectionName (84-84)
  • PackerSectionName (85-85)
  • NameSectionName (65-65)
  • ProvidersSectionName (67-67)
  • HooksSectionName (68-68)
  • TerraformComponentType (57-57)
  • ComponentTypeSectionName (98-98)
errors/errors.go (1)
  • ErrInvalidComponentMapType (252-252)
pkg/schema/schema.go (1)
  • AtmosConfiguration (54-100)
cmd/cmd_semantic_completion.go (7)
pkg/perf/perf.go (1)
  • Track (121-138)
pkg/config/config.go (1)
  • InitCliConfig (28-67)
pkg/schema/command.go (1)
  • Command (6-21)
pkg/component/registry.go (1)
  • ListAllComponents (157-186)
cmd/cmd_utils.go (1)
  • StackFlagCompletion (1113-1170)
pkg/flags/types.go (1)
  • CompletionFunc (21-21)
pkg/flags/interactive.go (2)
  • PromptForPositionalArg (180-195)
  • PromptForMissingRequired (105-119)
cmd/cmd_semantic_completion_test.go (4)
cmd/testkit_test.go (1)
  • NewTestKit (55-65)
pkg/schema/command.go (4)
  • Command (6-21)
  • CommandComponent (57-63)
  • CommandFlag (35-46)
  • CommandArgument (24-32)
cmd/cmd_semantic_completion.go (2)
  • PromptConfig (105-110)
  • DefaultPromptConfig (113-122)
pkg/flags/types.go (1)
  • CompletionFunc (21-21)
🪛 markdownlint-cli2 (0.18.1)
examples/custom-components/README.md

11-11: Fenced code blocks should have a language specified

(MD040, fenced-code-language)


40-40: Fenced code blocks should have a language specified

(MD040, fenced-code-language)

⏰ 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). (3)
  • GitHub Check: Acceptance Tests (windows)
  • GitHub Check: Acceptance Tests (macos)
  • GitHub Check: Summary
🔇 Additional comments (30)
examples/custom-components/stacks/catalog/script/deploy-app.yaml (1)

1-7: LGTM!

Clean example configuration. The variable structure aligns with Atmos patterns, and the defaults provide reasonable starting values for the custom component example.

examples/custom-components/components/script/deploy-app/deploy.sh (1)

1-5: No changes needed—the example is correct and well-documented.

The deploy.sh file is explicitly marked as "not executed" in both the README and its own comments. The actual custom command uses Go templates to access component vars (as shown in atmos.yaml), and the example clearly documents how values flow from the YAML config into the command steps via {{ .Component.vars.* }}. The uppercase variables in deploy.sh are just a reference showing what a real script might use if integrated elsewhere—they don't apply to this example since the script itself isn't run by the custom command.

internal/exec/vendor_utils.go (2)

362-362: Path handling simplified—looks correct.

The filepath.Join already produces OS-native paths, so removing ToSlash is appropriate here. The target path construction should work correctly across platforms.


537-537: Consistent with the path handling simplification.

JoinPathAndValidate delegates to JoinPath which uses filepath.Join for cross-platform path construction, followed by filepath.Abs to resolve absolute paths and filesystem validation. No inconsistent path separator handling patterns found in the file.

pkg/component/registry_test.go (2)

38-49: Well-structured mock implementation.

The ListComponents mock handles all three scenarios cleanly: error injection, per-stack mapping, and default components. Good approach for flexible test coverage.


386-495: Solid test coverage for ListAllComponents.

Table-driven tests cover the important cases: sorting, deduplication, error handling, and graceful degradation. The test isolation via Reset() in each subtest is appropriate.

internal/exec/stack_processor_process_stacks.go (3)

534-550: Custom component filter logic correctly implemented.

The builtInTypes map and componentTypeFilter check ensure custom types are only processed when appropriate. Past review feedback addressed.


557-562: Good error handling for malformed component config.

Returns a clear error with context when a component isn't a map. Past review feedback addressed.


563-606: Manual merge is acceptable for custom components' simpler needs.

The loop-based merge for vars/settings/env works correctly. While m.Merge() exists, custom components don't need the full inheritance/deep-merge semantics, so this lightweight approach is fine.

One note: if custom components later need deeper merge behavior (nested maps), you'd want to revisit this.

pkg/component/custom/provider_test.go (1)

35-87: Comprehensive ListComponents testing.

Good coverage of edge cases: empty config, missing sections, wrong component types, and correct sorting. Table-driven approach is clean.

cmd/cmd_utils.go (5)

152-156: Semantic completion wiring looks correct.

Setting up arg completion and flag completions for semantic types enables the tab-completion feature for custom commands.


540-543: Interactive prompting for semantic values.

Good UX improvement—prompts users for missing component/stack values when in interactive mode.


551-585: Clear separation between new and legacy paths.

The type-based processing (commandConfig.Component != nil) takes precedence, with legacy component_config as fallback. The comments make this distinction clear.


667-693: findTypedValue handles both arguments and flags correctly.

The distinction between arg.Type for arguments and flag.SemanticType for flags aligns with the schema design.


1354-1399: processCustomComponentType ties everything together.

Registers the custom type, locates component/stack values, and resolves configuration. The CheckErrorPrintAndExit pattern is consistent with other CLI code in this file.

internal/exec/stack_processor_process_stacks_test.go (3)

302-312: Good error path coverage for invalid custom component.

Tests that non-map component configs properly return ErrInvalidComponentMapType.


337-756: Extensive happy path coverage.

The table-driven tests cover a wide range of configuration scenarios. The validateResult callbacks mostly assert non-nil, which is acceptable for verifying no errors occur. More detailed assertions would strengthen these tests but aren't strictly necessary.


814-906: Custom component filter tests with metadata verification.

This addresses the past review comment. Lines 892-900 properly verify that component name, component_type, and vars are correctly injected into custom components.

internal/exec/describe_component.go (3)

422-426: Good short-circuit for explicit component type.

When ComponentType is provided explicitly, bypassing the fallback detection chain is the right approach. This enables custom component types to be processed without trying terraform/helmfile/packer first.


206-211: Proper propagation of ComponentType through the call chain.

The optional ComponentType field flows correctly from ExecuteDescribeComponentParams through to DescribeComponentContextParams. This maintains backward compatibility—when empty, the existing detection logic applies.

Also applies to: 217-231


388-405: The ComponentSection map is properly initialized and safe.

The code initializes configAndStacksInfo.ComponentSection = make(map[string]any) in ExecuteDescribeComponentWithContext before tryProcessWithComponentType is called, and ProcessStacks has a defensive nil check as well. The assignment at line 403 won't panic—there's no edge case here.

pkg/component/custom/provider.go (2)

58-79: Clean component discovery from stack config.

The ListComponents implementation correctly navigates the nested structure and handles missing sections gracefully. Sorting the results ensures deterministic output for completions.


114-136: Solid idempotent registration pattern.

EnsureRegistered properly checks for existing registration before creating a new provider. The error wrapping at line 132 follows the project's error handling conventions.

cmd/cmd_semantic_completion.go (4)

103-122: Good DI pattern for testability.

The PromptConfig struct with functional fields enables clean mocking in tests. DefaultPromptConfig provides production implementations while tests can substitute mock behavior.


71-74: Error logging for completion registration is appropriate.

Per learnings, RegisterFlagCompletionFunc rarely fails and errors are non-critical. Logging at trace level is reasonable.


220-248: nolint directive is justified here.

The //nolint:revive // argument-limit is reasonable given the parameters are logically grouped and necessary for the semantic completion context.


25-33: No issue—empty ConfigAndStacksInfo is the correct pattern for completion functions.

Completion functions throughout the codebase consistently use empty ConfigAndStacksInfo{} (see cmd_utils.go:707, :1261, workflow/utils.go:57, :92, terraform/utils.go:418, auth_list.go:82, :101). This is intentional: completions run in a separate shell context and should discover config via environment/defaults, not inherit the main command's CLI flags. The graceful error handling here is appropriate.

cmd/cmd_semantic_completion_test.go (3)

14-80: Comprehensive table-driven tests for flag completions.

Good coverage of stack, component, non-semantic flags, and nil component cases. Using NewTestKit(t) ensures proper RootCmd state cleanup.


144-234: Thorough argument prompting tests.

The test cases cover the key scenarios: required vs optional, existing values, empty component lists, and unknown types. The mock PromptConfig pattern enables clean isolation.


350-416: Good error path coverage for prompt helpers.

Tests for promptForStackValue and promptForComponentValue verify behavior when list functions fail or return empty results. This validates the graceful degradation paths.

Also applies to: 418-485

@mergify
Copy link

mergify bot commented Jan 2, 2026

💥 This pull request now has conflicts. Could you fix it @osterman? 🙏

@mergify mergify bot added the conflict This PR has conflicts label Jan 2, 2026
@osterman osterman force-pushed the feature/dev-3755-custom-component-types branch from 1e1afec to c86842c Compare January 3, 2026 01:36
@mergify mergify bot removed the conflict This PR has conflicts label Jan 3, 2026
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 (1)
pkg/component/custom/provider_test.go (1)

134-152: Good test coverage for EnsureRegistered.

Tests idempotency and empty type validation. Consider adding component.Reset() before these tests for isolation, though the unique type name "test-custom-type" reduces collision risk in practice.

🔎 Optional: Add Reset() for test isolation
 func TestEnsureRegistered(t *testing.T) {
+	component.Reset()
+
 	// Test registering a new type.
 	err := EnsureRegistered("test-custom-type", "components/test-custom-type")
📜 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 1e1afec and c86842c.

📒 Files selected for processing (25)
  • cmd/cmd_semantic_completion.go
  • cmd/cmd_semantic_completion_test.go
  • cmd/cmd_utils.go
  • cmd/cmd_utils_test.go
  • errors/errors.go
  • examples/custom-components/README.md
  • examples/custom-components/atmos.yaml
  • examples/custom-components/components/script/deploy-app/deploy.sh
  • examples/custom-components/stacks/catalog/script/deploy-app.yaml
  • examples/custom-components/stacks/deploy/dev.yaml
  • internal/exec/describe_component.go
  • internal/exec/describe_component_test.go
  • internal/exec/stack_processor_process_stacks.go
  • internal/exec/stack_processor_process_stacks_test.go
  • internal/exec/vendor_utils.go
  • pkg/component/custom/provider.go
  • pkg/component/custom/provider_test.go
  • pkg/component/registry.go
  • pkg/component/registry_test.go
  • pkg/schema/command.go
  • tests/fixtures/schemas/atmos/atmos-manifest/1.0/atmos-manifest.json
  • website/blog/2025-12-20-custom-component-types.mdx
  • website/docs/cli/configuration/commands.mdx
  • website/src/data/roadmap.js
  • website/static/schemas/atmos/atmos-manifest/1.0/atmos-manifest.json
🚧 Files skipped from review as they are similar to previous changes (9)
  • errors/errors.go
  • cmd/cmd_semantic_completion.go
  • cmd/cmd_semantic_completion_test.go
  • cmd/cmd_utils_test.go
  • internal/exec/describe_component_test.go
  • examples/custom-components/stacks/deploy/dev.yaml
  • examples/custom-components/stacks/catalog/script/deploy-app.yaml
  • examples/custom-components/components/script/deploy-app/deploy.sh
  • examples/custom-components/atmos.yaml
🧰 Additional context used
📓 Path-based instructions (9)
**/*.go

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

**/*.go: Use Viper for managing configuration, environment variables, and flags in CLI commands
Use interfaces for external dependencies to facilitate mocking and consider using testify/mock for creating mock implementations
All code must pass golangci-lint checks
Follow Go's error handling idioms: use meaningful error messages, wrap errors with context using fmt.Errorf("context: %w", err), and consider using custom error types for domain-specific errors
Follow standard Go coding style: use gofmt and goimports to format code, prefer short descriptive variable names, use kebab-case for command-line flags, and snake_case for environment variables
Document all exported functions, types, and methods following Go's documentation conventions
Document complex logic with inline comments in Go code
Support configuration via files, environment variables, and flags following the precedence order: flags > environment variables > config file > defaults
Provide clear error messages to users, include troubleshooting hints when appropriate, and log detailed errors for debugging

**/*.go: All comments must end with periods (enforced by godot linter)
Never delete existing comments without a very strong reason; preserve helpful comments explaining why/how/what/where, and update comments to match code when refactoring
Organize imports in three groups separated by blank lines, sorted alphabetically: (1) Go stdlib, (2) 3rd-party (NOT cloudposse/atmos), (3) Atmos packages. Maintain aliases: cfg, log, u, errUtils
Use flags.NewStandardParser() for command-specific flags; NEVER call viper.BindEnv() or viper.BindPFlag() directly (enforced by Forbidigo)
All errors MUST be wrapped using static errors defined in errors/errors.go; use errors.Join for combining multiple errors, fmt.Errorf with %w for adding string context, error builder for complex errors, and errors.Is() for error checking. Never use dynamic errors directly
Define interfaces for all major funct...

Files:

  • pkg/component/registry_test.go
  • internal/exec/stack_processor_process_stacks.go
  • pkg/component/custom/provider.go
  • pkg/component/registry.go
  • pkg/component/custom/provider_test.go
  • internal/exec/describe_component.go
  • internal/exec/vendor_utils.go
  • pkg/schema/command.go
  • cmd/cmd_utils.go
  • internal/exec/stack_processor_process_stacks_test.go
**/*_test.go

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

**/*_test.go: Every new feature must include comprehensive unit tests targeting >80% code coverage for all packages
Use table-driven tests for testing multiple scenarios in Go
Include integration tests for command flows and test CLI end-to-end when possible with test fixtures

**/*_test.go: Use cmd.NewTestKit(t) for cmd tests to auto-clean RootCmd state (flags, args)
Test behavior, not implementation; never test stub functions; avoid tautological tests; use errors.Is() for error checking; remove always-skipped tests
Prefer unit tests with mocks over integration tests; use interfaces and dependency injection for testability; use table-driven tests for comprehensive coverage; target >80% coverage; skip tests gracefully with helpers from tests/test_preconditions.go
Never manually edit golden snapshot files under tests/test-cases/ or tests/testdata/; always use -regenerate-snapshots flag. Never use pipe redirection when running tests as it breaks TTY detection

Files:

  • pkg/component/registry_test.go
  • pkg/component/custom/provider_test.go
  • internal/exec/stack_processor_process_stacks_test.go
pkg/**/*.go

📄 CodeRabbit inference engine (CLAUDE.md)

pkg/**/*.go: Add defer perf.Track(atmosConfig, "pkg.FuncName")() + blank line to all public functions, except trivial getters/setters, command constructors, simple factory functions, and functions that only delegate to another tracked function. Use nil if no atmosConfig param
Avoid adding new functions to pkg/utils/; create purpose-built packages for new functionality (e.g., pkg/store/, pkg/git/, pkg/pro/, pkg/filesystem/)

Files:

  • pkg/component/registry_test.go
  • pkg/component/custom/provider.go
  • pkg/component/registry.go
  • pkg/component/custom/provider_test.go
  • pkg/schema/command.go
internal/exec/**/*.go

📄 CodeRabbit inference engine (CLAUDE.md)

New templates should support Go templating with FuncMap() from internal/exec/template_funcs.go

Files:

  • internal/exec/stack_processor_process_stacks.go
  • internal/exec/describe_component.go
  • internal/exec/vendor_utils.go
  • internal/exec/stack_processor_process_stacks_test.go
cmd/**/*.go

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

cmd/**/*.go: Use Cobra's recommended command structure with a root command and subcommands, implementing each command in a separate file under cmd/ directory
Provide comprehensive help text for all commands and flags, include examples in command help, and follow Go's documentation conventions in Cobra command definitions
Provide meaningful feedback to users and include progress indicators for long-running operations in CLI commands

cmd/**/*.go: Add defer perf.Track(atmosConfig, "pkg.FuncName")() + blank line to all public functions, except trivial getters/setters, command constructors, simple factory functions, and functions that only delegate to another tracked function
Commands MUST use the command registry pattern via CommandProvider interface; see docs/prd/command-registry-pattern.md and cmd/internal/registry.go
Embed examples from cmd/markdown/*_usage.md using //go:embed and render with utils.PrintfMarkdown()

Files:

  • cmd/cmd_utils.go
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/static/schemas/atmos/atmos-manifest/1.0/atmos-manifest.json
  • website/src/data/roadmap.js
  • website/blog/2025-12-20-custom-component-types.mdx
  • website/docs/cli/configuration/commands.mdx
website/src/data/roadmap.js

📄 CodeRabbit inference engine (CLAUDE.md)

For PRs labeled minor/major, update roadmap.js: add milestone to relevant initiative with status: 'shipped', link to changelog with changelog: 'your-blog-slug', link to PR with pr: <pr-number>, update initiative progress percentage as (shipped milestones / total milestones) * 100

Files:

  • website/src/data/roadmap.js
website/blog/**/*.mdx

📄 CodeRabbit inference engine (CLAUDE.md)

Blog posts MUST use .mdx with YAML front matter (slug, title, authors, tags), <!--truncate--> after intro. Only use tags defined in website/blog/tags.yml (never invent new tags). Only use authors from website/blog/authors.yml or add new entry. Valid tags: feature, enhancement, bugfix, dx, breaking-change, security, documentation, deprecation, core

Files:

  • website/blog/2025-12-20-custom-component-types.mdx
website/docs/**/*.mdx

📄 CodeRabbit inference engine (CLAUDE.md)

Build the website after documentation changes: cd website && npm run build to verify no broken links, missing images, or MDX component rendering issues

Files:

  • website/docs/cli/configuration/commands.mdx
🧠 Learnings (62)
📓 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.
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-01T18:25:25.942Z
Learning: When adding new CLI command: (1) Create `cmd/[command]/` with CommandProvider interface, (2) Add blank import to `cmd/root.go`, (3) Implement in `internal/exec/mycommand.go`, (4) Add tests and Docusaurus docs in `website/docs/cli/commands/`, (5) Build website: `cd website && npm run build`. See `docs/developing-atmos-commands.md` and `docs/prd/command-registry-pattern.md`
📚 Learning: 2025-11-24T17:35:37.209Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: .cursor/rules/atmos-rules.mdc:0-0
Timestamp: 2025-11-24T17:35:37.209Z
Learning: Applies to **/*_test.go : Every new feature must include comprehensive unit tests targeting >80% code coverage for all packages

Applied to files:

  • pkg/component/registry_test.go
  • pkg/component/custom/provider_test.go
  • internal/exec/stack_processor_process_stacks_test.go
📚 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:

  • pkg/component/registry_test.go
  • internal/exec/stack_processor_process_stacks.go
  • pkg/component/registry.go
  • internal/exec/describe_component.go
  • pkg/schema/command.go
  • cmd/cmd_utils.go
  • internal/exec/stack_processor_process_stacks_test.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:

  • pkg/component/registry_test.go
📚 Learning: 2025-12-21T04:10:29.030Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 1891
File: internal/exec/describe_affected.go:468-468
Timestamp: 2025-12-21T04:10:29.030Z
Learning: In Go, package-level declarations (constants, variables, types, and functions) are visible to all files in the same package without imports. During reviews in cloudposse/atmos (and similar Go codebases), before suggesting to declare a new identifier, first check if it already exists in another file of the same package. If it exists, you can avoid adding a new declaration; if not, proceed with a proper package-level declaration. 

Applied to files:

  • pkg/component/registry_test.go
  • internal/exec/stack_processor_process_stacks.go
  • pkg/component/custom/provider.go
  • pkg/component/registry.go
  • pkg/component/custom/provider_test.go
  • internal/exec/describe_component.go
  • internal/exec/vendor_utils.go
  • pkg/schema/command.go
  • cmd/cmd_utils.go
  • internal/exec/stack_processor_process_stacks_test.go
📚 Learning: 2026-01-01T18:25:25.942Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-01T18:25:25.942Z
Learning: Stack pipeline: Load atmos.yaml → process imports/inheritance → apply overrides → render templates → generate config. Templates use Go templates + Gomplate with `atmos.Component()`, `!terraform.state`, `!terraform.output`, store integration

Applied to files:

  • internal/exec/stack_processor_process_stacks.go
  • examples/custom-components/README.md
  • internal/exec/describe_component.go
  • cmd/cmd_utils.go
  • internal/exec/stack_processor_process_stacks_test.go
  • website/blog/2025-12-20-custom-component-types.mdx
  • website/docs/cli/configuration/commands.mdx
📚 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_process_stacks.go
  • cmd/cmd_utils.go
  • internal/exec/stack_processor_process_stacks_test.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_process_stacks.go
  • internal/exec/vendor_utils.go
  • internal/exec/stack_processor_process_stacks_test.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.go
  • internal/exec/stack_processor_process_stacks_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/stack_processor_process_stacks.go
  • internal/exec/stack_processor_process_stacks_test.go
📚 Learning: 2025-05-22T15:42:10.906Z
Learnt from: aknysh
Repo: cloudposse/atmos PR: 1261
File: internal/exec/utils.go:639-640
Timestamp: 2025-05-22T15:42:10.906Z
Learning: In the Atmos codebase, when appending slices with `args := append(configAndStacksInfo.CliArgs, configAndStacksInfo.AdditionalArgsAndFlags...)`, it's intentional that the result is not stored back in the original slice. This pattern is used when the merged result serves a different purpose than the original slices, such as when creating a filtered version for component section assignments.

Applied to files:

  • internal/exec/stack_processor_process_stacks.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/stack_processor_process_stacks.go
  • internal/exec/stack_processor_process_stacks_test.go
📚 Learning: 2025-12-17T20:55:47.884Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 1874
File: internal/exec/describe_affected_utils_test.go:436-468
Timestamp: 2025-12-17T20:55:47.884Z
Learning: In the Atmos codebase, there are two different paths for the `locked` flag: (1) filtering logic in `internal/exec/component_utils.go` (`isComponentLocked()`) reads from `componentSection["metadata"]["locked"]` to determine which components to include/exclude, and (2) extraction/rendering logic in `pkg/list/extract/affected.go` reads from `settings.metadata.locked` to display the locked status in output. Tests for filtering behavior should use `metadata.locked`.

Applied to files:

  • internal/exec/stack_processor_process_stacks.go
  • internal/exec/stack_processor_process_stacks_test.go
📚 Learning: 2025-01-07T20:38:09.618Z
Learnt from: samtholiya
Repo: cloudposse/atmos PR: 896
File: cmd/editor_config.go:37-40
Timestamp: 2025-01-07T20:38:09.618Z
Learning: Error handling suggestion for `cmd.Help()` in `cmd/editor_config.go` was deferred as the code is planned for future modifications.

Applied to files:

  • internal/exec/stack_processor_process_stacks.go
📚 Learning: 2025-01-25T04:01:58.095Z
Learnt from: Listener430
Repo: cloudposse/atmos PR: 934
File: internal/exec/docs_generate.go:98-101
Timestamp: 2025-01-25T04:01:58.095Z
Learning: In the `generateSingleReadme` function of the docs generation feature (internal/exec/docs_generate.go), errors from `fetchAndParseYAML` should be logged and skipped rather than causing early returns. This is by design to process all inputs and collect all errors, instead of failing fast on the first error.

Applied to files:

  • internal/exec/stack_processor_process_stacks.go
📚 Learning: 2024-11-12T03:16:02.910Z
Learnt from: aknysh
Repo: cloudposse/atmos PR: 775
File: internal/exec/template_funcs_component.go:157-159
Timestamp: 2024-11-12T03:16:02.910Z
Learning: In the Go code for `componentFunc` in `internal/exec/template_funcs_component.go`, the function `cleanTerraformWorkspace` does not return errors, and it's acceptable if the file does not exist. Therefore, error handling for `cleanTerraformWorkspace` is not needed.

Applied to files:

  • internal/exec/stack_processor_process_stacks.go
📚 Learning: 2024-10-23T21:36:40.262Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 740
File: cmd/cmd_utils.go:340-359
Timestamp: 2024-10-23T21:36:40.262Z
Learning: In the Go codebase for Atmos, when reviewing functions like `checkAtmosConfig` in `cmd/cmd_utils.go`, avoid suggesting refactoring to return errors instead of calling `os.Exit` if such changes would significantly increase the scope due to the need to update multiple call sites.

Applied to files:

  • internal/exec/stack_processor_process_stacks.go
📚 Learning: 2024-12-02T21:26:32.337Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 808
File: pkg/config/config.go:478-483
Timestamp: 2024-12-02T21:26:32.337Z
Learning: In the 'atmos' project, when reviewing Go code like `pkg/config/config.go`, avoid suggesting file size checks after downloading remote configs if such checks aren't implemented elsewhere in the codebase.

Applied to files:

  • internal/exec/stack_processor_process_stacks.go
  • internal/exec/vendor_utils.go
📚 Learning: 2025-04-04T02:03:23.676Z
Learnt from: aknysh
Repo: cloudposse/atmos PR: 1185
File: internal/exec/yaml_func_store.go:26-26
Timestamp: 2025-04-04T02:03:23.676Z
Learning: The Atmos codebase currently uses `log.Fatal` for error handling in multiple places. The maintainers are aware this isn't an ideal pattern (should only be used in main() or init() functions) and plan to address it comprehensively in a separate PR. CodeRabbit should not flag these issues or push for immediate changes until that refactoring is complete.

Applied to files:

  • internal/exec/stack_processor_process_stacks.go
📚 Learning: 2026-01-01T18:25:25.942Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-01T18:25:25.942Z
Learning: Applies to cmd/**/*.go : Commands MUST use the command registry pattern via `CommandProvider` interface; see `docs/prd/command-registry-pattern.md` and `cmd/internal/registry.go`

Applied to files:

  • pkg/component/custom/provider.go
  • pkg/schema/command.go
  • cmd/cmd_utils.go
📚 Learning: 2026-01-01T18:25:25.942Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-01T18:25:25.942Z
Learning: Use Registry Pattern for extensibility; existing implementations include Command Registry (`cmd/internal/registry.go` with `CommandProvider` interface) and Store Registry (`pkg/store/registry.go` with multi-provider implementations)

Applied to files:

  • pkg/component/custom/provider.go
📚 Learning: 2025-11-24T17:35:37.209Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: .cursor/rules/atmos-rules.mdc:0-0
Timestamp: 2025-11-24T17:35:37.209Z
Learning: Applies to **/*_test.go : Include integration tests for command flows and test CLI end-to-end when possible with test fixtures

Applied to files:

  • pkg/component/custom/provider_test.go
  • cmd/cmd_utils.go
  • internal/exec/stack_processor_process_stacks_test.go
📚 Learning: 2026-01-01T18:25:25.942Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-01T18:25:25.942Z
Learning: Applies to **/*_test.go : Prefer unit tests with mocks over integration tests; use interfaces and dependency injection for testability; use table-driven tests for comprehensive coverage; target >80% coverage; skip tests gracefully with helpers from `tests/test_preconditions.go`

Applied to files:

  • pkg/component/custom/provider_test.go
📚 Learning: 2026-01-01T18:25:25.942Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-01T18:25:25.942Z
Learning: When adding new CLI command: (1) Create `cmd/[command]/` with CommandProvider interface, (2) Add blank import to `cmd/root.go`, (3) Implement in `internal/exec/mycommand.go`, (4) Add tests and Docusaurus docs in `website/docs/cli/commands/`, (5) Build website: `cd website && npm run build`. See `docs/developing-atmos-commands.md` and `docs/prd/command-registry-pattern.md`

Applied to files:

  • examples/custom-components/README.md
  • cmd/cmd_utils.go
  • website/blog/2025-12-20-custom-component-types.mdx
  • website/docs/cli/configuration/commands.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:

  • examples/custom-components/README.md
  • website/blog/2025-12-20-custom-component-types.mdx
  • website/docs/cli/configuration/commands.mdx
📚 Learning: 2025-11-24T17:35:37.209Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: .cursor/rules/atmos-rules.mdc:0-0
Timestamp: 2025-11-24T17:35:37.209Z
Learning: Applies to README.md : Update README.md with new commands and features

Applied to files:

  • examples/custom-components/README.md
📚 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:

  • examples/custom-components/README.md
  • website/src/data/roadmap.js
📚 Learning: 2025-01-09T22:27:25.538Z
Learnt from: samtholiya
Repo: cloudposse/atmos PR: 914
File: cmd/validate_stacks.go:20-23
Timestamp: 2025-01-09T22:27:25.538Z
Learning: The validate commands in Atmos can have different help handling implementations. Specifically, validate_component.go and validate_stacks.go are designed to handle help requests differently, with validate_stacks.go including positional argument checks while validate_component.go does not.

Applied to files:

  • examples/custom-components/README.md
  • cmd/cmd_utils.go
  • internal/exec/stack_processor_process_stacks_test.go
  • website/docs/cli/configuration/commands.mdx
📚 Learning: 2025-09-13T16:39:20.007Z
Learnt from: samtholiya
Repo: cloudposse/atmos PR: 1466
File: cmd/markdown/atmos_toolchain_aliases.md:2-4
Timestamp: 2025-09-13T16:39:20.007Z
Learning: In the cloudposse/atmos repository, CLI documentation files in cmd/markdown/ follow a specific format that uses " $ atmos command" (with leading space and dollar sign prompt) in code blocks. This is the established project convention and should not be changed to comply with standard markdownlint rules MD040 and MD014.

Applied to files:

  • examples/custom-components/README.md
  • website/blog/2025-12-20-custom-component-types.mdx
  • website/docs/cli/configuration/commands.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:

  • examples/custom-components/README.md
  • cmd/cmd_utils.go
  • website/blog/2025-12-20-custom-component-types.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:

  • tests/fixtures/schemas/atmos/atmos-manifest/1.0/atmos-manifest.json
  • website/docs/cli/configuration/commands.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:

  • tests/fixtures/schemas/atmos/atmos-manifest/1.0/atmos-manifest.json
  • cmd/cmd_utils.go
📚 Learning: 2024-10-22T23:00:20.627Z
Learnt from: Cerebrovinny
Repo: cloudposse/atmos PR: 737
File: internal/exec/vendor_utils.go:131-141
Timestamp: 2024-10-22T23:00:20.627Z
Learning: In the `ReadAndProcessVendorConfigFile` function in `internal/exec/vendor_utils.go`, the existence of the vendor config file is already checked, so additional file existence checks may be unnecessary.

Applied to files:

  • internal/exec/vendor_utils.go
📚 Learning: 2024-10-28T01:51:30.811Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 727
File: internal/exec/terraform_clean.go:329-332
Timestamp: 2024-10-28T01:51:30.811Z
Learning: In the Atmos Go code, when deleting directories or handling file paths (e.g., in `terraform_clean.go`), always resolve the absolute path using `filepath.Abs` and use the logger `u.LogWarning` for logging messages instead of using `fmt.Printf`.

Applied to files:

  • internal/exec/vendor_utils.go
📚 Learning: 2024-10-31T07:09:31.983Z
Learnt from: Cerebrovinny
Repo: cloudposse/atmos PR: 737
File: internal/exec/vendor_utils.go:181-182
Timestamp: 2024-10-31T07:09:31.983Z
Learning: In `internal/exec/vendor_utils.go`, the variables `mergedSources` and `mergedImports` are declared and used later in the code. Do not suggest removing them as unused variables.

Applied to files:

  • internal/exec/vendor_utils.go
📚 Learning: 2025-11-24T17:35:37.209Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: .cursor/rules/atmos-rules.mdc:0-0
Timestamp: 2025-11-24T17:35:37.209Z
Learning: Applies to cmd/**/*.go : Provide comprehensive help text for all commands and flags, include examples in command help, and follow Go's documentation conventions in Cobra command definitions

Applied to files:

  • pkg/schema/command.go
  • cmd/cmd_utils.go
📚 Learning: 2025-11-24T17:35:37.209Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: .cursor/rules/atmos-rules.mdc:0-0
Timestamp: 2025-11-24T17:35:37.209Z
Learning: Applies to cmd/**/*.go : Use Cobra's recommended command structure with a root command and subcommands, implementing each command in a separate file under `cmd/` directory

Applied to files:

  • pkg/schema/command.go
  • cmd/cmd_utils.go
📚 Learning: 2025-01-09T22:37:01.004Z
Learnt from: samtholiya
Repo: cloudposse/atmos PR: 914
File: cmd/terraform_commands.go:260-265
Timestamp: 2025-01-09T22:37:01.004Z
Learning: In the terraform commands implementation (cmd/terraform_commands.go), the direct use of `os.Args[2:]` for argument handling is intentionally preserved to avoid extensive refactoring. While it could be improved to use cobra's argument parsing, such changes should be handled in a dedicated PR to maintain focus and minimize risk.

Applied to files:

  • pkg/schema/command.go
  • cmd/cmd_utils.go
📚 Learning: 2026-01-01T18:25:25.942Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-01T18:25:25.942Z
Learning: Applies to **/*.go : Use functional options pattern for configuration instead of functions with many parameters to provide defaults and extensibility without breaking changes

Applied to files:

  • cmd/cmd_utils.go
📚 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:

  • cmd/cmd_utils.go
📚 Learning: 2026-01-01T18:25:25.942Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-01T18:25:25.942Z
Learning: Configuration loading precedence: CLI flags → ENV vars → config files → defaults (use Viper). Environment variables require ATMOS_ prefix via `viper.BindEnv("ATMOS_VAR", ...)`

Applied to files:

  • cmd/cmd_utils.go
📚 Learning: 2024-12-11T18:40:12.808Z
Learnt from: Listener430
Repo: cloudposse/atmos PR: 844
File: cmd/helmfile.go:37-37
Timestamp: 2024-12-11T18:40:12.808Z
Learning: In the atmos project, `cliConfig` is initialized within the `cmd` package in `root.go` and can be used in other command files.

Applied to files:

  • cmd/cmd_utils.go
📚 Learning: 2026-01-01T18:25:25.942Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-01T18:25:25.942Z
Learning: Applies to **/*.go : Organize imports in three groups separated by blank lines, sorted alphabetically: (1) Go stdlib, (2) 3rd-party (NOT cloudposse/atmos), (3) Atmos packages. Maintain aliases: `cfg`, `log`, `u`, `errUtils`

Applied to files:

  • cmd/cmd_utils.go
📚 Learning: 2026-01-01T18:25:25.942Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-01T18:25:25.942Z
Learning: Applies to pkg/**/*.go : Add `defer perf.Track(atmosConfig, "pkg.FuncName")()` + blank line to all public functions, except trivial getters/setters, command constructors, simple factory functions, and functions that only delegate to another tracked function. Use `nil` if no atmosConfig param

Applied to files:

  • cmd/cmd_utils.go
📚 Learning: 2025-05-30T03:21:37.197Z
Learnt from: aknysh
Repo: cloudposse/atmos PR: 1274
File: go.mod:63-63
Timestamp: 2025-05-30T03:21:37.197Z
Learning: The redis dependency (github.com/redis/go-redis/v9) in the atmos project is only used in tests, not in production code.

Applied to files:

  • cmd/cmd_utils.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:

  • cmd/cmd_utils.go
📚 Learning: 2025-02-18T13:18:53.146Z
Learnt from: samtholiya
Repo: cloudposse/atmos PR: 1068
File: cmd/vendor_pull.go:31-31
Timestamp: 2025-02-18T13:18:53.146Z
Learning: Error checking is not required for cobra.Command.RegisterFlagCompletionFunc calls as these are static configurations done at init time.

Applied to files:

  • cmd/cmd_utils.go
📚 Learning: 2025-02-07T19:21:38.028Z
Learnt from: samtholiya
Repo: cloudposse/atmos PR: 992
File: cmd/vendor_pull.go:31-31
Timestamp: 2025-02-07T19:21:38.028Z
Learning: The cobra.Command.RegisterFlagCompletionFunc method (as of cobra v1.8.1) never returns an error. It only initializes an internal map and stores the completion function, always returning nil. Error handling for this method call is unnecessary.

Applied to files:

  • cmd/cmd_utils.go
📚 Learning: 2025-02-07T19:21:38.028Z
Learnt from: samtholiya
Repo: cloudposse/atmos PR: 992
File: cmd/vendor_pull.go:31-31
Timestamp: 2025-02-07T19:21:38.028Z
Learning: The cobra.Command.RegisterFlagCompletionFunc method never returns an error as it simply stores the completion function in an internal map. Error handling for this method call is unnecessary.

Applied to files:

  • cmd/cmd_utils.go
📚 Learning: 2025-12-13T03:21:35.786Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 1813
File: cmd/terraform/shell.go:28-73
Timestamp: 2025-12-13T03:21:35.786Z
Learning: In Atmos, when calling cfg.InitCliConfig, you must first populate the schema.ConfigAndStacksInfo struct with global flag values using flags.ParseGlobalFlags(cmd, v) rather than passing an empty struct. The LoadConfig function (pkg/config/load.go) reads config selection fields (AtmosConfigFilesFromArg, AtmosConfigDirsFromArg, BasePath, ProfilesFromArg) directly from the ConfigAndStacksInfo struct, NOT from Viper. Passing an empty struct causes config selection flags (--base-path, --config, --config-path, --profile) to be silently ignored. Correct pattern: parse flags → populate struct → call InitCliConfig. See cmd/terraform/plan_diff.go for reference implementation.

Applied to files:

  • cmd/cmd_utils.go
  • internal/exec/stack_processor_process_stacks_test.go
📚 Learning: 2025-12-13T04:37:25.223Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 1686
File: cmd/root.go:0-0
Timestamp: 2025-12-13T04:37:25.223Z
Learning: In Atmos cmd/root.go Execute(), after cfg.InitCliConfig, we must call both toolchainCmd.SetAtmosConfig(&atmosConfig) and toolchain.SetAtmosConfig(&atmosConfig) so the CLI wrapper and the toolchain package receive configuration; missing either can cause nil-pointer panics in toolchain path resolution.

Applied to files:

  • cmd/cmd_utils.go
📚 Learning: 2024-11-16T17:30:52.893Z
Learnt from: pkbhowmick
Repo: cloudposse/atmos PR: 786
File: internal/exec/shell_utils.go:159-162
Timestamp: 2024-11-16T17:30:52.893Z
Learning: For the `atmos terraform shell` command in `internal/exec/shell_utils.go`, input validation for the custom shell prompt is not required, as users will use this as a CLI tool and any issues will impact themselves.

Applied to files:

  • cmd/cmd_utils.go
📚 Learning: 2025-12-13T04:37:40.435Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 1686
File: cmd/toolchain/get.go:23-40
Timestamp: 2025-12-13T04:37:40.435Z
Learning: In Go CLI command files using Cobra, constrain the subcommand to accept at most one positional argument (MaximumNArgs(1)) so it supports both listing all items (zero args) and fetching a specific item (one arg). Define and parse flags with a standard parser (e.g., flags.NewStandardParser()) and avoid binding flags to Viper (no viper.BindEnv/BindPFlag). This promotes explicit argument handling and predictable flag behavior across command files.

Applied to files:

  • cmd/cmd_utils.go
📚 Learning: 2026-01-01T18:25:25.942Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-01T18:25:25.942Z
Learning: Applies to internal/exec/**/*.go : New templates should support Go templating with `FuncMap()` from `internal/exec/template_funcs.go`

Applied to files:

  • internal/exec/stack_processor_process_stacks_test.go
📚 Learning: 2026-01-01T18:25:25.942Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-01T18:25:25.942Z
Learning: Applies to **/*_test.go : Test behavior, not implementation; never test stub functions; avoid tautological tests; use `errors.Is()` for error checking; remove always-skipped tests

Applied to files:

  • internal/exec/stack_processor_process_stacks_test.go
📚 Learning: 2025-11-24T17:35:37.209Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: .cursor/rules/atmos-rules.mdc:0-0
Timestamp: 2025-11-24T17:35:37.209Z
Learning: Applies to **/*_test.go : Use table-driven tests for testing multiple scenarios in Go

Applied to files:

  • internal/exec/stack_processor_process_stacks_test.go
📚 Learning: 2026-01-01T18:25:25.942Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-01T18:25:25.942Z
Learning: Applies to website/src/data/roadmap.js : For PRs labeled `minor`/`major`, update roadmap.js: add milestone to relevant initiative with `status: 'shipped'`, link to changelog with `changelog: 'your-blog-slug'`, link to PR with `pr: <pr-number>`, update initiative `progress` percentage as `(shipped milestones / total milestones) * 100`

Applied to files:

  • website/src/data/roadmap.js
📚 Learning: 2026-01-01T18:25:25.942Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-01T18:25:25.942Z
Learning: All new commands/flags/parameters MUST have Docusaurus documentation in `website/docs/cli/commands/` following frontmatter conventions, including purpose note and help screengrab; link to core concepts using `/core-concepts/` paths

Applied to files:

  • website/blog/2025-12-20-custom-component-types.mdx
  • website/docs/cli/configuration/commands.mdx
📚 Learning: 2026-01-01T18:25:25.942Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-01T18:25:25.942Z
Learning: Applies to website/docs/cli/commands/**/*.mdx : Link to core concepts using `/core-concepts/` paths; use definition lists instead of tables for arguments and flags; follow consistent section ordering: Usage → Examples → Arguments → Flags

Applied to files:

  • website/blog/2025-12-20-custom-component-types.mdx
  • website/docs/cli/configuration/commands.mdx
📚 Learning: 2026-01-01T18:25:25.942Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-01T18:25:25.942Z
Learning: Applies to website/docs/cli/commands/**/*.mdx : All CLI command documentation MUST include: (1) Frontmatter with title/sidebar_label/sidebar_class_name/id/description, (2) Intro component with brief description, (3) Screengrab with title and slug, (4) Usage section with shell code block, (5) Arguments/Flags with `<dl><dt>` tags, (6) Examples section with practical usage

Applied to files:

  • website/blog/2025-12-20-custom-component-types.mdx
  • website/docs/cli/configuration/commands.mdx
📚 Learning: 2025-10-10T23:51:36.597Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 1599
File: internal/exec/terraform.go:394-402
Timestamp: 2025-10-10T23:51:36.597Z
Learning: In Atmos (internal/exec/terraform.go), when adding OpenTofu-specific flags like `--var-file` for `init`, do not gate them based on command name (e.g., checking if `info.Command == "tofu"` or `info.Command == "opentofu"`) because command names don't reliably indicate the actual binary being executed (symlinks, aliases). Instead, document the OpenTofu requirement in code comments and documentation, trusting users who enable the feature (e.g., `PassVars`) to ensure their terraform command points to an OpenTofu binary.

Applied to files:

  • website/blog/2025-12-20-custom-component-types.mdx
📚 Learning: 2025-02-18T13:13:11.497Z
Learnt from: samtholiya
Repo: cloudposse/atmos PR: 1068
File: tests/snapshots/TestCLICommands_atmos_terraform_help.stdout.golden:59-64
Timestamp: 2025-02-18T13:13:11.497Z
Learning: For Atmos CLI help text, angle brackets in command examples and flag descriptions should be escaped using HTML entities (e.g., `&lt;component&gt;`) rather than converted to backticks or other markdown formatting.

Applied to files:

  • website/docs/cli/configuration/commands.mdx
🧬 Code graph analysis (5)
pkg/component/registry_test.go (2)
errors/errors.go (1)
  • ErrComponentProviderNotFound (330-330)
pkg/component/registry.go (1)
  • ListAllComponents (157-186)
pkg/component/registry.go (3)
pkg/schema/schema.go (1)
  • Context (562-577)
pkg/perf/perf.go (1)
  • Track (121-138)
errors/errors.go (1)
  • ErrComponentProviderNotFound (330-330)
pkg/component/custom/provider_test.go (2)
pkg/component/custom/provider.go (2)
  • NewProvider (23-30)
  • EnsureRegistered (117-136)
pkg/component/registry.go (1)
  • GetProvider (52-60)
internal/exec/vendor_utils.go (1)
pkg/utils/file_utils.go (1)
  • JoinPathAndValidate (178-199)
internal/exec/stack_processor_process_stacks_test.go (2)
errors/errors.go (1)
  • ErrInvalidComponentMapType (260-260)
internal/exec/stack_processor_process_stacks.go (1)
  • ProcessStackConfig (28-618)
🪛 LanguageTool
website/blog/2025-12-20-custom-component-types.mdx

[style] ~11-~11: Since ownership is already implied, this phrasing may be redundant.
Context: ...- Atmos custom commands can now define their own component types beyond terraform, `he...

(PRP_OWN)


[style] ~23-~23: Since ownership is already implied, this phrasing may be redundant.
Context: ...tom Component Types Now you can define your own component types directly in custom comm...

(PRP_OWN)


[grammar] ~77-~77: Use a hyphen to join words.
Context: ... data type (string, bool). ### Full Stack Inheritance Custom components inh...

(QB_NEW_EN_HYPHEN)

website/docs/cli/configuration/commands.mdx

[style] ~637-~637: Since ownership is already implied, this phrasing may be redundant.
Context: ...onent Types Custom commands can define their own component types beyond the built-in `te...

(PRP_OWN)


[typographical] ~733-~733: Consider using typographic quotation marks here.
Context: ...ponent_type }}| Component type (e.g., "script") | |{{ .Component.atmos_stack }}` | S...

(EN_QUOTES)


[typographical] ~745-~745: Consider using typographic quotation marks here.
Context: ...uired.** The component type name (e.g., "script", "ansible", "manifest") | | base_path...

(EN_QUOTES)


[typographical] ~745-~745: Consider using a typographic opening quote here.
Context: ...he component type name (e.g., "script", "ansible", "manifest") | | base_path | ...

(EN_QUOTES)


[typographical] ~745-~745: Consider using a typographic close quote here.
Context: ...nent type name (e.g., "script", "ansible", "manifest") | | base_path | Optional...

(EN_QUOTES)


[typographical] ~745-~745: Consider using typographic quotation marks here.
Context: ...t type name (e.g., "script", "ansible", "manifest") | | base_path | Optional. Base direc...

(EN_QUOTES)

🪛 markdownlint-cli2 (0.18.1)
examples/custom-components/README.md

11-11: Fenced code blocks should have a language specified

(MD040, fenced-code-language)


40-40: Fenced code blocks should have a language specified

(MD040, fenced-code-language)

⏰ 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 (34)
examples/custom-components/README.md (1)

1-61: LGTM!

The documentation clearly explains the custom components feature, provides a working example, and aligns well with the PR objectives. The structure, usage instructions, and template access explanation are all helpful.

internal/exec/vendor_utils.go (2)

362-362: LGTM - Cross-platform path handling.

Removing the ToSlash wrapper is appropriate here. filepath.Join already returns OS-native paths, and downstream code should handle them correctly.


537-537: LGTM - Simplified path handling.

Passing vendorConfigFilePath directly to JoinPathAndValidate is correct. The function already handles path normalization with filepath.Join and filepath.Abs internally, making the pre-conversion unnecessary.

internal/exec/describe_component.go (5)

206-206: LGTM - ComponentType field additions.

Adding the ComponentType field to both parameter structs enables explicit component type selection, which aligns with the custom component types feature. The optional nature maintains backward compatibility.

Also applies to: 221-221, 381-381


388-405: LGTM - Well-structured helper for type-specific processing.

The componentTypeProcessParams struct and tryProcessWithComponentType function cleanly encapsulate the logic for processing stacks with a specific component type. This reduces duplication in the detection logic below.


407-426: LGTM - Explicit component type short-circuit.

The early return when ComponentType is explicitly provided is correct. This enables custom component types to be processed directly without falling back to Terraform/Helmfile/Packer detection.


428-461: LGTM - Robust error handling in fallback logic.

The component type detection correctly distinguishes between "component not found" errors (ErrInvalidComponent) and other errors (syntax errors, etc.). This prevents masking real errors with generic "not found" messages, which was the issue in #1864.


503-503: LGTM - ComponentType propagation.

The detectComponentType call correctly passes the new ComponentType field through the params, enabling explicit component type selection when provided.

pkg/schema/command.go (5)

15-15: LGTM - Component field addition.

Adding the Component field to the Command struct enables associating custom commands with component types, which is central to this PR's objectives. The pointer with omitempty keeps it optional for commands that don't need it.


33-35: LGTM - Semantic argument typing.

The Type field on CommandArgument enables semantic completion and configuration resolution for component/stack arguments. The comments clearly explain the purpose.


47-49: LGTM - Semantic flag typing.

The SemanticType field on CommandFlag mirrors the functionality of CommandArgument.Type, enabling semantic completion and configuration resolution for flags. Clear comments and consistent design.


59-67: LGTM - Well-designed CommandComponent struct.

The CommandComponent struct cleanly defines custom component type metadata with sensible defaults. The comments explain template access and the default BasePath convention, making it easy to understand and use.


69-69: LGTM - Legacy marker clarifies evolution.

Marking CommandComponentConfig as "legacy" helps developers understand that CommandComponent is the new approach, while maintaining backward compatibility.

website/docs/cli/configuration/commands.mdx (1)

634-819: Documentation for custom component types looks solid.

The new section thoroughly covers:

  • Typed arguments and flags with type: component and semantic_type: stack
  • The component: configuration block with type and base_path
  • Template variable access via {{ .Component.* }}
  • Practical examples for script, ansible, and kubernetes use cases
  • Clear comparison with legacy component_config

This aligns well with the implementation in cmd/cmd_utils.go and the custom provider system.

internal/exec/stack_processor_process_stacks.go (1)

534-606: Custom component processing implementation looks good.

Previous review concerns are addressed:

  • componentTypeFilter is now respected (lines 547-550)
  • Invalid component config now returns an error instead of silent passthrough (lines 559-562)

One observation: the manual map iteration for merging vars/settings/env (lines 563-599) uses shallow copy semantics, while built-in types use m.Merge. This is likely intentional for simplicity with custom components, but worth noting if deep merge behavior becomes needed later.

pkg/component/registry.go (1)

154-186: Well-designed function for shell completion support.

The implementation:

  • Properly wraps provider-not-found errors
  • Uses graceful degradation for per-stack errors (appropriate for completion)
  • Deduplicates and sorts results
  • Tracks performance

The ctx parameter is passed to ListComponents but not checked in the loop. That's fine for this use case since completion should be fast.

pkg/component/registry_test.go (2)

386-496: Comprehensive test coverage for ListAllComponents.

Good coverage of:

  • Sorted results from single stack
  • Deduplication across multiple stacks
  • Error handling for unknown provider
  • Empty stacks map
  • Invalid config type handling
  • Graceful degradation on ListComponents errors

Table-driven approach with Reset() isolation is solid.


17-49: testProvider extensions enable flexible test scenarios.

The added fields (components, listError, listByStackMap) and updated ListComponents logic provide clean hooks for error injection and per-stack behavior testing.

pkg/component/custom/provider_test.go (1)

35-87: Thorough ListComponents test coverage.

Covers key scenarios: empty config, missing sections, wrong component type, and presence of target components with sorted output verification.

cmd/cmd_utils.go (5)

152-156: Semantic completion hooks properly integrated.

The calls to setSemanticArgCompletion and registerSemanticFlagCompletions enable tab-completion for typed arguments and flags in custom commands.


540-542: Interactive prompting for semantic values integrated.

This enables interactive selection when required component/stack values are missing.


551-585: Clean separation of new and legacy component config paths.

The conditional logic properly routes:

  • Custom component types → processCustomComponentTypedata["Component"]
  • Legacy component_config → existing flow → data["ComponentConfig"]

Backward compatibility preserved.


667-693: findTypedValue correctly handles the Type vs SemanticType distinction.

Arguments use Type, flags use SemanticType. The function cleanly searches both and returns the first match.


1355-1399: processCustomComponentType orchestrates custom component resolution correctly.

Flow:

  1. Find component name from typed argument/flag
  2. Find stack name from typed argument/flag
  3. Register custom component type
  4. Resolve component configuration
  5. Expose via data["Component"]

The unused atmosConfig parameter (line 1359) suggests future extensibility.

internal/exec/stack_processor_process_stacks_test.go (3)

302-312: LGTM on the custom component error path test.

This correctly validates that ErrInvalidComponentMapType is returned when a custom component value isn't a map. Good alignment with the error handling in stack_processor_process_stacks.go.


338-756: Solid coverage for the happy path scenarios.

The table-driven approach covers a comprehensive range of configurations. The validateResult callbacks are minimal but sufficient for verifying no panics or errors on valid inputs. If you want deeper assertions later, the structure supports it.


814-906: Good work addressing the metadata injection verification.

The test now properly asserts:

  • component name is injected correctly (line 895)
  • component_type metadata is set (line 896)
  • vars are merged and preserved (lines 898-900)

This addresses the previous review feedback and strengthens confidence in the custom component processing logic.

pkg/component/custom/provider.go (4)

1-30: Clean provider initialization.

Good structure. The perf.Track(nil, ...) usage in NewProvider follows guidelines for factory functions.


58-79: ListComponents implementation looks solid.

Safe handling of missing sections with early returns of empty slices. Sorted output ensures deterministic behavior.


131-133: Double %w usage is valid.

Just noting: using two %w verbs in Go 1.20+ allows errors.Is() to match against both wrapped errors. This is intentional and correct.


117-136: TOCTOU window is benign given Register semantics.

The check-then-register pattern (lines 125–130) has a TOCTOU window where concurrent goroutines could both see the provider as unregistered and attempt registration. However, this is harmless: component.Register is internally synchronized with a mutex and explicitly allows overwrites—per its docstring, "last registration wins, allowing plugin override." Worst case is duplicate work creating providers, but the registry state remains correct.

website/static/schemas/atmos/atmos-manifest/1.0/atmos-manifest.json (2)

163-190: Schema extension for custom components is well-structured.

Good approach: built-in types (terraform, helmfile, packer) remain explicit properties while unknown keys route to custom_components via additionalProperties. This maintains backward compatibility while enabling extensibility.


191-244: Custom component definitions look correct.

The custom_components definition mirrors the pattern used for built-in component types, and custom_component_manifest appropriately supports vars, env, settings, metadata, and locals. The additionalProperties: true provides flexibility for custom tooling needs.

tests/fixtures/schemas/atmos/atmos-manifest/1.0/atmos-manifest.json (1)

163-244: Test fixtures schema stays in sync with the main schema.

The changes here correctly mirror the website/static version. This ensures tests validate against the actual schema structure.

coderabbitai[bot]
coderabbitai bot previously approved these changes Jan 4, 2026
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)
website/blog/2025-12-20-custom-component-types.mdx (1)

11-11: Optional: Minor style refinements.

LanguageTool suggests a few stylistic tweaks:

  • Lines 11 and 23: Consider dropping "own" from "their own" and "your own" (slightly redundant, though common in docs)
  • Line 77: "Full-Stack" with hyphen instead of "Full Stack"

These are purely stylistic nitpicks—the current phrasing is clear and widely used. Feel free to defer or ignore.

Also applies to: 23-23, 77-77

📜 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 c86842c and 24fe365.

📒 Files selected for processing (3)
  • errors/errors.go
  • website/blog/2025-12-20-custom-component-types.mdx
  • website/src/data/roadmap.js
🚧 Files skipped from review as they are similar to previous changes (2)
  • errors/errors.go
  • website/src/data/roadmap.js
🧰 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/blog/2025-12-20-custom-component-types.mdx
website/blog/*.mdx

📄 CodeRabbit inference engine (CLAUDE.md)

PRs labeled minor or major MUST include a blog post at website/blog/YYYY-MM-DD-feature-name.mdx with YAML frontmatter, using only tags defined in website/blog/tags.yml

Files:

  • website/blog/2025-12-20-custom-component-types.mdx
🧠 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: 2026-01-04T00:55:21.698Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-04T00:55:21.698Z
Learning: Applies to website/docs/cli/commands/**/*.mdx : All CLI command documentation MUST include: frontmatter, Intro component, Screengrab, Usage section, Arguments/Flags in `<dl>` format, and Examples section

Applied to files:

  • website/blog/2025-12-20-custom-component-types.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/blog/2025-12-20-custom-component-types.mdx
📚 Learning: 2025-10-10T23:51:36.597Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 1599
File: internal/exec/terraform.go:394-402
Timestamp: 2025-10-10T23:51:36.597Z
Learning: In Atmos (internal/exec/terraform.go), when adding OpenTofu-specific flags like `--var-file` for `init`, do not gate them based on command name (e.g., checking if `info.Command == "tofu"` or `info.Command == "opentofu"`) because command names don't reliably indicate the actual binary being executed (symlinks, aliases). Instead, document the OpenTofu requirement in code comments and documentation, trusting users who enable the feature (e.g., `PassVars`) to ensure their terraform command points to an OpenTofu binary.

Applied to files:

  • website/blog/2025-12-20-custom-component-types.mdx
📚 Learning: 2025-11-29T17:35:01.177Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 1819
File: website/blog/2025-10-13-introducing-atmos-auth.md:5-6
Timestamp: 2025-11-29T17:35:01.177Z
Learning: In the Atmos blog (website/blog/), blog post authors should be set to the actual content author (the person who wrote the feature/content), not generic organization names like "cloudposse" or "atmos". If the actual author differs from the PR opener, use the actual author. Authors must exist in website/blog/authors.yml.

Applied to files:

  • website/blog/2025-12-20-custom-component-types.mdx
📚 Learning: 2025-12-13T06:07:37.766Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 1686
File: docs/prd/tool-dependencies-integration.md:58-64
Timestamp: 2025-12-13T06:07:37.766Z
Learning: cloudposse/atmos: For PRD docs (docs/prd/*.md), markdownlint issues like MD040/MD010/MD034 can be handled in a separate documentation cleanup commit and should not block the current PR.

Applied to files:

  • website/blog/2025-12-20-custom-component-types.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/blog/2025-12-20-custom-component-types.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/blog/2025-12-20-custom-component-types.mdx
📚 Learning: 2025-01-17T00:18:57.769Z
Learnt from: aknysh
Repo: cloudposse/atmos PR: 944
File: go.mod:206-206
Timestamp: 2025-01-17T00:18:57.769Z
Learning: For indirect dependencies with license compliance issues in the cloudposse/atmos repository, the team prefers to handle them in follow-up PRs rather than blocking the current changes, as these issues often require deeper investigation of the dependency tree.

Applied to files:

  • website/blog/2025-12-20-custom-component-types.mdx
📚 Learning: 2025-09-13T16:39:20.007Z
Learnt from: samtholiya
Repo: cloudposse/atmos PR: 1466
File: cmd/markdown/atmos_toolchain_aliases.md:2-4
Timestamp: 2025-09-13T16:39:20.007Z
Learning: In the cloudposse/atmos repository, CLI documentation files in cmd/markdown/ follow a specific format that uses " $ atmos command" (with leading space and dollar sign prompt) in code blocks. This is the established project convention and should not be changed to comply with standard markdownlint rules MD040 and MD014.

Applied to files:

  • website/blog/2025-12-20-custom-component-types.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/blog/2025-12-20-custom-component-types.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/blog/2025-12-20-custom-component-types.mdx
📚 Learning: 2025-02-18T13:13:11.497Z
Learnt from: samtholiya
Repo: cloudposse/atmos PR: 1068
File: tests/snapshots/TestCLICommands_atmos_terraform_help.stdout.golden:59-64
Timestamp: 2025-02-18T13:13:11.497Z
Learning: For Atmos CLI help text, angle brackets in command examples and flag descriptions should be escaped using HTML entities (e.g., `&lt;component&gt;`) rather than converted to backticks or other markdown formatting.

Applied to files:

  • website/blog/2025-12-20-custom-component-types.mdx
📚 Learning: 2024-11-22T12:38:33.132Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 768
File: internal/exec/vendor_utils.go:496-513
Timestamp: 2024-11-22T12:38:33.132Z
Learning: In the Atmos project, continue to flag path traversal issues in code reviews but acknowledge when they are expected and acceptable in specific cases.

Applied to files:

  • website/blog/2025-12-20-custom-component-types.mdx
🪛 LanguageTool
website/blog/2025-12-20-custom-component-types.mdx

[style] ~11-~11: Since ownership is already implied, this phrasing may be redundant.
Context: ...- Atmos custom commands can now define their own component types beyond terraform, `he...

(PRP_OWN)


[style] ~23-~23: Since ownership is already implied, this phrasing may be redundant.
Context: ...tom Component Types Now you can define your own component types directly in custom comm...

(PRP_OWN)


[grammar] ~77-~77: Use a hyphen to join words.
Context: ... data type (string, bool). ### Full Stack Inheritance Custom components inh...

(QB_NEW_EN_HYPHEN)

⏰ 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 (1)
website/blog/2025-12-20-custom-component-types.mdx (1)

1-192: Solid blog post structure and content.

The frontmatter is correct (author osterman properly set per previous review), the <!--truncate--> marker is in place, and the content follows a clear progression from problem to solution with concrete examples. The comparison table and getting-started section make this immediately actionable for users.

osterman and others added 8 commits January 15, 2026 21:37
…om commands

- Implement shell completion for semantic-typed flags and arguments (component/stack types)
- Add interactive prompting for missing required semantic-typed values
- Support custom component types in shell completions
- Register ValidArgsFunction for positional arguments with semantic types
- Add comprehensive test coverage for completion and prompting functionality
- Extract completion functions to separate file to manage file size

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

Co-Authored-By: Claude Haiku 4.5 <[email protected]>
Add tests to increase coverage by ~25% on files flagged by Codecov:

cmd/cmd_semantic_completion_test.go:
- TestDefaultPromptConfig: Validates default config returns valid functions
- TestPromptForStackValue: Tests stack prompting (4 cases)
- TestPromptForComponentValue: Tests component prompting (4 cases)
- TestCustomComponentCompletion: Tests completion closure behavior

cmd/cmd_utils_test.go:
- TestProcessCustomCommands: Tests custom command registration (9 cases)
- TestFindTypedValue: Tests typed value search in args/flags (7 cases)

internal/exec/describe_component_test.go:
- TestFilterAbstractComponents: Tests abstract component filtering (6 cases)
- TestWriteOutputToFile: Tests file writing behavior (3 cases)
- TestExtractImportsList: Tests imports extraction (7 cases)

internal/exec/stack_processor_process_stacks_test.go:
- TestProcessStackConfig_HappyPath: Tests valid config processing (24 cases)
- TestProcessStackConfig_ComponentTypeFilter: Tests component filtering (4 cases)

Also fixes pre-existing lint error in pkg/config/load.go:
- Use errors.As instead of type switch for wrapped error handling

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

Co-Authored-By: Claude Opus 4.5 <[email protected]>
The componentTypeFilter parameter was being applied to built-in types
(terraform, helmfile, packer) but not to custom component types. This
fix ensures that when a filter is set, custom types are also filtered
appropriately.

Added test coverage for this behavior.

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

Co-Authored-By: Claude Opus 4.5 <[email protected]>
filepath.ToSlash() converts backslashes to forward slashes, but when
used before filepath.Join() on Windows, it produces malformed paths
that fail file operations. filepath.Join() handles cross-platform
path construction correctly on its own.

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

Co-Authored-By: Claude Opus 4.5 <[email protected]>
…a tests

Address CodeRabbit review feedback:
- Return ErrInvalidComponentMapType when custom component config is not
  a map instead of silently passing it through. This surfaces
  configuration issues in stack files.
- Add assertions verifying that 'component' and 'component_type' metadata
  fields are correctly injected for custom components.
- Add test case for invalid custom component map type error path.

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

Co-Authored-By: Claude Opus 4.5 <[email protected]>
Link the "Custom component types with registry" and "Semantic type
completion" milestones to the custom-component-types blog post.

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

Co-Authored-By: Claude Opus 4.5 <[email protected]>
- Update blog post author from generic 'atmos' to 'osterman'
- Add pr: 1904 to custom component type milestones in roadmap
- Update Extensibility initiative progress from 80% to 87%

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

Co-Authored-By: Claude Opus 4.5 <[email protected]>
Add the custom-components example to TAGS_MAP and DOCS_MAP in the
file-browser plugin so it appears correctly in the examples browser
with proper tagging and documentation links.

Co-Authored-By: Claude Opus 4.5 <[email protected]>
@mergify
Copy link

mergify bot commented Jan 21, 2026

💥 This pull request now has conflicts. Could you fix it @osterman? 🙏

@mergify mergify bot added the conflict This PR has conflicts label Jan 21, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

conflict This PR has conflicts 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.

Custom Component Types workflow - being able to specify some external input Enabling Autocompletion for Custom CLI commands

2 participants