feat: Add global env section to atmos.yaml
what
- Add a root-level
envsection toatmos.yamlthat defines environment variables applied to all Atmos subprocesses - Create new
pkg/env/package by refactoringpkg/utils/env_utils.gowith global env support - Inject global env into terraform, helmfile, packer, workflows, custom commands, and auth exec contexts
why
- Provides a single location to configure environment variables that affect all Atmos operations
- Useful for settings like
AWS_DEFAULT_REGION,TF_PLUGIN_CACHE_DIR, proxy configurations, or logging flags - Works seamlessly with Atmos profiles - e.g., set
GITHUB_TOKENfor local dev while assuming it's already set in CI - Global env has lowest priority and can be overridden at stack or component level
references
- Follows existing env precedence: atmos.yaml env < stack env < component-type env < component env < overrides env
Summary by CodeRabbit
Release Notes
-
New Features
- Added
atmos envcommand to output global environment variables from atmos.yaml - Introduced global env section in atmos.yaml for setting variables across all Atmos subprocesses (Terraform, Helmfile, Packer, workflows, custom commands)
- Support for multiple output formats: bash, json, dotenv, and GitHub Actions
- Proper environment variable precedence handling: system < global < component/stack
- Added
-
Documentation
- Added documentation for the new env command and global environment configuration
βοΈ Tip: You can customize this high-level summary in your review settings.
Dependency Review
β No vulnerabilities or license issues found.Scanned Files
None
Codecov Report
:x: Patch coverage is 83.98268% with 74 lines in your changes missing coverage. Please review.
:white_check_mark: Project coverage is 72.97%. Comparing base (6b2c8c2) to head (4f6b2de).
:warning: Report is 1 commits behind head on main.
Additional details and impacted files
@@ Coverage Diff @@
## main #1829 +/- ##
==========================================
+ Coverage 72.90% 72.97% +0.07%
==========================================
Files 603 606 +3
Lines 56024 56329 +305
==========================================
+ Hits 40842 41104 +262
- Misses 12268 12311 +43
Partials 2914 2914
| Flag | Coverage Ξ | |
|---|---|---|
| unittests | 72.97% <83.98%> (+0.07%) |
:arrow_up: |
Flags with carried forward coverage won't be shown. Click here to find out more.
| Files with missing lines | Coverage Ξ | |
|---|---|---|
| cmd/auth_exec.go | 87.12% <100.00%> (+0.12%) |
:arrow_up: |
| cmd/root.go | 63.80% <ΓΈ> (ΓΈ) |
|
| internal/exec/stack_processor_process_stacks.go | 90.28% <100.00%> (+0.02%) |
:arrow_up: |
| internal/exec/terraform_output_utils.go | 67.98% <100.00%> (-0.59%) |
:arrow_down: |
| internal/exec/utils.go | 80.21% <100.00%> (ΓΈ) |
|
| internal/exec/validate_component.go | 61.68% <100.00%> (ΓΈ) |
|
| internal/exec/workflow_utils.go | 74.75% <100.00%> (+0.08%) |
:arrow_up: |
| pkg/config/casemap/casemap.go | 100.00% <100.00%> (ΓΈ) |
|
| pkg/env/env.go | 100.00% <100.00%> (ΓΈ) |
|
| pkg/env/global.go | 100.00% <100.00%> (ΓΈ) |
|
| ... and 6 more |
:rocket: New features to boost your workflow:
- :snowflake: Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
π Walkthrough
Walkthrough
Adds a centralized env utilities package, a new atmos env CLI command and docs, preserves YAML key casing across merged config files, and updates numerous execution paths to merge system, global, and component environment variables with defined precedence.
Changes
| Cohort / File(s) | Summary |
|---|---|
Environment package & tests pkg/env/env.go, pkg/env/global.go, pkg/env/env_test.go, pkg/env/global_test.go |
New env utilities: conversions, PATH helpers, UpdateEnvVar, Builder API, and multiple merge strategies (MergeGlobalEnv, MergeSystemEnv*, ApplyGlobalEnvToSlice) with perf tracking and tests. |
CLI env command & integration cmd/env/env.go, cmd/env/env_test.go, cmd/root.go, demo/screengrabs/demo-stacks.txt |
New atmos env command/provider; supports bash/json/dotenv/github formats, file/stdout output, GitHub Actions handling, tests, and command registration; help snapshots updated. |
Schema, casemap & config loading pkg/schema/schema.go, pkg/config/casemap/casemap.go, pkg/config/casemap/casemap_test.go, pkg/config/load.go, pkg/config/load_test.go, pkg/schema/schema_test.go, tests/snapshots/* |
Add AtmosConfiguration.Env and CaseMaps; new casemap package and load logic to extract/merge per-file original key casing for specified paths (env, auth.identities); tests and trace logs added. |
Shell/exec environment wiring & tests internal/exec/shell_utils.go, internal/exec/shell_utils_test.go, internal/exec/stack_processor_process_stacks.go, internal/exec/utils.go, internal/exec/terraform_output_utils.go, internal/exec/validate_component.go, internal/exec/workflow_utils.go, internal/exec/workflow_utils_test.go |
Replace legacy env helpers with env package; unify environment construction to include os.Environ() + global env + component env, handle TF_CLI_ARGS_* semantics, update ExecuteShell signature and call sites; tests adjusted. |
Command helpers & auth changes cmd/auth_exec.go, cmd/cmd_utils.go |
Use envpkg.MergeGlobalEnv / envpkg.UpdateEnvVar and pass merged baseEnv into shell preparation. |
Removed legacy utils & tests pkg/utils/env_utils.go (deleted), pkg/utils/env_utils_test.go (deleted) |
Deleted old environment utility implementations and their tests; functionality migrated to pkg/env. |
Test helpers, fixtures & examples tests/testhelpers/atmos_runner.go, tests/fixtures/scenarios/global-env/*, tests/fixtures/components/terraform/env-example/main.tf, tests/fixtures/scenarios/global-env/stacks/deploy/test.yaml, examples/demo-env/* |
Test helper switched to envpkg; new global-env scenario fixtures and Terraform/example demo for global/stack/component precedence; demo updated to show GitHub token usage. |
Docs & PRD website/docs/cli/configuration/env.mdx, website/docs/cli/commands/env.mdx, website/blog/2025-12-02-global-env-section.mdx, docs/prd/atmos-env-command.md |
Documentation, command docs, blog post and PRD for global env and atmos env usage and formats. |
YAML exec normalization pkg/utils/yaml_func_exec.go |
Trim trailing newline from shell command output prior to JSON unmarshalling. |
Misc snapshots/tests updates tests/snapshots/*, other updated tests |
Updated snapshots and tests to reflect added logging, changed env behavior, and new command presence. |
Sequence Diagram(s)
mermaid sequenceDiagram actor User participant CLI as atmos CLI participant Config as AtmosConfig (atmos.yaml) participant EnvPkg as pkg/env participant FS as File System participant Shell as Subprocess / GITHUB_ENV
User->>CLI: run `atmos env --format=<fmt> [--output file]`
CLI->>Config: LoadConfig (preserve case via casemap)
CLI->>EnvPkg: Merge/convert Env map -> []string (system + global)
CLI->>EnvPkg: Format env (bash | json | dotenv | github)
alt output to file
CLI->>FS: append formatted content
FS-->>CLI: file written
else write to stdout or GITHUB_ENV
CLI->>Shell: write to stdout or to $GITHUB_ENV (github format)
end
CLI-->>User: exit
Estimated code review effort
π― 4 (Complex) | β±οΈ ~65 minutes
Areas to focus during review:
- pkg/env/* and pkg/env/global.go: verify merge semantics, TF_CLI_ARGS_* prepend behavior, and edge-case tests.
- pkg/config/load.go + casemap: ensure multi-file extraction/tracking, ordering/wins semantics, and backward compatibility with IdentityCaseMap.
- internal/exec/*: ExecuteShell signature changes and consistent call-site updates (auth, workflow, terraform flows).
- cmd/env formatting helpers: escaping rules, heredoc behavior for GitHub format, and file append error handling.
Possibly related PRs
- cloudposse/atmos#943 β Related YAML !env/!include parsing and helpers that touch the same config/YAML processing concerns.
- cloudposse/atmos#1660 β Overlaps changes to shell execution and environment construction in internal/exec/shell_utils.go.
- cloudposse/atmos#1719 β Related modifications to shell environment merging and subprocess handling.
Suggested reviewers
- osterman
Pre-merge checks and finishing touches
β Failed checks (1 warning)
| Check name | Status | Explanation | Resolution |
|---|---|---|---|
| Docstring Coverage | β οΈ Warning | Docstring coverage is 55.81% which is insufficient. The required threshold is 80.00%. | You can run @coderabbitai generate docstrings to improve docstring coverage. |
β Passed checks (2 passed)
| Check name | Status | Explanation |
|---|---|---|
| Description Check | β Passed | Check skipped - CodeRabbitβs high-level summary is enabled. |
| Title check | β Passed | The title 'feat: Add global env section to atmos.yaml' directly and clearly summarizes the main change: introducing a new global environment configuration section to the Atmos YAML file. |
β¨ Finishing touches
- [ ] π Generate docstrings
π§ͺ Generate unit tests (beta)
- [ ] Create PR with unit tests
- [ ] Post copyable unit tests in a comment
- [ ] Commit unit tests in branch
osterman/global-env-section
π Recent review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Disabled knowledge base sources:
- Linear integration is disabled by default for public repositories
You can enable these sources in your CodeRabbit configuration.
π₯ Commits
Reviewing files that changed from the base of the PR and between 8c5761b30b51e5d612152c2da9231a3ea33e8d15 and 4f6b2de9e47e4986f65831d3bfe05b57f22858b6.
π Files selected for processing (3)
-
cmd/env/env_test.go(1 hunks) -
pkg/config/load.go(7 hunks) -
pkg/env/global_test.go(1 hunks)
π§ Files skipped from review as they are similar to previous changes (2)
- cmd/env/env_test.go
- pkg/env/global_test.go
π§° Additional context used
π Path-based instructions (1)
**/*.go
π CodeRabbit inference engine (.cursor/rules/atmos-rules.mdc)
**/*.go: Use Viper for managing configuration, environment variables, and flags in CLI commands Use interfaces for external dependencies to facilitate mocking and consider using testify/mock for creating mock implementations All code must pass golangci-lint checks Follow Go's error handling idioms: use meaningful error messages, wrap errors with context usingfmt.Errorf("context: %w", err), and consider using custom error types for domain-specific errors Follow standard Go coding style: usegofmtandgoimportsto format code, prefer short descriptive variable names, use kebab-case for command-line flags, and snake_case for environment variables Document all exported functions, types, and methods following Go's documentation conventions Document complex logic with inline comments in Go code Support configuration via files, environment variables, and flags following the precedence order: flags > environment variables > config file > defaults Provide clear error messages to users, include troubleshooting hints when appropriate, and log detailed errors for debugging
**/*.go: NEVER use fmt.Fprintf(os.Stdout/Stderr) or fmt.Println(); use data.* or ui.* functions instead All comments must end with periods (enforced by godot linter) Organize imports in three groups separated by blank lines, sorted alphabetically: 1) Go stdlib, 2) 3rd-party (NOT cloudposse/atmos), 3) Atmos packages; maintain aliases: cfg, log, u, errUtils Adddefer perf.Track(atmosConfig, "pkg.FuncName")()+ blank line to all public functions for performance tracking; use nil if no atmosConfig param All errors MUST be wrapped using static errors defined in errors/errors.go; use errors.Join for combining multiple errors; use fmt.Errorf with %w for adding string context; use error builder for complex errors; use errors.Is() for error checking; NEVER use dynamic errors directly Use go.uber.org/mock/mockgen with //go:generate directives for mock generation; never create manual mocks Keep files small...
Files:
-
pkg/config/load.go
π§ Learnings (28)
π 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/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: 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: osterman
Repo: cloudposse/atmos PR: 1686
File: internal/exec/workflow_utils.go:0-0
Timestamp: 2025-12-13T06:10:25.156Z
Learning: Atmos workflows: In internal/exec/workflow_utils.go ExecuteWorkflow, non-identity steps intentionally use baseWorkflowEnv, which is constructed from the parent environment with PATH modifications for the toolchain. Avoid appending os.Environ() again; prefer documenting this behavior and testing that standard environment variables are preserved.
Learnt from: osterman
Repo: cloudposse/atmos PR: 1686
File: docs/prd/tool-dependencies-integration.md:58-64
Timestamp: 2025-12-13T06:07:37.766Z
Learning: cloudposse/atmos: For PRD docs (docs/prd/*.md), markdownlint issues like MD040/MD010/MD034 can be handled in a separate documentation cleanup commit and should not block the current PR.
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-16T18:20:55.614Z
Learning: Applies to **/*.go : Use ATMOS_ prefix for environment variables with viper.BindEnv("ATMOS_VAR", "ATMOS_VAR", "FALLBACK")
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: 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.
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: 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: 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: 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: samtholiya
Repo: cloudposse/atmos PR: 1466
File: cmd/markdown/atmos_toolchain_aliases.md:2-4
Timestamp: 2025-09-13T16:39:20.007Z
Learning: In the cloudposse/atmos repository, CLI documentation files in cmd/markdown/ follow a specific format that uses " $ atmos command" (with leading space and dollar sign prompt) in code blocks. This is the established project convention and should not be changed to comply with standard markdownlint rules MD040 and MD014.
π Learning: 2025-12-13T03:21:35.786Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 1813
File: cmd/terraform/shell.go:28-73
Timestamp: 2025-12-13T03:21:35.786Z
Learning: In Atmos, when calling cfg.InitCliConfig, you must first populate the schema.ConfigAndStacksInfo struct with global flag values using flags.ParseGlobalFlags(cmd, v) rather than passing an empty struct. The LoadConfig function (pkg/config/load.go) reads config selection fields (AtmosConfigFilesFromArg, AtmosConfigDirsFromArg, BasePath, ProfilesFromArg) directly from the ConfigAndStacksInfo struct, NOT from Viper. Passing an empty struct causes config selection flags (--base-path, --config, --config-path, --profile) to be silently ignored. Correct pattern: parse flags β populate struct β call InitCliConfig. See cmd/terraform/plan_diff.go for reference implementation.
Applied to files:
-
pkg/config/load.go
π Learning: 2025-11-24T17:35:37.209Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: .cursor/rules/atmos-rules.mdc:0-0
Timestamp: 2025-11-24T17:35:37.209Z
Learning: Applies to **/*.go : Support configuration via files, environment variables, and flags following the precedence order: flags > environment variables > config file > defaults
Applied to files:
-
pkg/config/load.go
π Learning: 2025-12-16T18:20:55.614Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-16T18:20:55.614Z
Learning: Applies to **/*.go : Add `defer perf.Track(atmosConfig, "pkg.FuncName")()` + blank line to all public functions for performance tracking; use nil if no atmosConfig param
Applied to files:
-
pkg/config/load.go
π Learning: 2025-11-08T19:56:18.660Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 1697
File: internal/exec/oci_utils.go:0-0
Timestamp: 2025-11-08T19:56:18.660Z
Learning: In the Atmos codebase, when a function receives an `*schema.AtmosConfiguration` parameter, it should read configuration values from `atmosConfig.Settings` fields rather than using direct `os.Getenv()` or `viper.GetString()` calls. The Atmos pattern is: viper.BindEnv in cmd/root.go binds environment variables β Viper unmarshals into atmosConfig.Settings via mapstructure β business logic reads from the Settings struct. This provides centralized config management, respects precedence, and enables testability. Example: `atmosConfig.Settings.AtmosGithubToken` instead of `os.Getenv("ATMOS_GITHUB_TOKEN")` in functions like `getGHCRAuth` in internal/exec/oci_utils.go.
Applied to files:
-
pkg/config/load.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/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/config/load.go
π Learning: 2025-03-17T18:41:08.831Z
Learnt from: haitham911
Repo: cloudposse/atmos PR: 1085
File: pkg/config/imports.go:68-75
Timestamp: 2025-03-17T18:41:08.831Z
Learning: In the Atmos configuration import system, errors during config file merging are logged at debug level and the process continues with other imports rather than failing completely, prioritizing resilience over strict correctness.
Applied to files:
-
pkg/config/load.go
π Learning: 2025-04-03T10:57:04.602Z
Learnt from: haitham911
Repo: cloudposse/atmos PR: 1091
File: pkg/config/load_config_args.go:61-82
Timestamp: 2025-04-03T10:57:04.602Z
Learning: In the Atmos configuration system, errors in `mergeDefaultImports` and `mergeImports` functions are intentionally only logged as debug messages without returning errors, as they are considered non-critical. Only errors in critical functions like `mergeConfigFile` are returned to halt execution.
Applied to files:
-
pkg/config/load.go
π Learning: 2025-08-29T20:57:35.423Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 1433
File: cmd/theme_list.go:33-36
Timestamp: 2025-08-29T20:57:35.423Z
Learning: In the Atmos codebase, avoid using viper.SetEnvPrefix("ATMOS") with viper.AutomaticEnv() because canonical environment variable names are not exclusive to Atmos and could cause conflicts. Instead, use selective environment variable binding through the setEnv function in pkg/config/load.go with bindEnv(v, "config.key", "ENV_VAR_NAME") for specific environment variables.
Applied to files:
-
pkg/config/load.go
π Learning: 2024-10-23T21:36:40.262Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 740
File: cmd/cmd_utils.go:340-359
Timestamp: 2024-10-23T21:36:40.262Z
Learning: In the Go codebase for Atmos, when reviewing functions like `checkAtmosConfig` in `cmd/cmd_utils.go`, avoid suggesting refactoring to return errors instead of calling `os.Exit` if such changes would significantly increase the scope due to the need to update multiple call sites.
Applied to files:
-
pkg/config/load.go
π Learning: 2025-12-16T18:20:55.614Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-16T18:20:55.614Z
Learning: Applies to **/*.go : Use ATMOS_ prefix for environment variables with viper.BindEnv("ATMOS_VAR", "ATMOS_VAR", "FALLBACK")
Applied to files:
-
pkg/config/load.go
π Learning: 2025-02-09T18:43:53.902Z
Learnt from: haitham911
Repo: cloudposse/atmos PR: 808
File: pkg/config/loader.go:141-145
Timestamp: 2025-02-09T18:43:53.902Z
Learning: In the Atmos configuration loading process, errors during individual config file loading/merging should be logged but not propagate up to break the entire process. This design choice enables resilient partial configuration loading.
Applied to files:
-
pkg/config/load.go
π Learning: 2024-12-13T16:48:00.294Z
Learnt from: Listener430
Repo: cloudposse/atmos PR: 844
File: pkg/config/cache.go:42-42
Timestamp: 2024-12-13T16:48:00.294Z
Learning: The function `withCacheFileLock` in `pkg/config/cache.go` is currently unused and left for future upgrade.
Applied to files:
-
pkg/config/load.go
π Learning: 2024-10-22T23:00:20.627Z
Learnt from: Cerebrovinny
Repo: cloudposse/atmos PR: 737
File: internal/exec/vendor_utils.go:131-141
Timestamp: 2024-10-22T23:00:20.627Z
Learning: In the `ReadAndProcessVendorConfigFile` function in `internal/exec/vendor_utils.go`, the existence of the vendor config file is already checked, so additional file existence checks may be unnecessary.
Applied to files:
-
pkg/config/load.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:
-
pkg/config/load.go
π Learning: 2025-11-24T17:35:37.209Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: .cursor/rules/atmos-rules.mdc:0-0
Timestamp: 2025-11-24T17:35:37.209Z
Learning: Applies to **/*.go : Use Viper for managing configuration, environment variables, and flags in CLI commands
Applied to files:
-
pkg/config/load.go
π Learning: 2025-12-16T18:20:55.614Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-16T18:20:55.614Z
Learning: Applies to **/*.go : Code must be Linux/macOS/Windows compatible; use SDKs over binaries; use filepath.Join() instead of hardcoded path separators
Applied to files:
-
pkg/config/load.go
π Learning: 2025-12-13T04:37:45.831Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 1686
File: cmd/toolchain/get.go:23-40
Timestamp: 2025-12-13T04:37:45.831Z
Learning: In cmd/toolchain/get.go, the get subcommand intentionally uses cobra.MaximumNArgs(1) so it works with zero args (list all tools) or one arg (a specific tool). Flags are defined via flags.NewStandardParser() with --all (bool) and --limit (int); no direct viper.BindEnv/BindPFlag calls are used.
Applied to files:
-
pkg/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/config/load.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:
-
pkg/config/load.go
π Learning: 2025-12-16T18:20:55.614Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-16T18:20:55.614Z
Learning: Applies to **/*.go : Organize imports in three groups separated by blank lines, sorted alphabetically: 1) Go stdlib, 2) 3rd-party (NOT cloudposse/atmos), 3) Atmos packages; maintain aliases: cfg, log, u, errUtils
Applied to files:
-
pkg/config/load.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:
-
pkg/config/load.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: 2024-10-20T13:12:46.499Z
Learnt from: haitham911
Repo: cloudposse/atmos PR: 736
File: pkg/config/const.go:6-6
Timestamp: 2024-10-20T13:12:46.499Z
Learning: In `cmd/cmd_utils.go`, it's acceptable to have hardcoded references to `atmos.yaml` in logs, and it's not necessary to update them to use the `CliConfigFileName` constant.
Applied to files:
-
pkg/config/load.go
π Learning: 2025-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/config/load.go
π Learning: 2025-12-13T04:37:25.223Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 1686
File: cmd/root.go:0-0
Timestamp: 2025-12-13T04:37:25.223Z
Learning: In Atmos cmd/root.go Execute(), after cfg.InitCliConfig, we must call both toolchainCmd.SetAtmosConfig(&atmosConfig) and toolchain.SetAtmosConfig(&atmosConfig) so the CLI wrapper and the toolchain package receive configuration; missing either can cause nil-pointer panics in toolchain path resolution.
Applied to files:
-
pkg/config/load.go
π Learning: 2025-04-23T15:02:50.246Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 1202
File: pkg/utils/yaml_func_exec.go:104-104
Timestamp: 2025-04-23T15:02:50.246Z
Learning: In the Atmos codebase, direct calls to `os.Getenv` should be avoided. Instead, use `viper.BindEnv` for environment variable access. This provides a consistent approach to configuration management across the codebase.
Applied to files:
-
pkg/config/load.go
𧬠Code graph analysis (1)
pkg/config/load.go (3)
pkg/schema/schema.go (3)
Templates(360-362)Settings(919-923)AtmosConfiguration(54-99)pkg/config/casemap/casemap.go (4)
CaseMaps(20-22)ExtractFromYAML(67-89)CaseMap(17-17)New(25-27)pkg/logger/log.go (1)
Trace(14-16)
β° 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 (4)
pkg/config/load.go (4)
43-62: Concurrency assumption is now clearly documented.The comment block adequately explains that
mergedConfigFilesassumes sequential calls and warns about the need for refactoring if concurrent loading becomes necessary. This addresses the prior review concern.
1205-1224: Case preservation now correctly handles all merged configs.This implementation addresses the previous concern about case preservation only applying to the main config file. By tracking all merged files (via
trackMergedConfigFileinmergeConfigFile) and processing each one inpreserveCaseSensitiveMaps, the solution preserves case-sensitive keys from imports, profiles, and .atmos.d files with proper precedence.The best-effort error handling with
log.Traceis appropriate for this non-critical functionalityβconfig loading shouldn't fail if case preservation encounters issues.
1146-1158: No issues found.The project uses Go 1.24.5, which fully supports the slices package for common operations on slices. The use of
slices.Containson line 1153 is compatible with the project's Go version requirement.
321-330: Implementation correctly handles mapstructure collision.Both
AtmosConfiguration.EnvandTemplates.Settings.Envhavemapstructure:"-"tags in place, preventing collision withCommand.Env []CommandEnv. The schema already documents this collision avoidance with inline comments, and the manual extraction in load.go properly handles the workaround.
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 @coderabbitai help to get the list of available commands and usage tips.
[!WARNING]
This PR exceeds the recommended limit of 1,000 lines.
Large PRs are difficult to review and may be rejected due to their size.
Please verify that this PR does not address multiple issues. Consider refactoring it into smaller, more focused PRs to facilitate a smoother review process.
@coderabbitai full review please
@aknysh I'll perform a full review of all changes in this PR. This includes the new global env section, the pkg/env/ package refactoring, the new atmos env command, environment integration across all execution contexts, and all associated tests and documentation.
π§ Learnings used
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: 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: 1686
File: docs/prd/tool-dependencies-integration.md:58-64
Timestamp: 2025-12-13T06:07:37.766Z
Learning: cloudposse/atmos: For PRD docs (docs/prd/*.md), markdownlint issues like MD040/MD010/MD034 can be handled in a separate documentation cleanup commit and should not block the current PR.
Learnt from: 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-12-16T18:20:55.614Z
Learning: Applies to **/*.go : Use ATMOS_ prefix for environment variables with viper.BindEnv("ATMOS_VAR", "ATMOS_VAR", "FALLBACK")
Learnt from: osterman
Repo: cloudposse/atmos PR: 1686
File: internal/exec/workflow_utils.go:0-0
Timestamp: 2025-12-13T06:10:25.156Z
Learning: Atmos workflows: In internal/exec/workflow_utils.go ExecuteWorkflow, non-identity steps intentionally use baseWorkflowEnv, which is constructed from the parent environment with PATH modifications for the toolchain. Avoid appending os.Environ() again; prefer documenting this behavior and testing that standard environment variables are preserved.
β Actions performed
Full review triggered.
These changes were released in v1.202.0-rc.4.
These changes were released in v1.203.0-test.1.