-
-
Notifications
You must be signed in to change notification settings - Fork 135
feat: Add global env section to atmos.yaml #1829
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
Add support for a root-level `env` section in atmos.yaml that applies environment variables to all subprocesses spawned by Atmos. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
Dependency Review✅ No vulnerabilities or license issues found.Scanned FilesNone |
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #1829 +/- ##
==========================================
+ Coverage 72.13% 72.21% +0.08%
==========================================
Files 475 476 +1
Lines 45713 45802 +89
==========================================
+ Hits 32974 33077 +103
+ Misses 10118 10104 -14
Partials 2621 2621
Flags with carried forward coverage won't be shown. Click here to find out more.
🚀 New features to boost your workflow:
|
|
Warning Rate limit exceeded@osterman has exceeded the limit for the number of commits or files that can be reviewed per hour. Please wait 23 minutes and 51 seconds before requesting another review. ⌛ How to resolve this issue?After the wait time has elapsed, a review can be triggered using the We recommend that you space out your commits to avoid hitting the rate limit. 🚦 How do rate limits work?CodeRabbit enforces hourly rate limits for each developer per organization. Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout. Please see our FAQ for further information. 📒 Files selected for processing (6)
📝 WalkthroughWalkthroughAdds a new pkg/env package and wires Atmos global env (from atmos.yaml) into subprocess environments across commands, workflows, and component execution paths, implementing consistent merge/precedence logic (system < global < component), plus CLI command to emit envs, case-preservation support, tests, fixtures, and docs. Changes
Sequence Diagram(s)sequenceDiagram
participant Sys as System Env
participant Glob as Global Config (atmos.yaml)
participant Cmp as Stack/Component Env
participant Exec as Atmos Executor
participant Proc as Subprocess (Terraform/Helmfile/Packer/Command)
Exec->>Sys: read os.Environ()
Exec->>Glob: read atmosConfig.Env
Exec->>Exec: baseEnv = MergeGlobalEnv(System, Global)
alt identity provided
Exec->>Exec: identity/env vars override baseEnv
end
Exec->>Cmp: read stack/component env (if any)
Exec->>Exec: finalEnv = MergeSystemEnvWithGlobal(componentEnv, atmosConfig.Env)
Exec->>Proc: spawn subprocess with finalEnv
Proc->>Proc: runs with merged environment (System < Global < Component)
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes
Possibly related PRs
Suggested reviewers
Pre-merge checks and finishing touches❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 1
🧹 Nitpick comments (4)
pkg/env/global.go (1)
13-32: Clarify comment terminology.The comment on line 20-21 says "prepend to base env" but the code actually appends
globalEnvSliceafterbaseEnv(lines 28-29). The later comment (lines 24-26) correctly describes the behavior, but the earlier comment could confuse readers.Consider updating line 20-21 to match the actual behavior:
- // Convert global env map to slice and prepend to base env. - // This ensures global env can be overridden by any subsequent env vars. + // Convert global env map to slice and append to base env. + // This ensures global env can be overridden by subsequent env vars.pkg/env/env_test.go (1)
50-61: TestEnvironToMap relies on real environment.This test depends on the actual process environment, which could be flaky if PATH isn't set. Consider using
t.Setenvto set a known value and verify it appears in the result for deterministic testing. Based on learnings, tests should prefert.Setenvfor environment variable setup.func TestEnvironToMap(t *testing.T) { - // This test verifies the function works with the real environment. - result := EnvironToMap() - - // Should have at least some environment variables. - assert.NotEmpty(t, result, "Environment should not be empty") - - // PATH should typically exist. - if path, ok := result["PATH"]; ok { - assert.NotEmpty(t, path, "PATH should not be empty") - } + // Set a known env var for deterministic testing. + t.Setenv("TEST_ENVIRON_TO_MAP", "test_value") + + result := EnvironToMap() + + // Should have at least some environment variables. + assert.NotEmpty(t, result, "Environment should not be empty") + + // Verify our test variable is present. + assert.Equal(t, "test_value", result["TEST_ENVIRON_TO_MAP"]) }internal/exec/shell_utils.go (2)
538-582: Consider extracting shared logic between mergeEnvVars and mergeEnvVarsWithGlobal.These functions share ~90% of their code. The only difference is applying global env between system and component env. This could be refactored to reduce duplication.
One approach:
func mergeEnvVarsWithGlobal(componentEnvList []string, globalEnv map[string]string) []string { return mergeEnvVarsInternal(componentEnvList, globalEnv) } func mergeEnvVars(componentEnvList []string) []string { return mergeEnvVarsInternal(componentEnvList, nil) } func mergeEnvVarsInternal(componentEnvList []string, globalEnv map[string]string) []string { // single implementation }
611-642: Same duplication pattern in mergeEnvVarsSimpleWithGlobal.Similar to the previous comment -
mergeEnvVarsSimpleandmergeEnvVarsSimpleWithGlobalshare most of their logic.
📜 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 (18)
cmd/auth_exec.go(2 hunks)cmd/cmd_utils.go(3 hunks)internal/exec/shell_utils.go(8 hunks)internal/exec/shell_utils_test.go(1 hunks)internal/exec/stack_processor_process_stacks.go(4 hunks)internal/exec/utils.go(2 hunks)internal/exec/validate_component.go(2 hunks)internal/exec/workflow_utils.go(3 hunks)pkg/env/env.go(7 hunks)pkg/env/env_test.go(4 hunks)pkg/env/global.go(1 hunks)pkg/env/global_test.go(1 hunks)pkg/schema/schema.go(1 hunks)tests/fixtures/components/terraform/env-example/main.tf(1 hunks)tests/fixtures/scenarios/global-env/atmos.yaml(1 hunks)tests/fixtures/scenarios/global-env/stacks/deploy/test.yaml(1 hunks)tests/testhelpers/atmos_runner.go(2 hunks)website/blog/2025-12-02-global-env-section.mdx(1 hunks)
🧰 Additional context used
📓 Path-based instructions (5)
**/*.go
📄 CodeRabbit inference engine (CLAUDE.md)
**/*.go: Use functional options pattern to avoid functions with many parameters. Define Option functions that modify a Config struct and pass variadic options to New functions.
Use context.Context for cancellation signals, deadlines/timeouts, and request-scoped values (trace IDs). Context should be first parameter in functions that accept it. DO NOT use context for configuration, dependencies, or avoiding proper function parameters.
All comments must end with periods. This is enforced by the godot linter.
NEVER delete existing comments without a very strong reason. Preserve helpful comments, update them to match code changes, refactor for clarity, and add context when modifying code. Only remove factually incorrect, duplicated, or outdated comments.
Organize imports in three groups separated by blank lines (Go stdlib, 3rd-party excluding cloudposse/atmos, Atmos packages), sorted alphabetically. Maintain aliases: cfg, log, u, errUtils.
Add defer perf.Track(atmosConfig, "pkg.FuncName")() + blank line to all public functions. Use nil if no atmosConfig parameter.
All errors MUST be wrapped using static errors defined in errors/errors.go. Use errors.Join for combining multiple errors, fmt.Errorf with %w for adding string context, error builder for complex errors, and errors.Is() for error checking. NEVER use dynamic errors directly.
Use go.uber.org/mock/mockgen with //go:generate directives for mock generation. Never create manual mocks.
Use viper.BindEnv with ATMOS_ prefix for environment variables.
Use colors from pkg/ui/theme/colors.go for theme consistency.
Ensure Linux/macOS/Windows compatibility. Use SDKs over binaries. Use filepath.Join(), not hardcoded path separators.
Small focused files (<600 lines). One cmd/impl per file. Co-locate tests. Never use //revive:disable:file-length-limit.
**/*.go: Use Viper for managing configuration, environment variables, and flags in CLI commands
Use interfaces for external dependencies to facilitate mocking and consider us...
Files:
internal/exec/validate_component.gopkg/schema/schema.gocmd/auth_exec.gointernal/exec/utils.gointernal/exec/workflow_utils.gointernal/exec/stack_processor_process_stacks.gopkg/env/global_test.gotests/testhelpers/atmos_runner.gopkg/env/global.gointernal/exec/shell_utils_test.gopkg/env/env_test.gointernal/exec/shell_utils.gocmd/cmd_utils.gopkg/env/env.go
cmd/**/*.go
📄 CodeRabbit inference engine (CLAUDE.md)
cmd/**/*.go: Use unified flag parsing infrastructure in pkg/flags/. Commands MUST use flags.NewStandardParser() for command-specific flags. NEVER call viper.BindEnv() or viper.BindPFlag() directly outside pkg/flags/ (Forbidigo enforces this).
Telemetry is auto-enabled via RootCmd.ExecuteC(). Non-standard paths use telemetry.CaptureCmd(). Never capture user data.
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/auth_exec.gocmd/cmd_utils.go
website/blog/**/*.mdx
📄 CodeRabbit inference engine (CLAUDE.md)
PRs labeled minor/major MUST include blog post at website/blog/YYYY-MM-DD-feature-name.mdx with YAML front matter, after intro, tags (feature/enhancement/bugfix/contributors), and author (committer's GitHub username).
Files:
website/blog/2025-12-02-global-env-section.mdx
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/2025-12-02-global-env-section.mdx
**/*_test.go
📄 CodeRabbit inference engine (CLAUDE.md)
**/*_test.go: Prefer unit tests with mocks over integration tests. Use interfaces + dependency injection for testability. Generate mocks with go.uber.org/mock/mockgen. Use table-driven tests for comprehensive coverage. Target >80% code coverage.
Test behavior, not implementation. Never test stub functions. Avoid tautological tests. Make code testable with DI to avoid os.Exit and external systems. Use assert.ErrorIs(err, ErrSentinel) for stdlib/our errors.
**/*_test.go: Every new feature must include comprehensive unit tests targeting >80% code coverage for all packages
Use table-driven tests for testing multiple scenarios in Go
Include integration tests for command flows and test CLI end-to-end when possible with test fixtures
Files:
pkg/env/global_test.gointernal/exec/shell_utils_test.gopkg/env/env_test.go
🧠 Learnings (64)
📓 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: 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.
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.
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.
Learnt from: aknysh
Repo: cloudposse/atmos PR: 0
File: :0-0
Timestamp: 2025-01-19T22:30:27.600Z
Learning: The Atmos YAML function `!env` is used to retrieve environment variables and assign them to sections in stack manifests. It supports both simple types (string, number, boolean) and complex types (JSON-encoded lists, maps, objects).
Learnt from: Benbentwo
Repo: cloudposse/atmos PR: 1475
File: pkg/auth/providers/github/oidc.go:96-100
Timestamp: 2025-09-10T17:34:52.568Z
Learning: The ATMOS_ environment variable binding guideline applies to Atmos configuration variables, not external service-required environment variables like GitHub Actions OIDC variables (GITHUB_ACTIONS, ACTIONS_ID_TOKEN_*) which must use their standard names.
Learnt from: osterman
Repo: cloudposse/atmos PR: 1433
File: cmd/theme_list.go:33-36
Timestamp: 2025-08-29T20:57:35.423Z
Learning: In the Atmos codebase, avoid using viper.SetEnvPrefix("ATMOS") with viper.AutomaticEnv() because canonical environment variable names are not exclusive to Atmos and could cause conflicts. Instead, use selective environment variable binding through the setEnv function in pkg/config/load.go with bindEnv(v, "config.key", "ENV_VAR_NAME") for specific environment variables.
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-24T17:35:20.297Z
Learning: Applies to **/*.go : Use viper.BindEnv with ATMOS_ prefix for environment variables.
Learnt from: osterman
Repo: cloudposse/atmos PR: 1466
File: website/docs/cli/commands/toolchain/usage.mdx:117-121
Timestamp: 2025-09-08T01:25:44.958Z
Learning: The atmos toolchain has been updated to follow XDG Base Directory Specification with helper functions GetXDGCacheDir() and GetXDGTempCacheDir() in toolchain/xdg_cache.go, using XDG_CACHE_HOME when set and falling back to ~/.cache/atmos-toolchain, making it consistent with atmos core's XDG compliance.
Learnt from: osterman
Repo: cloudposse/atmos PR: 1202
File: pkg/utils/yaml_func_exec.go:104-104
Timestamp: 2025-04-23T15:02:50.246Z
Learning: In the Atmos codebase, direct calls to `os.Getenv` should be avoided. Instead, use `viper.BindEnv` for environment variable access. This provides a consistent approach to configuration management across the codebase.
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.
📚 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/validate_component.gointernal/exec/stack_processor_process_stacks.go
📚 Learning: 2025-04-23T15:02:50.246Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 1202
File: pkg/utils/yaml_func_exec.go:104-104
Timestamp: 2025-04-23T15:02:50.246Z
Learning: In the Atmos codebase, direct calls to `os.Getenv` should be avoided. Instead, use `viper.BindEnv` for environment variable access. This provides a consistent approach to configuration management across the codebase.
Applied to files:
internal/exec/validate_component.gocmd/auth_exec.gointernal/exec/utils.gointernal/exec/workflow_utils.gointernal/exec/stack_processor_process_stacks.gotests/testhelpers/atmos_runner.gopkg/env/global.gopkg/env/env_test.gointernal/exec/shell_utils.gocmd/cmd_utils.gopkg/env/env.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/validate_component.gopkg/schema/schema.gocmd/auth_exec.gotests/fixtures/scenarios/global-env/atmos.yamlinternal/exec/utils.gointernal/exec/workflow_utils.gointernal/exec/stack_processor_process_stacks.gowebsite/blog/2025-12-02-global-env-section.mdxpkg/env/global_test.gotests/testhelpers/atmos_runner.gopkg/env/global.gointernal/exec/shell_utils_test.gointernal/exec/shell_utils.gotests/fixtures/scenarios/global-env/stacks/deploy/test.yamlcmd/cmd_utils.gopkg/env/env.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/validate_component.gocmd/auth_exec.gointernal/exec/utils.gotests/testhelpers/atmos_runner.gopkg/env/env_test.gointernal/exec/shell_utils.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/validate_component.gocmd/auth_exec.gointernal/exec/utils.gointernal/exec/workflow_utils.gointernal/exec/stack_processor_process_stacks.gotests/testhelpers/atmos_runner.gointernal/exec/shell_utils_test.gointernal/exec/shell_utils.gocmd/cmd_utils.go
📚 Learning: 2024-12-11T18:40:12.808Z
Learnt from: Listener430
Repo: cloudposse/atmos PR: 844
File: cmd/helmfile.go:37-37
Timestamp: 2024-12-11T18:40:12.808Z
Learning: In the atmos project, `cliConfig` is initialized within the `cmd` package in `root.go` and can be used in other command files.
Applied to files:
internal/exec/validate_component.gocmd/auth_exec.gointernal/exec/utils.gointernal/exec/workflow_utils.gointernal/exec/stack_processor_process_stacks.gotests/testhelpers/atmos_runner.gointernal/exec/shell_utils.gocmd/cmd_utils.go
📚 Learning: 2025-08-29T20:57:35.423Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 1433
File: cmd/theme_list.go:33-36
Timestamp: 2025-08-29T20:57:35.423Z
Learning: In the Atmos codebase, avoid using viper.SetEnvPrefix("ATMOS") with viper.AutomaticEnv() because canonical environment variable names are not exclusive to Atmos and could cause conflicts. Instead, use selective environment variable binding through the setEnv function in pkg/config/load.go with bindEnv(v, "config.key", "ENV_VAR_NAME") for specific environment variables.
Applied to files:
internal/exec/validate_component.gopkg/schema/schema.gocmd/auth_exec.gotests/fixtures/scenarios/global-env/atmos.yamlinternal/exec/utils.gointernal/exec/workflow_utils.gointernal/exec/stack_processor_process_stacks.gowebsite/blog/2025-12-02-global-env-section.mdxpkg/env/global_test.gotests/testhelpers/atmos_runner.gopkg/env/global.gopkg/env/env_test.gointernal/exec/shell_utils.gocmd/cmd_utils.gopkg/env/env.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/validate_component.gopkg/schema/schema.gocmd/auth_exec.gointernal/exec/utils.gointernal/exec/workflow_utils.gointernal/exec/stack_processor_process_stacks.gotests/testhelpers/atmos_runner.gointernal/exec/shell_utils.gocmd/cmd_utils.go
📚 Learning: 2025-11-24T17:35:20.297Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-24T17:35:20.297Z
Learning: Applies to **/*.go : Organize imports in three groups separated by blank lines (Go stdlib, 3rd-party excluding cloudposse/atmos, Atmos packages), sorted alphabetically. Maintain aliases: cfg, log, u, errUtils.
Applied to files:
internal/exec/validate_component.gocmd/auth_exec.gointernal/exec/workflow_utils.gointernal/exec/stack_processor_process_stacks.gointernal/exec/shell_utils.gocmd/cmd_utils.go
📚 Learning: 2025-11-09T19:06:58.470Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 1752
File: pkg/profile/list/formatter_table.go:27-29
Timestamp: 2025-11-09T19:06:58.470Z
Learning: In the cloudposse/atmos repository, performance tracking with `defer perf.Track()` is enforced on all functions via linting, including high-frequency utility functions, formatters, and renderers. This is a repository-wide policy to maintain consistency and avoid making case-by-case judgment calls about which functions should have profiling.
Applied to files:
internal/exec/validate_component.gointernal/exec/utils.gointernal/exec/workflow_utils.gocmd/cmd_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/validate_component.gocmd/auth_exec.go
📚 Learning: 2025-02-06T13:38:07.216Z
Learnt from: Listener430
Repo: cloudposse/atmos PR: 984
File: internal/exec/copy_glob.go:0-0
Timestamp: 2025-02-06T13:38:07.216Z
Learning: The `u.LogTrace` function in the `cloudposse/atmos` repository accepts `atmosConfig` as its first parameter, followed by the message string.
Applied to files:
internal/exec/validate_component.go
📚 Learning: 2025-11-24T17:35:20.297Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-24T17:35:20.297Z
Learning: Applies to **/*.go : Use viper.BindEnv with ATMOS_ prefix for environment variables.
Applied to files:
pkg/schema/schema.gocmd/auth_exec.gotests/fixtures/components/terraform/env-example/main.tftests/fixtures/scenarios/global-env/atmos.yamlinternal/exec/utils.gointernal/exec/workflow_utils.gointernal/exec/stack_processor_process_stacks.gowebsite/blog/2025-12-02-global-env-section.mdxtests/testhelpers/atmos_runner.gopkg/env/global.gointernal/exec/shell_utils.gocmd/cmd_utils.gopkg/env/env.go
📚 Learning: 2025-11-24T17:35:20.297Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-24T17:35:20.297Z
Learning: Applies to **/*.go : Add defer perf.Track(atmosConfig, "pkg.FuncName")() + blank line to all public functions. Use nil if no atmosConfig parameter.
Applied to files:
pkg/schema/schema.gointernal/exec/workflow_utils.gopkg/env/global.gocmd/cmd_utils.go
📚 Learning: 2024-12-07T16:16:13.038Z
Learnt from: Listener430
Repo: cloudposse/atmos PR: 825
File: internal/exec/helmfile_generate_varfile.go:28-31
Timestamp: 2024-12-07T16:16:13.038Z
Learning: In `internal/exec/helmfile_generate_varfile.go`, the `--help` command (`./atmos helmfile generate varfile --help`) works correctly without requiring stack configurations, and the only change needed was to make `ProcessCommandLineArgs` exportable by capitalizing its name.
Applied to files:
cmd/auth_exec.gointernal/exec/utils.gointernal/exec/stack_processor_process_stacks.gointernal/exec/shell_utils_test.gointernal/exec/shell_utils.go
📚 Learning: 2025-09-29T15:47:10.908Z
Learnt from: aknysh
Repo: cloudposse/atmos PR: 1540
File: internal/exec/terraform_cli_args_utils.go:64-73
Timestamp: 2025-09-29T15:47:10.908Z
Learning: In the Atmos codebase, viper.BindEnv is required for CLI commands in the cmd/ package, but internal utilities can use os.Getenv directly when parsing environment variables for business logic purposes. The requirement to use viper is specific to the CLI interface layer, not all environment variable access throughout the codebase.
Applied to files:
cmd/auth_exec.gopkg/env/global.gopkg/env/env_test.gointernal/exec/shell_utils.gopkg/env/env.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:
cmd/auth_exec.gotests/fixtures/scenarios/global-env/atmos.yamlinternal/exec/utils.gointernal/exec/workflow_utils.gointernal/exec/stack_processor_process_stacks.gowebsite/blog/2025-12-02-global-env-section.mdxpkg/env/global_test.gotests/testhelpers/atmos_runner.gopkg/env/global.gointernal/exec/shell_utils_test.gopkg/env/env_test.gointernal/exec/shell_utils.gotests/fixtures/scenarios/global-env/stacks/deploy/test.yamlcmd/cmd_utils.gopkg/env/env.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:
cmd/auth_exec.gotests/fixtures/scenarios/global-env/atmos.yamlinternal/exec/utils.gointernal/exec/workflow_utils.gointernal/exec/stack_processor_process_stacks.gowebsite/blog/2025-12-02-global-env-section.mdxpkg/env/global_test.gotests/testhelpers/atmos_runner.gopkg/env/global.gointernal/exec/shell_utils_test.gopkg/env/env_test.gointernal/exec/shell_utils.gotests/fixtures/scenarios/global-env/stacks/deploy/test.yamlcmd/cmd_utils.go
📚 Learning: 2025-09-07T18:07:00.549Z
Learnt from: Benbentwo
Repo: cloudposse/atmos PR: 1452
File: cmd/auth_login.go:43-44
Timestamp: 2025-09-07T18:07:00.549Z
Learning: In the atmos project, the identity flag is defined as a persistent flag on the auth root command (cmd/auth.go), making it available to all auth subcommands without needing to be redefined in each individual subcommand.
Applied to files:
cmd/auth_exec.gointernal/exec/workflow_utils.go
📚 Learning: 2024-11-16T17:30:52.893Z
Learnt from: pkbhowmick
Repo: cloudposse/atmos PR: 786
File: internal/exec/shell_utils.go:159-162
Timestamp: 2024-11-16T17:30:52.893Z
Learning: For the `atmos terraform shell` command in `internal/exec/shell_utils.go`, input validation for the custom shell prompt is not required, as users will use this as a CLI tool and any issues will impact themselves.
Applied to files:
cmd/auth_exec.gointernal/exec/shell_utils_test.gointernal/exec/shell_utils.go
📚 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/components/terraform/env-example/main.tftests/fixtures/scenarios/global-env/atmos.yamltests/fixtures/scenarios/global-env/stacks/deploy/test.yaml
📚 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:
tests/fixtures/components/terraform/env-example/main.tftests/fixtures/scenarios/global-env/atmos.yamltests/fixtures/scenarios/global-env/stacks/deploy/test.yaml
📚 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:
tests/fixtures/components/terraform/env-example/main.tfinternal/exec/shell_utils.go
📚 Learning: 2025-09-10T17:34:52.568Z
Learnt from: Benbentwo
Repo: cloudposse/atmos PR: 1475
File: pkg/auth/providers/github/oidc.go:96-100
Timestamp: 2025-09-10T17:34:52.568Z
Learning: The ATMOS_ environment variable binding guideline applies to Atmos configuration variables, not external service-required environment variables like GitHub Actions OIDC variables (GITHUB_ACTIONS, ACTIONS_ID_TOKEN_*) which must use their standard names.
Applied to files:
tests/fixtures/components/terraform/env-example/main.tftests/fixtures/scenarios/global-env/atmos.yamlinternal/exec/workflow_utils.gowebsite/blog/2025-12-02-global-env-section.mdx
📚 Learning: 2025-01-19T22:30:27.600Z
Learnt from: aknysh
Repo: cloudposse/atmos PR: 0
File: :0-0
Timestamp: 2025-01-19T22:30:27.600Z
Learning: The Atmos YAML function `!env` is used to retrieve environment variables and assign them to sections in stack manifests. It supports both simple types (string, number, boolean) and complex types (JSON-encoded lists, maps, objects).
Applied to files:
tests/fixtures/components/terraform/env-example/main.tftests/fixtures/scenarios/global-env/atmos.yamlwebsite/blog/2025-12-02-global-env-section.mdxtests/fixtures/scenarios/global-env/stacks/deploy/test.yaml
📚 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/global-env/atmos.yamlwebsite/blog/2025-12-02-global-env-section.mdxtests/fixtures/scenarios/global-env/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/global-env/atmos.yamltests/fixtures/scenarios/global-env/stacks/deploy/test.yaml
📚 Learning: 2025-01-25T03:51:57.689Z
Learnt from: Listener430
Repo: cloudposse/atmos PR: 934
File: tests/fixtures/scenarios/docs-generate/README.md.gotmpl:99-118
Timestamp: 2025-01-25T03:51:57.689Z
Learning: For the cloudposse/atmos repository, changes to template contents should be handled in dedicated PRs and are typically considered out of scope for PRs focused on other objectives.
Applied to files:
tests/fixtures/scenarios/global-env/atmos.yamlwebsite/blog/2025-12-02-global-env-section.mdx
📚 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/fixtures/scenarios/global-env/atmos.yamlpkg/env/global_test.gotests/testhelpers/atmos_runner.gointernal/exec/shell_utils_test.gopkg/env/env_test.gointernal/exec/shell_utils.gotests/fixtures/scenarios/global-env/stacks/deploy/test.yamlcmd/cmd_utils.go
📚 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/global-env/atmos.yaml
📚 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/utils.gointernal/exec/stack_processor_process_stacks.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/utils.go
📚 Learning: 2024-11-19T23:00:45.899Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 795
File: internal/exec/stack_processor_utils.go:378-386
Timestamp: 2024-11-19T23:00:45.899Z
Learning: In the `ProcessYAMLConfigFile` function within `internal/exec/stack_processor_utils.go`, directory traversal in stack imports is acceptable and should not be restricted.
Applied to files:
internal/exec/utils.gointernal/exec/stack_processor_process_stacks.go
📚 Learning: 2025-05-22T15:42:10.906Z
Learnt from: aknysh
Repo: cloudposse/atmos PR: 1261
File: internal/exec/utils.go:639-640
Timestamp: 2025-05-22T15:42:10.906Z
Learning: In the Atmos codebase, when appending slices with `args := append(configAndStacksInfo.CliArgs, configAndStacksInfo.AdditionalArgsAndFlags...)`, it's intentional that the result is not stored back in the original slice. This pattern is used when the merged result serves a different purpose than the original slices, such as when creating a filtered version for component section assignments.
Applied to files:
internal/exec/utils.gopkg/env/global_test.gointernal/exec/shell_utils.go
📚 Learning: 2025-06-02T14:12:02.710Z
Learnt from: milldr
Repo: cloudposse/atmos PR: 1229
File: internal/exec/workflow_test.go:0-0
Timestamp: 2025-06-02T14:12:02.710Z
Learning: In the atmos codebase, workflow error handling was refactored to use `PrintErrorMarkdown` followed by returning specific error variables (like `ErrWorkflowNoSteps`, `ErrInvalidFromStep`, `ErrInvalidWorkflowStepType`, `ErrWorkflowStepFailed`) instead of `PrintErrorMarkdownAndExit`. This pattern allows proper error testing without the function terminating the process with `os.Exit`, enabling unit tests to assert on error conditions while maintaining excellent user-facing error formatting.
Applied to files:
internal/exec/workflow_utils.go
📚 Learning: 2025-09-08T01:25:44.958Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 1466
File: website/docs/cli/commands/toolchain/usage.mdx:117-121
Timestamp: 2025-09-08T01:25:44.958Z
Learning: XDG Base Directory Specification compliance implementation for atmos toolchain is complete: created toolchain/xdg_cache.go with GetXDGCacheDir() and GetXDGTempCacheDir() functions, updated toolchain/installer.go and cmd/toolchain_clean.go to use these XDG helpers, and changed all cache paths from hardcoded ~/.cache/tools-cache to XDG-compliant ${XDG_CACHE_HOME}/atmos-toolchain (or ~/.cache/atmos-toolchain fallback).
Applied to files:
internal/exec/workflow_utils.gointernal/exec/shell_utils.go
📚 Learning: 2025-05-30T03:21:37.197Z
Learnt from: aknysh
Repo: cloudposse/atmos PR: 1274
File: go.mod:63-63
Timestamp: 2025-05-30T03:21:37.197Z
Learning: The redis dependency (github.com/redis/go-redis/v9) in the atmos project is only used in tests, not in production code.
Applied to files:
internal/exec/workflow_utils.gocmd/cmd_utils.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/workflow_utils.gointernal/exec/stack_processor_process_stacks.gointernal/exec/shell_utils_test.gocmd/cmd_utils.go
📚 Learning: 2025-09-13T16:39:20.007Z
Learnt from: samtholiya
Repo: cloudposse/atmos PR: 1466
File: cmd/markdown/atmos_toolchain_aliases.md:2-4
Timestamp: 2025-09-13T16:39:20.007Z
Learning: In the cloudposse/atmos repository, CLI documentation files in cmd/markdown/ follow a specific format that uses " $ atmos command" (with leading space and dollar sign prompt) in code blocks. This is the established project convention and should not be changed to comply with standard markdownlint rules MD040 and MD014.
Applied to files:
website/blog/2025-12-02-global-env-section.mdx
📚 Learning: 2025-10-07T00:25:16.333Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 1498
File: website/src/components/Screengrabs/atmos-terraform-metadata--help.html:25-55
Timestamp: 2025-10-07T00:25:16.333Z
Learning: In Atmos CLI, subcommands inherit flags from their parent commands via Cobra's command inheritance. For example, `atmos terraform metadata --help` shows `--affected` and related flags inherited from the parent `terraform` command (defined in cmd/terraform.go), even though the metadata subcommand doesn't explicitly define these flags. This is expected Cobra behavior and auto-generated help screengrabs accurately reflect this inheritance.
Applied to files:
website/blog/2025-12-02-global-env-section.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 : Use table-driven tests for testing multiple scenarios in Go
Applied to files:
pkg/env/global_test.gopkg/env/env_test.go
📚 Learning: 2025-11-24T17:35:37.209Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: .cursor/rules/atmos-rules.mdc:0-0
Timestamp: 2025-11-24T17:35:37.209Z
Learning: Applies to **/*_test.go : Include integration tests for command flows and test CLI end-to-end when possible with test fixtures
Applied to files:
pkg/env/global_test.gopkg/env/env_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:
pkg/env/global_test.gopkg/env/env_test.go
📚 Learning: 2025-11-24T17:35:20.297Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-24T17:35:20.297Z
Learning: Applies to **/*_test.go : Test behavior, not implementation. Never test stub functions. Avoid tautological tests. Make code testable with DI to avoid os.Exit and external systems. Use assert.ErrorIs(err, ErrSentinel) for stdlib/our errors.
Applied to files:
pkg/env/global_test.gopkg/env/env_test.go
📚 Learning: 2025-11-24T17:35:20.297Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-24T17:35:20.297Z
Learning: Applies to **/*_test.go : Prefer unit tests with mocks over integration tests. Use interfaces + dependency injection for testability. Generate mocks with go.uber.org/mock/mockgen. Use table-driven tests for comprehensive coverage. Target >80% code coverage.
Applied to files:
pkg/env/global_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 : Support configuration via files, environment variables, and flags following the precedence order: flags > environment variables > config file > defaults
Applied to files:
pkg/env/global_test.gopkg/env/global.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:
pkg/env/global_test.go
📚 Learning: 2025-11-24T17:35:20.297Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-24T17:35:20.297Z
Learning: Applies to internal/exec/template_funcs.go : New configs support Go templating with FuncMap() from internal/exec/template_funcs.go. Implement template functions in internal/exec/template_funcs.go, register them, add tests, and update documentation.
Applied to files:
pkg/env/global_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:
pkg/env/global_test.gotests/testhelpers/atmos_runner.gointernal/exec/shell_utils_test.gopkg/env/env_test.go
📚 Learning: 2025-09-08T01:25:44.958Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 1466
File: website/docs/cli/commands/toolchain/usage.mdx:117-121
Timestamp: 2025-09-08T01:25:44.958Z
Learning: The atmos toolchain XDG compliance implementation is complete with GetXDGCacheDir() and GetXDGTempCacheDir() functions in toolchain/xdg_cache.go, updated installer.go and toolchain_clean.go to use these helpers, and changed cache paths from ~/.cache/tools-cache to ${XDG_CACHE_HOME}/atmos-toolchain (or ~/.cache/atmos-toolchain when XDG_CACHE_HOME is not set).
Applied to files:
tests/testhelpers/atmos_runner.go
📚 Learning: 2025-09-08T01:25:44.958Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 1466
File: website/docs/cli/commands/toolchain/usage.mdx:117-121
Timestamp: 2025-09-08T01:25:44.958Z
Learning: The atmos toolchain has been updated to follow XDG Base Directory Specification with helper functions GetXDGCacheDir() and GetXDGTempCacheDir() in toolchain/xdg_cache.go, using XDG_CACHE_HOME when set and falling back to ~/.cache/atmos-toolchain, making it consistent with atmos core's XDG compliance.
Applied to files:
tests/testhelpers/atmos_runner.gointernal/exec/shell_utils.gocmd/cmd_utils.go
📚 Learning: 2024-10-28T01:51:30.811Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 727
File: internal/exec/terraform_clean.go:329-332
Timestamp: 2024-10-28T01:51:30.811Z
Learning: In the Atmos Go code, when deleting directories or handling file paths (e.g., in `terraform_clean.go`), always resolve the absolute path using `filepath.Abs` and use the logger `u.LogWarning` for logging messages instead of using `fmt.Printf`.
Applied to files:
tests/testhelpers/atmos_runner.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:
tests/testhelpers/atmos_runner.go
📚 Learning: 2025-11-24T17:35:20.297Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-24T17:35:20.297Z
Learning: Applies to **/*.go : Ensure Linux/macOS/Windows compatibility. Use SDKs over binaries. Use filepath.Join(), not hardcoded path separators.
Applied to files:
tests/testhelpers/atmos_runner.gopkg/env/env_test.gopkg/env/env.go
📚 Learning: 2025-11-24T17:35:37.209Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: .cursor/rules/atmos-rules.mdc:0-0
Timestamp: 2025-11-24T17:35:37.209Z
Learning: Applies to **/*.go : Use Viper for managing configuration, environment variables, and flags in CLI commands
Applied to files:
pkg/env/global.gopkg/env/env_test.gointernal/exec/shell_utils.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/shell_utils_test.go
📚 Learning: 2025-04-10T20:48:22.687Z
Learnt from: samtholiya
Repo: cloudposse/atmos PR: 1147
File: pkg/config/load.go:0-0
Timestamp: 2025-04-10T20:48:22.687Z
Learning: In the `bindEnv` function in `pkg/config/load.go`, panic is used deliberately instead of returning errors because errors from `BindEnv` would only occur due to developer mistakes. Using panic helps with early detection of these developer errors during initialization.
Applied to files:
pkg/env/env_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:
pkg/env/env_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:
pkg/env/env_test.go
📚 Learning: 2024-12-25T20:28:47.526Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 887
File: internal/exec/stack_processor_utils.go:380-380
Timestamp: 2024-12-25T20:28:47.526Z
Learning: Windows path handling often requires `filepath.Join` to ensure correct separators and comparisons. Insufficient tests can break cross-platform compatibility, so migrating from `path.Join` to `filepath.Join` needs thorough testing on Windows before merging.
Applied to files:
pkg/env/env_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:
pkg/env/env_test.go
📚 Learning: 2025-09-23T04:43:31.857Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 1430
File: pkg/config/config.go:98-107
Timestamp: 2025-09-23T04:43:31.857Z
Learning: In the Atmos codebase, NO_PAGER environment variable handling is intentionally kept as direct os.Getenv() access in pkg/config/config.go rather than using Viper binding, because adding no_pager to the config file would be confusing for users. This is an acknowledged exception to the normal Viper binding pattern for environment variables.
Applied to files:
internal/exec/shell_utils.go
📚 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/global-env/stacks/deploy/test.yaml
🧬 Code graph analysis (8)
internal/exec/validate_component.go (2)
pkg/config/const.go (1)
ProcessEnvSectionName(88-88)pkg/env/env.go (1)
EnvironToMap(39-50)
cmd/auth_exec.go (1)
pkg/env/global.go (1)
MergeGlobalEnv(13-32)
internal/exec/stack_processor_process_stacks.go (1)
pkg/merge/merge.go (1)
Merge(389-427)
tests/testhelpers/atmos_runner.go (1)
pkg/env/env.go (1)
EnsureBinaryInPath(131-143)
pkg/env/global.go (1)
pkg/perf/perf.go (1)
Track(121-138)
internal/exec/shell_utils.go (2)
pkg/env/global.go (1)
MergeGlobalEnv(13-32)pkg/env/env.go (1)
UpdateEnvVar(147-170)
cmd/cmd_utils.go (2)
pkg/env/global.go (1)
MergeGlobalEnv(13-32)pkg/env/env.go (1)
UpdateEnvVar(147-170)
pkg/env/env.go (1)
pkg/perf/perf.go (1)
Track(121-138)
⏰ Context from checks skipped due to timeout of 900000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
- GitHub Check: Acceptance Tests (windows)
- GitHub Check: Summary
🔇 Additional comments (33)
tests/fixtures/components/terraform/env-example/main.tf (1)
10-13: LGTM!The extended filter pattern correctly captures environment variable prefixes needed to validate global env precedence. The regex alternation is well-formed.
pkg/schema/schema.go (1)
90-90: LGTM!The
Envfield addition is clean and follows the established pattern for optional configuration fields. Themap[string]stringtype is the right choice for environment variables.tests/fixtures/scenarios/global-env/stacks/deploy/test.yaml (1)
1-19: LGTM!Good test fixture. It clearly demonstrates the env precedence hierarchy with appropriate comments. The
OVERRIDE_MEvariable at stack level will validate that stack env overrides global env from atmos.yaml.internal/exec/utils.go (2)
20-20: LGTM!Import follows the established three-group organization pattern.
607-607: LGTM!The switch to
env.ConvertEnvVarscentralizes environment utilities in the dedicatedpkg/envpackage. Good refactor for maintainability.internal/exec/validate_component.go (2)
13-13: LGTM!Import properly placed in the Atmos packages group.
248-248: LGTM!Consistent with the refactor moving environment utilities to
pkg/env. The function provides process environment variables for validation schemas.tests/testhelpers/atmos_runner.go (2)
14-14: LGTM!Import updated to use the centralized env package. The
envpkgalias is clear.
166-166: LGTM!Correctly uses
envpkg.EnsureBinaryInPathfrom the refactored env package. The function ensures the test binary is discoverable in PATH for nested atmos calls.cmd/auth_exec.go (1)
17-17: LGTM! Clean integration of global env.The import and usage of the new env package follow the established patterns. The global environment is correctly merged with the system environment before passing to
PrepareShellEnvironment, ensuring proper precedence where global env can be overridden by identity-provided values.Also applies to: 110-112
tests/fixtures/scenarios/global-env/atmos.yaml (1)
1-27: Test fixture looks good.The fixture appropriately demonstrates the global env feature with clear examples of environment variables that can be overridden at different precedence levels.
internal/exec/workflow_utils.go (1)
21-21: Solid workflow environment integration.The changes correctly merge global env for workflow steps. The fallback to
baseEnvfor non-identity steps (line 200) ensures that even steps without authentication receive the global environment configuration, which is the intended behavior.Also applies to: 163-200
cmd/cmd_utils.go (1)
26-26: Consistent environment handling in custom commands.The migration to the env package utilities ensures custom commands benefit from global env support while maintaining the established precedence rules.
Also applies to: 466-467, 493-493
website/blog/2025-12-02-global-env-section.mdx (1)
1-52: Clear and helpful documentation.The blog post effectively introduces the new global env feature with practical examples and clearly explains the precedence rules. The use cases section helps users understand when to leverage this capability.
internal/exec/stack_processor_process_stacks.go (2)
24-35: Clean helper function.The
convertEnvMapStringToAnyhelper properly handles nil input and provides a clear conversion for the merge operations.
214-216: Consistent precedence across component types.The global env is correctly positioned as the lowest priority in the merge chain for Terraform, Helmfile, and Packer components. The comments clearly document the intent.
Also applies to: 315-316, 372-373
pkg/env/global.go (1)
36-48: Utility functions look solid.Both
ConvertMapToSliceandApplyGlobalEnvToSliceare well-implemented with appropriate nil/empty checks and clear semantics.Also applies to: 54-79
internal/exec/shell_utils_test.go (1)
463-465: Test updated correctly.The test now passes a non-nil
AtmosConfigurationinstance, aligning with the updated function signature forExecAuthShellCommand.pkg/env/env_test.go (3)
13-48: Well-structured table-driven tests for ConvertEnvVars.Good coverage of edge cases: empty map, nil values, "null" string values, and type conversion. Using
assert.ElementsMatchhandles map iteration order correctly.
63-102: Thorough coverage for splitStringAtFirstOccurrence.Edge cases well covered: normal split, value containing separator, no separator, empty value. Table-driven pattern applied correctly.
408-448: TestFindPathIndex covers case-insensitive PATH matching.Good coverage of uppercase, mixed case, lowercase, and missing PATH scenarios. This ensures Windows/Unix compatibility.
pkg/env/global_test.go (4)
10-58: TestMergeGlobalEnv covers key scenarios.Good coverage: empty global env, nil global env, single/multiple vars, empty base. Sorting before comparison handles map iteration order correctly.
60-106: TestConvertMapToSlice handles edge cases well.Covers nil map, empty map, single/multiple entries, empty values, and values with equals signs. This last case is important for env vars like
JAVA_OPTS=-Xmx=512m.
108-161: TestApplyGlobalEnvToSlice validates non-overwriting behavior.Key test case at lines 133-138: existing keys are NOT overwritten. This confirms global env has lower priority than existing (system) env. Good.
163-195: TestGlobalEnvPrecedence validates the priority chain.This integration test confirms: system env → global env → command env, with command env winning when duplicates exist. The shell will use the last occurrence, verified by checking order.
internal/exec/shell_utils.go (4)
53-56: Global env integration in ExecuteShellCommand looks correct.The precedence is properly implemented:
os.Environ()→ global env (viaMergeGlobalEnv) → command-specific env (viaappend). Clear comment explains the priority.
133-135: Using envpkg.UpdateEnvVar for shell env merging.Good refactor to use the centralized utility. This ensures consistent behavior across the codebase.
250-252: Global env added to Terraform shell.Correctly uses
mergeEnvVarsWithGlobalto includeatmosConfig.Env. Comment clearly documents priority.
349-350: Global env added to auth shell.Uses
mergeEnvVarsSimpleWithGlobalappropriately. Consistent with Terraform shell handling.pkg/env/env.go (4)
1-4: Good package documentation.Clear, concise description of the package's purpose. Comments end with periods as required.
52-61: splitStringAtFirstOccurrence is well-implemented.Returns a fixed-size array which is cleaner than variable-length slices. Handles edge cases correctly: no separator returns original string with empty second element.
84-94: Case-insensitive PATH matching for Windows compatibility.Using
strings.EqualFoldhandles Windows where PATH might be "Path". Good cross-platform design.
115-116: Defensive copy when appending to envSlice.Line 115:
append(append([]string{}, envSlice...), ...)creates a new slice to avoid mutating the original. Same pattern on line 169. This is correct defensive programming.
- Fix comment terminology in pkg/env/global.go (prepend -> append) - Improve TestEnvironToMap to use t.Setenv for deterministic testing - Refactor mergeEnvVars functions to reduce code duplication 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
Extract the mergeEnvVars* functions from internal/exec/shell_utils.go to pkg/env/global.go for better code organization and testability. The shell_utils.go now delegates to the new public MergeSystemEnv* functions. Added comprehensive tests for all new functions. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
|
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. |
- Add ConvertMapStringToAny to convert map[string]string to map[string]any - Add EnvironToMapFiltered for filtering env vars by keys and prefixes - Update stack_processor_process_stacks.go to use envpkg.ConvertMapStringToAny - Update terraform_output_utils.go to use envpkg.EnvironToMapFiltered - Add comprehensive tests for new functions 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
Fix substring false positive in EnsureBinaryInPath where
strings.Contains("/usr/local/bin", "/usr/local/b") would
incorrectly match. Now splits PATH by separator and checks
for exact directory match.
Added test case to verify substring paths are not falsely matched.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Adds a Builder type with methods for constructing environment variable
slices using a fluent API:
- NewBuilder(initial) - create builder with optional initial slice
- WithEnv(keyValue) - add raw "KEY=value" string
- WithEnvVar(key, value) - add key and value separately
- WithEnvVarf(key, format, args...) - add with formatted value
- WithEnvMap(map) - add all entries from a map
- Build() - return the constructed slice
Example usage:
env := NewBuilder(os.Environ()).
WithEnvVar("HOME", "/home/user").
WithEnvVarf("ATMOS_SHLVL", "%d", newShellLevel).
Build()
Also fixes linting issues:
- Add perf.Track() to CommandEnvToMap and Builder methods
- Fix appendAssign issues in shell_utils.go and global_test.go
- Reduce nesting complexity in global.go mergeSystemEnvInternal
- Fix godot comment style for const declarations
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Remove thin delegation functions from shell_utils.go: - mergeEnvVars -> envpkg.MergeSystemEnv - mergeEnvVarsWithGlobal -> envpkg.MergeSystemEnvWithGlobal - mergeEnvVarsSimple -> envpkg.MergeSystemEnvSimple - mergeEnvVarsSimpleWithGlobal -> envpkg.MergeSystemEnvSimpleWithGlobal These wrappers added no value - just indirection. Callers now use the env package directly. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
Remove duplicate function from shell_utils.go that duplicated the env package's ConvertMapToSlice functionality. Also removes unused envVarSeparator constant. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
Replace template function examples ({{ env }}, {{ exec }}) with
the preferred YAML functions (!env, !exec) throughout the
CLI env configuration documentation.
YAML functions are the recommended approach for dynamic values
in atmos.yaml and stack manifests.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
The initial Configuration example should demonstrate using !exec to get the GitHub token from the gh CLI, not !env to read GH_TOKEN. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
Use proper YAML function syntax: - !exec command args (not !exec [array]) - !env VAR default (not !env [VAR, default]) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
Remove hallucinated ${HOME} shell expansion syntax that doesn't work in YAML values.
Use static paths instead. Also remove hyperlink from chapter title.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
…bles Adds a new CLI command that outputs environment variables from the `env` section of atmos.yaml in various formats (bash, json, dotenv, github). Key features: - Default bash format for shell eval: `eval $(atmos env)` - GitHub Actions integration with automatic $GITHUB_ENV detection - Works seamlessly with Atmos profiles - Sorted, deterministic output 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
Minimal example demonstrating how to use `atmos env` to export GITHUB_TOKEN for the GitHub Terraform provider. Fetches star count for cloudposse/atmos repository. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
The github_repository data source doesn't export stargazers_count. Updated to use description, html_url, and default_branch instead. Also added stage variable to silence terraform warnings. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
More accurately reflects what the component does since GitHub provider doesn't expose star count. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
Make GitHub CLI installation and authentication steps more explicit. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
… !exec Viper automatically lowercases all YAML map keys, which breaks case-sensitive environment variables like GITHUB_TOKEN (became github_token). This fix adds a generalized case preservation utility that can be used for any config section. Changes: - Add pkg/config/casemap/ package for case-sensitive map key preservation - Update config loading to preserve case for "env" and "auth.identities" paths - Add GetCaseSensitiveMap() method to AtmosConfiguration - Update cmd/env to use case-preserved environment variables - Strip trailing newlines from !exec output to match shell $(cmd) behavior 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 2
🧹 Nitpick comments (7)
examples/demo-env/README.md (2)
17-17: Wrap bare URL in markdown link syntax.Line 17 contains a bare URL that should be wrapped in markdown link format for better rendering and markdown linting compliance.
-2. **Authenticate with GitHub**: +1. **GitHub CLI** - Install from [https://cli.github.com/](https://cli.github.com/) +2. **Authenticate with GitHub**:
54-59: Specify language for output code block.The example output block should specify a language identifier for proper syntax highlighting in markdown renderers.
Example output: -``` +```hcl default_branch = "main"pkg/utils/yaml_func_exec.go (1)
6-7: Trim logic is solid; consider CRLF for Windows compatibility.The newline trimming before JSON unmarshal is a nice touch and matches
$(cmd)behavior, and addingstringsis appropriate. On Windows, though, command output often ends with\r\n, sostrings.TrimRight(res, "\n")may leave a trailing\r. To keep behavior consistent across platforms, consider:res = strings.TrimRight(res, "\r\n")This still only removes trailing newlines but handles CRLF correctly as well.
Also applies to: 28-31
examples/demo-env/components/terraform/github-repo/main.tf (1)
1-3: Consider clarifying GITHUB_TOKEN availability in comments. The inline note abouteval $(atmos env)nicely demonstrates the new feature, but could mention when GITHUB_TOKEN is required (e.g., during terraform plan/apply, or only in CI/dev).Example enhancement:
# GitHub provider uses GITHUB_TOKEN from environment -# Export it with: eval $(atmos env) +# Ensure GITHUB_TOKEN is available in environment (required for terraform apply) +# Export global env with: eval $(atmos env)pkg/schema/schema.go (1)
220-236: Add performance tracking to public method.The GetCaseSensitiveMap method is missing performance tracking. Per coding guidelines, all public functions should include
defer perf.Track().Apply this diff:
func (a *AtmosConfiguration) GetCaseSensitiveMap(path string) map[string]string { + defer perf.Track(a, "schema.GetCaseSensitiveMap")() + var source map[string]string switch path {cmd/env/env.go (2)
47-50: Consider using errors.Join for error wrapping.Per coding guidelines, errors should be wrapped using static errors from
errors/errors.gowitherrors.Join.- return fmt.Errorf("failed to load atmos config: %w", err) + return errors.Join(errUtils.ErrLoadConfig, err)Note: This requires adding
"errors"to stdlib imports and ensuringErrLoadConfigexists in the errors package.
121-145: DRY opportunity for escaping logic.Both
formatBashandformatDotenvuse the same single-quote escaping. Consider extracting to a helper.// escapeSingleQuotes escapes single quotes for shell-safe literals. func escapeSingleQuotes(s string) string { return strings.ReplaceAll(s, "'", "'\\''") }
📜 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/env/env.go(1 hunks)cmd/env/env_test.go(1 hunks)cmd/root.go(1 hunks)demo/screengrabs/demo-stacks.txt(1 hunks)docs/prd/atmos-env-command.md(1 hunks)examples/demo-env/.gitignore(1 hunks)examples/demo-env/README.md(1 hunks)examples/demo-env/atmos.yaml(1 hunks)examples/demo-env/components/terraform/github-repo/main.tf(1 hunks)examples/demo-env/components/terraform/github-repo/outputs.tf(1 hunks)examples/demo-env/components/terraform/github-repo/variables.tf(1 hunks)examples/demo-env/components/terraform/github-repo/versions.tf(1 hunks)examples/demo-env/stacks/deploy/demo.yaml(1 hunks)pkg/config/casemap/casemap.go(1 hunks)pkg/config/casemap/casemap_test.go(1 hunks)pkg/config/load.go(3 hunks)pkg/schema/schema.go(3 hunks)pkg/utils/yaml_func_exec.go(2 hunks)website/docs/cli/commands/env.mdx(1 hunks)
✅ Files skipped from review due to trivial changes (1)
- examples/demo-env/.gitignore
🧰 Additional context used
📓 Path-based instructions (7)
**/*.go
📄 CodeRabbit inference engine (CLAUDE.md)
**/*.go: Use functional options pattern to avoid functions with many parameters. Define Option functions that modify a Config struct and pass variadic options to New functions.
Use context.Context for cancellation signals, deadlines/timeouts, and request-scoped values (trace IDs). Context should be first parameter in functions that accept it. DO NOT use context for configuration, dependencies, or avoiding proper function parameters.
All comments must end with periods. This is enforced by the godot linter.
NEVER delete existing comments without a very strong reason. Preserve helpful comments, update them to match code changes, refactor for clarity, and add context when modifying code. Only remove factually incorrect, duplicated, or outdated comments.
Organize imports in three groups separated by blank lines (Go stdlib, 3rd-party excluding cloudposse/atmos, Atmos packages), sorted alphabetically. Maintain aliases: cfg, log, u, errUtils.
Add defer perf.Track(atmosConfig, "pkg.FuncName")() + blank line to all public functions. Use nil if no atmosConfig parameter.
All errors MUST be wrapped using static errors defined in errors/errors.go. Use errors.Join for combining multiple errors, fmt.Errorf with %w for adding string context, error builder for complex errors, and errors.Is() for error checking. NEVER use dynamic errors directly.
Use go.uber.org/mock/mockgen with //go:generate directives for mock generation. Never create manual mocks.
Use viper.BindEnv with ATMOS_ prefix for environment variables.
Use colors from pkg/ui/theme/colors.go for theme consistency.
Ensure Linux/macOS/Windows compatibility. Use SDKs over binaries. Use filepath.Join(), not hardcoded path separators.
Small focused files (<600 lines). One cmd/impl per file. Co-locate tests. Never use //revive:disable:file-length-limit.
**/*.go: Use Viper for managing configuration, environment variables, and flags in CLI commands
Use interfaces for external dependencies to facilitate mocking and consider us...
Files:
cmd/env/env_test.gopkg/config/casemap/casemap_test.gopkg/schema/schema.gocmd/env/env.gocmd/root.gopkg/config/load.gopkg/utils/yaml_func_exec.gopkg/config/casemap/casemap.go
cmd/**/*.go
📄 CodeRabbit inference engine (CLAUDE.md)
cmd/**/*.go: Use unified flag parsing infrastructure in pkg/flags/. Commands MUST use flags.NewStandardParser() for command-specific flags. NEVER call viper.BindEnv() or viper.BindPFlag() directly outside pkg/flags/ (Forbidigo enforces this).
Telemetry is auto-enabled via RootCmd.ExecuteC(). Non-standard paths use telemetry.CaptureCmd(). Never capture user data.
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/env/env_test.gocmd/env/env.gocmd/root.go
**/*_test.go
📄 CodeRabbit inference engine (CLAUDE.md)
**/*_test.go: Prefer unit tests with mocks over integration tests. Use interfaces + dependency injection for testability. Generate mocks with go.uber.org/mock/mockgen. Use table-driven tests for comprehensive coverage. Target >80% code coverage.
Test behavior, not implementation. Never test stub functions. Avoid tautological tests. Make code testable with DI to avoid os.Exit and external systems. Use assert.ErrorIs(err, ErrSentinel) for stdlib/our errors.
**/*_test.go: Every new feature must include comprehensive unit tests targeting >80% code coverage for all packages
Use table-driven tests for testing multiple scenarios in Go
Include integration tests for command flows and test CLI end-to-end when possible with test fixtures
Files:
cmd/env/env_test.gopkg/config/casemap/casemap_test.go
cmd/**/*_test.go
📄 CodeRabbit inference engine (CLAUDE.md)
ALWAYS use cmd.NewTestKit(t) for cmd package tests to auto-clean RootCmd state (flags, args). Required for any test touching RootCmd.
Files:
cmd/env/env_test.go
docs/prd/**/*.md
📄 CodeRabbit inference engine (CLAUDE.md)
Create PRD documentation in docs/prd/ using kebab-case filenames (e.g., command-registry-pattern.md, error-handling-strategy.md).
Files:
docs/prd/atmos-env-command.md
website/docs/cli/commands/**/*.mdx
📄 CodeRabbit inference engine (CLAUDE.md)
website/docs/cli/commands/**/*.mdx: All commands and flags need Docusaurus documentation in website/docs/cli/commands/. Usefor arguments/flags. Build website after changes: cd website && npm run build.
Use Docusaurus conventions with frontmatter, purpose note, screengrab, usage/examples/arguments/flags sections for CLI command documentation.
Files:
website/docs/cli/commands/env.mdx
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/docs/cli/commands/env.mdx
🧠 Learnings (66)
📓 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: 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.
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.
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.
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: aknysh
Repo: cloudposse/atmos PR: 0
File: :0-0
Timestamp: 2025-01-19T22:30:27.600Z
Learning: The Atmos YAML function `!env` is used to retrieve environment variables and assign them to sections in stack manifests. It supports both simple types (string, number, boolean) and complex types (JSON-encoded lists, maps, objects).
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.
Learnt from: osterman
Repo: cloudposse/atmos PR: 1433
File: cmd/theme_list.go:33-36
Timestamp: 2025-08-29T20:57:35.423Z
Learning: In the Atmos codebase, avoid using viper.SetEnvPrefix("ATMOS") with viper.AutomaticEnv() because canonical environment variable names are not exclusive to Atmos and could cause conflicts. Instead, use selective environment variable binding through the setEnv function in pkg/config/load.go with bindEnv(v, "config.key", "ENV_VAR_NAME") for specific environment variables.
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.
📚 Learning: 2024-11-25T17:17:15.703Z
Learnt from: RoseSecurity
Repo: cloudposse/atmos PR: 797
File: pkg/list/atmos.yaml:213-214
Timestamp: 2024-11-25T17:17:15.703Z
Learning: The file `pkg/list/atmos.yaml` is primarily intended for testing purposes.
Applied to files:
examples/demo-env/atmos.yamldocs/prd/atmos-env-command.mddemo/screengrabs/demo-stacks.txt
📚 Learning: 2024-12-01T00:33:20.298Z
Learnt from: aknysh
Repo: cloudposse/atmos PR: 810
File: examples/tests/stacks/catalog/terraform/template-functions-test2/defaults.yaml:28-32
Timestamp: 2024-12-01T00:33:20.298Z
Learning: In `examples/tests/stacks/catalog/terraform/template-functions-test2/defaults.yaml`, `!exec atmos terraform output` is used in examples to demonstrate its usage, even though `!terraform.output` is the recommended approach according to the documentation.
Applied to files:
examples/demo-env/atmos.yamlexamples/demo-env/stacks/deploy/demo.yamlexamples/demo-env/components/terraform/github-repo/outputs.tfexamples/demo-env/README.mdwebsite/docs/cli/commands/env.mdx
📚 Learning: 2024-12-12T15:17:45.245Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 808
File: examples/demo-atmos.d/atmos.d/tools/helmfile.yml:10-10
Timestamp: 2024-12-12T15:17:45.245Z
Learning: In `examples/demo-atmos.d/atmos.d/tools/helmfile.yml`, when suggesting changes to `kubeconfig_path`, ensure that the values use valid Go template syntax.
Applied to files:
examples/demo-env/atmos.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:
examples/demo-env/atmos.yamlexamples/demo-env/stacks/deploy/demo.yamldemo/screengrabs/demo-stacks.txtexamples/demo-env/components/terraform/github-repo/main.tfexamples/demo-env/README.md
📚 Learning: 2025-09-10T17:34:52.568Z
Learnt from: Benbentwo
Repo: cloudposse/atmos PR: 1475
File: pkg/auth/providers/github/oidc.go:96-100
Timestamp: 2025-09-10T17:34:52.568Z
Learning: The ATMOS_ environment variable binding guideline applies to Atmos configuration variables, not external service-required environment variables like GitHub Actions OIDC variables (GITHUB_ACTIONS, ACTIONS_ID_TOKEN_*) which must use their standard names.
Applied to files:
examples/demo-env/atmos.yamldocs/prd/atmos-env-command.mddemo/screengrabs/demo-stacks.txtexamples/demo-env/components/terraform/github-repo/main.tfexamples/demo-env/README.mdwebsite/docs/cli/commands/env.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:
examples/demo-env/atmos.yamldocs/prd/atmos-env-command.mdexamples/demo-env/README.md
📚 Learning: 2025-09-08T01:25:44.958Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 1466
File: website/docs/cli/commands/toolchain/usage.mdx:117-121
Timestamp: 2025-09-08T01:25:44.958Z
Learning: The atmos toolchain has been updated to follow XDG Base Directory Specification with helper functions GetXDGCacheDir() and GetXDGTempCacheDir() in toolchain/xdg_cache.go, using XDG_CACHE_HOME when set and falling back to ~/.cache/atmos-toolchain, making it consistent with atmos core's XDG compliance.
Applied to files:
examples/demo-env/atmos.yamldemo/screengrabs/demo-stacks.txtpkg/schema/schema.go
📚 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:
examples/demo-env/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:
examples/demo-env/atmos.yamldocs/prd/atmos-env-command.mdpkg/schema/schema.gocmd/env/env.gopkg/config/load.goexamples/demo-env/README.md
📚 Learning: 2025-09-13T16:39:20.007Z
Learnt from: samtholiya
Repo: cloudposse/atmos PR: 1466
File: cmd/markdown/atmos_toolchain_aliases.md:2-4
Timestamp: 2025-09-13T16:39:20.007Z
Learning: In the cloudposse/atmos repository, CLI documentation files in cmd/markdown/ follow a specific format that uses " $ atmos command" (with leading space and dollar sign prompt) in code blocks. This is the established project convention and should not be changed to comply with standard markdownlint rules MD040 and MD014.
Applied to files:
examples/demo-env/atmos.yamldocs/prd/atmos-env-command.mddemo/screengrabs/demo-stacks.txtcmd/env/env.gowebsite/docs/cli/commands/env.mdx
📚 Learning: 2025-10-07T00:25:16.333Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 1498
File: website/src/components/Screengrabs/atmos-terraform-metadata--help.html:25-55
Timestamp: 2025-10-07T00:25:16.333Z
Learning: In Atmos CLI, subcommands inherit flags from their parent commands via Cobra's command inheritance. For example, `atmos terraform metadata --help` shows `--affected` and related flags inherited from the parent `terraform` command (defined in cmd/terraform.go), even though the metadata subcommand doesn't explicitly define these flags. This is expected Cobra behavior and auto-generated help screengrabs accurately reflect this inheritance.
Applied to files:
examples/demo-env/atmos.yamldocs/prd/atmos-env-command.mddemo/screengrabs/demo-stacks.txtcmd/env/env.gocmd/root.gowebsite/docs/cli/commands/env.mdx
📚 Learning: 2025-01-19T22:30:27.600Z
Learnt from: aknysh
Repo: cloudposse/atmos PR: 0
File: :0-0
Timestamp: 2025-01-19T22:30:27.600Z
Learning: The Atmos YAML function `!env` is used to retrieve environment variables and assign them to sections in stack manifests. It supports both simple types (string, number, boolean) and complex types (JSON-encoded lists, maps, objects).
Applied to files:
examples/demo-env/atmos.yamldocs/prd/atmos-env-command.mdexamples/demo-env/README.mdwebsite/docs/cli/commands/env.mdx
📚 Learning: 2025-11-24T17:35:20.297Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-24T17:35:20.297Z
Learning: Applies to **/*.go : Use viper.BindEnv with ATMOS_ prefix for environment variables.
Applied to files:
examples/demo-env/atmos.yamlcmd/env/env.gocmd/root.gopkg/config/load.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:
examples/demo-env/atmos.yamlcmd/env/env_test.godocs/prd/atmos-env-command.mdcmd/root.goexamples/demo-env/README.md
📚 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:
examples/demo-env/atmos.yamldocs/prd/atmos-env-command.mdpkg/schema/schema.gocmd/env/env.gocmd/root.gopkg/config/load.gowebsite/docs/cli/commands/env.mdx
📚 Learning: 2024-12-03T05:29:07.718Z
Learnt from: aknysh
Repo: cloudposse/atmos PR: 810
File: internal/exec/terraform_utils.go:145-146
Timestamp: 2024-12-03T05:29:07.718Z
Learning: In the Atmos project, a 5-minute timeout in the `execTerraformOutput` function is acceptable for retrieving `terraform output` for a component in a stack.
Applied to files:
examples/demo-env/atmos.yamlexamples/demo-env/stacks/deploy/demo.yaml
📚 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/env/env_test.gopkg/config/casemap/casemap_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/env/env_test.gopkg/config/casemap/casemap_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/env/env_test.gopkg/config/casemap/casemap_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:
cmd/env/env_test.go
📚 Learning: 2025-11-24T17:35:20.297Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-24T17:35:20.297Z
Learning: Applies to **/*_test.go : Test behavior, not implementation. Never test stub functions. Avoid tautological tests. Make code testable with DI to avoid os.Exit and external systems. Use assert.ErrorIs(err, ErrSentinel) for stdlib/our errors.
Applied to files:
cmd/env/env_test.gopkg/config/casemap/casemap_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:
cmd/env/env_test.go
📚 Learning: 2025-11-24T17:35:20.297Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-24T17:35:20.297Z
Learning: Applies to **/*.go : Small focused files (<600 lines). One cmd/impl per file. Co-locate tests. Never use //revive:disable:file-length-limit.
Applied to files:
cmd/env/env_test.gopkg/config/casemap/casemap_test.go
📚 Learning: 2025-11-24T17:35:20.297Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-24T17:35:20.297Z
Learning: Applies to internal/exec/template_funcs.go : New configs support Go templating with FuncMap() from internal/exec/template_funcs.go. Implement template functions in internal/exec/template_funcs.go, register them, add tests, and update documentation.
Applied to files:
cmd/env/env_test.gopkg/config/casemap/casemap_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:
cmd/env/env_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:
docs/prd/atmos-env-command.mddemo/screengrabs/demo-stacks.txtcmd/env/env.gocmd/root.gopkg/utils/yaml_func_exec.gowebsite/docs/cli/commands/env.mdx
📚 Learning: 2025-10-10T23:51:36.597Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 1599
File: internal/exec/terraform.go:394-402
Timestamp: 2025-10-10T23:51:36.597Z
Learning: In Atmos (internal/exec/terraform.go), when adding OpenTofu-specific flags like `--var-file` for `init`, do not gate them based on command name (e.g., checking if `info.Command == "tofu"` or `info.Command == "opentofu"`) because command names don't reliably indicate the actual binary being executed (symlinks, aliases). Instead, document the OpenTofu requirement in code comments and documentation, trusting users who enable the feature (e.g., `PassVars`) to ensure their terraform command points to an OpenTofu binary.
Applied to files:
docs/prd/atmos-env-command.mdcmd/env/env.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:
docs/prd/atmos-env-command.mddemo/screengrabs/demo-stacks.txtwebsite/docs/cli/commands/env.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:
docs/prd/atmos-env-command.mddemo/screengrabs/demo-stacks.txtwebsite/docs/cli/commands/env.mdx
📚 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/atmos-env-command.mdcmd/env/env.gowebsite/docs/cli/commands/env.mdx
📚 Learning: 2025-11-24T17:35:20.297Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-24T17:35:20.297Z
Learning: Applies to **/*_test.go : Prefer unit tests with mocks over integration tests. Use interfaces + dependency injection for testability. Generate mocks with go.uber.org/mock/mockgen. Use table-driven tests for comprehensive coverage. Target >80% code coverage.
Applied to files:
pkg/config/casemap/casemap_test.go
📚 Learning: 2025-09-29T02:20:11.636Z
Learnt from: aknysh
Repo: cloudposse/atmos PR: 1540
File: internal/exec/validate_component.go:117-118
Timestamp: 2025-09-29T02:20:11.636Z
Learning: The ValidateComponent function in internal/exec/validate_component.go had its componentSection parameter type refined from `any` to `map[string]any` without adding new parameters. This is a type safety improvement, not a signature change requiring call site updates.
Applied to files:
pkg/config/casemap/casemap_test.gopkg/config/load.gopkg/config/casemap/casemap.go
📚 Learning: 2024-10-27T16:59:26.187Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 729
File: internal/exec/help.go:48-51
Timestamp: 2024-10-27T16:59:26.187Z
Learning: In the Atmos CLI help messages, when providing examples that include the version number, use the actual version variable (e.g., `version.Version`) instead of placeholders like `<version>`.
Applied to files:
demo/screengrabs/demo-stacks.txt
📚 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:
demo/screengrabs/demo-stacks.txt
📚 Learning: 2025-02-18T13:13:11.497Z
Learnt from: samtholiya
Repo: cloudposse/atmos PR: 1068
File: tests/snapshots/TestCLICommands_atmos_terraform_help.stdout.golden:59-64
Timestamp: 2025-02-18T13:13:11.497Z
Learning: For Atmos CLI help text, angle brackets in command examples and flag descriptions should be escaped using HTML entities (e.g., `<component>`) rather than converted to backticks or other markdown formatting.
Applied to files:
demo/screengrabs/demo-stacks.txt
📚 Learning: 2025-01-16T11:41:35.531Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 942
File: internal/exec/describe_affected_utils.go:802-807
Timestamp: 2025-01-16T11:41:35.531Z
Learning: When checking if a component is enabled in Atmos, use standardized helper function that includes logging. The function should check the `enabled` field in the component's metadata section and log a trace message when skipping disabled components.
Applied to files:
demo/screengrabs/demo-stacks.txt
📚 Learning: 2024-10-23T21:36:40.262Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 740
File: cmd/cmd_utils.go:340-359
Timestamp: 2024-10-23T21:36:40.262Z
Learning: In the Go codebase for Atmos, when reviewing functions like `checkAtmosConfig` in `cmd/cmd_utils.go`, avoid suggesting refactoring to return errors instead of calling `os.Exit` if such changes would significantly increase the scope due to the need to update multiple call sites.
Applied to files:
pkg/schema/schema.gocmd/env/env.gopkg/config/load.gopkg/utils/yaml_func_exec.go
📚 Learning: 2025-08-29T20:57:35.423Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 1433
File: cmd/theme_list.go:33-36
Timestamp: 2025-08-29T20:57:35.423Z
Learning: In the Atmos codebase, avoid using viper.SetEnvPrefix("ATMOS") with viper.AutomaticEnv() because canonical environment variable names are not exclusive to Atmos and could cause conflicts. Instead, use selective environment variable binding through the setEnv function in pkg/config/load.go with bindEnv(v, "config.key", "ENV_VAR_NAME") for specific environment variables.
Applied to files:
pkg/schema/schema.gocmd/env/env.gocmd/root.gopkg/config/load.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:
pkg/schema/schema.gocmd/root.gopkg/config/load.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:
pkg/schema/schema.go
📚 Learning: 2025-11-24T17:35:20.297Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-24T17:35:20.297Z
Learning: Applies to **/*.go : Organize imports in three groups separated by blank lines (Go stdlib, 3rd-party excluding cloudposse/atmos, Atmos packages), sorted alphabetically. Maintain aliases: cfg, log, u, errUtils.
Applied to files:
pkg/schema/schema.gocmd/env/env.gocmd/root.gopkg/config/load.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:
pkg/schema/schema.gopkg/config/load.go
📚 Learning: 2024-10-20T13:12:46.499Z
Learnt from: haitham911
Repo: cloudposse/atmos PR: 736
File: pkg/config/const.go:6-6
Timestamp: 2024-10-20T13:12:46.499Z
Learning: In `cmd/cmd_utils.go`, it's acceptable to have hardcoded references to `atmos.yaml` in logs, and it's not necessary to update them to use the `CliConfigFileName` constant.
Applied to files:
pkg/schema/schema.gocmd/env/env.gopkg/config/load.go
📚 Learning: 2025-11-24T17:35:20.297Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-24T17:35:20.297Z
Learning: Applies to **/*.go : Add defer perf.Track(atmosConfig, "pkg.FuncName")() + blank line to all public functions. Use nil if no atmosConfig parameter.
Applied to files:
pkg/schema/schema.gopkg/config/load.gopkg/utils/yaml_func_exec.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:
pkg/schema/schema.gopkg/config/load.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:
pkg/schema/schema.gopkg/config/load.go
📚 Learning: 2025-11-24T17:35:37.209Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: .cursor/rules/atmos-rules.mdc:0-0
Timestamp: 2025-11-24T17:35:37.209Z
Learning: Applies to **/*.go : Use Viper for managing configuration, environment variables, and flags in CLI commands
Applied to files:
pkg/schema/schema.gopkg/config/casemap/casemap.go
📚 Learning: 2025-11-24T17:35:37.209Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: .cursor/rules/atmos-rules.mdc:0-0
Timestamp: 2025-11-24T17:35:37.209Z
Learning: Applies to cmd/**/*.go : Provide comprehensive help text for all commands and flags, include examples in command help, and follow Go's documentation conventions in Cobra command definitions
Applied to files:
cmd/env/env.go
📚 Learning: 2025-09-29T15:47:10.908Z
Learnt from: aknysh
Repo: cloudposse/atmos PR: 1540
File: internal/exec/terraform_cli_args_utils.go:64-73
Timestamp: 2025-09-29T15:47:10.908Z
Learning: In the Atmos codebase, viper.BindEnv is required for CLI commands in the cmd/ package, but internal utilities can use os.Getenv directly when parsing environment variables for business logic purposes. The requirement to use viper is specific to the CLI interface layer, not all environment variable access throughout the codebase.
Applied to files:
cmd/env/env.gocmd/root.go
📚 Learning: 2025-01-30T19:30:59.120Z
Learnt from: samtholiya
Repo: cloudposse/atmos PR: 959
File: cmd/workflow.go:74-74
Timestamp: 2025-01-30T19:30:59.120Z
Learning: Error handling for `cmd.Usage()` is not required in the Atmos CLI codebase, as confirmed by the maintainer.
Applied to files:
cmd/env/env.gocmd/root.go
📚 Learning: 2025-04-23T15:02:50.246Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 1202
File: pkg/utils/yaml_func_exec.go:104-104
Timestamp: 2025-04-23T15:02:50.246Z
Learning: In the Atmos codebase, direct calls to `os.Getenv` should be avoided. Instead, use `viper.BindEnv` for environment variable access. This provides a consistent approach to configuration management across the codebase.
Applied to files:
cmd/env/env.gopkg/config/load.go
📚 Learning: 2025-11-24T17:35:20.297Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-24T17:35:20.297Z
Learning: When adding new CLI commands: 1) Create cmd/[command]/ with CommandProvider interface, 2) Add blank import to cmd/root.go, 3) Implement in internal/exec/mycommand.go, 4) Add tests in cmd/mycommand/mycommand_test.go, 5) Create Docusaurus docs, 6) Build website.
Applied to files:
cmd/root.go
📚 Learning: 2025-01-09T19:53:29.847Z
Learnt from: Listener430
Repo: cloudposse/atmos PR: 912
File: pkg/config/config.go:91-92
Timestamp: 2025-01-09T19:53:29.847Z
Learning: In the Atmos project, the `core.inject_github_token` configuration is required to be enabled (`true`) by default to support authenticated GitHub requests and help bypass rate limits.
Applied to files:
examples/demo-env/components/terraform/github-repo/main.tfexamples/demo-env/README.md
📚 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:
pkg/config/load.gopkg/utils/yaml_func_exec.go
📚 Learning: 2025-02-06T13:38:07.216Z
Learnt from: Listener430
Repo: cloudposse/atmos PR: 984
File: internal/exec/copy_glob.go:0-0
Timestamp: 2025-02-06T13:38:07.216Z
Learning: The `u.LogTrace` function in the `cloudposse/atmos` repository accepts `atmosConfig` as its first parameter, followed by the message string.
Applied to files:
pkg/config/load.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:
pkg/utils/yaml_func_exec.go
📚 Learning: 2024-12-17T07:08:41.288Z
Learnt from: aknysh
Repo: cloudposse/atmos PR: 863
File: internal/exec/yaml_func_terraform_output.go:34-38
Timestamp: 2024-12-17T07:08:41.288Z
Learning: In the `processTagTerraformOutput` function within `internal/exec/yaml_func_terraform_output.go`, parameters are separated by spaces and do not contain spaces. Therefore, using `strings.Fields()` for parsing is acceptable, and there's no need to handle parameters with spaces.
Applied to files:
pkg/utils/yaml_func_exec.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:
pkg/utils/yaml_func_exec.go
📚 Learning: 2024-11-30T22:07:08.610Z
Learnt from: aknysh
Repo: cloudposse/atmos PR: 810
File: internal/exec/yaml_func_terraform_output.go:35-40
Timestamp: 2024-11-30T22:07:08.610Z
Learning: In the Go function `processTagTerraformOutput` in `internal/exec/yaml_func_terraform_output.go`, parameters cannot contain spaces. The code splits the input by spaces, and if the parameters contain spaces, `len(parts) != 3` will fail and show an error to the user.
Applied to files:
pkg/utils/yaml_func_exec.go
📚 Learning: 2024-11-16T17:30:52.893Z
Learnt from: pkbhowmick
Repo: cloudposse/atmos PR: 786
File: internal/exec/shell_utils.go:159-162
Timestamp: 2024-11-16T17:30:52.893Z
Learning: For the `atmos terraform shell` command in `internal/exec/shell_utils.go`, input validation for the custom shell prompt is not required, as users will use this as a CLI tool and any issues will impact themselves.
Applied to files:
pkg/utils/yaml_func_exec.go
📚 Learning: 2025-11-09T19:06:58.470Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 1752
File: pkg/profile/list/formatter_table.go:27-29
Timestamp: 2025-11-09T19:06:58.470Z
Learning: In the cloudposse/atmos repository, performance tracking with `defer perf.Track()` is enforced on all functions via linting, including high-frequency utility functions, formatters, and renderers. This is a repository-wide policy to maintain consistency and avoid making case-by-case judgment calls about which functions should have profiling.
Applied to files:
pkg/utils/yaml_func_exec.go
📚 Learning: 2025-11-30T04:16:24.155Z
Learnt from: aknysh
Repo: cloudposse/atmos PR: 1821
File: pkg/merge/deferred.go:34-48
Timestamp: 2025-11-30T04:16:24.155Z
Learning: In the cloudposse/atmos repository, the `defer perf.Track()` guideline applies to functions that perform meaningful work (I/O, computation, external calls), but explicitly excludes trivial accessors/mutators (e.g., simple getters, setters with single integer increments, string joins, or map appends) where the tracking overhead would exceed the actual method cost and provide no actionable performance data. Hot-path methods called in tight loops should especially avoid perf.Track() if they perform only trivial operations.
Applied to files:
pkg/utils/yaml_func_exec.go
📚 Learning: 2025-11-24T17:35:20.297Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-24T17:35:20.297Z
Learning: Applies to website/docs/cli/commands/**/*.mdx : Use Docusaurus conventions with frontmatter, purpose note, screengrab, usage/examples/arguments/flags sections for CLI command documentation.
Applied to files:
website/docs/cli/commands/env.mdx
📚 Learning: 2025-11-24T17:35:20.297Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-24T17:35:20.297Z
Learning: Applies to website/docs/cli/commands/**/*.mdx : All commands and flags need Docusaurus documentation in website/docs/cli/commands/. Use <dl> for arguments/flags. Build website after changes: cd website && npm run build.
Applied to files:
website/docs/cli/commands/env.mdx
📚 Learning: 2025-11-24T17:35:37.209Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: .cursor/rules/atmos-rules.mdc:0-0
Timestamp: 2025-11-24T17:35:37.209Z
Learning: Applies to README.md : Update README.md with new commands and features
Applied to files:
website/docs/cli/commands/env.mdx
🧬 Code graph analysis (3)
cmd/env/env_test.go (1)
cmd/env/env.go (1)
SupportedFormats(27-27)
pkg/config/casemap/casemap_test.go (1)
pkg/config/casemap/casemap.go (4)
ExtractFromYAML(67-89)New(25-27)CaseMap(17-17)CaseMaps(20-22)
pkg/schema/schema.go (1)
pkg/config/casemap/casemap.go (1)
CaseMaps(20-22)
🪛 LanguageTool
docs/prd/atmos-env-command.md
[uncategorized] ~45-~45: The official name of this software platform is spelled with a capital “H”.
Context: ...utput format: bash, json, dotenv, github | | --output | -o | (none) | Outpu...
(GITHUB)
[uncategorized] ~46-~46: The official name of this software platform is spelled with a capital “H”.
Context: ...| -o | (none) | Output file path. For github format, defaults to $GITHUB_ENV | #...
(GITHUB)
[typographical] ~54-~54: Consider using typographic quotation marks here.
Context: ...EY='value'|.envfiles | |json|{"KEY": "value"}| Programmatic consumption | |githu...
(EN_QUOTES)
[uncategorized] ~55-~55: The official name of this software platform is spelled with a capital “H”.
Context: ...value"}| Programmatic consumption | |github|KEY=value| GitHub Actions$GITHU...
(GITHUB)
[uncategorized] ~79-~79: The official name of this software platform is spelled with a capital “H”.
Context: ... "/tmp/terraform-plugin-cache" } ``` github: GitHub Actions environment file form...
(GITHUB)
[uncategorized] ~87-~87: The official name of this software platform is spelled with a capital “H”.
Context: ...`` ## GitHub Actions Integration When --format=github is specified: 1. If `--output` is pro...
(GITHUB)
[uncategorized] ~117-~117: The official name of this software platform is spelled with a capital “H”.
Context: ...) - Output formats: bash, json, dotenv, github - File output with --output flag **O...
(GITHUB)
examples/demo-env/README.md
[uncategorized] ~80-~80: The official name of this software platform is spelled with a capital “H”.
Context: ...ion. ## GitHub Actions For CI/CD, use --format=github to write directly to $GITHUB_ENV: `...
(GITHUB)
website/docs/cli/commands/env.mdx
[uncategorized] ~84-~84: The official name of this software platform is spelled with a capital “H”.
Context: ...ules" terraform init ``` The --format github option automatically writes to the `$G...
(GITHUB)
[typographical] ~116-~116: Consider using typographic quotation marks here.
Context: ...s for Docker, direnv, etc. | | json | {"KEY": "value"} | Programmatic consumption with jq, s...
(EN_QUOTES)
[uncategorized] ~117-~117: The official name of this software platform is spelled with a capital “H”.
Context: ...mmatic consumption with jq, scripts | | github | KEY=value | GitHub Actions `$GITHU...
(GITHUB)
[uncategorized] ~141-~141: The official name of this software platform is spelled with a capital “H”.
Context: ... "/tmp/terraform-plugin-cache" } ``` github: GitHub Actions environment file form...
(GITHUB)
[typographical] ~181-~181: Consider using typographic quotation marks here.
Context: ... # Static values AWS_SDK_LOAD_CONFIG: "true" TF_PLUGIN_CACHE_DIR: /tmp/terraform-p...
(EN_QUOTES)
🪛 markdownlint-cli2 (0.18.1)
docs/prd/atmos-env-command.md
66-66: Fenced code blocks should have a language specified
(MD040, fenced-code-language)
80-80: Fenced code blocks should have a language specified
(MD040, fenced-code-language)
examples/demo-env/README.md
17-17: Bare URL used
(MD034, no-bare-urls)
54-54: 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 (windows)
- GitHub Check: Acceptance Tests (macos)
- GitHub Check: Acceptance Tests (linux)
- GitHub Check: Summary
🔇 Additional comments (21)
examples/demo-env/components/terraform/github-repo/versions.tf (1)
1-10: LGTM! Standard Terraform version constraints and provider requirements are well-defined.examples/demo-env/components/terraform/github-repo/variables.tf (1)
1-11: LGTM! Variables are well-defined with appropriate defaults and descriptions.examples/demo-env/components/terraform/github-repo/main.tf (1)
6-8: LGTM! Data source correctly uses the repository variable to fetch GitHub repository information.examples/demo-env/components/terraform/github-repo/outputs.tf (1)
1-19: LGTM! Outputs are well-structured and correctly reference the GitHub repository data source attributes.examples/demo-env/stacks/deploy/demo.yaml (1)
1-8: LGTM - Clean demo configuration.The demo stack configuration is straightforward and properly structured for the new env feature demonstration.
demo/screengrabs/demo-stacks.txt (1)
49-49: LGTM - Correct alphabetical placement.The new env command help entry is properly positioned in alphabetical order.
cmd/root.go (1)
50-50: LGTM - Correct command registration pattern.The side-effect import follows the established command registry pattern used by other built-in commands.
website/docs/cli/commands/env.mdx (1)
1-203: LGTM - Comprehensive documentation.The documentation clearly explains the env command's purpose, usage patterns, output formats, and integration scenarios. Examples are practical and well-structured. The Notes section effectively covers important caveats like sorting, escaping, and scope limitations.
cmd/env/env_test.go (1)
1-243: LGTM - Comprehensive test coverage.The test suite covers all formatting functions with appropriate edge cases:
- Empty inputs and single/multiple variables
- Special character handling (quotes, spaces, special chars)
- Multiline values for GitHub format
- File operations (creation and appending)
- Deterministic key sorting
Tests follow Go best practices: table-driven patterns, t.TempDir() for file isolation, and clear test names.
pkg/config/casemap/casemap_test.go (1)
1-180: LGTM - Excellent test coverage.The test suite comprehensively validates casemap functionality:
- YAML extraction for single and nested paths
- Case preservation across multiple styles (SCREAMING_SNAKE, camelCase, PascalCase, etc.)
- Error handling for invalid YAML and missing paths
- Nil safety checks throughout
- Table-driven tests for case style variations
Tests are well-structured and follow Go best practices.
docs/prd/atmos-env-command.md (1)
1-175: LGTM - Well-structured PRD.The PRD clearly documents the env command's requirements, interface, and implementation approach. It covers:
- Clear problem statement and solution
- Detailed command interface with practical examples
- Format specifications with escaping rules
- GitHub Actions integration (GITHUB_ENV handling, append behavior)
- Scope boundaries (global env in v1, component/stack env future)
- Technical design referencing existing patterns
- Testing strategy and success metrics
The document provides solid guidance for implementation and review.
pkg/config/load.go (3)
283-289: Good refactoring to a generic case-preservation approach.The shift from identity-only case preservation to a general
preserveCaseSensitiveMapsfunction nicely supports the new globalenvsection while maintaining backward compatibility.
969-974: Clean declarative approach for case-sensitive paths.Module-level variable clearly documents which YAML paths need case preservation. Easy to extend in the future.
976-1010: Solid implementation with good error handling.The function gracefully handles missing config files and maintains backward compatibility for
Auth.IdentityCaseMap. One minor consideration:The function reads the config file a second time (line 985) after Viper already loaded it. For large config files this could be optimized, but the impact is negligible for typical atmos.yaml sizes.
pkg/config/casemap/casemap.go (4)
1-13: Well-documented package with clear purpose.Good explanation of why this exists (Viper lowercasing issue). Import organization is correct.
34-40: Defensive nil-check on receiver.Nice touch handling the nil receiver case in
Get. Prevents panics ifCaseMapswasn't initialized.
65-89: Solid extraction logic.Iterates paths, navigates to each section, and builds lowercase→original mappings. Handles missing sections gracefully by continuing to the next path.
91-103: No changes needed tonavigateToPathfor case handling.The function works as designed. It navigates Viper's lowercased key structure using lowercase paths from
caseSensitivePaths(e.g.,"auth.identities"). Viper automatically lowercases all map keys during unmarshalling, so the lowercase paths correctly match the keys in the navigated map. The original case preservation happens separately incasemap.goby extracting values directly from the raw YAML. All YAML files in the codebase use lowercase keys (auth:, notAuth:), confirming this approach is consistent with expected inputs.cmd/env/env.go (3)
3-19: Imports well-organized.Three groups properly separated: stdlib, third-party (cobra), and atmos packages with correct aliases.
190-204: Clean initialization with proper registration.Flag definitions and completion registration look good. Silent ignore of completion errors is acceptable.
206-242: Provider implementation is complete.All interface methods implemented, even if returning nil for unused capabilities. Follows the existing command pattern.
| # Global environment variables | ||
| # These are exported to all Terraform commands via `atmos env` | ||
| env: | ||
| # GitHub token for the GitHub provider (retrieved dynamically) | ||
| GITHUB_TOKEN: !exec gh auth token |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Security concern: Retrieving sensitive credentials via !exec in example.
While the global env feature is useful for settings like AWS_DEFAULT_REGION, TF_PLUGIN_CACHE_DIR, or proxy configuration, retrieving sensitive credentials (like GitHub tokens) via !exec and exposing them as environment variables poses security risks:
- Tokens may appear in process listings, debugger output, or error messages
- Downstream subprocesses could inadvertently log or expose the credential
- This pattern doesn't align with secure credential handling best practices
Consider either:
- Replacing this with a non-sensitive example (e.g.,
GITHUB_OWNER: myorg) - Adding explicit security documentation if this pattern is intentional
🤖 Prompt for AI Agents
In examples/demo-env/atmos.yaml around lines 19 to 23, the example uses
`GITHUB_TOKEN: !exec gh auth token`, which exposes a sensitive credential via
exec into a global environment; replace this with a non-sensitive placeholder
(e.g., GITHUB_OWNER: myorg or GITHUB_REPO: example) or remove the token entry
entirely, and if you must demonstrate token usage instead add a clear comment
and link to secure handling docs explaining alternatives (use
environment-specific secret storage, CI secret injection, or credential helpers)
rather than showing `!exec` for tokens.
- Use ATMOS_EOF_<key> as heredoc delimiter for GitHub format to prevent collision if env var value contains "EOF" on its own line - Add security considerations section to demo-env README explaining best practices for credential management 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 2
♻️ Duplicate comments (1)
cmd/env/env.go (1)
147-163: GitHub heredoc delimiter can still collide with multiline values.Using
ATMOS_EOF_<KEY>as the heredoc marker is safer than plainEOF, but if a multiline value ever contains that exact string on its own line, theGITHUB_ENVparser will still truncate the value.To make this fully robust, generate a delimiter per variable that’s guaranteed not to appear in the value (for example, start from
ATMOS_<KEY>_<random_or_hash>and, if it appears in the value, tweak the suffix until it doesn’t) and then use that delimiter for both open/close lines.
🧹 Nitpick comments (2)
cmd/env/env.go (2)
191-205: Flags are wired directly instead of via the unified flags.Builder.This command defines
--formatand--outputdirectly onenvCmd.Flags()and returnsnilfromGetFlagsBuilder(). That works, but it sidesteps thepkg/flagsbuilder pattern used elsewhere, which provides consistent flag wiring and Viper binding.It’d be cleaner to:
- Implement a
flags.Builderfor this command (usingflags.NewStandardParser()), defineformat/outputthere, and- Return that builder from
GetFlagsBuilder()instead ofnil.This keeps the env command aligned with the rest of the CLI flag infrastructure.
29-34: Help text is good; consider adding concrete usage examples.The Short/Long descriptions read well, but for discoverability it would help to add an
Examplesection onenvCmdshowing common patterns, e.g.:
atmos envpiping intoevalfor local shells.atmos env --format=dotenv --output=.envfor tooling.atmos env --format=githubusage inside a GitHub Actions step.This follows the project pattern of including examples in command help.
📜 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)
cmd/env/env.go(1 hunks)cmd/env/env_test.go(1 hunks)examples/demo-env/README.md(1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
- cmd/env/env_test.go
🧰 Additional context used
📓 Path-based instructions (2)
**/*.go
📄 CodeRabbit inference engine (CLAUDE.md)
**/*.go: Use functional options pattern to avoid functions with many parameters. Define Option functions that modify a Config struct and pass variadic options to New functions.
Use context.Context for cancellation signals, deadlines/timeouts, and request-scoped values (trace IDs). Context should be first parameter in functions that accept it. DO NOT use context for configuration, dependencies, or avoiding proper function parameters.
All comments must end with periods. This is enforced by the godot linter.
NEVER delete existing comments without a very strong reason. Preserve helpful comments, update them to match code changes, refactor for clarity, and add context when modifying code. Only remove factually incorrect, duplicated, or outdated comments.
Organize imports in three groups separated by blank lines (Go stdlib, 3rd-party excluding cloudposse/atmos, Atmos packages), sorted alphabetically. Maintain aliases: cfg, log, u, errUtils.
Add defer perf.Track(atmosConfig, "pkg.FuncName")() + blank line to all public functions. Use nil if no atmosConfig parameter.
All errors MUST be wrapped using static errors defined in errors/errors.go. Use errors.Join for combining multiple errors, fmt.Errorf with %w for adding string context, error builder for complex errors, and errors.Is() for error checking. NEVER use dynamic errors directly.
Use go.uber.org/mock/mockgen with //go:generate directives for mock generation. Never create manual mocks.
Use viper.BindEnv with ATMOS_ prefix for environment variables.
Use colors from pkg/ui/theme/colors.go for theme consistency.
Ensure Linux/macOS/Windows compatibility. Use SDKs over binaries. Use filepath.Join(), not hardcoded path separators.
Small focused files (<600 lines). One cmd/impl per file. Co-locate tests. Never use //revive:disable:file-length-limit.
**/*.go: Use Viper for managing configuration, environment variables, and flags in CLI commands
Use interfaces for external dependencies to facilitate mocking and consider us...
Files:
cmd/env/env.go
cmd/**/*.go
📄 CodeRabbit inference engine (CLAUDE.md)
cmd/**/*.go: Use unified flag parsing infrastructure in pkg/flags/. Commands MUST use flags.NewStandardParser() for command-specific flags. NEVER call viper.BindEnv() or viper.BindPFlag() directly outside pkg/flags/ (Forbidigo enforces this).
Telemetry is auto-enabled via RootCmd.ExecuteC(). Non-standard paths use telemetry.CaptureCmd(). Never capture user data.
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/env/env.go
🧠 Learnings (30)
📓 Common learnings
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.
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: 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.
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.
Learnt from: Benbentwo
Repo: cloudposse/atmos PR: 1475
File: pkg/auth/providers/github/oidc.go:96-100
Timestamp: 2025-09-10T17:34:52.568Z
Learning: The ATMOS_ environment variable binding guideline applies to Atmos configuration variables, not external service-required environment variables like GitHub Actions OIDC variables (GITHUB_ACTIONS, ACTIONS_ID_TOKEN_*) which must use their standard names.
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: 1433
File: cmd/theme_list.go:33-36
Timestamp: 2025-08-29T20:57:35.423Z
Learning: In the Atmos codebase, avoid using viper.SetEnvPrefix("ATMOS") with viper.AutomaticEnv() because canonical environment variable names are not exclusive to Atmos and could cause conflicts. Instead, use selective environment variable binding through the setEnv function in pkg/config/load.go with bindEnv(v, "config.key", "ENV_VAR_NAME") for specific environment variables.
Learnt from: aknysh
Repo: cloudposse/atmos PR: 0
File: :0-0
Timestamp: 2025-01-19T22:30:27.600Z
Learning: The Atmos YAML function `!env` is used to retrieve environment variables and assign them to sections in stack manifests. It supports both simple types (string, number, boolean) and complex types (JSON-encoded lists, maps, objects).
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.
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.
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.
📚 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/env/env.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/env/env.go
📚 Learning: 2025-11-24T17:35:20.297Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-24T17:35:20.297Z
Learning: Applies to **/*.go : Use viper.BindEnv with ATMOS_ prefix for environment variables.
Applied to files:
cmd/env/env.go
📚 Learning: 2025-11-08T19:56:18.660Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 1697
File: internal/exec/oci_utils.go:0-0
Timestamp: 2025-11-08T19:56:18.660Z
Learning: In the Atmos codebase, when a function receives an `*schema.AtmosConfiguration` parameter, it should read configuration values from `atmosConfig.Settings` fields rather than using direct `os.Getenv()` or `viper.GetString()` calls. The Atmos pattern is: viper.BindEnv in cmd/root.go binds environment variables → Viper unmarshals into atmosConfig.Settings via mapstructure → business logic reads from the Settings struct. This provides centralized config management, respects precedence, and enables testability. Example: `atmosConfig.Settings.AtmosGithubToken` instead of `os.Getenv("ATMOS_GITHUB_TOKEN")` in functions like `getGHCRAuth` in internal/exec/oci_utils.go.
Applied to files:
cmd/env/env.goexamples/demo-env/README.md
📚 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:
cmd/env/env.go
📚 Learning: 2025-08-29T20:57:35.423Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 1433
File: cmd/theme_list.go:33-36
Timestamp: 2025-08-29T20:57:35.423Z
Learning: In the Atmos codebase, avoid using viper.SetEnvPrefix("ATMOS") with viper.AutomaticEnv() because canonical environment variable names are not exclusive to Atmos and could cause conflicts. Instead, use selective environment variable binding through the setEnv function in pkg/config/load.go with bindEnv(v, "config.key", "ENV_VAR_NAME") for specific environment variables.
Applied to files:
cmd/env/env.go
📚 Learning: 2025-11-24T17:35:37.209Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: .cursor/rules/atmos-rules.mdc:0-0
Timestamp: 2025-11-24T17:35:37.209Z
Learning: Applies to cmd/**/*.go : Provide comprehensive help text for all commands and flags, include examples in command help, and follow Go's documentation conventions in Cobra command definitions
Applied to files:
cmd/env/env.go
📚 Learning: 2025-09-13T16:39:20.007Z
Learnt from: samtholiya
Repo: cloudposse/atmos PR: 1466
File: cmd/markdown/atmos_toolchain_aliases.md:2-4
Timestamp: 2025-09-13T16:39:20.007Z
Learning: In the cloudposse/atmos repository, CLI documentation files in cmd/markdown/ follow a specific format that uses " $ atmos command" (with leading space and dollar sign prompt) in code blocks. This is the established project convention and should not be changed to comply with standard markdownlint rules MD040 and MD014.
Applied to files:
cmd/env/env.go
📚 Learning: 2025-11-24T17:35:20.297Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-24T17:35:20.297Z
Learning: Applies to **/*.go : Organize imports in three groups separated by blank lines (Go stdlib, 3rd-party excluding cloudposse/atmos, Atmos packages), sorted alphabetically. Maintain aliases: cfg, log, u, errUtils.
Applied to files:
cmd/env/env.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/env/env.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:
cmd/env/env.go
📚 Learning: 2025-01-07T20:38:09.618Z
Learnt from: samtholiya
Repo: cloudposse/atmos PR: 896
File: cmd/editor_config.go:37-40
Timestamp: 2025-01-07T20:38:09.618Z
Learning: Error handling suggestion for `cmd.Help()` in `cmd/editor_config.go` was deferred as the code is planned for future modifications.
Applied to files:
cmd/env/env.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:
cmd/env/env.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:
cmd/env/env.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/env/env.go
📚 Learning: 2025-09-29T15:47:10.908Z
Learnt from: aknysh
Repo: cloudposse/atmos PR: 1540
File: internal/exec/terraform_cli_args_utils.go:64-73
Timestamp: 2025-09-29T15:47:10.908Z
Learning: In the Atmos codebase, viper.BindEnv is required for CLI commands in the cmd/ package, but internal utilities can use os.Getenv directly when parsing environment variables for business logic purposes. The requirement to use viper is specific to the CLI interface layer, not all environment variable access throughout the codebase.
Applied to files:
cmd/env/env.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/env/env.go
📚 Learning: 2024-10-20T13:12:46.499Z
Learnt from: haitham911
Repo: cloudposse/atmos PR: 736
File: pkg/config/const.go:6-6
Timestamp: 2024-10-20T13:12:46.499Z
Learning: In `cmd/cmd_utils.go`, it's acceptable to have hardcoded references to `atmos.yaml` in logs, and it's not necessary to update them to use the `CliConfigFileName` constant.
Applied to files:
cmd/env/env.go
📚 Learning: 2025-01-30T19:30:59.120Z
Learnt from: samtholiya
Repo: cloudposse/atmos PR: 959
File: cmd/workflow.go:74-74
Timestamp: 2025-01-30T19:30:59.120Z
Learning: Error handling for `cmd.Usage()` is not required in the Atmos CLI codebase, as confirmed by the maintainer.
Applied to files:
cmd/env/env.go
📚 Learning: 2025-04-23T15:02:50.246Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 1202
File: pkg/utils/yaml_func_exec.go:104-104
Timestamp: 2025-04-23T15:02:50.246Z
Learning: In the Atmos codebase, direct calls to `os.Getenv` should be avoided. Instead, use `viper.BindEnv` for environment variable access. This provides a consistent approach to configuration management across the codebase.
Applied to files:
cmd/env/env.go
📚 Learning: 2025-09-10T17:34:52.568Z
Learnt from: Benbentwo
Repo: cloudposse/atmos PR: 1475
File: pkg/auth/providers/github/oidc.go:96-100
Timestamp: 2025-09-10T17:34:52.568Z
Learning: The ATMOS_ environment variable binding guideline applies to Atmos configuration variables, not external service-required environment variables like GitHub Actions OIDC variables (GITHUB_ACTIONS, ACTIONS_ID_TOKEN_*) which must use their standard names.
Applied to files:
examples/demo-env/README.md
📚 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:
examples/demo-env/README.md
📚 Learning: 2025-01-25T03:51:57.689Z
Learnt from: Listener430
Repo: cloudposse/atmos PR: 934
File: tests/fixtures/scenarios/docs-generate/README.md.gotmpl:99-118
Timestamp: 2025-01-25T03:51:57.689Z
Learning: For the cloudposse/atmos repository, changes to template contents should be handled in dedicated PRs and are typically considered out of scope for PRs focused on other objectives.
Applied to files:
examples/demo-env/README.md
📚 Learning: 2024-11-25T17:17:15.703Z
Learnt from: RoseSecurity
Repo: cloudposse/atmos PR: 797
File: pkg/list/atmos.yaml:213-214
Timestamp: 2024-11-25T17:17:15.703Z
Learning: The file `pkg/list/atmos.yaml` is primarily intended for testing purposes.
Applied to files:
examples/demo-env/README.md
📚 Learning: 2025-01-19T22:30:27.600Z
Learnt from: aknysh
Repo: cloudposse/atmos PR: 0
File: :0-0
Timestamp: 2025-01-19T22:30:27.600Z
Learning: The Atmos YAML function `!env` is used to retrieve environment variables and assign them to sections in stack manifests. It supports both simple types (string, number, boolean) and complex types (JSON-encoded lists, maps, objects).
Applied to files:
examples/demo-env/README.md
📚 Learning: 2024-12-01T00:33:20.298Z
Learnt from: aknysh
Repo: cloudposse/atmos PR: 810
File: examples/tests/stacks/catalog/terraform/template-functions-test2/defaults.yaml:28-32
Timestamp: 2024-12-01T00:33:20.298Z
Learning: In `examples/tests/stacks/catalog/terraform/template-functions-test2/defaults.yaml`, `!exec atmos terraform output` is used in examples to demonstrate its usage, even though `!terraform.output` is the recommended approach according to the documentation.
Applied to files:
examples/demo-env/README.md
📚 Learning: 2025-01-09T19:53:29.847Z
Learnt from: Listener430
Repo: cloudposse/atmos PR: 912
File: pkg/config/config.go:91-92
Timestamp: 2025-01-09T19:53:29.847Z
Learning: In the Atmos project, the `core.inject_github_token` configuration is required to be enabled (`true`) by default to support authenticated GitHub requests and help bypass rate limits.
Applied to files:
examples/demo-env/README.md
📚 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:
examples/demo-env/README.md
📚 Learning: 2025-03-21T19:03:25.228Z
Learnt from: Listener430
Repo: cloudposse/atmos PR: 1076
File: internal/exec/go_getter_utils.go:198-209
Timestamp: 2025-03-21T19:03:25.228Z
Learning: In the `exec` package of Atmos, the `injectToken` method in `CustomGitDetector` is designed to intentionally overwrite any existing credentials when injecting tokens into Git URLs. This behavior is by design.
Applied to files:
examples/demo-env/README.md
🧬 Code graph analysis (1)
cmd/env/env.go (5)
cmd/cmd_utils.go (1)
Contains(943-950)errors/errors.go (2)
ErrInvalidArgumentError(546-546)ErrRequiredFlagNotProvided(200-200)pkg/config/config.go (1)
InitCliConfig(28-67)pkg/schema/schema.go (2)
ConfigAndStacksInfo(642-736)AtmosConfiguration(54-97)pkg/utils/json_utils.go (2)
WriteToFileAsJSON(104-130)PrintAsJSON(18-27)
🪛 LanguageTool
examples/demo-env/README.md
[uncategorized] ~80-~80: The official name of this software platform is spelled with a capital “H”.
Context: ...ion. ## GitHub Actions For CI/CD, use --format=github to write directly to $GITHUB_ENV: `...
(GITHUB)
[style] ~107-~107: Using many exclamation marks might seem excessive (in this case: 5 exclamation marks for a text that’s 1956 characters long)
Context: ...ts Manager, HashiCorp Vault) via the !store YAML function instead of !exec. 4. Output masking: Atmos aut...
(EN_EXCESSIVE_EXCLAMATION)
🪛 markdownlint-cli2 (0.18.1)
examples/demo-env/README.md
17-17: Bare URL used
(MD034, no-bare-urls)
54-54: Fenced code blocks should have a language specified
(MD040, fenced-code-language)
⏰ Context from checks skipped due to timeout of 900000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
- GitHub Check: Acceptance Tests (windows)
- GitHub Check: Acceptance Tests (linux)
- GitHub Check: Summary
🔇 Additional comments (3)
examples/demo-env/README.md (2)
1-107: Documentation is clear and well-aligned with the feature.The README effectively demonstrates the
atmos envcommand for the GitHub provider use case. The structure flows logically from prerequisites through practical examples to security considerations, which adds helpful context. The GitHub Actions section and security guidance are particularly valuable for users adopting this pattern.
54-59: Specify language for fenced code block.The code block is missing a language identifier. Based on the content, this appears to be JSON or text output.
-Example output: -``` +Example output: +```json default_branch = "main"⛔ Skipped due to learnings
Learnt from: osterman Repo: cloudposse/atmos PR: 808 File: examples/demo-atmos-cli-imports/atmos.yaml:7-7 Timestamp: 2024-12-12T15:15:46.457Z Learning: In example configuration files, such as `examples/demo-atmos-cli-imports/atmos.yaml`, it's acceptable to use `refs/heads/main` in remote URLs.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.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.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: 1714 File: NOTICE:0-0 Timestamp: 2025-11-01T20:24:29.557Z Learning: In the cloudposse/atmos repository, the NOTICE file is programmatically generated and should not be manually edited. Issues with dependency license URLs in NOTICE will be resolved when upstream package metadata is corrected.cmd/env/env.go (1)
104-189: Formatting helpers are straightforward and deterministic.
outputEnvAsJSON/bash/dotenv,formatBash,formatDotenv,formatGitHub,writeEnvToFile, andsortedKeysare all small, readable, and produce stable, sorted output. The single-quote escaping for bash/dotenv and append behavior for non-JSON formats look correct.
| RunE: func(cmd *cobra.Command, args []string) error { | ||
| // Get output format. | ||
| format, _ := cmd.Flags().GetString("format") | ||
| if !slices.Contains(SupportedFormats, format) { | ||
| return fmt.Errorf("%w: invalid format '%s', supported formats: %s", | ||
| errUtils.ErrInvalidArgumentError, format, strings.Join(SupportedFormats, ", ")) | ||
| } | ||
|
|
||
| // Get output file path. | ||
| output, _ := cmd.Flags().GetString("output") | ||
|
|
||
| // Load atmos configuration (processStacks=false since env command doesn't require stack manifests). | ||
| atmosConfig, err := cfg.InitCliConfig(schema.ConfigAndStacksInfo{}, false) | ||
| if err != nil { | ||
| return fmt.Errorf("failed to load atmos config: %w", err) | ||
| } | ||
|
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Config loading here may bypass CLI overrides for config path/base-path.
RunE calls cfg.InitCliConfig(schema.ConfigAndStacksInfo{}, false) with an empty ConfigAndStacksInfo, so persistent flags like --config, --config-path, and --base-path that RootCmd collects into ConfigAndStacksInfo are not applied for this command. That can make atmos env behave differently from other commands when users rely on those overrides.
Consider either:
- Reusing the already-initialized CLI config that other commands use, or
- Factoring out a helper that builds
schema.ConfigAndStacksInfofrom the current*cobra.Commandand using that here, so config resolution/precedence stays consistent.
🤖 Prompt for AI Agents
In cmd/env/env.go around lines 35 to 51, the code calls cfg.InitCliConfig with
an empty schema.ConfigAndStacksInfo which ignores persistent CLI overrides (e.g.
--config, --config-path, --base-path) collected on the root command; change this
so InitCliConfig receives the actual ConfigAndStacksInfo built from the current
cobra command or reuse the already-initialized CLI config used by other
commands. Concretely, either invoke the shared helper that returns the
initialized CLI config or construct a schema.ConfigAndStacksInfo from
cmd.Flags()/cmd.Root() (or call the same function the root command uses) and
pass that populated struct into cfg.InitCliConfig so config path/base-path
overrides are respected.
|
|
||
| ## Prerequisites | ||
|
|
||
| 1. **GitHub CLI** - Install from https://cli.github.com/ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Format bare URL as markdown link.
Line 17 has a bare URL that should be wrapped in markdown link syntax.
-2. **Authenticate with GitHub**:
- ```bash
- gh auth login
- ```
-3. **Terraform** >= 1.0
-4. **Atmos CLI**
+2. **Authenticate with GitHub**:
+ ```bash
+ gh auth login
+ ```
+3. **Terraform** >= 1.0
+4. **Atmos CLI** - Install from [GitHub CLI](https://cli.github.com/)Actually, this should be:
-1. **GitHub CLI** - Install from https://cli.github.com/
+1. **GitHub CLI** - Install from [GitHub CLI](https://cli.github.com/)🧰 Tools
🪛 markdownlint-cli2 (0.18.1)
17-17: Bare URL used
(MD034, no-bare-urls)
🤖 Prompt for AI Agents
In examples/demo-env/README.md around line 17, the "GitHub CLI" entry contains a
bare URL; replace the bare URL with markdown link syntax and update the list so
the install/auth steps are clear: change the item to e.g. "Authenticate with
GitHub:" followed by a fenced bash code block for `gh auth login`, and update
the subsequent list items so "Atmos CLI" references the GitHub CLI URL using a
markdown link like [GitHub CLI](https://cli.github.com/); ensure numbering and
code-fence formatting are consistent.
Resolved conflict in cmd/root.go by keeping both imports: - cmd/env (from this branch) - cmd/devcontainer (from main) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
what
envsection toatmos.yamlthat defines environment variables applied to all Atmos subprocessespkg/env/package by refactoringpkg/utils/env_utils.gowith global env supportwhy
AWS_DEFAULT_REGION,TF_PLUGIN_CACHE_DIR, proxy configurations, or logging flagsGITHUB_TOKENfor local dev while assuming it's already set in CIreferences
Summary by CodeRabbit
✏️ Tip: You can customize this high-level summary in your review settings.