atmos icon indicating copy to clipboard operation
atmos copied to clipboard

feat: Add global env section to atmos.yaml

Open osterman opened this issue 3 months ago β€’ 4 comments

what

  • Add a root-level env section to atmos.yaml that defines environment variables applied to all Atmos subprocesses
  • Create new pkg/env/ package by refactoring pkg/utils/env_utils.go with 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_TOKEN for 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 env command 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
  • Documentation

    • Added documentation for the new env command and global environment configuration

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

osterman avatar Dec 03 '25 00:12 osterman

Dependency Review

βœ… No vulnerabilities or license issues found.

Scanned Files

None

github-actions[bot] avatar Dec 03 '25 00:12 github-actions[bot]

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.

Files with missing lines Patch % Lines
cmd/env/env.go 51.12% 62 Missing and 3 partials :warning:
pkg/config/load.go 86.00% 4 Missing and 3 partials :warning:
cmd/cmd_utils.go 50.00% 1 Missing :warning:
internal/exec/shell_utils.go 88.88% 1 Missing :warning:
Additional details and impacted files

Impacted file tree graph

@@            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

... and 5 files with indirect coverage changes

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

codecov[bot] avatar Dec 03 '25 00:12 codecov[bot]

πŸ“ 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 using fmt.Errorf("context: %w", err), and consider using custom error types for domain-specific errors Follow standard Go coding style: use gofmt and goimports to format code, prefer short descriptive variable names, use kebab-case for command-line flags, and snake_case for environment variables Document all exported functions, types, and methods following Go's documentation conventions Document complex logic with inline comments in Go code Support configuration via files, environment variables, and flags following the precedence order: flags > environment variables > config file > defaults Provide clear error messages to users, include troubleshooting hints when appropriate, and log detailed errors for debugging

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

Files:

  • 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 mergedConfigFiles assumes 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 trackMergedConfigFile in mergeConfigFile) and processing each one in preserveCaseSensitiveMaps, the solution preserves case-sensitive keys from imports, profiles, and .atmos.d files with proper precedence.

The best-effort error handling with log.Trace is 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.Contains on line 1153 is compatible with the project's Go version requirement.


321-330: Implementation correctly handles mapstructure collision.

Both AtmosConfiguration.Env and Templates.Settings.Env have mapstructure:"-" tags in place, preventing collision with Command.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.

❀️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

coderabbitai[bot] avatar Dec 03 '25 00:12 coderabbitai[bot]

[!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.

mergify[bot] avatar Dec 03 '25 02:12 mergify[bot]

@coderabbitai full review please

aknysh avatar Dec 16 '25 18:12 aknysh

@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.

coderabbitai[bot] avatar Dec 16 '25 18:12 coderabbitai[bot]

These changes were released in v1.202.0-rc.4.

github-actions[bot] avatar Dec 17 '25 01:12 github-actions[bot]

These changes were released in v1.203.0-test.1.

github-actions[bot] avatar Dec 19 '25 17:12 github-actions[bot]