fix: Resolve file-scoped locals in stack configurations#1939
Conversation
Dependency Review✅ No vulnerabilities or license issues found.Scanned FilesNone |
|
@coderabbitai full review please |
|
@aknysh: I'll conduct a full review of all the changes in this PR. ✅ Actions performedFull review triggered. |
📝 WalkthroughWalkthroughPre-template extraction and resolution of file‑scoped locals added. Stack manifests are parsed for global and section‑specific locals, resolved with section‑presence flags, flattened into a Changes
Sequence Diagram(s)sequenceDiagram
autonumber
actor User
participant CLI as Atmos CLI
participant FS as Filesystem
participant Extractor as Locals Extractor
participant Resolver as Locals Resolver
participant Context as Template Context
participant Engine as Template Engine
User->>CLI: run "atmos describe locals" or process stacks
CLI->>FS: read stack manifest(s) (raw YAML)
FS-->>Extractor: raw YAML
Activate Extractor
Extractor->>Resolver: parse locals sections (global, terraform, helmfile, packer)
Resolver->>Resolver: set HasTerraformLocals/HasHelmfileLocals/HasPackerLocals
Resolver->>Resolver: resolve templates inside locals (detect cycles)
Resolver->>Resolver: conditionally merge per‑section locals into flattened map
Resolver-->>Extractor: flattened locals map per stack
Deactivate Extractor
Extractor-->>Context: inject `.locals` into template context
Context->>Engine: render templates referencing `.locals`
Engine-->>CLI: formatted output (yaml/json) for describe‑locals
Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes Possibly related PRs
Suggested reviewers
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing touches🧪 Generate unit tests (beta)
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. Comment |
There was a problem hiding this comment.
Actionable comments posted: 0
🧹 Nitpick comments (2)
tests/cli_locals_test.go (1)
11-21: Tests only verify command execution success, not output correctness.These integration tests assert only that no error occurs. They don't validate that locals are actually resolved correctly in the output (e.g., checking that
{{ .locals.* }}templates are replaced with expected values).For comprehensive coverage, consider adding assertions on the output content or at minimum capturing stdout to verify resolved locals appear.
Also applies to: 24-34, 37-47, 51-62
internal/exec/stack_processor_utils.go (1)
70-99: Silent error handling may hide configuration issues.The function logs at Trace level and returns the original context when locals extraction fails. While this ensures template processing continues, users might not realize their locals have syntax errors until unexpected template output appears.
Consider logging at Debug or Warn level for extraction failures to improve discoverability, especially during development.
🔎 Optional: Increase log visibility for extraction failures
resolvedLocals, localsErr := extractLocalsFromRawYAML(atmosConfig, yamlContent, filePath) if localsErr != nil { - log.Trace("Failed to extract locals from file", "file", relativeFilePath, "error", localsErr) + log.Debug("Failed to extract locals from file", "file", relativeFilePath, "error", localsErr) return context }
📜 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.
📒 Files selected for processing (8)
docs/fixes/file-scoped-locals-not-working.mdinternal/exec/stack_processor_locals.gointernal/exec/stack_processor_utils.gointernal/exec/stack_processor_utils_test.gotests/cli_locals_test.gotests/fixtures/scenarios/locals/stacks/deploy/dev.yamltests/fixtures/scenarios/locals/stacks/deploy/prod.yamlwebsite/blog/2026-01-06-file-scoped-locals-fix.mdx
🧰 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 usingfmt.Errorf("context: %w", err), and consider using custom error types for domain-specific errors
Follow standard Go coding style: usegofmtandgoimportsto 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 bygodotlinter) in Go code
Organize imports into three groups separated by blank lines, sorted alphabetically: Go stdlib, 3rd-party (NOT cloudposse/atmos), then Atmos packages with maintained aliases (cfg,log,u,errUtils)
All errors MUST be wrapped using static errors defined inerrors/errors.go- useerrors.Joinfor combining errors,fmt.Errorfwith%wfor context, anderrors.Is()for error checking
Never manually create mocks - usego.uber.org/mock/mockgenwith//go:generatedirectives in Go code
Keep files small and focused - under 600 lines with one cmd/impl per file, co-locate tests, never use//revive:disable:file-length-limit
Use colors frompkg/ui/theme/colors.gofor all UI theming in Go code
Code must be compatible with Linux, macOS, and Windows - use SDKs over binaries, usefilepath.Join()instead of h...
Files:
tests/cli_locals_test.gointernal/exec/stack_processor_utils.gointernal/exec/stack_processor_locals.gointernal/exec/stack_processor_utils_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 fixturesPrefer unit tests with mocks over integration tests - use interfaces and dependency injection for testability, generate mocks with
go.uber.org/mock/mockgen, use table-driven tests, target >80% coverage
Files:
tests/cli_locals_test.gointernal/exec/stack_processor_utils_test.go
**/{pkg,internal,cmd}/**/*.go
📄 CodeRabbit inference engine (CLAUDE.md)
Add
defer perf.Track(atmosConfig, "pkg.FuncName")()plus blank line to all public functions, usingnilif no atmosConfig param - exceptions: trivial getters/setters, command constructors, simple factories, functions delegating to tracked functions
Files:
internal/exec/stack_processor_utils.gointernal/exec/stack_processor_locals.gointernal/exec/stack_processor_utils_test.go
website/**
📄 CodeRabbit inference engine (.cursor/rules/atmos-rules.mdc)
website/**: Update website documentation in thewebsite/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 thewebsite/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/2026-01-06-file-scoped-locals-fix.mdx
website/blog/*.mdx
📄 CodeRabbit inference engine (CLAUDE.md)
PRs labeled
minorormajorMUST include a blog post atwebsite/blog/YYYY-MM-DD-feature-name.mdxwith YAML frontmatter, using only tags defined inwebsite/blog/tags.yml
Files:
website/blog/2026-01-06-file-scoped-locals-fix.mdx
🧠 Learnings (34)
📚 Learning: 2024-12-03T04:01:16.446Z
Learnt from: aknysh
Repo: cloudposse/atmos PR: 810
File: website/docs/core-concepts/stacks/yaml-functions/terraform.output.mdx:0-0
Timestamp: 2024-12-03T04:01:16.446Z
Learning: In the `terraform.output.mdx` documentation file (`website/docs/core-concepts/stacks/yaml-functions/terraform.output.mdx`), the cache invalidation and cache scope behavior for the `!terraform.output` function are already described.
Applied to files:
docs/fixes/file-scoped-locals-not-working.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 : Include integration tests for command flows and test CLI end-to-end when possible with test fixtures
Applied to files:
tests/cli_locals_test.gointernal/exec/stack_processor_utils_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:
tests/cli_locals_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:
tests/cli_locals_test.gointernal/exec/stack_processor_utils_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:
tests/cli_locals_test.gointernal/exec/stack_processor_utils_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:
tests/cli_locals_test.gointernal/exec/stack_processor_utils.gointernal/exec/stack_processor_locals.gointernal/exec/stack_processor_utils_test.go
📚 Learning: 2025-11-11T03:47:59.576Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 1686
File: toolchain/which_test.go:166-223
Timestamp: 2025-11-11T03:47:59.576Z
Learning: In the cloudposse/atmos repo, tests that manipulate environment variables should use testing.T.Setenv for automatic setup/teardown instead of os.Setenv/Unsetenv.
Applied to files:
tests/cli_locals_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:
tests/cli_locals_test.go
📚 Learning: 2026-01-04T00:55:21.720Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-04T00:55:21.720Z
Learning: Applies to **/*.go : Keep files small and focused - under 600 lines with one cmd/impl per file, co-locate tests, never use `//revive:disable:file-length-limit`
Applied to files:
tests/cli_locals_test.go
📚 Learning: 2026-01-04T00:55:21.720Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-04T00:55:21.720Z
Learning: Applies to **/{pkg,internal,cmd}/**/*.go : Add `defer perf.Track(atmosConfig, "pkg.FuncName")()` plus blank line to all public functions, using `nil` if no atmosConfig param - exceptions: trivial getters/setters, command constructors, simple factories, functions delegating to tracked functions
Applied to files:
tests/cli_locals_test.gointernal/exec/stack_processor_utils_test.go
📚 Learning: 2025-12-10T18:32:51.237Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 1808
File: cmd/terraform/backend/backend_delete_test.go:9-23
Timestamp: 2025-12-10T18:32:51.237Z
Learning: In cmd subpackages (e.g., cmd/terraform/backend/), tests cannot use cmd.NewTestKit(t) due to Go's test visibility rules (NewTestKit is in a parent package test file). These tests only need TestKit if they execute commands through RootCmd or modify RootCmd state. Structural tests that only verify command structure/flags without touching RootCmd don't require TestKit cleanup.
Applied to files:
tests/cli_locals_test.go
📚 Learning: 2025-08-15T14:43:41.030Z
Learnt from: aknysh
Repo: cloudposse/atmos PR: 1352
File: pkg/store/artifactory_store_test.go:108-113
Timestamp: 2025-08-15T14:43:41.030Z
Learning: In test files for the atmos project, it's acceptable to ignore errors from os.Setenv/Unsetenv operations during test environment setup and teardown, as these are controlled test scenarios.
Applied to files:
tests/cli_locals_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: In the atmos codebase, t.Chdir() is a valid method call on *testing.T objects and works correctly for changing directories in tests. This is implemented through custom testing framework extensions and is used consistently throughout the test suite.
Applied to files:
tests/cli_locals_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: In the atmos codebase, t.Chdir() is a valid method call on *testing.T objects and works correctly for changing directories in tests.
Applied to files:
tests/cli_locals_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: In the atmos codebase, t.Chdir() is a valid method that can be called on *testing.T objects. This functionality is implemented through custom testing framework extensions and is used consistently throughout the test suite for changing working directories during tests.
Applied to files:
tests/cli_locals_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:
tests/cli_locals_test.gointernal/exec/stack_processor_utils.gointernal/exec/stack_processor_locals.gointernal/exec/stack_processor_utils_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_utils.gointernal/exec/stack_processor_utils_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_utils.gointernal/exec/stack_processor_utils_test.go
📚 Learning: 2024-10-20T00:57:53.500Z
Learnt from: haitham911
Repo: cloudposse/atmos PR: 731
File: internal/exec/validate_stacks.go:0-0
Timestamp: 2024-10-20T00:57:53.500Z
Learning: In `internal/exec/validate_stacks.go`, when downloading the Atmos JSON Schema file to the temp directory, the temporary file is overwritten each time, so explicit removal is not necessary.
Applied to files:
internal/exec/stack_processor_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:
internal/exec/stack_processor_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 **/*.go : Use Viper for managing configuration, environment variables, and flags in CLI commands
Applied to files:
internal/exec/stack_processor_utils.go
📚 Learning: 2025-04-24T01:06:15.259Z
Learnt from: haitham911
Repo: cloudposse/atmos PR: 1202
File: pkg/config/process_yaml.go:0-0
Timestamp: 2025-04-24T01:06:15.259Z
Learning: When processing YAML structures with gopkg.in/yaml.v3, the Value field of a Node is only meant for scalar values. Complex data types like maps and arrays are represented through child nodes in the YAML tree structure.
Applied to files:
internal/exec/stack_processor_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:
internal/exec/stack_processor_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:
internal/exec/stack_processor_utils.go
📚 Learning: 2026-01-04T00:55:21.720Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-04T00:55:21.720Z
Learning: Applies to **/*.go : Organize imports into three groups separated by blank lines, sorted alphabetically: Go stdlib, 3rd-party (NOT cloudposse/atmos), then Atmos packages with maintained aliases (`cfg`, `log`, `u`, `errUtils`)
Applied to files:
internal/exec/stack_processor_utils.go
📚 Learning: 2025-12-24T04:29:23.938Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 1891
File: pkg/ci/terraform/templates/apply.md:17-17
Timestamp: 2025-12-24T04:29:23.938Z
Learning: In the cloudposse/atmos repository, Terraform CI templates (pkg/ci/terraform/templates/*.md) are rendered using TerraformTemplateContext (defined in pkg/ci/terraform/context.go), not the base ci.TemplateContext. TerraformTemplateContext provides top-level fields: .Resources (ci.ResourceCounts), .HasChanges() method, and .HasDestroy field, which are correctly accessed directly in templates without a .Result prefix.
Applied to files:
internal/exec/stack_processor_utils.gointernal/exec/stack_processor_locals.go
📚 Learning: 2026-01-04T00:55:21.720Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-04T00:55:21.720Z
Learning: Applies to website/blog/*.mdx : 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`
Applied to files:
website/blog/2026-01-06-file-scoped-locals-fix.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/2026-01-06-file-scoped-locals-fix.mdx
📚 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_locals.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:
internal/exec/stack_processor_locals.gointernal/exec/stack_processor_utils_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_locals.gointernal/exec/stack_processor_utils_test.go
📚 Learning: 2026-01-04T00:55:21.720Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-04T00:55:21.720Z
Learning: New config templates support Go templating with `FuncMap()` from `internal/exec/template_funcs.go`
Applied to files:
internal/exec/stack_processor_locals.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_locals.go
📚 Learning: 2025-09-30T19:03:50.738Z
Learnt from: Cerebrovinny
Repo: cloudposse/atmos PR: 1560
File: pkg/utils/string_utils.go:43-64
Timestamp: 2025-09-30T19:03:50.738Z
Learning: In the Atmos codebase, YAML tags like !terraform.output rely on positional arguments, so the SplitStringByDelimiter function in pkg/utils/string_utils.go must preserve empty strings (even after trimming quotes) to maintain the correct number of positional arguments. Filtering out empty values after trimming would collapse the array and break these function calls.
Applied to files:
internal/exec/stack_processor_utils_test.go
🧬 Code graph analysis (3)
tests/cli_locals_test.go (2)
cmd/root.go (1)
RootCmd(333-515)pkg/logger/log.go (1)
Fatalf(69-71)
internal/exec/stack_processor_utils.go (4)
pkg/schema/schema.go (1)
AtmosConfiguration(54-100)pkg/perf/perf.go (1)
Track(121-138)internal/exec/stack_processor_locals.go (1)
ProcessStackLocals(86-148)pkg/logger/log.go (1)
Trace(14-16)
internal/exec/stack_processor_locals.go (2)
pkg/config/const.go (1)
LocalsSectionName(71-71)pkg/schema/schema.go (3)
Terraform(412-435)Helmfile(449-456)Packer(458-461)
🪛 LanguageTool
docs/fixes/file-scoped-locals-not-working.md
[style] ~145-~145: Since ownership is already implied, this phrasing may be redundant.
Context: ... discovered: when sections don't define their own locals, ProcessStackLocals set them t...
(PRP_OWN)
[typographical] ~188-~188: Consider using a typographic opening quote here.
Context: ...es: - Self-referencing locals (e.g., `name_prefix: "{{ .locals.namespace }}-{{ .locals.envir...
(EN_QUOTES)
[typographical] ~231-~231: To join two clauses or introduce examples, consider using an em dash.
Context: ... 1. TestExtractLocalsFromRawYAML_Basic - Basic locals extraction 2. `TestExtractL...
(DASH_RULE)
[style] ~280-~280: Since ownership is already implied, this phrasing may be redundant.
Context: ...rraform/helmfile/packer) doesn't define its own locals, ProcessStackLocals was settin...
(PRP_OWN)
[typographical] ~294-~294: Consider using a typographic opening quote here.
Context: ...als section ``` Before fix: Result was namespace: "global-acme" (wrong - helmfile/packer o...
(EN_QUOTES)
[typographical] ~295-~295: Consider using a typographic opening quote here.
Context: ...erwrote terraform) After fix: Result is namespace: "terraform-acme" (correct - only section...
(EN_QUOTES)
[style] ~298-~298: Since ownership is already implied, this phrasing may be redundant.
Context: ... track which sections explicitly define their own locals. Only merge section locals when ...
(PRP_OWN)
[typographical] ~302-~302: To join two clauses or introduce examples, consider using an em dash.
Context: ... 1. atmos describe locals command - Not implemented in this fix; could be ad...
(DASH_RULE)
[typographical] ~303-~303: To join two clauses or introduce examples, consider using an em dash.
Context: ... debugging 2. Component-level locals - Requires per-component template scoping ...
(DASH_RULE)
⏰ Context from checks skipped due to timeout of 900000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (4)
- GitHub Check: Acceptance Tests (windows)
- GitHub Check: Acceptance Tests (macos)
- GitHub Check: Acceptance Tests (linux)
- GitHub Check: Summary
🔇 Additional comments (21)
internal/exec/stack_processor_locals.go (3)
109-112: Solid fix for the section override bug.The HasXLocals flag pattern correctly prevents sections without explicit locals from overwriting values during merge. This addresses the bug mentioned in the docs where helmfile/packer were overwriting terraform's values when they all pointed to the same global reference.
Also applies to: 124-127, 139-142
164-173: Clear documentation on the new flags.The field documentation makes their purpose obvious. Nice work.
175-207: Merge logic implements correct precedence.The method correctly merges global first, then conditionally overlays section locals only when explicitly defined. The nil check and defensive handling are appropriate.
tests/fixtures/scenarios/locals/stacks/deploy/prod.yaml (1)
39-43: Good test coverage for global and terraform-scope locals.The fixture appropriately demonstrates the supported locals usage pattern, with a helpful comment indicating scope.
tests/fixtures/scenarios/locals/stacks/deploy/dev.yaml (1)
47-51: Consistent fixture pattern across multiple components.Both components correctly demonstrate global and terraform-scope locals usage. The fixtures provide good test coverage.
Also applies to: 57-61
website/blog/2026-01-06-file-scoped-locals-fix.mdx (2)
11-162: Excellent documentation of the fix.The blog post clearly explains the problem, solution, and usage patterns. The before/after examples and limitations section are particularly helpful for users.
7-7: The "bugfix" tag is valid. It exists inwebsite/blog/tags.yml, so the blog post correctly follows the coding guidelines.docs/fixes/file-scoped-locals-not-working.md (1)
1-310: Comprehensive technical documentation.This internal doc provides excellent detail on the problem, solution, and testing. The section explaining the override bug (lines 277-299) adds valuable context for why the HasXLocals flags were necessary.
tests/cli_locals_test.go (2)
1-62: LGTM on structure and idioms.Good use of
t.Chdir()andt.Setenv()per project conventions. The tests cover dev, prod, describe stacks, and circular dependency scenarios which aligns with the PR objectives.
11-21: SetArgs/Execute pattern is idiomatic—no test pollution concern.Each test calls
cmd.RootCmd.SetArgs(...)andcmd.Execute()without explicit cleanup. This is the established pattern across all integration tests (tests/describe_test.go, tests/validate_schema_test.go, tests/cli_source_provisioner_workdir_test.go, etc.). TheExecute()function reinitializes configuration fresh on each call viacfg.InitCliConfig(), so RootCmd state doesn't persist between tests.internal/exec/stack_processor_utils.go (2)
30-68: Well-structured locals extraction with proper documentation.The function has comprehensive documentation explaining the extraction order (global → section → component) and the purpose. The perf.Track call is correctly placed. The delegation to
ProcessStackLocalsandMergeForTemplateContext()keeps this function focused.
492-508: Correct integration point for pre-template locals extraction.The placement before template processing (Line 510) ensures
{{ .locals.* }}references are available during template execution. The guardif !skipTemplatesProcessingInImportscorrectly prevents unnecessary extraction when templates are skipped.internal/exec/stack_processor_utils_test.go (9)
1435-1453: Solid basic test case.Verifies extraction of simple locals and template resolution (namespace + environment → name_prefix). Good coverage of the core use case.
1455-1468: Good edge case coverage for missing locals.The assertion
assert.Empty(t, result)verifies the function returns a usable empty map rather than nil, which is safe for template processing.
1481-1494: Invalid YAML test provides good error coverage.The test confirms error handling for malformed YAML and that the error message is descriptive.
1585-1598: Circular dependency detection is properly tested.This validates that the resolver detects cycles and fails gracefully with a descriptive error.
1600-1616: Self-reference resolution order is tested.The test verifies that chained dependencies (a → b → c) resolve correctly in the expected order. This is a key behavior for the locals feature.
1639-1655: Section override precedence is explicitly tested.This confirms that terraform section locals override global locals with the same key, which is the expected behavior per the PR objectives.
1678-1689: Nil atmosConfig test ensures robustness.Good defensive test ensuring the function handles nil config gracefully without panics.
1704-1718: Empty locals section test is valuable.Distinguishes between "no locals key" (nil) and "empty locals: {}" (empty map). This edge case matters for downstream consumers.
1435-1718: Comprehensive test coverage for the new locals extraction feature.The 16 tests cover the full spectrum: happy paths, edge cases, error conditions, section-specific behaviors, and precedence rules. This aligns well with the coding guidelines requiring >80% coverage.
…log level - Updated integration tests to verify actual resolved values using ExecuteDescribeComponent and ExecuteDescribeStacks instead of just checking command execution success - Changed log level from Trace to Debug for locals extraction failures to improve discoverability during development - Fixed API signatures in tests to match current function parameters 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
📝 WalkthroughWalkthroughThis PR implements a fix for file-scoped locals that weren't being resolved in templates. The solution extracts locals from raw YAML before template processing, tracks section-specific locals with new flags, and merges them into the template context to enable {{ .locals.* }} references throughout stack configurations. Changes
Sequence DiagramsequenceDiagram
participant CLI as CLI Command
participant Processor as Stack Processor
participant YAMLExt as YAML Extractor
participant LocalsCtx as LocalsContext
participant TemplateEng as Template Engine
participant Output as Output
CLI->>Processor: Process Stack Config
Processor->>YAMLExt: extractLocalsFromRawYAML(rawYAML)
YAMLExt->>YAMLExt: Parse YAML to map
YAMLExt->>LocalsCtx: Return locals map
Processor->>LocalsCtx: ProcessStackLocals(globals, sections)
LocalsCtx->>LocalsCtx: Set HasTerraformLocals, HasHelmfileLocals, HasPackerLocals flags
LocalsCtx->>LocalsCtx: Resolve cross-references
LocalsCtx->>Processor: Return resolved LocalsContext
Processor->>LocalsCtx: MergeForTemplateContext()
LocalsCtx->>LocalsCtx: Copy global locals
LocalsCtx->>LocalsCtx: Conditionally merge section locals (if hasLocals==true)
LocalsCtx->>Processor: Return flattened locals map
Processor->>TemplateEng: context["locals"] = flattened map
TemplateEng->>TemplateEng: Render {{ .locals.* }} references
TemplateEng->>Output: Return rendered configuration
Output->>CLI: Display results
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Possibly related PRs
Suggested reviewers
Pre-merge checks and finishing touches✅ Passed checks (5 passed)
✨ Finishing touches
🧪 Generate unit tests (beta)
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. Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Fix all issues with AI Agents
In @internal/exec/stack_processor_utils.go:
- Around line 43-52: The YAML parse error in extractLocalsFromRawYAML should be
wrapped with the project sentinel error (errUtils.ErrInvalidStackManifest)
before returning; update the error return after yaml.Unmarshal in
extractLocalsFromRawYAML to wrap the parse error with
errUtils.ErrInvalidStackManifest (i.e., return nil, fmt.Errorf("%w: failed to
parse YAML for locals extraction: %v", errUtils.ErrInvalidStackManifest, err))
so it follows the same static-error pattern used elsewhere in this file.
🧹 Nitpick comments (2)
tests/cli_locals_test.go (1)
11-21: Tests only verify no error, not actual locals resolution.These integration tests confirm commands execute without error but don't validate that locals were actually resolved. Consider capturing stdout and asserting on resolved values (e.g.,
app_name: "acme-dev-mock-instance-1").Additionally,
cmd.RootCmd.SetArgspersists between tests. Without resetting state, test execution order could affect results.🔎 Consider capturing and validating output
// Example pattern for capturing output var buf bytes.Buffer cmd.RootCmd.SetOut(&buf) cmd.RootCmd.SetErr(&buf) defer func() { cmd.RootCmd.SetOut(nil) cmd.RootCmd.SetErr(nil) }() cmd.RootCmd.SetArgs([]string{"describe", "component", "mock/instance-1", "--stack", "dev-us-east-1", "--format", "yaml"}) if err := cmd.Execute(); err != nil { t.Fatalf("Failed to execute command: %v", err) } output := buf.String() assert.Contains(t, output, "app_name: acme-dev-mock-instance-1")internal/exec/stack_processor_utils.go (1)
492-508: Consider consolidating duplicate comments.The comment block is helpful, but lines 504-505 duplicate the statement from the beginning of the block. The extensive example (lines 495-503) nicely illustrates the feature, but you could remove the duplicate line and keep just the comprehensive comment block.
🔎 Optional: Consolidate comments
// Extract and resolve file-scoped locals before template processing. // Locals can reference other locals using {{ .locals.X }} syntax. // The resolved locals are added to the template context so they're available during template processing. // This enables patterns like: // locals: // stage: prod // name_prefix: "{{ .locals.stage }}-app" // components: // terraform: // myapp: // vars: // name: "{{ .locals.name_prefix }}" - // Extract and resolve file-scoped locals before template processing. - // Locals are added to the template context so {{ .locals.* }} references work. if !skipTemplatesProcessingInImports { context = extractAndAddLocalsToContext(atmosConfig, stackYamlConfig, filePath, relativeFilePath, context) }
📜 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.
📒 Files selected for processing (8)
docs/fixes/file-scoped-locals-not-working.mdinternal/exec/stack_processor_locals.gointernal/exec/stack_processor_utils.gointernal/exec/stack_processor_utils_test.gotests/cli_locals_test.gotests/fixtures/scenarios/locals/stacks/deploy/dev.yamltests/fixtures/scenarios/locals/stacks/deploy/prod.yamlwebsite/blog/2026-01-06-file-scoped-locals-fix.mdx
🧰 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 usingfmt.Errorf("context: %w", err), and consider using custom error types for domain-specific errors
Follow standard Go coding style: usegofmtandgoimportsto 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 bygodotlinter) in Go code
Organize imports into three groups separated by blank lines, sorted alphabetically: Go stdlib, 3rd-party (NOT cloudposse/atmos), then Atmos packages with maintained aliases (cfg,log,u,errUtils)
All errors MUST be wrapped using static errors defined inerrors/errors.go- useerrors.Joinfor combining errors,fmt.Errorfwith%wfor context, anderrors.Is()for error checking
Never manually create mocks - usego.uber.org/mock/mockgenwith//go:generatedirectives in Go code
Keep files small and focused - under 600 lines with one cmd/impl per file, co-locate tests, never use//revive:disable:file-length-limit
Use colors frompkg/ui/theme/colors.gofor all UI theming in Go code
Code must be compatible with Linux, macOS, and Windows - use SDKs over binaries, usefilepath.Join()instead of h...
Files:
internal/exec/stack_processor_utils.gotests/cli_locals_test.gointernal/exec/stack_processor_locals.gointernal/exec/stack_processor_utils_test.go
**/{pkg,internal,cmd}/**/*.go
📄 CodeRabbit inference engine (CLAUDE.md)
Add
defer perf.Track(atmosConfig, "pkg.FuncName")()plus blank line to all public functions, usingnilif no atmosConfig param - exceptions: trivial getters/setters, command constructors, simple factories, functions delegating to tracked functions
Files:
internal/exec/stack_processor_utils.gointernal/exec/stack_processor_locals.gointernal/exec/stack_processor_utils_test.go
website/**
📄 CodeRabbit inference engine (.cursor/rules/atmos-rules.mdc)
website/**: Update website documentation in thewebsite/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 thewebsite/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/2026-01-06-file-scoped-locals-fix.mdx
website/blog/*.mdx
📄 CodeRabbit inference engine (CLAUDE.md)
PRs labeled
minorormajorMUST include a blog post atwebsite/blog/YYYY-MM-DD-feature-name.mdxwith YAML frontmatter, using only tags defined inwebsite/blog/tags.yml
Files:
website/blog/2026-01-06-file-scoped-locals-fix.mdx
**/*_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 fixturesPrefer unit tests with mocks over integration tests - use interfaces and dependency injection for testability, generate mocks with
go.uber.org/mock/mockgen, use table-driven tests, target >80% coverage
Files:
tests/cli_locals_test.gointernal/exec/stack_processor_utils_test.go
🧠 Learnings (33)
📓 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: 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.
📚 Learning: 2024-12-03T04:01:16.446Z
Learnt from: aknysh
Repo: cloudposse/atmos PR: 810
File: website/docs/core-concepts/stacks/yaml-functions/terraform.output.mdx:0-0
Timestamp: 2024-12-03T04:01:16.446Z
Learning: In the `terraform.output.mdx` documentation file (`website/docs/core-concepts/stacks/yaml-functions/terraform.output.mdx`), the cache invalidation and cache scope behavior for the `!terraform.output` function are already described.
Applied to files:
docs/fixes/file-scoped-locals-not-working.md
📚 Learning: 2024-11-19T23:00:45.899Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 795
File: internal/exec/stack_processor_utils.go:378-386
Timestamp: 2024-11-19T23:00:45.899Z
Learning: In the `ProcessYAMLConfigFile` function within `internal/exec/stack_processor_utils.go`, directory traversal in stack imports is acceptable and should not be restricted.
Applied to files:
internal/exec/stack_processor_utils.gointernal/exec/stack_processor_utils_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_utils.gotests/cli_locals_test.gointernal/exec/stack_processor_locals.gointernal/exec/stack_processor_utils_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 **/*.go : Use Viper for managing configuration, environment variables, and flags in CLI commands
Applied to files:
internal/exec/stack_processor_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:
internal/exec/stack_processor_utils.go
📚 Learning: 2025-04-24T01:06:15.259Z
Learnt from: haitham911
Repo: cloudposse/atmos PR: 1202
File: pkg/config/process_yaml.go:0-0
Timestamp: 2025-04-24T01:06:15.259Z
Learning: When processing YAML structures with gopkg.in/yaml.v3, the Value field of a Node is only meant for scalar values. Complex data types like maps and arrays are represented through child nodes in the YAML tree structure.
Applied to files:
internal/exec/stack_processor_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:
internal/exec/stack_processor_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:
internal/exec/stack_processor_utils.go
📚 Learning: 2026-01-04T00:55:21.720Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-04T00:55:21.720Z
Learning: Applies to **/*.go : Organize imports into three groups separated by blank lines, sorted alphabetically: Go stdlib, 3rd-party (NOT cloudposse/atmos), then Atmos packages with maintained aliases (`cfg`, `log`, `u`, `errUtils`)
Applied to files:
internal/exec/stack_processor_utils.gotests/cli_locals_test.go
📚 Learning: 2025-12-24T04:29:23.938Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 1891
File: pkg/ci/terraform/templates/apply.md:17-17
Timestamp: 2025-12-24T04:29:23.938Z
Learning: In the cloudposse/atmos repository, Terraform CI templates (pkg/ci/terraform/templates/*.md) are rendered using TerraformTemplateContext (defined in pkg/ci/terraform/context.go), not the base ci.TemplateContext. TerraformTemplateContext provides top-level fields: .Resources (ci.ResourceCounts), .HasChanges() method, and .HasDestroy field, which are correctly accessed directly in templates without a .Result prefix.
Applied to files:
internal/exec/stack_processor_utils.gointernal/exec/stack_processor_locals.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_utils.gotests/cli_locals_test.gointernal/exec/stack_processor_locals.gointernal/exec/stack_processor_utils_test.go
📚 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/2026-01-06-file-scoped-locals-fix.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/2026-01-06-file-scoped-locals-fix.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 **/*_test.go : Include integration tests for command flows and test CLI end-to-end when possible with test fixtures
Applied to files:
tests/cli_locals_test.gointernal/exec/stack_processor_utils_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:
tests/cli_locals_test.go
📚 Learning: 2026-01-04T00:55:21.720Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-04T00:55:21.720Z
Learning: Applies to **/{pkg,internal,cmd}/**/*.go : Add `defer perf.Track(atmosConfig, "pkg.FuncName")()` plus blank line to all public functions, using `nil` if no atmosConfig param - exceptions: trivial getters/setters, command constructors, simple factories, functions delegating to tracked functions
Applied to files:
tests/cli_locals_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:
tests/cli_locals_test.gointernal/exec/stack_processor_utils_test.go
📚 Learning: 2026-01-04T00:55:21.720Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-04T00:55:21.720Z
Learning: Applies to **/*.go : Keep files small and focused - under 600 lines with one cmd/impl per file, co-locate tests, never use `//revive:disable:file-length-limit`
Applied to files:
tests/cli_locals_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:
tests/cli_locals_test.go
📚 Learning: 2025-11-11T03:47:59.576Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 1686
File: toolchain/which_test.go:166-223
Timestamp: 2025-11-11T03:47:59.576Z
Learning: In the cloudposse/atmos repo, tests that manipulate environment variables should use testing.T.Setenv for automatic setup/teardown instead of os.Setenv/Unsetenv.
Applied to files:
tests/cli_locals_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:
tests/cli_locals_test.gointernal/exec/stack_processor_utils_test.go
📚 Learning: 2025-08-15T14:43:41.030Z
Learnt from: aknysh
Repo: cloudposse/atmos PR: 1352
File: pkg/store/artifactory_store_test.go:108-113
Timestamp: 2025-08-15T14:43:41.030Z
Learning: In test files for the atmos project, it's acceptable to ignore errors from os.Setenv/Unsetenv operations during test environment setup and teardown, as these are controlled test scenarios.
Applied to files:
tests/cli_locals_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: In the atmos codebase, t.Chdir() is a valid method call on *testing.T objects and works correctly for changing directories in tests. This is implemented through custom testing framework extensions and is used consistently throughout the test suite.
Applied to files:
tests/cli_locals_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: In the atmos codebase, t.Chdir() is a valid method call on *testing.T objects and works correctly for changing directories in tests.
Applied to files:
tests/cli_locals_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: In the atmos codebase, t.Chdir() is a valid method that can be called on *testing.T objects. This functionality is implemented through custom testing framework extensions and is used consistently throughout the test suite for changing working directories during tests.
Applied to files:
tests/cli_locals_test.go
📚 Learning: 2025-12-10T18:32:51.237Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 1808
File: cmd/terraform/backend/backend_delete_test.go:9-23
Timestamp: 2025-12-10T18:32:51.237Z
Learning: In cmd subpackages (e.g., cmd/terraform/backend/), tests cannot use cmd.NewTestKit(t) due to Go's test visibility rules (NewTestKit is in a parent package test file). These tests only need TestKit if they execute commands through RootCmd or modify RootCmd state. Structural tests that only verify command structure/flags without touching RootCmd don't require TestKit cleanup.
Applied to files:
tests/cli_locals_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:
internal/exec/stack_processor_locals.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_locals.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_locals.go
📚 Learning: 2026-01-04T00:55:21.720Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-04T00:55:21.720Z
Learning: New config templates support Go templating with `FuncMap()` from `internal/exec/template_funcs.go`
Applied to files:
internal/exec/stack_processor_locals.go
📚 Learning: 2024-11-13T21:37:07.852Z
Learnt from: Cerebrovinny
Repo: cloudposse/atmos PR: 764
File: internal/exec/describe_stacks.go:289-295
Timestamp: 2024-11-13T21:37:07.852Z
Learning: In the `internal/exec/describe_stacks.go` file of the `atmos` project written in Go, avoid extracting the stack name handling logic into a helper function within the `ExecuteDescribeStacks` method, even if the logic appears duplicated.
Applied to files:
internal/exec/stack_processor_utils_test.go
📚 Learning: 2025-09-30T19:03:50.738Z
Learnt from: Cerebrovinny
Repo: cloudposse/atmos PR: 1560
File: pkg/utils/string_utils.go:43-64
Timestamp: 2025-09-30T19:03:50.738Z
Learning: In the Atmos codebase, YAML tags like !terraform.output rely on positional arguments, so the SplitStringByDelimiter function in pkg/utils/string_utils.go must preserve empty strings (even after trimming quotes) to maintain the correct number of positional arguments. Filtering out empty values after trimming would collapse the array and break these function calls.
Applied to files:
internal/exec/stack_processor_utils_test.go
🧬 Code graph analysis (2)
tests/cli_locals_test.go (2)
cmd/root.go (1)
RootCmd(333-515)pkg/logger/log.go (1)
Fatalf(69-71)
internal/exec/stack_processor_utils_test.go (1)
pkg/schema/schema.go (1)
AtmosConfiguration(54-100)
🪛 LanguageTool
docs/fixes/file-scoped-locals-not-working.md
[style] ~145-~145: Since ownership is already implied, this phrasing may be redundant.
Context: ... discovered: when sections don't define their own locals, ProcessStackLocals set them t...
(PRP_OWN)
[typographical] ~188-~188: Consider using a typographic opening quote here.
Context: ...es: - Self-referencing locals (e.g., `name_prefix: "{{ .locals.namespace }}-{{ .locals.envir...
(EN_QUOTES)
[typographical] ~231-~231: To join two clauses or introduce examples, consider using an em dash.
Context: ... 1. TestExtractLocalsFromRawYAML_Basic - Basic locals extraction 2. `TestExtractL...
(DASH_RULE)
[style] ~280-~280: Since ownership is already implied, this phrasing may be redundant.
Context: ...rraform/helmfile/packer) doesn't define its own locals, ProcessStackLocals was settin...
(PRP_OWN)
[typographical] ~294-~294: Consider using a typographic opening quote here.
Context: ...als section ``` Before fix: Result was namespace: "global-acme" (wrong - helmfile/packer o...
(EN_QUOTES)
[typographical] ~295-~295: Consider using a typographic opening quote here.
Context: ...erwrote terraform) After fix: Result is namespace: "terraform-acme" (correct - only section...
(EN_QUOTES)
[style] ~298-~298: Since ownership is already implied, this phrasing may be redundant.
Context: ... track which sections explicitly define their own locals. Only merge section locals when ...
(PRP_OWN)
[typographical] ~302-~302: To join two clauses or introduce examples, consider using an em dash.
Context: ... 1. atmos describe locals command - Not implemented in this fix; could be ad...
(DASH_RULE)
[typographical] ~303-~303: To join two clauses or introduce examples, consider using an em dash.
Context: ... debugging 2. Component-level locals - Requires per-component template scoping ...
(DASH_RULE)
⏰ Context from checks skipped due to timeout of 900000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: Summary
🔇 Additional comments (16)
tests/fixtures/scenarios/locals/stacks/deploy/dev.yaml (1)
47-51: LGTM!Clean demonstration of the file-scoped locals feature. The component vars properly reference global (
name_prefix) and terraform-scope (backend_bucket) locals.tests/fixtures/scenarios/locals/stacks/deploy/prod.yaml (1)
39-43: LGTM!Properly mirrors the dev fixture structure for prod environment, validating consistent locals behavior across environments.
internal/exec/stack_processor_locals.go (3)
199-207: LGTM!The helper is well-encapsulated and follows the guard clause pattern.
109-142: LGTM!Section-specific locals detection is correctly implemented. Each section checks for the
localskey after extraction, ensuring the flags accurately reflect explicit locals definitions.
175-197: No changes needed.MergeForTemplateContextintentionally merges all sections (guarded by boolean flags) for stack-level template processing. Each section already contains global locals via inheritance, and component-level processing correctly usesGetForComponentTypeinstead.website/blog/2026-01-06-file-scoped-locals-fix.mdx (1)
1-162: LGTM!Well-written blog post that clearly documents the fix, expected behavior, and known limitations. The code examples effectively demonstrate the feature.
docs/fixes/file-scoped-locals-not-working.md (1)
1-309: LGTM!Thorough technical documentation that captures the root cause, solution, and testing approach. The bug discovery section is particularly valuable for future maintainers.
internal/exec/stack_processor_utils_test.go (6)
1481-1494: LGTM!The invalid YAML test correctly uses malformed content that will fail parsing.
1435-1453: LGTM!Solid basic test that validates template resolution within locals (
name_prefixreferencesnamespaceandenvironment).
1555-1583: Good coverage for multi-section locals.This test validates that all three section types (terraform, helmfile, packer) can define and resolve their own locals. Confirms the merge behavior documented in the PR.
1585-1598: Circular dependency detection verified.Good test that confirms the resolver properly detects and reports circular dependencies in locals.
1639-1655: Section override behavior validated.Confirms terraform-scope locals properly override global locals with the same key.
1704-1718: Edge case: empty locals section returns empty map, not nil.Good distinction - ensures template processing receives a valid (though empty) map rather than nil.
tests/cli_locals_test.go (1)
49-62: Thelocals-circularfixture exists attests/fixtures/scenarios/locals-circular/. The test reference is valid.internal/exec/stack_processor_utils.go (2)
3-25: LGTM - Import organization follows guidelines.The new
gopkg.in/yaml.v3import is correctly placed in the 3rd-party group, and all imports are properly organized into the three required groups with correct sorting.
70-99: No action needed — context["locals"] overwrite is correct behavior.The function correctly uses file-scoped locals. At line 507,
extractAndAddLocalsToContextsetscontext["locals"]for the current file before import processing. Later, during hierarchical import merging (lines 796–800), parent context takes explicit precedence, so parent locals override imported file locals when both exist. This is the intended behavior: each file has its own file-scoped locals, and parent wins in conflicts. The silent error handling (lines 81–84) is also documented—the comment states "or original if extraction fails," making this a deliberate fail-soft approach.
|
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. |
Codecov Report❌ Patch coverage is Additional details and impacted files@@ Coverage Diff @@
## main #1939 +/- ##
==========================================
+ Coverage 74.05% 74.13% +0.07%
==========================================
Files 770 772 +2
Lines 69352 69744 +392
==========================================
+ Hits 51361 51703 +342
- Misses 14585 14615 +30
- Partials 3406 3426 +20
Flags with carried forward coverage won't be shown. Click here to find out more.
🚀 New features to boost your workflow:
|
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 Fix all issues with AI Agents
In @tests/cli_locals_test.go:
- Around line 129-132: The test uses unguarded type assertions on foundStack and
its nested maps (components, terraform, mock/instance-1, vars) which can panic;
replace these with safe "comma, ok" checks (or test assertions like
require.True/Ok) for each cast (e.g., checking foundStack["components"] is
map[string]any, components["terraform"] is map[string]any, etc.) and call
t.Fatalf (or the test helper) with a clear message when a check fails so the
test fails cleanly instead of panicking.
- Around line 139-196: The test TestLocalsCircularDependency currently uses
unguarded type assertions for components and terraform (components :=
foundStack["components"].(map[string]any) and terraform :=
components["terraform"].(map[string]any)); change these to guarded assertions
(e.g. components, ok := foundStack["components"].(map[string]any);
require.True(t, ok, "components should be a map") and terraform, ok :=
components["terraform"].(map[string]any); require.True(t, ok, "terraform should
be a map")) or use require.IsType/require.NotNil to fail the test instead of
causing a panic so the test remains defensive like the earlier loop.
📜 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.
📒 Files selected for processing (3)
internal/exec/stack_processor_utils.gointernal/exec/stack_processor_utils_test.gotests/cli_locals_test.go
🧰 Additional context used
📓 Path-based instructions (3)
**/*.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 usingfmt.Errorf("context: %w", err), and consider using custom error types for domain-specific errors
Follow standard Go coding style: usegofmtandgoimportsto 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 bygodotlinter) in Go code
Organize imports into three groups separated by blank lines, sorted alphabetically: Go stdlib, 3rd-party (NOT cloudposse/atmos), then Atmos packages with maintained aliases (cfg,log,u,errUtils)
All errors MUST be wrapped using static errors defined inerrors/errors.go- useerrors.Joinfor combining errors,fmt.Errorfwith%wfor context, anderrors.Is()for error checking
Never manually create mocks - usego.uber.org/mock/mockgenwith//go:generatedirectives in Go code
Keep files small and focused - under 600 lines with one cmd/impl per file, co-locate tests, never use//revive:disable:file-length-limit
Use colors frompkg/ui/theme/colors.gofor all UI theming in Go code
Code must be compatible with Linux, macOS, and Windows - use SDKs over binaries, usefilepath.Join()instead of h...
Files:
internal/exec/stack_processor_utils.gotests/cli_locals_test.gointernal/exec/stack_processor_utils_test.go
**/{pkg,internal,cmd}/**/*.go
📄 CodeRabbit inference engine (CLAUDE.md)
Add
defer perf.Track(atmosConfig, "pkg.FuncName")()plus blank line to all public functions, usingnilif no atmosConfig param - exceptions: trivial getters/setters, command constructors, simple factories, functions delegating to tracked functions
Files:
internal/exec/stack_processor_utils.gointernal/exec/stack_processor_utils_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 fixturesPrefer unit tests with mocks over integration tests - use interfaces and dependency injection for testability, generate mocks with
go.uber.org/mock/mockgen, use table-driven tests, target >80% coverage
Files:
tests/cli_locals_test.gointernal/exec/stack_processor_utils_test.go
🧠 Learnings (40)
📚 Learning: 2024-11-19T23:00:45.899Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 795
File: internal/exec/stack_processor_utils.go:378-386
Timestamp: 2024-11-19T23:00:45.899Z
Learning: In the `ProcessYAMLConfigFile` function within `internal/exec/stack_processor_utils.go`, directory traversal in stack imports is acceptable and should not be restricted.
Applied to files:
internal/exec/stack_processor_utils.gointernal/exec/stack_processor_utils_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_utils.gointernal/exec/stack_processor_utils_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_utils.gointernal/exec/stack_processor_utils_test.go
📚 Learning: 2024-10-20T00:57:53.500Z
Learnt from: haitham911
Repo: cloudposse/atmos PR: 731
File: internal/exec/validate_stacks.go:0-0
Timestamp: 2024-10-20T00:57:53.500Z
Learning: In `internal/exec/validate_stacks.go`, when downloading the Atmos JSON Schema file to the temp directory, the temporary file is overwritten each time, so explicit removal is not necessary.
Applied to files:
internal/exec/stack_processor_utils.gointernal/exec/stack_processor_utils_test.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_utils.gointernal/exec/stack_processor_utils_test.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_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/stack_processor_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:
internal/exec/stack_processor_utils.go
📚 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:
internal/exec/stack_processor_utils.go
📚 Learning: 2025-10-22T14:55:44.014Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 1695
File: pkg/auth/manager.go:169-171
Timestamp: 2025-10-22T14:55:44.014Z
Learning: Go 1.20+ supports multiple %w verbs in fmt.Errorf, which returns an error implementing Unwrap() []error. This is valid and does not panic. Atmos uses Go 1.24.8 and configures errorlint with errorf-multi: true to validate this pattern.
Applied to files:
internal/exec/stack_processor_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:
internal/exec/stack_processor_utils.gointernal/exec/stack_processor_utils_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 **/*.go : Use Viper for managing configuration, environment variables, and flags in CLI commands
Applied to files:
internal/exec/stack_processor_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:
internal/exec/stack_processor_utils.go
📚 Learning: 2025-04-24T01:06:15.259Z
Learnt from: haitham911
Repo: cloudposse/atmos PR: 1202
File: pkg/config/process_yaml.go:0-0
Timestamp: 2025-04-24T01:06:15.259Z
Learning: When processing YAML structures with gopkg.in/yaml.v3, the Value field of a Node is only meant for scalar values. Complex data types like maps and arrays are represented through child nodes in the YAML tree structure.
Applied to files:
internal/exec/stack_processor_utils.go
📚 Learning: 2026-01-04T00:55:21.720Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-04T00:55:21.720Z
Learning: Applies to **/*.go : Organize imports into three groups separated by blank lines, sorted alphabetically: Go stdlib, 3rd-party (NOT cloudposse/atmos), then Atmos packages with maintained aliases (`cfg`, `log`, `u`, `errUtils`)
Applied to files:
internal/exec/stack_processor_utils.go
📚 Learning: 2025-12-24T04:29:23.938Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 1891
File: pkg/ci/terraform/templates/apply.md:17-17
Timestamp: 2025-12-24T04:29:23.938Z
Learning: In the cloudposse/atmos repository, Terraform CI templates (pkg/ci/terraform/templates/*.md) are rendered using TerraformTemplateContext (defined in pkg/ci/terraform/context.go), not the base ci.TemplateContext. TerraformTemplateContext provides top-level fields: .Resources (ci.ResourceCounts), .HasChanges() method, and .HasDestroy field, which are correctly accessed directly in templates without a .Result prefix.
Applied to files:
internal/exec/stack_processor_utils.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_utils.gotests/cli_locals_test.gointernal/exec/stack_processor_utils_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:
tests/cli_locals_test.gointernal/exec/stack_processor_utils_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:
tests/cli_locals_test.gointernal/exec/stack_processor_utils_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:
tests/cli_locals_test.gointernal/exec/stack_processor_utils_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:
tests/cli_locals_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 **/*.go : Use interfaces for external dependencies to facilitate mocking and consider using testify/mock for creating mock implementations
Applied to files:
tests/cli_locals_test.go
📚 Learning: 2026-01-04T00:55:21.720Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-04T00:55:21.720Z
Learning: Applies to **/*_test.go : Prefer unit tests with mocks over integration tests - use interfaces and dependency injection for testability, generate mocks with `go.uber.org/mock/mockgen`, use table-driven tests, target >80% coverage
Applied to files:
tests/cli_locals_test.go
📚 Learning: 2026-01-04T00:55:21.720Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-04T00:55:21.720Z
Learning: Applies to **/*.go : Keep files small and focused - under 600 lines with one cmd/impl per file, co-locate tests, never use `//revive:disable:file-length-limit`
Applied to files:
tests/cli_locals_test.go
📚 Learning: 2025-12-10T18:32:51.237Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 1808
File: cmd/terraform/backend/backend_delete_test.go:9-23
Timestamp: 2025-12-10T18:32:51.237Z
Learning: In cmd subpackages (e.g., cmd/terraform/backend/), tests cannot use cmd.NewTestKit(t) due to Go's test visibility rules (NewTestKit is in a parent package test file). These tests only need TestKit if they execute commands through RootCmd or modify RootCmd state. Structural tests that only verify command structure/flags without touching RootCmd don't require TestKit cleanup.
Applied to files:
tests/cli_locals_test.go
📚 Learning: 2026-01-04T00:55:21.720Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-04T00:55:21.720Z
Learning: Applies to cmd/**/*_test.go : Always use `cmd.NewTestKit(t)` for cmd tests to auto-clean RootCmd state
Applied to files:
tests/cli_locals_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:
tests/cli_locals_test.go
📚 Learning: 2025-08-15T14:43:41.030Z
Learnt from: aknysh
Repo: cloudposse/atmos PR: 1352
File: pkg/store/artifactory_store_test.go:108-113
Timestamp: 2025-08-15T14:43:41.030Z
Learning: In test files for the atmos project, it's acceptable to ignore errors from os.Setenv/Unsetenv operations during test environment setup and teardown, as these are controlled test scenarios.
Applied to files:
tests/cli_locals_test.go
📚 Learning: 2025-11-11T03:47:59.576Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 1686
File: toolchain/which_test.go:166-223
Timestamp: 2025-11-11T03:47:59.576Z
Learning: In the cloudposse/atmos repo, tests that manipulate environment variables should use testing.T.Setenv for automatic setup/teardown instead of os.Setenv/Unsetenv.
Applied to files:
tests/cli_locals_test.gointernal/exec/stack_processor_utils_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:
tests/cli_locals_test.go
📚 Learning: 2026-01-04T00:55:21.720Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-04T00:55:21.720Z
Learning: Applies to **/{pkg,internal,cmd}/**/*.go : Add `defer perf.Track(atmosConfig, "pkg.FuncName")()` plus blank line to all public functions, using `nil` if no atmosConfig param - exceptions: trivial getters/setters, command constructors, simple factories, functions delegating to tracked functions
Applied to files:
internal/exec/stack_processor_utils_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_utils_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:
internal/exec/stack_processor_utils_test.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/stack_processor_utils_test.go
📚 Learning: 2025-04-11T22:06:46.999Z
Learnt from: samtholiya
Repo: cloudposse/atmos PR: 1147
File: internal/exec/validate_schema.go:42-57
Timestamp: 2025-04-11T22:06:46.999Z
Learning: The "ExecuteAtmosValidateSchemaCmd" function in internal/exec/validate_schema.go has been reviewed and confirmed to have acceptable cognitive complexity despite static analysis warnings. The function uses a clean structure with only three if statements for error handling and delegates complex operations to helper methods.
Applied to files:
internal/exec/stack_processor_utils_test.go
📚 Learning: 2025-09-13T18:06:07.674Z
Learnt from: samtholiya
Repo: cloudposse/atmos PR: 1466
File: toolchain/list.go:39-42
Timestamp: 2025-09-13T18:06:07.674Z
Learning: In the cloudposse/atmos repository, for UI messages in the toolchain package, use utils.PrintfMessageToTUI instead of log.Error or fmt.Fprintln(os.Stderr, ...). Import pkg/utils with alias "u" to follow the established pattern.
Applied to files:
internal/exec/stack_processor_utils_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:
internal/exec/stack_processor_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:
internal/exec/stack_processor_utils_test.go
📚 Learning: 2025-08-16T23:32:40.412Z
Learnt from: aknysh
Repo: cloudposse/atmos PR: 1405
File: internal/exec/describe_dependents_test.go:455-456
Timestamp: 2025-08-16T23:32:40.412Z
Learning: In the cloudposse/atmos Go codebase, `InitCliConfig` returns a `schema.AtmosConfiguration` value (not a pointer), while `ExecuteDescribeDependents` expects a `*schema.AtmosConfiguration` pointer parameter. Therefore, when passing the result of `InitCliConfig` to `ExecuteDescribeDependents`, use `&atmosConfig` to pass the address of the value.
Applied to files:
internal/exec/stack_processor_utils_test.go
📚 Learning: 2025-09-30T19:03:50.738Z
Learnt from: Cerebrovinny
Repo: cloudposse/atmos PR: 1560
File: pkg/utils/string_utils.go:43-64
Timestamp: 2025-09-30T19:03:50.738Z
Learning: In the Atmos codebase, YAML tags like !terraform.output rely on positional arguments, so the SplitStringByDelimiter function in pkg/utils/string_utils.go must preserve empty strings (even after trimming quotes) to maintain the correct number of positional arguments. Filtering out empty values after trimming would collapse the array and break these function calls.
Applied to files:
internal/exec/stack_processor_utils_test.go
🧬 Code graph analysis (2)
internal/exec/stack_processor_utils.go (4)
pkg/perf/perf.go (1)
Track(121-138)errors/errors.go (1)
ErrInvalidStackManifest(305-305)internal/exec/stack_processor_locals.go (1)
ProcessStackLocals(86-148)pkg/logger/log.go (2)
Debug(24-26)Trace(14-16)
tests/cli_locals_test.go (3)
pkg/config/config.go (1)
InitCliConfig(28-67)pkg/schema/schema.go (1)
ConfigAndStacksInfo(727-824)internal/exec/describe_component.go (1)
ExecuteDescribeComponentParams(203-210)
⏰ 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 (16)
tests/cli_locals_test.go (3)
1-12: LGTM!Imports are well-organized following the three-group pattern (stdlib, testify, atmos packages). Clean and focused.
14-49: Well-structured integration test.Good coverage for the dev environment scenario. The test validates end-to-end locals resolution in vars and backend sections, directly addressing issue #1933.
51-80: Solid prod environment coverage.Mirrors the dev test well. Consider adding backend assertion for full parity, but not blocking.
internal/exec/stack_processor_utils.go (4)
16-16: LGTM!Import of
gopkg.in/yaml.v3is appropriate for YAML parsing in locals extraction.
30-68: Well-documented function with proper error wrapping.The double
%wpattern at line 51 is valid for Go 1.20+ which the codebase uses. The perf.Track call follows guidelines. Previous review concern about error wrapping has been addressed.
70-100: Clean helper with graceful error handling.Good pattern: logs errors at Debug level for discoverability, returns original context on failure to avoid breaking the pipeline.
493-507: Well-documented integration point.The extensive comment block explains the design clearly. Locals extraction happens before template processing, enabling
{{ .locals.* }}syntax in subsequent template execution.internal/exec/stack_processor_utils_test.go (9)
4-4: LGTM!Import additions for
errorsanderrUtilsare necessary for error type checking in the new tests.Also applies to: 12-12
1437-1455: Good basic test.Verifies template resolution within locals works correctly.
1457-1470: LGTM!Validates graceful handling when no locals section exists.
1483-1497: Proper error verification pattern.Using
errors.Is()at line 1495 correctly checks the error chain. Good practice.
1499-1556: Comprehensive section-specific coverage.Tests for terraform, helmfile, and packer sections verify that section locals merge correctly with global locals.
1588-1601: Important edge case coverage.Circular dependency detection is critical for preventing infinite loops during locals resolution.
1603-1619: Good chain resolution test.Validates that multi-level dependencies resolve correctly in order.
1642-1658: Key override behavior verified.This test confirms section-level locals correctly take precedence over global locals.
1660-1721: Solid boundary condition coverage.Tests for nil config, empty locals, comments-only YAML, and template isolation validate the function's defensive behavior.
…scribe locals` command, add docs
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Fix all issues with AI Agents
In @cmd/describe_locals.go:
- Around line 98-103: The code reads the "query" flag (flags.Changed("query")
and assigns to args.Query) but the flag is never registered; update init() to
register the flag on describeLocalsCmd (e.g., add a
PersistentFlags().StringP("query", "q", "", "JMESPath query to filter output")
call) so flags.GetString("query") succeeds, or remove the entire conditional
block that references flags.Changed("query") and args.Query if you prefer to
drop support; modify the describeLocalsCmd init path accordingly.
🧹 Nitpick comments (4)
docs/fixes/file-scoped-locals-not-working.md (1)
300-310: Add language specifier to fenced code block.The directory tree block at line 300 lacks a language identifier. Consider using
textorplaintextfor consistency with markdownlint rules.Proposed fix
-``` +```text locals-deep-import-chain/ ├── atmos.yamlcmd/describe_locals.go (1)
113-127: Comprehensive flag setup.Good use of
AddStackCompletionfor shell completion and clear help text for the--stackflag.As per coding guidelines, consider adding examples in the command help. The
Longdescription could include usage examples.Optional: Add example to command
var describeLocalsCmd = &cobra.Command{ Use: "locals", Short: "Display locals from Atmos stack manifests", Long: "This command displays the locals defined in Atmos stack manifests.", + Example: ` # Show all locals + atmos describe locals + + # Show locals for a specific stack + atmos describe locals --stack deploy/dev + + # Output as JSON + atmos describe locals --format json`, FParseErrWhitelist: struct{ UnknownFlags bool }{UnknownFlags: false},internal/exec/describe_locals_test.go (1)
11-60: Good table-driven test coverage for deriveStackFileName.Covers the key scenarios: simple, nested, deeply nested paths, empty base path fallback, and alternate extension (.yml).
Consider adding a test case for when
filePathdoesn't containstacksBasePathto verify the fallback behavior is correct in that edge case.Optional: Additional edge case
{ name: "file path not under base path", stacksBasePath: "/path/to/stacks", filePath: "/other/location/dev.yaml", expected: "dev", // or whatever the expected fallback is },internal/exec/describe_locals.go (1)
229-264: Consider logging template/pattern evaluation errors.The function silently ignores errors when evaluating name template (line 248) and name pattern (line 257), falling back to the next method. While this provides a robust fallback chain, template evaluation errors might indicate configuration issues that would be helpful to surface.
Consider adding debug-level logging when these operations fail so users can troubleshoot misconfigured templates or patterns.
📜 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.
📒 Files selected for processing (19)
cmd/describe_locals.godocs/fixes/file-scoped-locals-not-working.mdinternal/exec/describe_locals.gointernal/exec/describe_locals_test.gointernal/exec/stack_processor_locals_test.gotests/cli_locals_test.gotests/fixtures/scenarios/locals-deep-import-chain/atmos.yamltests/fixtures/scenarios/locals-deep-import-chain/stacks/deploy/final.yamltests/fixtures/scenarios/locals-deep-import-chain/stacks/mixins/base.yamltests/fixtures/scenarios/locals-deep-import-chain/stacks/mixins/layer1.yamltests/fixtures/scenarios/locals-deep-import-chain/stacks/mixins/layer2.yamltests/fixtures/scenarios/locals-file-scoped/atmos.yamltests/fixtures/scenarios/locals-file-scoped/stacks/deploy/test.yamltests/fixtures/scenarios/locals-file-scoped/stacks/mixins/base.yamltests/fixtures/scenarios/locals-not-inherited/atmos.yamltests/fixtures/scenarios/locals-not-inherited/stacks/deploy/test.yamltests/fixtures/scenarios/locals-not-inherited/stacks/mixins/base.yamlwebsite/blog/2026-01-06-file-scoped-locals-fix.mdxwebsite/docs/cli/commands/describe/describe-locals.mdx
✅ Files skipped from review due to trivial changes (1)
- tests/fixtures/scenarios/locals-not-inherited/atmos.yaml
🧰 Additional context used
📓 Path-based instructions (7)
**/*.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 usingfmt.Errorf("context: %w", err), and consider using custom error types for domain-specific errors
Follow standard Go coding style: usegofmtandgoimportsto 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 bygodotlinter) in Go code
Organize imports into three groups separated by blank lines, sorted alphabetically: Go stdlib, 3rd-party (NOT cloudposse/atmos), then Atmos packages with maintained aliases (cfg,log,u,errUtils)
All errors MUST be wrapped using static errors defined inerrors/errors.go- useerrors.Joinfor combining errors,fmt.Errorfwith%wfor context, anderrors.Is()for error checking
Never manually create mocks - usego.uber.org/mock/mockgenwith//go:generatedirectives in Go code
Keep files small and focused - under 600 lines with one cmd/impl per file, co-locate tests, never use//revive:disable:file-length-limit
Use colors frompkg/ui/theme/colors.gofor all UI theming in Go code
Code must be compatible with Linux, macOS, and Windows - use SDKs over binaries, usefilepath.Join()instead of h...
Files:
internal/exec/describe_locals_test.gotests/cli_locals_test.gointernal/exec/describe_locals.gointernal/exec/stack_processor_locals_test.gocmd/describe_locals.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 fixturesPrefer unit tests with mocks over integration tests - use interfaces and dependency injection for testability, generate mocks with
go.uber.org/mock/mockgen, use table-driven tests, target >80% coverage
Files:
internal/exec/describe_locals_test.gotests/cli_locals_test.gointernal/exec/stack_processor_locals_test.go
**/{pkg,internal,cmd}/**/*.go
📄 CodeRabbit inference engine (CLAUDE.md)
Add
defer perf.Track(atmosConfig, "pkg.FuncName")()plus blank line to all public functions, usingnilif no atmosConfig param - exceptions: trivial getters/setters, command constructors, simple factories, functions delegating to tracked functions
Files:
internal/exec/describe_locals_test.gointernal/exec/describe_locals.gointernal/exec/stack_processor_locals_test.gocmd/describe_locals.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 undercmd/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
Files:
cmd/describe_locals.go
website/**
📄 CodeRabbit inference engine (.cursor/rules/atmos-rules.mdc)
website/**: Update website documentation in thewebsite/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 thewebsite/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/2026-01-06-file-scoped-locals-fix.mdxwebsite/docs/cli/commands/describe/describe-locals.mdx
website/blog/*.mdx
📄 CodeRabbit inference engine (CLAUDE.md)
PRs labeled
minorormajorMUST include a blog post atwebsite/blog/YYYY-MM-DD-feature-name.mdxwith YAML frontmatter, using only tags defined inwebsite/blog/tags.yml
Files:
website/blog/2026-01-06-file-scoped-locals-fix.mdx
website/docs/cli/commands/**/*.mdx
📄 CodeRabbit inference engine (CLAUDE.md)
All CLI command documentation MUST include: frontmatter, Intro component, Screengrab, Usage section, Arguments/Flags in
<dl>format, and Examples section
Files:
website/docs/cli/commands/describe/describe-locals.mdx
🧠 Learnings (58)
📓 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: osterman
Repo: cloudposse/atmos PR: 1891
File: pkg/ci/terraform/templates/apply.md:17-17
Timestamp: 2025-12-24T04:29:23.938Z
Learning: In the cloudposse/atmos repository, Terraform CI templates (pkg/ci/terraform/templates/*.md) are rendered using TerraformTemplateContext (defined in pkg/ci/terraform/context.go), not the base ci.TemplateContext. TerraformTemplateContext provides top-level fields: .Resources (ci.ResourceCounts), .HasChanges() method, and .HasDestroy field, which are correctly accessed directly in templates without a .Result prefix.
📚 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:
tests/fixtures/scenarios/locals-deep-import-chain/atmos.yamltests/fixtures/scenarios/locals-file-scoped/atmos.yamltests/fixtures/scenarios/locals-not-inherited/stacks/deploy/test.yamltests/fixtures/scenarios/locals-file-scoped/stacks/mixins/base.yamltests/fixtures/scenarios/locals-deep-import-chain/stacks/mixins/layer1.yamltests/fixtures/scenarios/locals-file-scoped/stacks/deploy/test.yaml
📚 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/scenarios/locals-deep-import-chain/atmos.yamltests/fixtures/scenarios/locals-file-scoped/atmos.yamltests/fixtures/scenarios/locals-file-scoped/stacks/mixins/base.yamltests/fixtures/scenarios/locals-file-scoped/stacks/deploy/test.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:
tests/fixtures/scenarios/locals-deep-import-chain/atmos.yamltests/fixtures/scenarios/locals-file-scoped/atmos.yaml
📚 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:
tests/fixtures/scenarios/locals-deep-import-chain/atmos.yamlinternal/exec/describe_locals_test.gotests/fixtures/scenarios/locals-file-scoped/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:
tests/fixtures/scenarios/locals-deep-import-chain/atmos.yamltests/fixtures/scenarios/locals-file-scoped/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:
tests/fixtures/scenarios/locals-deep-import-chain/atmos.yamltests/fixtures/scenarios/locals-file-scoped/atmos.yamltests/fixtures/scenarios/locals-not-inherited/stacks/deploy/test.yamltests/fixtures/scenarios/locals-deep-import-chain/stacks/mixins/layer1.yamltests/fixtures/scenarios/locals-file-scoped/stacks/deploy/test.yaml
📚 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:
tests/fixtures/scenarios/locals-deep-import-chain/atmos.yamltests/fixtures/scenarios/locals-file-scoped/atmos.yamlcmd/describe_locals.go
📚 Learning: 2025-02-24T22:46:39.744Z
Learnt from: haitham911
Repo: cloudposse/atmos PR: 1085
File: pkg/config/load.go:219-221
Timestamp: 2025-02-24T22:46:39.744Z
Learning: In the Atmos configuration system, imports from atmos.d are optional. When import errors occur, they should be logged at debug level and the process should continue, rather than failing completely.
Applied to files:
tests/fixtures/scenarios/locals-deep-import-chain/atmos.yaml
📚 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:
tests/fixtures/scenarios/locals-deep-import-chain/atmos.yamltests/fixtures/scenarios/locals-file-scoped/atmos.yamltests/cli_locals_test.gotests/fixtures/scenarios/locals-not-inherited/stacks/deploy/test.yaml
📚 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:
tests/fixtures/scenarios/locals-deep-import-chain/atmos.yaml
📚 Learning: 2025-12-24T04:29:23.938Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 1891
File: pkg/ci/terraform/templates/apply.md:17-17
Timestamp: 2025-12-24T04:29:23.938Z
Learning: In the cloudposse/atmos repository, Terraform CI templates (pkg/ci/terraform/templates/*.md) are rendered using TerraformTemplateContext (defined in pkg/ci/terraform/context.go), not the base ci.TemplateContext. TerraformTemplateContext provides top-level fields: .Resources (ci.ResourceCounts), .HasChanges() method, and .HasDestroy field, which are correctly accessed directly in templates without a .Result prefix.
Applied to files:
tests/fixtures/scenarios/locals-deep-import-chain/atmos.yamltests/fixtures/scenarios/locals-file-scoped/atmos.yamlinternal/exec/stack_processor_locals_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/describe_locals_test.gotests/cli_locals_test.gointernal/exec/describe_locals.gocmd/describe_locals.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/describe_locals_test.gointernal/exec/describe_locals.gointernal/exec/stack_processor_locals_test.gocmd/describe_locals.go
📚 Learning: 2024-10-20T00:41:57.135Z
Learnt from: haitham911
Repo: cloudposse/atmos PR: 731
File: internal/exec/validate_stacks.go:93-98
Timestamp: 2024-10-20T00:41:57.135Z
Learning: When downloading schema files in `internal/exec/validate_stacks.go`, use a consistent temporary file name to overwrite the file each time and avoid creating multiple temporary files.
Applied to files:
internal/exec/describe_locals_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_locals_test.gotests/cli_locals_test.gointernal/exec/stack_processor_locals_test.go
📚 Learning: 2024-10-20T00:57:53.500Z
Learnt from: haitham911
Repo: cloudposse/atmos PR: 731
File: internal/exec/validate_stacks.go:0-0
Timestamp: 2024-10-20T00:57:53.500Z
Learning: In `internal/exec/validate_stacks.go`, when downloading the Atmos JSON Schema file to the temp directory, the temporary file is overwritten each time, so explicit removal is not necessary.
Applied to files:
internal/exec/describe_locals_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_locals_test.gotests/cli_locals_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/describe_locals_test.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:
internal/exec/describe_locals_test.gotests/fixtures/scenarios/locals-deep-import-chain/stacks/deploy/final.yamltests/fixtures/scenarios/locals-not-inherited/stacks/deploy/test.yamltests/fixtures/scenarios/locals-file-scoped/stacks/deploy/test.yamlwebsite/docs/cli/commands/describe/describe-locals.mdx
📚 Learning: 2025-11-11T03:47:59.576Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 1686
File: toolchain/which_test.go:166-223
Timestamp: 2025-11-11T03:47:59.576Z
Learning: In the cloudposse/atmos repo, tests that manipulate environment variables should use testing.T.Setenv for automatic setup/teardown instead of os.Setenv/Unsetenv.
Applied to files:
internal/exec/describe_locals_test.gotests/cli_locals_test.gointernal/exec/stack_processor_locals_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_locals_test.gotests/cli_locals_test.gointernal/exec/describe_locals.gointernal/exec/stack_processor_locals_test.gocmd/describe_locals.go
📚 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/scenarios/locals-file-scoped/atmos.yamlwebsite/blog/2026-01-06-file-scoped-locals-fix.mdx
📚 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:
tests/fixtures/scenarios/locals-file-scoped/atmos.yamltests/cli_locals_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:
tests/cli_locals_test.gointernal/exec/stack_processor_locals_test.go
📚 Learning: 2026-01-04T00:55:21.720Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-04T00:55:21.720Z
Learning: Applies to **/*.go : Keep files small and focused - under 600 lines with one cmd/impl per file, co-locate tests, never use `//revive:disable:file-length-limit`
Applied to files:
tests/cli_locals_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:
tests/cli_locals_test.gointernal/exec/stack_processor_locals_test.go
📚 Learning: 2026-01-04T00:55:21.720Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-04T00:55:21.720Z
Learning: Applies to **/*_test.go : Prefer unit tests with mocks over integration tests - use interfaces and dependency injection for testability, generate mocks with `go.uber.org/mock/mockgen`, use table-driven tests, target >80% coverage
Applied to files:
tests/cli_locals_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 **/*.go : Use interfaces for external dependencies to facilitate mocking and consider using testify/mock for creating mock implementations
Applied to files:
tests/cli_locals_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 **/*.go : All code must pass golangci-lint checks
Applied to files:
tests/cli_locals_test.go
📚 Learning: 2025-12-10T18:32:51.237Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 1808
File: cmd/terraform/backend/backend_delete_test.go:9-23
Timestamp: 2025-12-10T18:32:51.237Z
Learning: In cmd subpackages (e.g., cmd/terraform/backend/), tests cannot use cmd.NewTestKit(t) due to Go's test visibility rules (NewTestKit is in a parent package test file). These tests only need TestKit if they execute commands through RootCmd or modify RootCmd state. Structural tests that only verify command structure/flags without touching RootCmd don't require TestKit cleanup.
Applied to files:
tests/cli_locals_test.go
📚 Learning: 2026-01-04T00:55:21.720Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-04T00:55:21.720Z
Learning: Applies to **/{pkg,internal,cmd}/**/*.go : Add `defer perf.Track(atmosConfig, "pkg.FuncName")()` plus blank line to all public functions, using `nil` if no atmosConfig param - exceptions: trivial getters/setters, command constructors, simple factories, functions delegating to tracked functions
Applied to files:
tests/cli_locals_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:
tests/cli_locals_test.go
📚 Learning: 2024-10-30T13:25:45.965Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 727
File: internal/exec/terraform_clean.go:405-412
Timestamp: 2024-10-30T13:25:45.965Z
Learning: In `internal/exec/terraform_clean.go`, when appending `stackFolders` to `folders` in the `handleCleanSubCommand` function, it's unnecessary to check if `stackFolders` is nil before appending, because in Go, appending a nil slice is safe and does not cause a panic.
Applied to files:
tests/cli_locals_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:
tests/cli_locals_test.go
📚 Learning: 2025-02-19T05:50:35.853Z
Learnt from: samtholiya
Repo: cloudposse/atmos PR: 1068
File: tests/snapshots/TestCLICommands_atmos_terraform_apply_--help.stdout.golden:0-0
Timestamp: 2025-02-19T05:50:35.853Z
Learning: Backtick formatting should only be applied to flag descriptions in Go source files, not in golden test files (test snapshots) as they are meant to capture the raw command output.
Applied to files:
tests/cli_locals_test.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:
tests/cli_locals_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:
tests/cli_locals_test.gointernal/exec/stack_processor_locals_test.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:
tests/cli_locals_test.go
📚 Learning: 2025-04-11T22:06:46.999Z
Learnt from: samtholiya
Repo: cloudposse/atmos PR: 1147
File: internal/exec/validate_schema.go:42-57
Timestamp: 2025-04-11T22:06:46.999Z
Learning: The "ExecuteAtmosValidateSchemaCmd" function in internal/exec/validate_schema.go has been reviewed and confirmed to have acceptable cognitive complexity despite static analysis warnings. The function uses a clean structure with only three if statements for error handling and delegates complex operations to helper methods.
Applied to files:
tests/cli_locals_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:
tests/cli_locals_test.go
📚 Learning: 2024-11-20T18:38:34.525Z
Learnt from: aknysh
Repo: cloudposse/atmos PR: 768
File: internal/exec/vendor_component_utils.go:312-316
Timestamp: 2024-11-20T18:38:34.525Z
Learning: Ensure that mixin package type determination supports local files, handling them consistently with component package type determination.
Applied to files:
tests/fixtures/scenarios/locals-file-scoped/stacks/mixins/base.yaml
📚 Learning: 2026-01-04T00:55:21.720Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-04T00:55:21.720Z
Learning: Applies to **/*.go : Use `viper.BindEnv("ATMOS_VAR", "ATMOS_VAR", "FALLBACK")` for environment variables - ATMOS_ prefix required in Go code
Applied to files:
tests/fixtures/scenarios/locals-file-scoped/stacks/mixins/base.yaml
📚 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/describe_locals.gocmd/describe_locals.go
📚 Learning: 2025-08-16T23:32:40.412Z
Learnt from: aknysh
Repo: cloudposse/atmos PR: 1405
File: internal/exec/describe_dependents_test.go:455-456
Timestamp: 2025-08-16T23:32:40.412Z
Learning: In the cloudposse/atmos Go codebase, `InitCliConfig` returns a `schema.AtmosConfiguration` value (not a pointer), while `ExecuteDescribeDependents` expects a `*schema.AtmosConfiguration` pointer parameter. Therefore, when passing the result of `InitCliConfig` to `ExecuteDescribeDependents`, use `&atmosConfig` to pass the address of the value.
Applied to files:
internal/exec/describe_locals.gocmd/describe_locals.go
📚 Learning: 2025-08-16T23:33:07.477Z
Learnt from: aknysh
Repo: cloudposse/atmos PR: 1405
File: internal/exec/describe_dependents_test.go:651-652
Timestamp: 2025-08-16T23:33:07.477Z
Learning: In the cloudposse/atmos Go codebase, ExecuteDescribeDependents expects a pointer to AtmosConfiguration (*schema.AtmosConfiguration), so when calling it with a value returned by cfg.InitCliConfig (which returns schema.AtmosConfiguration), the address-of operator (&) is necessary: ExecuteDescribeDependents(&atmosConfig, ...).
Applied to files:
internal/exec/describe_locals.gocmd/describe_locals.go
📚 Learning: 2025-08-15T14:43:41.030Z
Learnt from: aknysh
Repo: cloudposse/atmos PR: 1352
File: pkg/store/artifactory_store_test.go:108-113
Timestamp: 2025-08-15T14:43:41.030Z
Learning: In test files for the atmos project, it's acceptable to ignore errors from os.Setenv/Unsetenv operations during test environment setup and teardown, as these are controlled test scenarios.
Applied to files:
internal/exec/stack_processor_locals_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_locals_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/describe_locals.gowebsite/docs/cli/commands/describe/describe-locals.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 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/describe_locals.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/describe_locals.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/describe_locals.go
📚 Learning: 2024-12-03T04:01:16.446Z
Learnt from: aknysh
Repo: cloudposse/atmos PR: 810
File: website/docs/core-concepts/stacks/yaml-functions/terraform.output.mdx:0-0
Timestamp: 2024-12-03T04:01:16.446Z
Learning: In the `terraform.output.mdx` documentation file (`website/docs/core-concepts/stacks/yaml-functions/terraform.output.mdx`), the cache invalidation and cache scope behavior for the `!terraform.output` function are already described.
Applied to files:
docs/fixes/file-scoped-locals-not-working.md
📚 Learning: 2026-01-04T00:55:21.720Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-04T00:55:21.720Z
Learning: Applies to website/blog/*.mdx : 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`
Applied to files:
website/blog/2026-01-06-file-scoped-locals-fix.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/docs/cli/commands/describe/describe-locals.mdx
📚 Learning: 2026-01-04T00:55:21.720Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-04T00:55:21.720Z
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/docs/cli/commands/describe/describe-locals.mdx
📚 Learning: 2025-01-19T15:49:15.593Z
Learnt from: samtholiya
Repo: cloudposse/atmos PR: 955
File: tests/snapshots/TestCLICommands_atmos_validate_editorconfig_--help.stdout.golden:0-0
Timestamp: 2025-01-19T15:49:15.593Z
Learning: In future commits, the help text for Atmos CLI commands should be limited to only show component and stack parameters for commands that actually use them. This applies to the example usage section in command help text.
Applied to files:
website/docs/cli/commands/describe/describe-locals.mdx
📚 Learning: 2025-09-27T20:50:20.564Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 1533
File: pkg/config/load.go:585-637
Timestamp: 2025-09-27T20:50:20.564Z
Learning: In the cloudposse/atmos repository, command merging prioritizes precedence over display ordering. Help commands are displayed lexicographically regardless of internal array order, so the mergeCommandArrays function focuses on ensuring the correct precedence chain (top-level file wins) rather than maintaining specific display order.
Applied to files:
website/docs/cli/commands/describe/describe-locals.mdx
🧬 Code graph analysis (4)
internal/exec/describe_locals_test.go (1)
pkg/schema/schema.go (1)
AtmosConfiguration(54-100)
tests/cli_locals_test.go (4)
pkg/config/config.go (1)
InitCliConfig(28-67)pkg/schema/schema.go (1)
ConfigAndStacksInfo(727-824)internal/exec/describe_component.go (1)
ExecuteDescribeComponentParams(203-210)internal/exec/describe_locals.go (1)
ExecuteDescribeLocals(93-117)
internal/exec/describe_locals.go (4)
pkg/config/const.go (2)
VarsSectionName(69-69)NameSectionName(65-65)internal/exec/stack_processor_locals.go (2)
ProcessStackLocals(86-148)LocalsContext(152-173)internal/exec/stack_utils.go (1)
GetStackNamePattern(206-208)pkg/config/utils.go (2)
GetContextFromVars(727-755)GetContextPrefix(758-828)
cmd/describe_locals.go (3)
internal/exec/cli_utils.go (1)
ProcessCommandLineArgs(80-201)pkg/config/config.go (1)
InitCliConfig(28-67)internal/exec/describe_locals.go (3)
NewDescribeLocalsExec(45-54)DescribeLocalsExec(30-32)DescribeLocalsArgs(20-25)
🪛 LanguageTool
docs/fixes/file-scoped-locals-not-working.md
[style] ~145-~145: Since ownership is already implied, this phrasing may be redundant.
Context: ... discovered: when sections don't define their own locals, ProcessStackLocals set them t...
(PRP_OWN)
[typographical] ~188-~188: Consider using a typographic opening quote here.
Context: ...es: - Self-referencing locals (e.g., `name_prefix: "{{ .locals.namespace }}-{{ .locals.envir...
(EN_QUOTES)
[typographical] ~238-~238: To join two clauses or introduce examples, consider using an em dash.
Context: ... 1. TestExtractLocalsFromRawYAML_Basic - Basic locals extraction 2. `TestExtractL...
(DASH_RULE)
[typographical] ~259-~259: To join two clauses or introduce examples, consider using an em dash.
Context: ...stLocalsContext_MergeForTemplateContext` - Verifies merge behavior (global → terraf...
(DASH_RULE)
[style] ~313-~313: Since ownership is already implied, this phrasing may be redundant.
Context: ...validates: 1. Each file can only access its own locals (file-scoped) 2. Locals are NOT ...
(PRP_OWN)
[style] ~377-~377: Since ownership is already implied, this phrasing may be redundant.
Context: ...rraform/helmfile/packer) doesn't define its own locals, ProcessStackLocals was settin...
(PRP_OWN)
[typographical] ~391-~391: Consider using a typographic opening quote here.
Context: ...als section ``` Before fix: Result was namespace: "global-acme" (wrong - helmfile/packer o...
(EN_QUOTES)
[typographical] ~392-~392: Consider using a typographic opening quote here.
Context: ...erwrote terraform) After fix: Result is namespace: "terraform-acme" (correct - only section...
(EN_QUOTES)
[style] ~395-~395: Since ownership is already implied, this phrasing may be redundant.
Context: ... track which sections explicitly define their own locals. Only merge section locals when ...
(PRP_OWN)
[style] ~424-~424: ‘merged together’ might be wordy. Consider a shorter alternative.
Context: ...s (if defined) - merged: All locals merged together (global first, then sections) Example ...
(EN_WORDINESS_PREMIUM_MERGED_TOGETHER)
website/blog/2026-01-06-file-scoped-locals-fix.mdx
[typographical] ~96-~96: To join two clauses or introduce examples, consider using an em dash.
Context: ...cket: acme-dev-tfstate ``` - global - Root-level locals from the stack file - ...
(DASH_RULE)
[typographical] ~97-~97: To join two clauses or introduce examples, consider using an em dash.
Context: ...ack file - terraform/helmfile/packer - Section-specific locals (only shown if d...
(DASH_RULE)
[typographical] ~98-~98: To join two clauses or introduce examples, consider using an em dash.
Context: ...als (only shown if defined) - merged - All locals merged together (global first...
(DASH_RULE)
[style] ~98-~98: ‘merged together’ might be wordy. Consider a shorter alternative.
Context: ...n if defined) - merged - All locals merged together (global first, then sections) ### Sect...
(EN_WORDINESS_PREMIUM_MERGED_TOGETHER)
website/docs/cli/commands/describe/describe-locals.mdx
[typographical] ~189-~189: To join two clauses or introduce examples, consider using an em dash.
Context: ...nent`](/cli/commands/describe/component) - Describe a component's full configuratio...
(DASH_RULE)
[typographical] ~194-~194: To join two clauses or introduce examples, consider using an em dash.
Context: ... - File-Scoped Locals - Learn more about defining and using loca...
(DASH_RULE)
🪛 markdownlint-cli2 (0.18.1)
docs/fixes/file-scoped-locals-not-working.md
300-300: 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). (4)
- GitHub Check: Acceptance Tests (linux)
- GitHub Check: Acceptance Tests (macos)
- GitHub Check: Acceptance Tests (windows)
- GitHub Check: Summary
There was a problem hiding this comment.
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/stack_processor_locals.go (1)
13-47: Comment mismatch: ExtractAndResolveLocals doesn’t necessarily return nil when no locals exist.The docstring says “or nil if no locals section”, but when
parentLocals != nil, the function returns a copy even if the section has nolocalskey (Line 29-32). That’s probably correct behavior—just update the comment to avoid confusing API consumers.
🤖 Fix all issues with AI agents
In @cmd/describe_locals.go:
- Around line 154-170: Update the --stack flag help text on describeLocalsCmd
(the call to describeLocalsCmd.Flags().StringP("stack", ...)) to remove the
"batch processing" wording and clearly state that parse errors in the matched
stack are reported while YAML parse errors in other stacks are skipped during
the search; replace the existing Note sentence with: "Note: parse errors in the
matched stack are reported; errors in other stacks are skipped during the
search."
🧹 Nitpick comments (5)
docs/prd/file-scoped-locals.md (1)
1590-1738: Consolidate duplicateddescribe localssections to avoid drift.The PRD documents
atmos describe localstwice (Line 1590+ and again Line 1680+). I’d merge these into a single canonical section (examples + output shapes + key design decisions) to reduce the chance the two versions diverge.internal/exec/stack_processor_locals.go (1)
196-226: MergeForTemplateContext: consider documenting (or detecting) cross-section key collisions.Flattening section locals (Terraform/Helmfile/Packer) into one
.localsmap means overlapping keys across sections will deterministically override based on merge order (Line 199-223). Even if “uncommon”, it can produce surprising results during whole-file template processing.A small doc note (“avoid reusing the same local key across tool sections”) or an optional collision check with a clear error would prevent footguns.
internal/exec/stack_processor_utils.go (1)
74-133: Nice: file-scoped enforcement is explicit; improve the “--stack” hint value.Clearing inherited
context["locals"](Line 90-95) is a clean way to enforce file-scoped semantics.Minor UX nit: the circular-dependency hint uses
--stack %swithrelativeFilePath(Line 114-115). If--stackexpects a logical name or extension-less path, consider formatting the hint to the accepted shape (or explicitly note extensions are OK).cmd/describe_locals_test.go (1)
17-280: Solid wiring coverage; consider asserting “missing --stack” fails before expensive init (if you change the implementation).The tests cover the main success + error paths well (Line 17-280). If you adopt a fail-fast change in the command (check
--stackbeforeinitCliConfig/validateStacks), you can extend the “missing stack” tests with simple call counters to lock that behavior in.cmd/describe_locals.go (1)
62-112: Fail fast on missing--stackto avoid unnecessary config+stack validation.Right now the command loads config and validates stacks before rejecting missing
--stack(Line 78-106). Since--stackis required, you can movesetCliArgsForDescribeLocalsCli+ the empty check earlier and returnErrStackRequired*beforeinitCliConfig/validateStacks.
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Fix all issues with AI agents
In @docs/prd/file-scoped-locals.md:
- Around line 1643-1650: The Implementation Notes reference the wrong path for
the describe locals command; update the documentation so the file path
`cmd/describe/describe_locals.go` is corrected to the actual implementation
location `cmd/describe_locals.go` in the "Implementation Notes" section (which
mentions CommandProvider and the files `internal/exec/describe_locals.go` and
`internal/exec/stack_processor_locals.go` / function `ProcessStackLocals()`),
ensuring all mentions of the old subdirectory form are replaced.
📜 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.
📒 Files selected for processing (4)
cmd/describe_locals.gocmd/describe_locals_test.godocs/prd/file-scoped-locals.mderrors/errors.go
🚧 Files skipped from review as they are similar to previous changes (1)
- errors/errors.go
🧰 Additional context used
📓 Path-based instructions (6)
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 undercmd/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
Files:
cmd/describe_locals.gocmd/describe_locals_test.go
**/*.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 usingfmt.Errorf("context: %w", err), and consider using custom error types for domain-specific errors
Follow standard Go coding style: usegofmtandgoimportsto 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 bygodotlinter) in Go code
Organize imports into three groups separated by blank lines, sorted alphabetically: Go stdlib, 3rd-party (NOT cloudposse/atmos), then Atmos packages with maintained aliases (cfg,log,u,errUtils)
All errors MUST be wrapped using static errors defined inerrors/errors.go- useerrors.Joinfor combining errors,fmt.Errorfwith%wfor context, anderrors.Is()for error checking
Never manually create mocks - usego.uber.org/mock/mockgenwith//go:generatedirectives in Go code
Keep files small and focused - under 600 lines with one cmd/impl per file, co-locate tests, never use//revive:disable:file-length-limit
Use colors frompkg/ui/theme/colors.gofor all UI theming in Go code
Code must be compatible with Linux, macOS, and Windows - use SDKs over binaries, usefilepath.Join()instead of h...
Files:
cmd/describe_locals.gocmd/describe_locals_test.go
**/{pkg,internal,cmd}/**/*.go
📄 CodeRabbit inference engine (CLAUDE.md)
Add
defer perf.Track(atmosConfig, "pkg.FuncName")()plus blank line to all public functions, usingnilif no atmosConfig param - exceptions: trivial getters/setters, command constructors, simple factories, functions delegating to tracked functions
Files:
cmd/describe_locals.gocmd/describe_locals_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 fixturesPrefer unit tests with mocks over integration tests - use interfaces and dependency injection for testability, generate mocks with
go.uber.org/mock/mockgen, use table-driven tests, target >80% coverage
Files:
cmd/describe_locals_test.go
cmd/**/*_test.go
📄 CodeRabbit inference engine (CLAUDE.md)
Always use
cmd.NewTestKit(t)for cmd tests to auto-clean RootCmd state
Files:
cmd/describe_locals_test.go
docs/prd/**/*.md
📄 CodeRabbit inference engine (CLAUDE.md)
Place all Product Requirement Documents (PRDs) in
docs/prd/using kebab-case filenames
Files:
docs/prd/file-scoped-locals.md
🧠 Learnings (45)
📓 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: 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.
📚 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/describe_locals.gocmd/describe_locals_test.godocs/prd/file-scoped-locals.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 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/describe_locals.gocmd/describe_locals_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:
cmd/describe_locals.gocmd/describe_locals_test.godocs/prd/file-scoped-locals.md
📚 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/describe_locals.godocs/prd/file-scoped-locals.md
📚 Learning: 2025-08-16T23:32:40.412Z
Learnt from: aknysh
Repo: cloudposse/atmos PR: 1405
File: internal/exec/describe_dependents_test.go:455-456
Timestamp: 2025-08-16T23:32:40.412Z
Learning: In the cloudposse/atmos Go codebase, `InitCliConfig` returns a `schema.AtmosConfiguration` value (not a pointer), while `ExecuteDescribeDependents` expects a `*schema.AtmosConfiguration` pointer parameter. Therefore, when passing the result of `InitCliConfig` to `ExecuteDescribeDependents`, use `&atmosConfig` to pass the address of the value.
Applied to files:
cmd/describe_locals.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:
cmd/describe_locals.gocmd/describe_locals_test.godocs/prd/file-scoped-locals.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 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/describe_locals.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/describe_locals.gocmd/describe_locals_test.go
📚 Learning: 2025-05-22T19:58:32.988Z
Learnt from: samtholiya
Repo: cloudposse/atmos PR: 1255
File: cmd/describe_affected.go:122-123
Timestamp: 2025-05-22T19:58:32.988Z
Learning: The "pager" flag is defined as a PersistentFlag at the describe command level in cmd/describe.go, making it available to all subcommands including describeAffectedCmd without needing to redeclare it.
Applied to files:
cmd/describe_locals.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:
cmd/describe_locals.gocmd/describe_locals_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:
cmd/describe_locals.gocmd/describe_locals_test.go
📚 Learning: 2025-09-05T14:57:37.360Z
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.
Applied to files:
cmd/describe_locals.godocs/prd/file-scoped-locals.md
📚 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:
cmd/describe_locals.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/describe_locals.gocmd/describe_locals_test.godocs/prd/file-scoped-locals.md
📚 Learning: 2025-06-07T19:28:21.289Z
Learnt from: samtholiya
Repo: cloudposse/atmos PR: 1266
File: cmd/describe_affected.go:0-0
Timestamp: 2025-06-07T19:28:21.289Z
Learning: In the Atmos codebase, using panic for unsupported flag types in flag processing functions like setDescribeAffectedFlagValueInCliArgs is the expected behavior rather than returning errors. This pattern is preferred for developer errors when unsupported types are added to the flagsKeyValue map.
Applied to files:
cmd/describe_locals.gocmd/describe_locals_test.go
📚 Learning: 2025-11-10T03:03:31.505Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 0
File: :0-0
Timestamp: 2025-11-10T03:03:31.505Z
Learning: In the Atmos codebase, commands using the `StandardParser` flag pattern (from pkg/flags) do NOT need explicit `viper.BindPFlag()` calls in their code. The StandardParser encapsulates flag binding internally: flags are registered via `parser.RegisterFlags(cmd)` in init(), and bound via `parser.BindFlagsToViper(cmd, v)` in RunE, which internally calls viper.BindPFlag for each flag. This pattern is used throughout Atmos (e.g., cmd/toolchain/get.go, cmd/toolchain/info.go, cmd/toolchain/install.go, cmd/toolchain/path.go). Do not flag missing viper.BindPFlag calls when StandardParser is used.
Applied to files:
cmd/describe_locals.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/describe_locals.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:
cmd/describe_locals.go
📚 Learning: 2025-08-16T23:33:07.477Z
Learnt from: aknysh
Repo: cloudposse/atmos PR: 1405
File: internal/exec/describe_dependents_test.go:651-652
Timestamp: 2025-08-16T23:33:07.477Z
Learning: In the cloudposse/atmos Go codebase, ExecuteDescribeDependents expects a pointer to AtmosConfiguration (*schema.AtmosConfiguration), so when calling it with a value returned by cfg.InitCliConfig (which returns schema.AtmosConfiguration), the address-of operator (&) is necessary: ExecuteDescribeDependents(&atmosConfig, ...).
Applied to files:
cmd/describe_locals.go
📚 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:
cmd/describe_locals.godocs/prd/file-scoped-locals.md
📚 Learning: 2025-02-03T06:00:11.419Z
Learnt from: samtholiya
Repo: cloudposse/atmos PR: 959
File: cmd/describe_config.go:20-20
Timestamp: 2025-02-03T06:00:11.419Z
Learning: The `describe config` command should use `PrintErrorMarkdownAndExit` with empty title and suggestion for consistency with other commands.
Applied to files:
cmd/describe_locals.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/describe_locals.gocmd/describe_locals_test.godocs/prd/file-scoped-locals.md
📚 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:
cmd/describe_locals.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/describe_locals.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/describe_locals.gocmd/describe_locals_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:
cmd/describe_locals.gocmd/describe_locals_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:
cmd/describe_locals_test.go
📚 Learning: 2026-01-04T00:55:21.720Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-04T00:55:21.720Z
Learning: Applies to **/*_test.go : Prefer unit tests with mocks over integration tests - use interfaces and dependency injection for testability, generate mocks with `go.uber.org/mock/mockgen`, use table-driven tests, target >80% coverage
Applied to files:
cmd/describe_locals_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:
cmd/describe_locals_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:
cmd/describe_locals_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/describe_locals_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: Ensure all tests pass, verify code coverage meets targets, run golangci-lint and fix any issues, and update documentation before submitting pull requests
Applied to files:
cmd/describe_locals_test.go
📚 Learning: 2026-01-04T00:55:21.720Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-04T00:55:21.720Z
Learning: Applies to **/*.go : Never manually create mocks - use `go.uber.org/mock/mockgen` with `//go:generate` directives in Go code
Applied to files:
cmd/describe_locals_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 **/*.go : Use interfaces for external dependencies to facilitate mocking and consider using testify/mock for creating mock implementations
Applied to files:
cmd/describe_locals_test.go
📚 Learning: 2025-02-19T05:50:35.853Z
Learnt from: samtholiya
Repo: cloudposse/atmos PR: 1068
File: tests/snapshots/TestCLICommands_atmos_terraform_apply_--help.stdout.golden:0-0
Timestamp: 2025-02-19T05:50:35.853Z
Learning: Backtick formatting should only be applied to flag descriptions in Go source files, not in golden test files (test snapshots) as they are meant to capture the raw command output.
Applied to files:
cmd/describe_locals_test.go
📚 Learning: 2026-01-04T00:55:21.720Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-04T00:55:21.720Z
Learning: Applies to cmd/**/*_test.go : Always use `cmd.NewTestKit(t)` for cmd tests to auto-clean RootCmd state
Applied to files:
cmd/describe_locals_test.go
📚 Learning: 2024-12-03T04:01:16.446Z
Learnt from: aknysh
Repo: cloudposse/atmos PR: 810
File: website/docs/core-concepts/stacks/yaml-functions/terraform.output.mdx:0-0
Timestamp: 2024-12-03T04:01:16.446Z
Learning: In the `terraform.output.mdx` documentation file (`website/docs/core-concepts/stacks/yaml-functions/terraform.output.mdx`), the cache invalidation and cache scope behavior for the `!terraform.output` function are already described.
Applied to files:
docs/prd/file-scoped-locals.md
📚 Learning: 2026-01-09T04:49:35.038Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 1907
File: demos/fixtures/acme/stacks/catalog/api.yaml:1-29
Timestamp: 2026-01-09T04:49:35.038Z
Learning: In the cloudposse/atmos demos/fixtures, components can provide Terraform outputs via `remote_state_backend.static` configuration blocks instead of traditional Terraform output blocks. This pattern is used for demo/fixture purposes to simulate cross-component state references without deploying actual infrastructure. The `!terraform.state` YAML function reads from these static backends.
Applied to files:
docs/prd/file-scoped-locals.md
📚 Learning: 2025-12-24T04:29:23.938Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 1891
File: pkg/ci/terraform/templates/apply.md:17-17
Timestamp: 2025-12-24T04:29:23.938Z
Learning: In the cloudposse/atmos repository, Terraform CI templates (pkg/ci/terraform/templates/*.md) are rendered using TerraformTemplateContext (defined in pkg/ci/terraform/context.go), not the base ci.TemplateContext. TerraformTemplateContext provides top-level fields: .Resources (ci.ResourceCounts), .HasChanges() method, and .HasDestroy field, which are correctly accessed directly in templates without a .Result prefix.
Applied to files:
docs/prd/file-scoped-locals.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:
docs/prd/file-scoped-locals.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:
docs/prd/file-scoped-locals.md
📚 Learning: 2025-02-24T22:46:39.744Z
Learnt from: haitham911
Repo: cloudposse/atmos PR: 1085
File: pkg/config/load.go:219-221
Timestamp: 2025-02-24T22:46:39.744Z
Learning: In the Atmos configuration system, imports from atmos.d are optional. When import errors occur, they should be logged at debug level and the process should continue, rather than failing completely.
Applied to files:
docs/prd/file-scoped-locals.md
📚 Learning: 2025-09-27T20:50:20.564Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 1533
File: pkg/config/load.go:585-637
Timestamp: 2025-09-27T20:50:20.564Z
Learning: In the cloudposse/atmos repository, command merging prioritizes precedence over display ordering. Help commands are displayed lexicographically regardless of internal array order, so the mergeCommandArrays function focuses on ensuring the correct precedence chain (top-level file wins) rather than maintaining specific display order.
Applied to files:
docs/prd/file-scoped-locals.md
📚 Learning: 2025-12-13T06:07:34.794Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 1686
File: docs/prd/tool-dependencies-integration.md:58-64
Timestamp: 2025-12-13T06:07:34.794Z
Learning: For docs in the cloudposse/atmos repository under docs/prd/, markdownlint issues MD040, MD010, and MD034 should be deferred to a separate documentation cleanup commit and must not block the current PR. If needed, address these issues in a follow-up PR dedicated to documentation improvements.
Applied to files:
docs/prd/file-scoped-locals.md
🪛 LanguageTool
docs/prd/file-scoped-locals.md
[style] ~239-~239: Since ownership is already implied, this phrasing may be redundant.
Context: ...ribute - Override inherited locals with its own definitions ## Behavior Clarifications...
(PRP_OWN)
[typographical] ~1843-~1843: To join two clauses or introduce examples, consider using an em dash.
Context: ...internal/exec/stack_processor_locals.go- LocalsContext and extraction -internal...
(DASH_RULE)
[typographical] ~1844-~1844: To join two clauses or introduce examples, consider using an em dash.
Context: ...ack_processor_process_stacks_helpers.go` - ComponentLocals and BaseComponentLocals ...
(DASH_RULE)
[typographical] ~1845-~1845: To join two clauses or introduce examples, consider using an em dash.
Context: ...or_process_stacks_helpers_extraction.go- Component locals extraction -internal/...
(DASH_RULE)
[typographical] ~1846-~1846: To join two clauses or introduce examples, consider using an em dash.
Context: ...r_process_stacks_helpers_inheritance.go- Component locals inheritance -internal...
(DASH_RULE)
[typographical] ~1847-~1847: To join two clauses or introduce examples, consider using an em dash.
Context: ...internal/exec/stack_processor_utils.go - Base component locals extraction and mer...
(DASH_RULE)
[typographical] ~1848-~1848: To join two clauses or introduce examples, consider using an em dash.
Context: ...internal/exec/stack_processor_merge.go - Component locals merging in final output...
(DASH_RULE)
[typographical] ~1849-~1849: To join two clauses or introduce examples, consider using an em dash.
Context: ...put - internal/exec/describe_locals.go - DescribeLocalsExec implementation with c...
(DASH_RULE)
[typographical] ~1850-~1850: To join two clauses or introduce examples, consider using an em dash.
Context: ...ponent locals - cmd/describe_locals.go - CLI command definition - `pkg/locals/res...
(DASH_RULE)
[typographical] ~1851-~1851: To join two clauses or introduce examples, consider using an em dash.
Context: ...nd definition - pkg/locals/resolver.go - Dependency resolution with cycle detecti...
(DASH_RULE)
[typographical] ~1852-~1852: To join two clauses or introduce examples, consider using an em dash.
Context: ...cycle detection - pkg/schema/schema.go - BaseComponentLocals field in BaseCompone...
(DASH_RULE)
[typographical] ~1853-~1853: To join two clauses or introduce examples, consider using an em dash.
Context: ...BaseComponentConfig - errors/errors.go - Sentinel errors for locals (including Er...
(DASH_RULE)
[typographical] ~1873-~1873: Consider using a typographic opening quote here.
Context: ... Example: If your atmos.yaml has name_pattern: "{stage}-{environment}" and you have a f...
(EN_QUOTES)
[typographical] ~1882-~1882: Consider using a typographic close quote here.
Context: ...ith the --stack flag, you're asking: *"What locals would be available to this c...
(EN_QUOTES)
[typographical] ~1882-~1882: Consider using a typographic close quote here.
Context: ...is component during template processing?"* The component argument does not m...
(EN_QUOTES)
⏰ Context from checks skipped due to timeout of 900000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
- GitHub Check: Acceptance Tests (linux)
- GitHub Check: Acceptance Tests (windows)
- GitHub Check: Summary
🔇 Additional comments (13)
cmd/describe_locals_test.go (6)
1-15: Imports are well-organized.Follows the three-group convention and uses the expected package aliases.
17-67: Well-structured test with proper dependency verification.Good approach tracking each callback to confirm the execution flow. The mock setup follows the expected pattern.
115-162: Solid fail-fast verification.Testing that expensive operations (config init, stack validation) are skipped when required flags are missing is valuable defensive testing.
213-279: Good use of table-driven tests for error scenarios.Covers the key error paths cleanly without duplication.
319-380: Flag parsing tests cover the key scenarios.Default format verification and partial flag combinations are well tested.
382-407: Proper use of NewTestKit for cmd tests.Follows the coding guidelines for auto-cleaning RootCmd state.
cmd/describe_locals.go (5)
1-14: Import organization follows guidelines.Proper three-group separation with expected aliases.
18-49: Comprehensive command definition with helpful examples.The help text clearly explains both stack-only and component queries. Examples cover the main use cases.
64-114: Good fail-fast pattern and dependency injection.The early
--stackcheck before expensive init operations is a nice UX optimization. The perf.Track usage with nil is correct per guidelines.
116-153: Clean flag parsing with proper error wrapping.Using
flags.Changed()avoids overwriting values unnecessarily. Error wrapping follows the static error pattern.
155-171: Well-documented flags with shell completion support.Good call using
Flags()instead ofPersistentFlags()since there are no subcommands. The stack flag help text explaining both path and logical name support is helpful.docs/prd/file-scoped-locals.md (2)
192-240: Component-level locals inheritance documentation is clear.The hierarchy diagram and examples effectively explain the merge order: Global → Section → Base Component → Component.
1815-1854: Implementation status section is a useful addition.Having the status checklist and file inventory helps readers understand what's been implemented vs. planned.
There was a problem hiding this comment.
Actionable comments posted: 0
🧹 Nitpick comments (1)
docs/prd/file-scoped-locals.md (1)
1880-1910: Consider clarifying component argument semantics.The explanation in lines 1882-1888 states the component argument determines type for section-specific merging, but doesn't mention component-level locals until line 1910. This creates a small gap in the reader's understanding.
✍️ Suggested enhancement
Consider adding one sentence after line 1888 to complete the picture:
The component argument does **not** mean the locals come from the component definition. Instead: 1. Atmos determines the component's type (terraform, helmfile, or packer) 2. Atmos merges the global locals with the corresponding section-specific locals +3. Atmos includes component-level locals (including those inherited from base components) 3. The result shows what `{{ .locals.* }}` references would resolve to for that componentThis makes the three-part merge explicit before the example.
📜 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.
📒 Files selected for processing (1)
docs/prd/file-scoped-locals.md
🧰 Additional context used
📓 Path-based instructions (1)
docs/prd/**/*.md
📄 CodeRabbit inference engine (CLAUDE.md)
Place all Product Requirement Documents (PRDs) in
docs/prd/using kebab-case filenames
Files:
docs/prd/file-scoped-locals.md
🧠 Learnings (20)
📓 Common learnings
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.
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: 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.
Learnt from: osterman
Repo: cloudposse/atmos PR: 1891
File: pkg/ci/terraform/templates/apply.md:17-17
Timestamp: 2025-12-24T04:29:23.938Z
Learning: In the cloudposse/atmos repository, Terraform CI templates (pkg/ci/terraform/templates/*.md) are rendered using TerraformTemplateContext (defined in pkg/ci/terraform/context.go), not the base ci.TemplateContext. TerraformTemplateContext provides top-level fields: .Resources (ci.ResourceCounts), .HasChanges() method, and .HasDestroy field, which are correctly accessed directly in templates without a .Result prefix.
📚 Learning: 2024-12-03T04:01:16.446Z
Learnt from: aknysh
Repo: cloudposse/atmos PR: 810
File: website/docs/core-concepts/stacks/yaml-functions/terraform.output.mdx:0-0
Timestamp: 2024-12-03T04:01:16.446Z
Learning: In the `terraform.output.mdx` documentation file (`website/docs/core-concepts/stacks/yaml-functions/terraform.output.mdx`), the cache invalidation and cache scope behavior for the `!terraform.output` function are already described.
Applied to files:
docs/prd/file-scoped-locals.md
📚 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:
docs/prd/file-scoped-locals.md
📚 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:
docs/prd/file-scoped-locals.md
📚 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:
docs/prd/file-scoped-locals.md
📚 Learning: 2024-11-01T15:44:12.617Z
Learnt from: RoseSecurity
Repo: cloudposse/atmos PR: 757
File: cmd/docs.go:42-59
Timestamp: 2024-11-01T15:44:12.617Z
Learning: In `cmd/docs.go`, when implementing width detection for the `docsCmd` command, it's acceptable to keep the code inline without extracting it into a separate function, as per the user's preference for compact readability and maintainability in Go code.
Applied to files:
docs/prd/file-scoped-locals.md
📚 Learning: 2026-01-09T04:49:35.038Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 1907
File: demos/fixtures/acme/stacks/catalog/api.yaml:1-29
Timestamp: 2026-01-09T04:49:35.038Z
Learning: In the cloudposse/atmos demos/fixtures, components can provide Terraform outputs via `remote_state_backend.static` configuration blocks instead of traditional Terraform output blocks. This pattern is used for demo/fixture purposes to simulate cross-component state references without deploying actual infrastructure. The `!terraform.state` YAML function reads from these static backends.
Applied to files:
docs/prd/file-scoped-locals.md
📚 Learning: 2025-12-24T04:29:23.938Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 1891
File: pkg/ci/terraform/templates/apply.md:17-17
Timestamp: 2025-12-24T04:29:23.938Z
Learning: In the cloudposse/atmos repository, Terraform CI templates (pkg/ci/terraform/templates/*.md) are rendered using TerraformTemplateContext (defined in pkg/ci/terraform/context.go), not the base ci.TemplateContext. TerraformTemplateContext provides top-level fields: .Resources (ci.ResourceCounts), .HasChanges() method, and .HasDestroy field, which are correctly accessed directly in templates without a .Result prefix.
Applied to files:
docs/prd/file-scoped-locals.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:
docs/prd/file-scoped-locals.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:
docs/prd/file-scoped-locals.md
📚 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:
docs/prd/file-scoped-locals.md
📚 Learning: 2025-10-07T00:25:16.333Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 1498
File: website/src/components/Screengrabs/atmos-terraform-metadata--help.html:25-55
Timestamp: 2025-10-07T00:25:16.333Z
Learning: In Atmos CLI, subcommands inherit flags from their parent commands via Cobra's command inheritance. For example, `atmos terraform metadata --help` shows `--affected` and related flags inherited from the parent `terraform` command (defined in cmd/terraform.go), even though the metadata subcommand doesn't explicitly define these flags. This is expected Cobra behavior and auto-generated help screengrabs accurately reflect this inheritance.
Applied to files:
docs/prd/file-scoped-locals.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:
docs/prd/file-scoped-locals.md
📚 Learning: 2025-02-24T22:46:39.744Z
Learnt from: haitham911
Repo: cloudposse/atmos PR: 1085
File: pkg/config/load.go:219-221
Timestamp: 2025-02-24T22:46:39.744Z
Learning: In the Atmos configuration system, imports from atmos.d are optional. When import errors occur, they should be logged at debug level and the process should continue, rather than failing completely.
Applied to files:
docs/prd/file-scoped-locals.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:
docs/prd/file-scoped-locals.md
📚 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:
docs/prd/file-scoped-locals.md
📚 Learning: 2025-09-27T20:50:20.564Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 1533
File: pkg/config/load.go:585-637
Timestamp: 2025-09-27T20:50:20.564Z
Learning: In the cloudposse/atmos repository, command merging prioritizes precedence over display ordering. Help commands are displayed lexicographically regardless of internal array order, so the mergeCommandArrays function focuses on ensuring the correct precedence chain (top-level file wins) rather than maintaining specific display order.
Applied to files:
docs/prd/file-scoped-locals.md
📚 Learning: 2025-09-05T14:57:37.360Z
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.
Applied to files:
docs/prd/file-scoped-locals.md
📚 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:
docs/prd/file-scoped-locals.md
📚 Learning: 2025-12-13T06:07:34.794Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 1686
File: docs/prd/tool-dependencies-integration.md:58-64
Timestamp: 2025-12-13T06:07:34.794Z
Learning: For docs in the cloudposse/atmos repository under docs/prd/, markdownlint issues MD040, MD010, and MD034 should be deferred to a separate documentation cleanup commit and must not block the current PR. If needed, address these issues in a follow-up PR dedicated to documentation improvements.
Applied to files:
docs/prd/file-scoped-locals.md
🪛 LanguageTool
docs/prd/file-scoped-locals.md
[style] ~239-~239: Since ownership is already implied, this phrasing may be redundant.
Context: ...ribute - Override inherited locals with its own definitions ## Behavior Clarifications...
(PRP_OWN)
[typographical] ~1843-~1843: To join two clauses or introduce examples, consider using an em dash.
Context: ...internal/exec/stack_processor_locals.go- LocalsContext and extraction -internal...
(DASH_RULE)
[typographical] ~1844-~1844: To join two clauses or introduce examples, consider using an em dash.
Context: ...ack_processor_process_stacks_helpers.go` - ComponentLocals and BaseComponentLocals ...
(DASH_RULE)
[typographical] ~1845-~1845: To join two clauses or introduce examples, consider using an em dash.
Context: ...or_process_stacks_helpers_extraction.go- Component locals extraction -internal/...
(DASH_RULE)
[typographical] ~1846-~1846: To join two clauses or introduce examples, consider using an em dash.
Context: ...r_process_stacks_helpers_inheritance.go- Component locals inheritance -internal...
(DASH_RULE)
[typographical] ~1847-~1847: To join two clauses or introduce examples, consider using an em dash.
Context: ...internal/exec/stack_processor_utils.go - Base component locals extraction and mer...
(DASH_RULE)
[typographical] ~1848-~1848: To join two clauses or introduce examples, consider using an em dash.
Context: ...internal/exec/stack_processor_merge.go - Component locals merging in final output...
(DASH_RULE)
[typographical] ~1849-~1849: To join two clauses or introduce examples, consider using an em dash.
Context: ...put - internal/exec/describe_locals.go - DescribeLocalsExec implementation with c...
(DASH_RULE)
[typographical] ~1850-~1850: To join two clauses or introduce examples, consider using an em dash.
Context: ...ponent locals - cmd/describe_locals.go - CLI command definition - `pkg/locals/res...
(DASH_RULE)
[typographical] ~1851-~1851: To join two clauses or introduce examples, consider using an em dash.
Context: ...nd definition - pkg/locals/resolver.go - Dependency resolution with cycle detecti...
(DASH_RULE)
[typographical] ~1852-~1852: To join two clauses or introduce examples, consider using an em dash.
Context: ...cycle detection - pkg/schema/schema.go - BaseComponentLocals field in BaseCompone...
(DASH_RULE)
[typographical] ~1853-~1853: To join two clauses or introduce examples, consider using an em dash.
Context: ...BaseComponentConfig - errors/errors.go - Sentinel errors for locals (including Er...
(DASH_RULE)
[typographical] ~1873-~1873: Consider using a typographic opening quote here.
Context: ... Example: If your atmos.yaml has name_pattern: "{stage}-{environment}" and you have a f...
(EN_QUOTES)
[typographical] ~1882-~1882: Consider using a typographic close quote here.
Context: ...ith the --stack flag, you're asking: *"What locals would be available to this c...
(EN_QUOTES)
[typographical] ~1882-~1882: Consider using a typographic close quote here.
Context: ...is component during template processing?"* The component argument does not m...
(EN_QUOTES)
⏰ Context from checks skipped due to timeout of 900000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: Summary
🔇 Additional comments (5)
docs/prd/file-scoped-locals.md (5)
100-113: Clear illustration of merged locals model.The addition of
vpc_nameand the updated comment on line 105 effectively demonstrate how components access merged locals (global + section scope). The example accurately reflects the resolution semantics described later in the document.
192-240: Component-level locals inheritance well-documented.The new section clearly distinguishes file-scoped locals (no cross-file inheritance) from component-level locals (inherit via
metadata.inherits). The resolution order hierarchy (Global → Section → Base Component → Component) is explicitly stated and matches the implementation described in PR objectives.The inheritance example effectively demonstrates:
- Base component defining reusable locals
- Child component inheriting and overriding specific values
- How inherited locals are accessible in templates
304-333: File-scoped vs component-level locals clearly distinguished.The updated example effectively demonstrates the boundary between file-scoped locals (which don't cross imports) and component-level locals (which inherit via
metadata.inherits). The inline comments marking "File-scoped" vs "Component-level" help readers understand the different semantics.
371-396: Resolution order accurately updated.The three-scope resolution model (global → section → component-level) is correctly documented with component-level locals now included as scope 3. The note about inheritance from base components maintains consistency with the inheritance section.
1588-1650:atmos describe localscommand well-specified.The command documentation clearly explains:
- Required
--stackflag for file-scoped semantics- Two output modes: stack view (shows scope separation) vs component view (shows merged locals)
- Output format follows Atmos schema conventions
- Support for JSON, query, and file output options
The examples effectively demonstrate both use cases and the design decisions provide clear rationale for the implementation approach.
There was a problem hiding this comment.
Actionable comments posted: 0
🧹 Nitpick comments (4)
docs/prd/file-scoped-locals.md (4)
192-240: Clarify precedence when component-level locals conflict with section-level locals.The introduction of component-level locals inheritance is well-documented, but the precedence rules when names collide aren't explicit. For example, if a component defines
locals.regionand the terraform section also defineslocals.region, which takes precedence in the merged context?The resolution order on lines 230-234 suggests component-level wins, but this should be stated clearly in prose, not just implied by the order. Consider adding a subsection like:
**Precedence rules for name conflicts:** - Component locals override section-specific locals - Section-specific locals override global locals - Base component locals are overridden by derived component locals
304-333: Template syntax doesn't distinguish between file-scoped and component-level locals—consider adding guidance.Lines 329-332 show that
{{ .locals.vpc_type }}works whenvpc_typecomes from component-level inheritance, but the same syntax would fail for file-scoped locals from imported files. Users can't tell from the template syntax alone which type of local they're referencing.Consider adding a note in this section or in the "Behavior Clarifications" table about how to determine local scope when debugging template failures. For example:
**Note:** Template syntax `{{ .locals.* }}` is the same for all local types. To determine if a local is file-scoped or component-level: - Check if it's defined under `components.terraform.COMPONENT.locals` (component-level) - Check if it's defined at root level or in terraform/helmfile/packer sections (file-scoped)
1588-1650: Define "Atmos schema format" and "direct format" for clarity.Lines 1617, 1632, and 1636-1642 reference "Atmos stack manifest schema format" and "direct format" without defining these terms. Users unfamiliar with Atmos internals might not understand what this means or how to use the output.
Consider adding a brief explanation:
**Output Format:** The command outputs locals in the same YAML structure used in stack manifest files. This means: - You can copy the output directly into a stack manifest file - The structure matches the schema defined in `pkg/datafetcher/schema/stacks/stack-config/1.0.json` - "Direct format" refers to the flattened structure (vs. the internal merged representation)Alternatively, if "direct format" is an existing Atmos concept, add a reference to where it's documented.
1816-1920: Implementation status section is valuable—consider moving design clarifications earlier.This section effectively documents what's been implemented and provides crucial design clarifications. The "Design Clarifications" subsection (lines 1862-1920) contains important information about how
atmos describe localsworks that users need to understand the feature.Consider moving lines 1862-1920 up to the "Debugging Locals" section (around line 1590) where the command is first introduced. This would help users understand the command's behavior when they first encounter it, rather than requiring them to read to the end of the document.
📜 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.
📒 Files selected for processing (1)
docs/prd/file-scoped-locals.md
🧰 Additional context used
📓 Path-based instructions (1)
docs/prd/**/*.md
📄 CodeRabbit inference engine (CLAUDE.md)
Place all Product Requirement Documents (PRDs) in
docs/prd/using kebab-case filenames
Files:
docs/prd/file-scoped-locals.md
🧠 Learnings (19)
📓 Common learnings
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.
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: 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.
📚 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:
docs/prd/file-scoped-locals.md
📚 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:
docs/prd/file-scoped-locals.md
📚 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:
docs/prd/file-scoped-locals.md
📚 Learning: 2024-11-01T15:44:12.617Z
Learnt from: RoseSecurity
Repo: cloudposse/atmos PR: 757
File: cmd/docs.go:42-59
Timestamp: 2024-11-01T15:44:12.617Z
Learning: In `cmd/docs.go`, when implementing width detection for the `docsCmd` command, it's acceptable to keep the code inline without extracting it into a separate function, as per the user's preference for compact readability and maintainability in Go code.
Applied to files:
docs/prd/file-scoped-locals.md
📚 Learning: 2026-01-09T04:49:35.038Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 1907
File: demos/fixtures/acme/stacks/catalog/api.yaml:1-29
Timestamp: 2026-01-09T04:49:35.038Z
Learning: In the cloudposse/atmos demos/fixtures, components can provide Terraform outputs via `remote_state_backend.static` configuration blocks instead of traditional Terraform output blocks. This pattern is used for demo/fixture purposes to simulate cross-component state references without deploying actual infrastructure. The `!terraform.state` YAML function reads from these static backends.
Applied to files:
docs/prd/file-scoped-locals.md
📚 Learning: 2025-12-24T04:29:23.938Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 1891
File: pkg/ci/terraform/templates/apply.md:17-17
Timestamp: 2025-12-24T04:29:23.938Z
Learning: In the cloudposse/atmos repository, Terraform CI templates (pkg/ci/terraform/templates/*.md) are rendered using TerraformTemplateContext (defined in pkg/ci/terraform/context.go), not the base ci.TemplateContext. TerraformTemplateContext provides top-level fields: .Resources (ci.ResourceCounts), .HasChanges() method, and .HasDestroy field, which are correctly accessed directly in templates without a .Result prefix.
Applied to files:
docs/prd/file-scoped-locals.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:
docs/prd/file-scoped-locals.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:
docs/prd/file-scoped-locals.md
📚 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:
docs/prd/file-scoped-locals.md
📚 Learning: 2025-10-07T00:25:16.333Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 1498
File: website/src/components/Screengrabs/atmos-terraform-metadata--help.html:25-55
Timestamp: 2025-10-07T00:25:16.333Z
Learning: In Atmos CLI, subcommands inherit flags from their parent commands via Cobra's command inheritance. For example, `atmos terraform metadata --help` shows `--affected` and related flags inherited from the parent `terraform` command (defined in cmd/terraform.go), even though the metadata subcommand doesn't explicitly define these flags. This is expected Cobra behavior and auto-generated help screengrabs accurately reflect this inheritance.
Applied to files:
docs/prd/file-scoped-locals.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:
docs/prd/file-scoped-locals.md
📚 Learning: 2025-02-24T22:46:39.744Z
Learnt from: haitham911
Repo: cloudposse/atmos PR: 1085
File: pkg/config/load.go:219-221
Timestamp: 2025-02-24T22:46:39.744Z
Learning: In the Atmos configuration system, imports from atmos.d are optional. When import errors occur, they should be logged at debug level and the process should continue, rather than failing completely.
Applied to files:
docs/prd/file-scoped-locals.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:
docs/prd/file-scoped-locals.md
📚 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:
docs/prd/file-scoped-locals.md
📚 Learning: 2025-09-27T20:50:20.564Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 1533
File: pkg/config/load.go:585-637
Timestamp: 2025-09-27T20:50:20.564Z
Learning: In the cloudposse/atmos repository, command merging prioritizes precedence over display ordering. Help commands are displayed lexicographically regardless of internal array order, so the mergeCommandArrays function focuses on ensuring the correct precedence chain (top-level file wins) rather than maintaining specific display order.
Applied to files:
docs/prd/file-scoped-locals.md
📚 Learning: 2025-09-05T14:57:37.360Z
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.
Applied to files:
docs/prd/file-scoped-locals.md
📚 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:
docs/prd/file-scoped-locals.md
📚 Learning: 2025-12-13T06:07:34.794Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 1686
File: docs/prd/tool-dependencies-integration.md:58-64
Timestamp: 2025-12-13T06:07:34.794Z
Learning: For docs in the cloudposse/atmos repository under docs/prd/, markdownlint issues MD040, MD010, and MD034 should be deferred to a separate documentation cleanup commit and must not block the current PR. If needed, address these issues in a follow-up PR dedicated to documentation improvements.
Applied to files:
docs/prd/file-scoped-locals.md
🪛 LanguageTool
docs/prd/file-scoped-locals.md
[style] ~239-~239: Since ownership is already implied, this phrasing may be redundant.
Context: ...ribute - Override inherited locals with its own definitions ## Behavior Clarifications...
(PRP_OWN)
[typographical] ~1843-~1843: To join two clauses or introduce examples, consider using an em dash.
Context: ...internal/exec/stack_processor_locals.go- LocalsContext and extraction -internal...
(DASH_RULE)
[typographical] ~1844-~1844: To join two clauses or introduce examples, consider using an em dash.
Context: ...ack_processor_process_stacks_helpers.go` - ComponentLocals and BaseComponentLocals ...
(DASH_RULE)
[typographical] ~1845-~1845: To join two clauses or introduce examples, consider using an em dash.
Context: ...or_process_stacks_helpers_extraction.go- Component locals extraction -internal/...
(DASH_RULE)
[typographical] ~1846-~1846: To join two clauses or introduce examples, consider using an em dash.
Context: ...r_process_stacks_helpers_inheritance.go- Component locals inheritance -internal...
(DASH_RULE)
[typographical] ~1847-~1847: To join two clauses or introduce examples, consider using an em dash.
Context: ...internal/exec/stack_processor_utils.go - Base component locals extraction and mer...
(DASH_RULE)
[typographical] ~1848-~1848: To join two clauses or introduce examples, consider using an em dash.
Context: ...internal/exec/stack_processor_merge.go - Component locals merging in final output...
(DASH_RULE)
[typographical] ~1849-~1849: To join two clauses or introduce examples, consider using an em dash.
Context: ...put - internal/exec/describe_locals.go - DescribeLocalsExec implementation with c...
(DASH_RULE)
[typographical] ~1850-~1850: To join two clauses or introduce examples, consider using an em dash.
Context: ...ponent locals - cmd/describe_locals.go - CLI command definition - `pkg/locals/res...
(DASH_RULE)
[typographical] ~1851-~1851: To join two clauses or introduce examples, consider using an em dash.
Context: ...nd definition - pkg/locals/resolver.go - Dependency resolution with cycle detecti...
(DASH_RULE)
[typographical] ~1852-~1852: To join two clauses or introduce examples, consider using an em dash.
Context: ...cycle detection - pkg/schema/schema.go - BaseComponentLocals field in BaseCompone...
(DASH_RULE)
[typographical] ~1853-~1853: To join two clauses or introduce examples, consider using an em dash.
Context: ...BaseComponentConfig - errors/errors.go - Sentinel errors for locals (including Er...
(DASH_RULE)
[typographical] ~1873-~1873: Consider using a typographic opening quote here.
Context: ... Example: If your atmos.yaml has name_pattern: "{stage}-{environment}" and you have a f...
(EN_QUOTES)
[typographical] ~1882-~1882: Consider using a typographic close quote here.
Context: ...ith the --stack flag, you're asking: *"What locals would be available to this c...
(EN_QUOTES)
[typographical] ~1882-~1882: Consider using a typographic close quote here.
Context: ...is component during template processing?"* The component argument does not m...
(EN_QUOTES)
⏰ Context from checks skipped due to timeout of 900000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: Summary
🔇 Additional comments (1)
docs/prd/file-scoped-locals.md (1)
1-1920: Comprehensive documentation that clearly defines the locals feature.This PRD effectively documents both the requirements and implementation of file-scoped locals. The examples throughout are helpful, especially the distinction between file-scoped locals (not inherited) and component-level locals (inherited from base components). The implementation status section provides valuable context about what's been delivered.
A few optional suggestions for improved clarity:
- Make precedence rules more explicit when locals at different scopes have the same name
- Define "Atmos schema format" terminology for users unfamiliar with it
- Consider moving design clarifications earlier in the document where the command is introduced
These are polish items—the core documentation is solid and ready for users to understand the feature.
There was a problem hiding this comment.
Actionable comments posted: 0
🧹 Nitpick comments (1)
docs/prd/file-scoped-locals.md (1)
244-244: Optional: Minor style improvements flagged by LanguageTool.LanguageTool has identified some style refinements:
- Line 244: "its own definitions" could be simplified to "own definitions"
- Lines 1852-1862: Em dashes could replace hyphens in list items for better typography
- Lines 1882, 1891: Consider typographic quotes for consistency
Based on learnings, these style issues in PRD docs can be handled in a separate documentation cleanup commit if desired.
Also applies to: 1852-1862, 1882-1882, 1891-1891
📜 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.
📒 Files selected for processing (1)
docs/prd/file-scoped-locals.md
🧰 Additional context used
📓 Path-based instructions (1)
docs/prd/**/*.md
📄 CodeRabbit inference engine (CLAUDE.md)
Place all Product Requirement Documents (PRDs) in
docs/prd/using kebab-case filenames
Files:
docs/prd/file-scoped-locals.md
🧠 Learnings (20)
📓 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: 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.
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.
📚 Learning: 2024-12-03T04:01:16.446Z
Learnt from: aknysh
Repo: cloudposse/atmos PR: 810
File: website/docs/core-concepts/stacks/yaml-functions/terraform.output.mdx:0-0
Timestamp: 2024-12-03T04:01:16.446Z
Learning: In the `terraform.output.mdx` documentation file (`website/docs/core-concepts/stacks/yaml-functions/terraform.output.mdx`), the cache invalidation and cache scope behavior for the `!terraform.output` function are already described.
Applied to files:
docs/prd/file-scoped-locals.md
📚 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:
docs/prd/file-scoped-locals.md
📚 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:
docs/prd/file-scoped-locals.md
📚 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:
docs/prd/file-scoped-locals.md
📚 Learning: 2024-11-01T15:44:12.617Z
Learnt from: RoseSecurity
Repo: cloudposse/atmos PR: 757
File: cmd/docs.go:42-59
Timestamp: 2024-11-01T15:44:12.617Z
Learning: In `cmd/docs.go`, when implementing width detection for the `docsCmd` command, it's acceptable to keep the code inline without extracting it into a separate function, as per the user's preference for compact readability and maintainability in Go code.
Applied to files:
docs/prd/file-scoped-locals.md
📚 Learning: 2026-01-09T04:49:35.038Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 1907
File: demos/fixtures/acme/stacks/catalog/api.yaml:1-29
Timestamp: 2026-01-09T04:49:35.038Z
Learning: In the cloudposse/atmos demos/fixtures, components can provide Terraform outputs via `remote_state_backend.static` configuration blocks instead of traditional Terraform output blocks. This pattern is used for demo/fixture purposes to simulate cross-component state references without deploying actual infrastructure. The `!terraform.state` YAML function reads from these static backends.
Applied to files:
docs/prd/file-scoped-locals.md
📚 Learning: 2025-12-24T04:29:23.938Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 1891
File: pkg/ci/terraform/templates/apply.md:17-17
Timestamp: 2025-12-24T04:29:23.938Z
Learning: In the cloudposse/atmos repository, Terraform CI templates (pkg/ci/terraform/templates/*.md) are rendered using TerraformTemplateContext (defined in pkg/ci/terraform/context.go), not the base ci.TemplateContext. TerraformTemplateContext provides top-level fields: .Resources (ci.ResourceCounts), .HasChanges() method, and .HasDestroy field, which are correctly accessed directly in templates without a .Result prefix.
Applied to files:
docs/prd/file-scoped-locals.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:
docs/prd/file-scoped-locals.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:
docs/prd/file-scoped-locals.md
📚 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:
docs/prd/file-scoped-locals.md
📚 Learning: 2025-10-07T00:25:16.333Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 1498
File: website/src/components/Screengrabs/atmos-terraform-metadata--help.html:25-55
Timestamp: 2025-10-07T00:25:16.333Z
Learning: In Atmos CLI, subcommands inherit flags from their parent commands via Cobra's command inheritance. For example, `atmos terraform metadata --help` shows `--affected` and related flags inherited from the parent `terraform` command (defined in cmd/terraform.go), even though the metadata subcommand doesn't explicitly define these flags. This is expected Cobra behavior and auto-generated help screengrabs accurately reflect this inheritance.
Applied to files:
docs/prd/file-scoped-locals.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:
docs/prd/file-scoped-locals.md
📚 Learning: 2025-02-24T22:46:39.744Z
Learnt from: haitham911
Repo: cloudposse/atmos PR: 1085
File: pkg/config/load.go:219-221
Timestamp: 2025-02-24T22:46:39.744Z
Learning: In the Atmos configuration system, imports from atmos.d are optional. When import errors occur, they should be logged at debug level and the process should continue, rather than failing completely.
Applied to files:
docs/prd/file-scoped-locals.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:
docs/prd/file-scoped-locals.md
📚 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:
docs/prd/file-scoped-locals.md
📚 Learning: 2025-09-27T20:50:20.564Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 1533
File: pkg/config/load.go:585-637
Timestamp: 2025-09-27T20:50:20.564Z
Learning: In the cloudposse/atmos repository, command merging prioritizes precedence over display ordering. Help commands are displayed lexicographically regardless of internal array order, so the mergeCommandArrays function focuses on ensuring the correct precedence chain (top-level file wins) rather than maintaining specific display order.
Applied to files:
docs/prd/file-scoped-locals.md
📚 Learning: 2025-09-05T14:57:37.360Z
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.
Applied to files:
docs/prd/file-scoped-locals.md
📚 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:
docs/prd/file-scoped-locals.md
📚 Learning: 2025-12-13T06:07:34.794Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 1686
File: docs/prd/tool-dependencies-integration.md:58-64
Timestamp: 2025-12-13T06:07:34.794Z
Learning: For docs in the cloudposse/atmos repository under docs/prd/, markdownlint issues MD040, MD010, and MD034 should be deferred to a separate documentation cleanup commit and must not block the current PR. If needed, address these issues in a follow-up PR dedicated to documentation improvements.
Applied to files:
docs/prd/file-scoped-locals.md
🪛 LanguageTool
docs/prd/file-scoped-locals.md
[style] ~244-~244: Since ownership is already implied, this phrasing may be redundant.
Context: ...ribute - Override inherited locals with its own definitions ## Behavior Clarifications...
(PRP_OWN)
[typographical] ~1852-~1852: To join two clauses or introduce examples, consider using an em dash.
Context: ...internal/exec/stack_processor_locals.go- LocalsContext and extraction -internal...
(DASH_RULE)
[typographical] ~1853-~1853: To join two clauses or introduce examples, consider using an em dash.
Context: ...ack_processor_process_stacks_helpers.go` - ComponentLocals and BaseComponentLocals ...
(DASH_RULE)
[typographical] ~1854-~1854: To join two clauses or introduce examples, consider using an em dash.
Context: ...or_process_stacks_helpers_extraction.go- Component locals extraction -internal/...
(DASH_RULE)
[typographical] ~1855-~1855: To join two clauses or introduce examples, consider using an em dash.
Context: ...r_process_stacks_helpers_inheritance.go- Component locals inheritance -internal...
(DASH_RULE)
[typographical] ~1856-~1856: To join two clauses or introduce examples, consider using an em dash.
Context: ...internal/exec/stack_processor_utils.go - Base component locals extraction and mer...
(DASH_RULE)
[typographical] ~1857-~1857: To join two clauses or introduce examples, consider using an em dash.
Context: ...internal/exec/stack_processor_merge.go - Component locals merging in final output...
(DASH_RULE)
[typographical] ~1858-~1858: To join two clauses or introduce examples, consider using an em dash.
Context: ...put - internal/exec/describe_locals.go - DescribeLocalsExec implementation with c...
(DASH_RULE)
[typographical] ~1859-~1859: To join two clauses or introduce examples, consider using an em dash.
Context: ...ponent locals - cmd/describe_locals.go - CLI command definition - `pkg/locals/res...
(DASH_RULE)
[typographical] ~1860-~1860: To join two clauses or introduce examples, consider using an em dash.
Context: ...nd definition - pkg/locals/resolver.go - Dependency resolution with cycle detecti...
(DASH_RULE)
[typographical] ~1861-~1861: To join two clauses or introduce examples, consider using an em dash.
Context: ...cycle detection - pkg/schema/schema.go - BaseComponentLocals field in BaseCompone...
(DASH_RULE)
[typographical] ~1862-~1862: To join two clauses or introduce examples, consider using an em dash.
Context: ...BaseComponentConfig - errors/errors.go - Sentinel errors for locals (including Er...
(DASH_RULE)
[typographical] ~1882-~1882: Consider using a typographic opening quote here.
Context: ... Example: If your atmos.yaml has name_pattern: "{stage}-{environment}" and you have a f...
(EN_QUOTES)
[typographical] ~1891-~1891: Consider using a typographic close quote here.
Context: ...ith the --stack flag, you're asking: *"What locals would be available to this c...
(EN_QUOTES)
[typographical] ~1891-~1891: Consider using a typographic close quote here.
Context: ...is component during template processing?"* The component argument does not m...
(EN_QUOTES)
⏰ Context from checks skipped due to timeout of 900000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (4)
- GitHub Check: Acceptance Tests (macos)
- GitHub Check: Acceptance Tests (linux)
- GitHub Check: Acceptance Tests (windows)
- GitHub Check: Summary
🔇 Additional comments (6)
docs/prd/file-scoped-locals.md (6)
88-113: Clear multi-scope locals example.The example effectively demonstrates how global and terraform-section locals work together, with the updated comment on line 105 accurately reflecting that components use merged locals from both scopes.
166-245: Comprehensive inheritance model documentation.The updated scope resolution section clearly distinguishes between file-scoped locals (not inherited across imports) and component-level locals (inherited via
metadata.inherits). The resolution order, precedence rules, and concrete examples provide excellent clarity for users implementing this feature.
293-343: Excellent edge case documentation with debugging guidance.This section effectively clarifies the difference between file-scoped locals (defined at root/section level, not inheritable) and component-level locals (defined in component blocks, inheritable). The debugging notes on lines 340-343 provide practical guidance for distinguishing between the two types when troubleshooting template failures.
378-405: Consistent cross-scope reference documentation.The updated section accurately describes how locals from outer scopes (global) flow into inner scopes (component-type and component-level), with the resolution order matching the precedence rules documented earlier in the PRD.
1595-1656: Well-documented debugging command with clear examples.The
atmos describe localscommand documentation is comprehensive, with clear examples of stack-level and component-level queries. The note on line 1612 appropriately emphasizes that--stackis required due to the file-scoped nature of locals. The output format guidance (lines 1626-1627) usefully specifies that output follows Atmos stack manifest schema and can be copied directly into manifest files.
1827-1921: Implementation status and design clarifications enhance usability.The Implementation Status section provides transparency about what's been delivered vs. planned, aligning well with the PR objectives. The Design Clarifications (lines 1873-1921) proactively address common user questions about:
- Stack name resolution (logical names vs. file paths)
- Component argument semantics (merged locals shown, not component-defined locals)
- File-scoped isolation (predictability and safety)
These clarifications will reduce user confusion and support questions.
|
These changes were released in v1.204.0-rc.4. |
what
{{ .locals.* }}now correctly resolve to their defined valuesterraform:,helmfile:,packer:) correctly override global localsmetadata.inheritsatmos describe localscommand to inspect and debug locals configurations--stackflag is required - locals are file-scoped, so a specific stack must be specifiedprod-us-east-1) and file paths (e.g.,deploy/prod)Example Output
Stack Locals (by file path or logical name)
The output is in direct stack manifest format - it can be redirected to a file and used as a valid stack manifest:
Component Locals
When a component is specified, the output shows the merged locals available to that component (global + section-specific + component-level + inherited from base components):
Query Specific Values
Component-Level Locals with Inheritance
Components can define their own
locals:section that inherits from base components:Locals resolution order:
Global → Section → Base Component → ComponentManual Testing Results
Test Fixture:
locals-logical-namesStack-level locals (using logical stack name):
cd tests/fixtures/scenarios/locals-logical-names atmos describe locals --stack dev-us-east-1Stack-level locals (using file path):
Same output as above.
Stack-level locals (JSON format):
{ "locals": { "env_prefix": "acme-dev", "full_prefix": "acme-dev-us-east-1", "namespace": "acme" }, "terraform": { "locals": { "backend_bucket": "acme-dev-tfstate", "tf_only": "terraform-specific-dev" } } }Terraform component locals:
Helmfile component locals:
Test Fixture:
locals-component-levelStandalone component with its own locals:
cd tests/fixtures/scenarios/locals-component-level atmos describe locals standalone -s dev-us-east-1Component inheriting from base with locals override (
vpc/dev):Component inheriting from base without locals override (
vpc/standard):why
ProcessStackLocals()existed but was never called during stack processing.localscontext was not provided to template execution, causing templates to remain unresolved{{ .locals.* }}templates showed raw template strings instead of resolved valuesTechnical Changes
extractLocalsFromRawYAML()- Parses YAML and extracts/resolves locals before template processingextractAndAddLocalsToContext()- Helper to add resolved locals to template contextLocalsContext.MergeForTemplateContext()- Merges all scope levels into flat map for templatesHasTerraformLocals,HasHelmfileLocals,HasPackerLocalsto properly handle overridesatmos describe localscommand - Command to inspect locals for a specific stack with schema-compliant outputComponentLocalsandBaseComponentLocalsfields in stack processingmetadata.inheritsTest Coverage
stack_processor_utils_test.go)stack_processor_locals_test.go)describe_locals_test.go)cmd/describe_locals_test.go)cli_locals_test.go)Key test areas:
extractLocalsFromRawYAML- 95.8% coverageProcessStackLocals- 100% coverageExtractAndResolveLocals- 100% coverageTest Fixtures
tests/fixtures/scenarios/locals-deep-import-chain/- Tests file-scoped locals across deep import chainstests/fixtures/scenarios/locals-logical-names/- Tests logical stack name resolutiontests/fixtures/scenarios/locals-component-level/- Tests component-level locals with inheritanceDocumentation
website/docs/cli/commands/describe/describe-locals.mdxwebsite/blog/2026-01-06-file-scoped-locals-fix.mdxdocs/prd/file-scoped-locals.mdreferences
Summary by CodeRabbit
New Features
Bug Fixes
Documentation
Tests
UX
✏️ Tip: You can customize this high-level summary in your review settings.