Skip to content

Fix: Enable auto-import of provisioned identities from profiles#1865

Open
osterman wants to merge 17 commits intomainfrom
osterman/fix-identity-import
Open

Fix: Enable auto-import of provisioned identities from profiles#1865
osterman wants to merge 17 commits intomainfrom
osterman/fix-identity-import

Conversation

@osterman
Copy link
Member

@osterman osterman commented Dec 12, 2025

what

  • Add injectProvisionedIdentitiesPostLoad() function that runs after profiles are loaded, ensuring auth.providers (which may be defined in profiles) is available before checking for provisioned identity cache files
  • Add processFileImportsIfPresent() helper to enable import: directives in profile files (previously silently ignored)
  • Comprehensive test coverage for both provisioned identity injection and profile imports

why

Provisioned identities were not auto-importing when auth.providers was defined in a profile because the provider check happened during early config loading, before profiles were merged. Additionally, import: directives inside profile files were completely ignored. These changes fix both issues, allowing proper auto-discovery of provisioned identities from cache files.

references

Fixes provisioned identity auto-import for profiles with auto_provision_identities: true configured.

Summary by CodeRabbit

  • New Features

    • Identity display now preserves original casing and appears with that casing across identity lists and UI views.
  • Improvements

    • Config loading processes file imports earlier and re-applies user config so user overrides take precedence over provisioned identities.
    • More detailed trace-level diagnostics for provisioning, import, and config discovery flows.
    • Case-preservation extended to include provisioned identity data.
  • Tests

    • Significantly expanded test coverage for provisioning, imports, precedence, case-preservation, and config discovery.

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

@osterman osterman requested a review from a team as a code owner December 12, 2025 21:12
@github-actions github-actions bot added the size/m Medium size PR label Dec 12, 2025
@github-actions
Copy link

github-actions bot commented Dec 12, 2025

Dependency Review

✅ No vulnerabilities or license issues found.

Scanned Files

None

@github-actions github-actions bot added size/l Large size PR and removed size/m Medium size PR labels Dec 12, 2025
@osterman osterman added the patch A minor, backward compatible change label Dec 12, 2025
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Dec 12, 2025

Warning

Rate limit exceeded

@autofix-ci[bot] has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 23 minutes and 24 seconds before requesting another review.

⌛ How to resolve this issue?

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

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

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

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

Please see our FAQ for further information.

📥 Commits

Reviewing files that changed from the base of the PR and between d960476 and 710c0ac.

📒 Files selected for processing (4)
  • NOTICE
  • tests/snapshots/TestCLICommands_Valid_Log_Level_in_Config_File.stderr.golden
  • tests/snapshots/TestCLICommands_atmos_describe_config_imports.stderr.golden
  • tests/snapshots/TestCLICommands_atmos_describe_configuration.stderr.golden
📝 Walkthrough

Walkthrough

Injects provisioned identities after profile loading (non-fatal on failure), processes per-file imports before merging, re-applies user config and profiles for precedence, preserves original-case provisioned identities via IdentityCaseMap, and exposes GetIdentityDisplayName on AuthManager used by formatters.

Changes

Cohort / File(s) Summary
Config Loading Core
pkg/config/load.go
Reordered load flow: process per-file imports before merging, inject provisioned identities post-profile load, reapply user config and profiles for precedence, and increase trace-level logging.
Provisioned Identity Case Preservation
pkg/config/provisioned_identity_case.go
New file: reads provider cache YAML under XDG cache, extracts auth.identities preserving original case, and populates AtmosConfiguration.IdentityCaseMap without overwriting user mappings.
Config Tests
pkg/config/load_test.go, pkg/config/profiles_test.go
Large suite of tests added for post-load provisioning, import processing, precedence rules (user vs provisioned), case-preservation edge cases, and config discovery.
Auth Interface & Manager
pkg/auth/types/interfaces.go, pkg/auth/manager.go, pkg/auth/types/mock_interfaces.go
Added GetIdentityDisplayName(lowercaseKey string) string to AuthManager interface and manager; mocks updated accordingly.
Auth Formatters & Consumers
pkg/auth/list/formatter_table.go, pkg/auth/list/formatter_tree.go, internal/exec/terraform_output_utils.go
Consumers now call GetIdentityDisplayName to display original-case identity names (fallback to input when map absent).
Auth Tests & Stubs
pkg/auth/manager_case_test.go, pkg/auth/providers/aws/saml_test.go, pkg/auth/hooks_test.go, cmd/auth_console_test.go
Test stubs and tests updated/added to surface GetIdentityDisplayName and validate case-preservation behavior.
Golden Snapshot
tests/snapshots/TestCLICommands_Valid_Log_Level_in_Config_File.stderr.golden
Updated diagnostics reflecting new provisioning/injection/reapply logging and expanded discovery traces.

Sequence Diagram(s)

sequenceDiagram
    autonumber
    participant User
    participant CLI
    participant ConfigLoader
    participant FS as FileSystem/Imports
    participant Profiles
    participant XDG as XDG Cache
    participant AuthMgr
    participant Formatter

    User->>CLI: run command (load config)
    CLI->>ConfigLoader: LoadConfig()
    ConfigLoader->>FS: scan directory (detect files)
    FS-->>ConfigLoader: file list (processFileImportsIfPresent)
    ConfigLoader->>Profiles: load and merge profiles
    Profiles-->>ConfigLoader: merged profiles + user config
    ConfigLoader->>XDG: injectProvisionedIdentitiesPostLoad()
    Note right of XDG: read per-provider cache YAML\nextract auth.identities (preserve case)
    XDG-->>ConfigLoader: populate IdentityCaseMap (non-fatal)
    ConfigLoader->>ConfigLoader: reapplyUserConfigForPrecedence()
    ConfigLoader->>ConfigLoader: reapply profiles if specified
    ConfigLoader->>ConfigLoader: preserveProvisionedIdentityCase()
    ConfigLoader-->>CLI: final AtmosConfiguration
    CLI->>AuthMgr: ResolveIdentity(...) / GetIdentityDisplayName(key)
    AuthMgr-->>CLI: display name (original case or fallback)
    CLI->>Formatter: format list/tree (uses GetIdentityDisplayName)
    Formatter-->>User: rendered output with preserved case
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

Suggested reviewers

  • aknysh
  • milldr
🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title directly reflects the main change: enabling auto-import of provisioned identities from profiles, which aligns with the PR's primary objective and the substantial changes to config loading and identity injection logic.
Docstring Coverage ✅ Passed Docstring coverage is 94.44% which is sufficient. The required threshold is 80.00%.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch osterman/fix-identity-import

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
Copy link
Contributor

coderabbitai bot commented Dec 12, 2025

📝 Walkthrough

Walkthrough

The changes extend the config loading pipeline with post-load provisioned identity injection, user config precedence reapplication, and import processing hooks. Functions enable provisioned identities to load after profiles, ensure user config overrides provisioned data, and process import directives within individual config files with non-fatal error handling.

Changes

Cohort / File(s) Summary
Post-load provisioning and precedence logic
pkg/config/load.go
Introduces injectProvisionedIdentitiesPostLoad to load provisioned identity files after profile application; reapplyUserConfigForPrecedence to re-merge user config after provisioned identities; reapplyProfilesToEnforceConfigPrecedence to re-apply profiles; processFileImportsIfPresent to parse and apply import directives within individual files; updates loadAtmosConfigsFromDirectory and mergeDefaultImports to invoke import processing for each loaded file. All new steps use non-fatal, debug-level logging for failures.
Load.go test coverage
pkg/config/load_test.go
Adds TestInjectProvisionedIdentitiesPostLoad (provider skipping, cache presence, identity loading from provisioned-identities.yaml, multiple provider handling) and TestInjectProvisionedIdentitiesPostLoad_ErrorHandling (invalid cache handling); adds TestUserConfigOverridesProvisionedIdentities to verify user config merging and precedence re-application override semantics.
Profile import tests
pkg/config/profiles_test.go
Introduces TestProfileWithImports (import directives in profile files, value merging, override semantics) and TestProcessFileImportsIfPresent (import processing helper validation, missing import handling). Both construct temporary directories, write test files, and assert configuration outcomes.

Sequence Diagram

sequenceDiagram
    participant Client
    participant LoadConfig
    participant ProfileLoader
    participant ProvisionedLoader
    participant UserConfig
    participant ImportProcessor

    Client->>LoadConfig: LoadConfig()
    LoadConfig->>ProfileLoader: Load & apply profiles
    ProfileLoader-->>LoadConfig: Profiles applied
    
    LoadConfig->>ProvisionedLoader: injectProvisionedIdentitiesPostLoad()
    ProvisionedLoader->>ProvisionedLoader: Read provisioned-identities.yaml
    ProvisionedLoader-->>LoadConfig: Identities injected (non-fatal)
    
    LoadConfig->>ProfileLoader: reapplyProfilesToEnforceConfigPrecedence()
    ProfileLoader-->>LoadConfig: Profiles re-applied
    
    LoadConfig->>UserConfig: reapplyUserConfigForPrecedence()
    UserConfig->>UserConfig: Re-merge main config file
    UserConfig-->>LoadConfig: User config precedence restored
    
    LoadConfig->>ImportProcessor: processFileImportsIfPresent()
    ImportProcessor->>ImportProcessor: Parse & apply imports
    ImportProcessor-->>LoadConfig: Imports processed (non-fatal)
    
    LoadConfig-->>Client: Final merged config
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

  • Precedence semantics: Verify that the order of operations (profiles → provisioned identities → user config re-application → imports) maintains correct override hierarchy across all scenarios
  • load.go integration points: Review how new functions hook into loadAtmosConfigsFromDirectory, mergeDefaultImports, and the main LoadConfig flow to ensure no race conditions or missing cases
  • Error handling coverage: Confirm all non-fatal error paths (debug logging) are appropriate and don't mask critical failures; validate test coverage for error scenarios in load_test.go
  • Import processing logic: Assess processFileImportsIfPresent correctness when called at multiple points in the loading pipeline

Pre-merge checks and finishing touches

✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately captures the main change: enabling auto-import of provisioned identities from profiles, which is central to the PR's objectives.
Docstring Coverage ✅ Passed Docstring coverage is 93.33% which is sufficient. The required threshold is 80.00%.
✨ 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/fix-identity-import

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.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

Caution

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

⚠️ Outside diff range comments (1)
pkg/config/load.go (1)

842-890: Process imports before merging the file to match documented precedence semantics.

loadAtmosConfigsFromDirectory() currently merges the file first, then processes its imports. Since Viper's MergeConfig() overwrites existing keys, imports end up overwriting the file's values—backwards from the documented behavior in mergeConfig() ("importing file always takes precedence over imported files"). This is especially problematic for profile files.

Swap the order: process imports first, then merge the file itself.

for _, filePath := range foundPaths {
+	// Process any imports in the file first so the file itself can override them.
+	// This matches mergeConfig() precedence semantics.
+	if err := processFileImportsIfPresent(filePath, filepath.Dir(filePath), dst); err != nil {
+		log.Debug("Failed to process imports in file", "file", filePath, "error", err)
+		// Non-fatal: continue loading even if import processing fails.
+	}
+
 	if err := mergeConfigFile(filePath, dst); err != nil {
 		return fmt.Errorf("%w: failed to load configuration file from %s: %s: %w", errUtils.ErrParseFile, source, filePath, err)
 	}
-
-	// Process any imports in the file.
-	// This enables import: directives to work in profile files.
-	if err := processFileImportsIfPresent(filePath, filepath.Dir(filePath), dst); err != nil {
-		log.Debug("Failed to process imports in file", "file", filePath, "error", err)
-		// Non-fatal: continue loading even if import processing fails.
-	}
 
 	log.Trace("Loaded configuration file", "path", filePath, "source", source)
 }
🧹 Nitpick comments (2)
pkg/config/load_test.go (2)

1039-1158: Small test cleanup: remove (or assert on) the unused expectIdentitiesLoad field.
Right now it’s set per case but never read, which makes the table harder to scan.


1189-1257: Add coverage for “user override via imported config” (not inline) to validate precedence re-application.
Given the new “re-apply user config” step, a key case is: atmos.yaml imports another file that defines/overrides auth.identities.*; provisioned injection should not permanently win over those imported user values.

📜 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 2f28bdc and 0551854.

📒 Files selected for processing (3)
  • pkg/config/load.go (4 hunks)
  • pkg/config/load_test.go (1 hunks)
  • pkg/config/profiles_test.go (1 hunks)
🧰 Additional context used
📓 Path-based instructions (3)
**/*.go

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

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

**/*.go: All comments must end with periods (enforced by godot linter)
NEVER delete existing comments without a very strong reason. Comments document why/how/what/where. Preserve helpful comments, update to match code, refactor for clarity, add context when modifying.
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")() with a blank line to all public functions. Use nil if no atmosConfig parameter is available.
Define interfaces for all major functionality. Use dependency injection for testability. Generate mocks with go.uber.org/mock/mockgen. Avoid integration tests by mocking external dependencies.
Use //go:generate directives with go.uber.org/mock/mockgen for mock generation. Never creat...

Files:

  • pkg/config/load_test.go
  • pkg/config/profiles_test.go
  • pkg/config/load.go
**/*_test.go

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

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

**/*_test.go: Prefer unit tests with mocks over integration tests. Use interfaces and dependency injection for testability. Generate mocks with go.uber.org/mock/mockgen. Use table-driven tests for comprehensive coverage. Target >80% coverage.
Test behavior, not implementation. Never test stub functions. Avoid tautological tests. Make code testable using DI. No coverage theater. Remove always-skipped tests. Table-driven tests need real scenarios. Use assert.ErrorIs(err, ErrSentinel) for our/stdlib errors.
Tests must call actual production code, never duplicate logic.
Use t.Skipf("reason") with clear context for test skipping. CLI tests auto-build temp binaries.
Never use pipe redirection (2>&1, | head, | tail) when running tests. Piping breaks TTY detection → ASCII fallback → wrong snapshots.
Tests skip gracefully with helpers from tests/test_preconditions.go.

Files:

  • pkg/config/load_test.go
  • pkg/config/profiles_test.go
pkg/**/*.go

📄 CodeRabbit inference engine (CLAUDE.md)

pkg/**/*.go: For complex domains with multiple operations, use Service-Oriented Architecture with one Service struct per domain, provider interfaces for classes of problems, default implementations, mock implementations, and dependency injection for testability.
Follow multi-provider registry pattern: 1) Define interface in dedicated package, 2) Implement per provider, 3) Register implementations, 4) Generate mocks.

Files:

  • pkg/config/load_test.go
  • pkg/config/profiles_test.go
  • pkg/config/load.go
🧠 Learnings (19)
📚 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/config/profiles_test.go
📚 Learning: 2025-12-10T23:12:15.805Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-10T23:12:15.805Z
Learning: Applies to **/*_test.go : Test behavior, not implementation. Never test stub functions. Avoid tautological tests. Make code testable using DI. No coverage theater. Remove always-skipped tests. Table-driven tests need real scenarios. Use `assert.ErrorIs(err, ErrSentinel)` for our/stdlib errors.

Applied to files:

  • pkg/config/profiles_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:

  • pkg/config/profiles_test.go
📚 Learning: 2025-10-02T19:17:51.630Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 1504
File: pkg/profiler/profiler.go:20-31
Timestamp: 2025-10-02T19:17:51.630Z
Learning: In pkg/profiler/profiler.go, profiler-specific errors (ErrUnsupportedProfileType, ErrStartCPUProfile, ErrStartTraceProfile, ErrCreateProfileFile) must remain local and cannot be moved to errors/errors.go due to an import cycle: pkg/profiler → errors → pkg/schema → pkg/profiler. This is a valid exception to the centralized errors policy.

Applied to files:

  • pkg/config/profiles_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/config/profiles_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/config/profiles_test.go
📚 Learning: 2025-12-10T23:12:15.805Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-10T23:12:15.805Z
Learning: Applies to **/*.go : Add `defer perf.Track(atmosConfig, "pkg.FuncName")()` with a blank line to all public functions. Use `nil` if no atmosConfig parameter is available.

Applied to files:

  • pkg/config/profiles_test.go
📚 Learning: 2025-12-10T23:12:15.805Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-10T23:12:15.805Z
Learning: Applies to **/*_test.go : Tests skip gracefully with helpers from `tests/test_preconditions.go`.

Applied to files:

  • pkg/config/profiles_test.go
📚 Learning: 2025-11-11T03:47:59.576Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 1686
File: toolchain/which_test.go:166-223
Timestamp: 2025-11-11T03:47:59.576Z
Learning: In the cloudposse/atmos repo, tests that manipulate environment variables should use testing.T.Setenv for automatic setup/teardown instead of os.Setenv/Unsetenv.

Applied to files:

  • pkg/config/profiles_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:

  • pkg/config/profiles_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:

  • pkg/config/profiles_test.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/profiles_test.go
📚 Learning: 2025-12-10T23:12:15.805Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-10T23:12:15.805Z
Learning: Applies to **/*.go : Use functional options pattern for configuration instead of many parameters. Provides defaults and extensibility without breaking changes.

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: 2025-12-10T23:12:15.805Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-10T23:12:15.805Z
Learning: Applies to cmd/**/*.go : Configuration loading precedence: CLI flags → ENV vars → config files → defaults (use Viper).

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: 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: 2025-12-10T23:12:15.805Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-10T23:12:15.805Z
Learning: Applies to cmd/**/*.go : Use `viper.BindEnv("ATMOS_VAR", "ATMOS_VAR", "FALLBACK")` - ATMOS_ prefix required for environment variables.

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
🧬 Code graph analysis (1)
pkg/config/load.go (3)
pkg/schema/schema.go (1)
  • AtmosConfiguration (53-96)
pkg/xdg/xdg.go (1)
  • GetXDGCacheDir (33-35)
pkg/auth/provisioning/writer.go (1)
  • ProvisionedFileName (26-26)
⏰ Context from checks skipped due to timeout of 900000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Summary
🔇 Additional comments (1)
pkg/config/profiles_test.go (1)

489-568: Nice coverage for processFileImportsIfPresent happy-path / no-op / missing import.
This aligns with the “non-fatal import processing” design.

coderabbitai[bot]
coderabbitai bot previously approved these changes Dec 12, 2025
@codecov
Copy link

codecov bot commented Dec 13, 2025

Codecov Report

❌ Patch coverage is 70.50360% with 41 lines in your changes missing coverage. Please review.
✅ Project coverage is 73.48%. Comparing base (638d1b8) to head (42fbc93).
⚠️ Report is 1 commits behind head on main.

Files with missing lines Patch % Lines
pkg/config/load.go 56.94% 20 Missing and 11 partials ⚠️
pkg/config/provisioned_identity_case.go 89.79% 3 Missing and 2 partials ⚠️
internal/exec/terraform_output_utils.go 0.00% 3 Missing ⚠️
pkg/auth/list/formatter_table.go 50.00% 1 Missing and 1 partial ⚠️

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

Additional details and impacted files

Impacted file tree graph

@@            Coverage Diff             @@
##             main    #1865      +/-   ##
==========================================
+ Coverage   73.33%   73.48%   +0.15%     
==========================================
  Files         564      566       +2     
  Lines       54336    54732     +396     
==========================================
+ Hits        39847    40221     +374     
  Misses      11625    11625              
- Partials     2864     2886      +22     
Flag Coverage Δ
unittests 73.48% <70.50%> (+0.15%) ⬆️

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

Files with missing lines Coverage Δ
pkg/auth/list/formatter_tree.go 86.61% <100.00%> (+0.14%) ⬆️
pkg/auth/manager.go 85.76% <100.00%> (+0.14%) ⬆️
pkg/auth/list/formatter_table.go 93.10% <50.00%> (-1.27%) ⬇️
internal/exec/terraform_output_utils.go 68.04% <0.00%> (-0.54%) ⬇️
pkg/config/provisioned_identity_case.go 89.79% <89.79%> (ø)
pkg/config/load.go 75.72% <56.94%> (-2.55%) ⬇️

... and 17 files with indirect coverage changes

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

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

♻️ Duplicate comments (3)
pkg/config/load.go (2)

1027-1035: Guard correctly respects auto_provision_identities setting.

The nil check combined with the boolean check ensures cached identities are only loaded when explicitly enabled. This addresses the previous review concern.


1053-1075: Imports are re-processed for proper precedence.

Using mergeConfig(v, dir, name, true) ensures that overrides in user's imported files also take precedence over provisioned identities. This addresses the previous review concern.

pkg/config/profiles_test.go (1)

393-500: Precedence semantics are correctly tested.

The test at lines 439-447 verifies that importing file takes precedence over imported files (expects 120, not 80). The subdirectory placement at line 438 (importSubdir: "imports") prevents double-loading via directory scan.

📜 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 93d2e6b and e515409.

📒 Files selected for processing (6)
  • pkg/config/load.go (5 hunks)
  • pkg/config/load_test.go (1 hunks)
  • pkg/config/profiles_test.go (1 hunks)
  • tests/snapshots/TestCLICommands_Valid_Log_Level_in_Config_File.stderr.golden (1 hunks)
  • tests/snapshots/TestCLICommands_atmos_describe_config_imports.stderr.golden (1 hunks)
  • tests/snapshots/TestCLICommands_atmos_describe_configuration.stderr.golden (1 hunks)
🧰 Additional context used
📓 Path-based instructions (2)
**/*.go

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

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

**/*.go: Comment style: All comments must end with periods (enforced by godot linter)
Import organization: Three groups separated by blank lines (stdlib, 3rd-party, Atmos packages), sorted alphabetically within groups, maintain aliases: cfg, log, u, errUtils
Performance tracking: Add defer perf.Track(atmosConfig, "pkg.FuncName")() + blank line to all public functions. Use nil if no atmosConfig param
Error handling: ALL user-facing errors MUST use ErrorBuilder with sentinel errors from errors/errors.go. ALWAYS use errors.Is() for checking, NEVER string comparison. ALWAYS use assert.ErrorIs() in tests, NEVER assert.Contains(err.Error(), ...)
Mock generation: Use go.uber.org/mock/mockgen with //go:generate directives. Never manual mocks
File organization: Keep files small and focused (<600 lines). One cmd/impl per file. Co-locate tests. Never use `//revive:disable:file-lengt...

Files:

  • pkg/config/profiles_test.go
  • pkg/config/load.go
  • pkg/config/load_test.go
**/*_test.go

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

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

**/*_test.go: Test skipping conventions: Use t.Skipf("reason") with clear context. CLI tests auto-build temp binaries
Golden snapshots: NEVER manually edit golden snapshot files - Always use -regenerate-snapshots flag. Snapshots capture exact output including invisible formatting (lipgloss padding, ANSI codes, trailing whitespace). Different environments produce different output. Never use pipe redirection (2>&1, | head, | tail) when running tests as piping breaks TTY detection

Files:

  • pkg/config/profiles_test.go
  • pkg/config/load_test.go
🧠 Learnings (46)
📓 Common learnings
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.
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.
Learnt from: haitham911
Repo: cloudposse/atmos PR: 1085
File: pkg/config/load.go:219-221
Timestamp: 2025-02-24T22:46:39.744Z
Learning: In the Atmos configuration system, imports from atmos.d are optional. When import errors occur, they should be logged at debug level and the process should continue, rather than failing completely.
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: 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.
📚 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/config/profiles_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/config/profiles_test.go
📚 Learning: 2025-10-02T19:17:51.630Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 1504
File: pkg/profiler/profiler.go:20-31
Timestamp: 2025-10-02T19:17:51.630Z
Learning: In pkg/profiler/profiler.go, profiler-specific errors (ErrUnsupportedProfileType, ErrStartCPUProfile, ErrStartTraceProfile, ErrCreateProfileFile) must remain local and cannot be moved to errors/errors.go due to an import cycle: pkg/profiler → errors → pkg/schema → pkg/profiler. This is a valid exception to the centralized errors policy.

Applied to files:

  • pkg/config/profiles_test.go
📚 Learning: 2025-12-13T00:52:18.278Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-13T00:52:18.278Z
Learning: Applies to **/*.go : Import organization: Three groups separated by blank lines (stdlib, 3rd-party, Atmos packages), sorted alphabetically within groups, maintain aliases: `cfg`, `log`, `u`, `errUtils`

Applied to files:

  • pkg/config/profiles_test.go
  • 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 **/*_test.go : Use table-driven tests for testing multiple scenarios in Go

Applied to files:

  • pkg/config/profiles_test.go
📚 Learning: 2025-12-13T00:52:18.278Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-13T00:52:18.278Z
Learning: Applies to **/*.go : Configuration loading: Precedence: CLI flags → ENV vars → config files → defaults (use Viper)

Applied to files:

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

  • pkg/config/profiles_test.go
  • tests/snapshots/TestCLICommands_atmos_describe_config_imports.stderr.golden
📚 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/profiles_test.go
  • pkg/config/load.go
📚 Learning: 2025-09-10T21:17:55.273Z
Learnt from: samtholiya
Repo: cloudposse/atmos PR: 1466
File: toolchain/http_client_test.go:3-10
Timestamp: 2025-09-10T21:17:55.273Z
Learning: In the cloudposse/atmos repository, imports should never be changed as per samtholiya's coding guidelines.

Applied to files:

  • pkg/config/profiles_test.go
  • pkg/config/load.go
  • tests/snapshots/TestCLICommands_atmos_describe_config_imports.stderr.golden
📚 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/config/profiles_test.go
📚 Learning: 2025-11-11T03:47:59.576Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 1686
File: toolchain/which_test.go:166-223
Timestamp: 2025-11-11T03:47:59.576Z
Learning: In the cloudposse/atmos repo, tests that manipulate environment variables should use testing.T.Setenv for automatic setup/teardown instead of os.Setenv/Unsetenv.

Applied to files:

  • pkg/config/profiles_test.go
  • tests/snapshots/TestCLICommands_Valid_Log_Level_in_Config_File.stderr.golden
📚 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:

  • pkg/config/profiles_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:

  • pkg/config/profiles_test.go
  • tests/snapshots/TestCLICommands_Valid_Log_Level_in_Config_File.stderr.golden
📚 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
  • tests/snapshots/TestCLICommands_atmos_describe_configuration.stderr.golden
  • tests/snapshots/TestCLICommands_Valid_Log_Level_in_Config_File.stderr.golden
📚 Learning: 2024-12-25T20:28:19.618Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 887
File: internal/exec/workflow_utils.go:167-169
Timestamp: 2024-12-25T20:28:19.618Z
Learning: The user plans to revert the change from `path.Join` to `filepath.Join` in this PR due to testing gaps and will open a new PR to safely handle the migration without breaking `main`.

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
  • tests/snapshots/TestCLICommands_Valid_Log_Level_in_Config_File.stderr.golden
📚 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:

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

  • pkg/config/load.go
  • tests/snapshots/TestCLICommands_atmos_describe_configuration.stderr.golden
  • tests/snapshots/TestCLICommands_atmos_describe_config_imports.stderr.golden
📚 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-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
  • tests/snapshots/TestCLICommands_atmos_describe_config_imports.stderr.golden
  • tests/snapshots/TestCLICommands_Valid_Log_Level_in_Config_File.stderr.golden
📚 Learning: 2025-01-17T00:18:57.769Z
Learnt from: aknysh
Repo: cloudposse/atmos PR: 944
File: go.mod:206-206
Timestamp: 2025-01-17T00:18:57.769Z
Learning: For indirect dependencies with license compliance issues in the cloudposse/atmos repository, the team prefers to handle them in follow-up PRs rather than blocking the current changes, as these issues often require deeper investigation of the dependency tree.

Applied to files:

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

Applied to files:

  • 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: 2025-12-13T00:52:18.278Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-13T00:52:18.278Z
Learning: Applies to **/*.go : Environment variables: Use `viper.BindEnv("ATMOS_VAR", "ATMOS_VAR", "FALLBACK")` - ATMOS_ prefix required

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
  • tests/snapshots/TestCLICommands_Valid_Log_Level_in_Config_File.stderr.golden
📚 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-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/snapshots/TestCLICommands_atmos_describe_configuration.stderr.golden
  • tests/snapshots/TestCLICommands_atmos_describe_config_imports.stderr.golden
  • tests/snapshots/TestCLICommands_Valid_Log_Level_in_Config_File.stderr.golden
📚 Learning: 2024-10-20T13:12:46.499Z
Learnt from: haitham911
Repo: cloudposse/atmos PR: 736
File: pkg/config/const.go:6-6
Timestamp: 2024-10-20T13:12:46.499Z
Learning: In `cmd/cmd_utils.go`, it's acceptable to have hardcoded references to `atmos.yaml` in logs, and it's not necessary to update them to use the `CliConfigFileName` constant.

Applied to files:

  • tests/snapshots/TestCLICommands_atmos_describe_configuration.stderr.golden
  • tests/snapshots/TestCLICommands_atmos_describe_config_imports.stderr.golden
  • tests/snapshots/TestCLICommands_Valid_Log_Level_in_Config_File.stderr.golden
📚 Learning: 2025-02-14T23:12:38.030Z
Learnt from: Listener430
Repo: cloudposse/atmos PR: 1061
File: tests/snapshots/TestCLICommands_atmos_vendor_pull_ssh.stderr.golden:8-8
Timestamp: 2025-02-14T23:12:38.030Z
Learning: Test snapshots in the Atmos project, particularly for dry run scenarios, may be updated during the development process, and temporary inconsistencies in their content should not be flagged as issues.

Applied to files:

  • tests/snapshots/TestCLICommands_atmos_describe_configuration.stderr.golden
  • tests/snapshots/TestCLICommands_atmos_describe_config_imports.stderr.golden
  • tests/snapshots/TestCLICommands_Valid_Log_Level_in_Config_File.stderr.golden
📚 Learning: 2025-12-13T00:52:18.278Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-13T00:52:18.278Z
Learning: Test data: Use fixtures in `tests/test-cases/`: `atmos.yaml`, `stacks/`, `components/`. NEVER modify `tests/test-cases/` or `tests/testdata/` unless explicitly instructed. Golden snapshots are sensitive to minor changes

Applied to files:

  • tests/snapshots/TestCLICommands_atmos_describe_configuration.stderr.golden
  • tests/snapshots/TestCLICommands_atmos_describe_config_imports.stderr.golden
  • tests/snapshots/TestCLICommands_Valid_Log_Level_in_Config_File.stderr.golden
📚 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:

  • tests/snapshots/TestCLICommands_atmos_describe_configuration.stderr.golden
  • tests/snapshots/TestCLICommands_Valid_Log_Level_in_Config_File.stderr.golden
📚 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:

  • tests/snapshots/TestCLICommands_atmos_describe_configuration.stderr.golden
  • tests/snapshots/TestCLICommands_atmos_describe_config_imports.stderr.golden
📚 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:

  • tests/snapshots/TestCLICommands_atmos_describe_configuration.stderr.golden
📚 Learning: 2025-02-03T06:00:11.419Z
Learnt from: samtholiya
Repo: cloudposse/atmos PR: 959
File: cmd/describe_config.go:20-20
Timestamp: 2025-02-03T06:00:11.419Z
Learning: The `describe config` command should use `PrintErrorMarkdownAndExit` with empty title and suggestion for consistency with other commands.

Applied to files:

  • tests/snapshots/TestCLICommands_atmos_describe_configuration.stderr.golden
📚 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:

  • tests/snapshots/TestCLICommands_atmos_describe_configuration.stderr.golden
  • tests/snapshots/TestCLICommands_atmos_describe_config_imports.stderr.golden
  • tests/snapshots/TestCLICommands_Valid_Log_Level_in_Config_File.stderr.golden
📚 Learning: 2025-02-24T22:46:39.744Z
Learnt from: haitham911
Repo: cloudposse/atmos PR: 1085
File: pkg/config/load.go:219-221
Timestamp: 2025-02-24T22:46:39.744Z
Learning: In the Atmos configuration system, imports from atmos.d are optional. When import errors occur, they should be logged at debug level and the process should continue, rather than failing completely.

Applied to files:

  • tests/snapshots/TestCLICommands_atmos_describe_configuration.stderr.golden
  • tests/snapshots/TestCLICommands_atmos_describe_config_imports.stderr.golden
  • tests/snapshots/TestCLICommands_Valid_Log_Level_in_Config_File.stderr.golden
📚 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/snapshots/TestCLICommands_atmos_describe_configuration.stderr.golden
📚 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/snapshots/TestCLICommands_atmos_describe_configuration.stderr.golden
  • tests/snapshots/TestCLICommands_atmos_describe_config_imports.stderr.golden
📚 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:

  • tests/snapshots/TestCLICommands_atmos_describe_configuration.stderr.golden
  • tests/snapshots/TestCLICommands_Valid_Log_Level_in_Config_File.stderr.golden
📚 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/snapshots/TestCLICommands_atmos_describe_configuration.stderr.golden
📚 Learning: 2024-10-23T22:11:41.077Z
Learnt from: haitham911
Repo: cloudposse/atmos PR: 727
File: internal/exec/path_utils.go:145-146
Timestamp: 2024-10-23T22:11:41.077Z
Learning: In the `atmos` project, the preference is to print relative paths in log messages instead of full paths.

Applied to files:

  • tests/snapshots/TestCLICommands_atmos_describe_configuration.stderr.golden
  • tests/snapshots/TestCLICommands_atmos_describe_config_imports.stderr.golden
📚 Learning: 2025-12-13T00:52:18.278Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-13T00:52:18.278Z
Learning: Adding new CLI command: 1) Create `cmd/[command]/` with CommandProvider interface, 2) Add blank import to `cmd/root.go`: `_ "github.com/cloudposse/atmos/cmd/mycommand"`, 3) Implement in `internal/exec/mycommand.go`, 4) Add tests in `cmd/mycommand/mycommand_test.go`, 5) Create Docusaurus docs in `website/docs/cli/commands/<command>/<subcommand>.mdx`, 6) Build website: `cd website && npm run build`. See `docs/developing-atmos-commands.md` and `docs/prd/command-registry-pattern.md`

Applied to files:

  • tests/snapshots/TestCLICommands_atmos_describe_config_imports.stderr.golden
  • tests/snapshots/TestCLICommands_Valid_Log_Level_in_Config_File.stderr.golden
📚 Learning: 2025-04-03T11:00:27.980Z
Learnt from: haitham911
Repo: cloudposse/atmos PR: 1091
File: pkg/config/imports.go:0-0
Timestamp: 2025-04-03T11:00:27.980Z
Learning: The Atmos configuration system intentionally supports both HTTP and HTTPS protocols for remote imports, as confirmed by the project maintainers. This is implemented in the `isRemoteImport` and `processRemoteImport` functions in pkg/config/imports.go.

Applied to files:

  • tests/snapshots/TestCLICommands_atmos_describe_config_imports.stderr.golden
📚 Learning: 2025-02-03T05:57:18.407Z
Learnt from: samtholiya
Repo: cloudposse/atmos PR: 959
File: cmd/cmd_utils.go:121-148
Timestamp: 2025-02-03T05:57:18.407Z
Learning: The Atmos CLI should fail fast (exit) when encountering configuration errors, including command alias configuration issues, to prevent undefined behavior. Use LogErrorAndExit instead of returning errors in such cases.

Applied to files:

  • tests/snapshots/TestCLICommands_Valid_Log_Level_in_Config_File.stderr.golden
🧬 Code graph analysis (1)
pkg/config/load.go (3)
pkg/schema/schema.go (1)
  • AtmosConfiguration (53-96)
pkg/xdg/xdg.go (1)
  • GetXDGCacheDir (33-35)
pkg/auth/provisioning/writer.go (1)
  • ProvisionedFileName (26-26)
⏰ 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 (9)
tests/snapshots/TestCLICommands_atmos_describe_configuration.stderr.golden (1)

1-24: Snapshot reflects increased config loading iterations.

The additional "Loaded configuration directory" entries align with the new post-load provisioning and reapplication logic. Config is now loaded multiple times to support precedence semantics.

tests/snapshots/TestCLICommands_Valid_Log_Level_in_Config_File.stderr.golden (1)

7-32: Trace logs capture new provisioning workflow.

The new trace messages document the post-load provisioning checks and user config reapplication. This provides good observability into the config loading sequence.

pkg/config/load.go (3)

275-303: Post-load provisioning flow is well-structured.

The sequence is correct:

  1. Inject provisioned identities after profiles
  2. Re-apply user config for precedence
  3. Re-apply profiles if specified

Non-fatal error handling maintains resilience per the project's design philosophy. Based on learnings, errors during config file merging should be logged and continue rather than fail completely.


869-899: Clean helper for import processing.

Good separation of concerns. The early return when no imports exist avoids unnecessary work.


837-858: Import-first processing maintains correct precedence.

The comment at lines 842-844 is a helpful warning. Users should place import files in subdirectories to avoid double-loading.

pkg/config/profiles_test.go (1)

502-581: Good coverage for import processing edge cases.

Tests cover no imports, valid imports, and missing import files. The missing import file test correctly expects non-fatal behavior per project resilience guidelines.

pkg/config/load_test.go (2)

1039-1164: Comprehensive test coverage for post-load injection.

Table-driven tests cover all key scenarios including the auto_provision_identities guard (lines 1139-1163). Good use of t.TempDir() and t.Setenv() for test isolation.


1219-1288: End-to-end precedence test validates the complete flow.

This test correctly demonstrates that:

  1. Provisioned identities merge with existing config
  2. User config reapplication restores user-defined values
  3. Auto-provisioned identities not overridden by user persist

Solid integration test for the new functionality.

tests/snapshots/TestCLICommands_atmos_describe_config_imports.stderr.golden (1)

7-7: Snapshot correctly captures the new multi-stage processing flow.

The additional processConfigImports log entries align with the PR's new post-load provisioning and profile import handling. These duplicate messages appear to be intentional trace points showing the import resolution happening at multiple stages.

Worth confirming: if these represent separate logical stages (initial load, profile imports, post-load injection), the duplication makes sense. If they indicate redundant work, there might be room for optimization. Based on the AI summary mentioning "probe points", this looks intentional.

Also applies to: 9-9, 17-17, 21-21, 23-23

coderabbitai[bot]
coderabbitai bot previously approved these changes Dec 13, 2025
@github-actions github-actions bot added size/xl Extra large size PR and removed size/l Large size PR labels Dec 13, 2025
@mergify
Copy link

mergify bot commented Dec 13, 2025

Warning

This PR exceeds the recommended limit of 1,000 lines.

Large PRs are difficult to review and may be rejected due to their size.

Please verify that this PR does not address multiple issues.
Consider refactoring it into smaller, more focused PRs to facilitate a smoother review process.

@mergify
Copy link

mergify bot commented Dec 14, 2025

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

@mergify mergify bot added conflict This PR has conflicts and removed conflict This PR has conflicts labels Dec 14, 2025
coderabbitai[bot]
coderabbitai bot previously approved these changes Dec 14, 2025
coderabbitai[bot]
coderabbitai bot previously approved these changes Dec 14, 2025
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (4)
pkg/config/load_test.go (2)

1040-1189: injectProvisionedIdentitiesPostLoad tests cover key provisioning scenarios well.

The table-driven cases exercise no providers, providers without caches, enabled/disabled auto_provision_identities, and multi-provider behavior against the XDG cache layout, which is what this path needs. One tiny nit: the expectIdentitiesLoad field isn’t used anywhere and could be dropped or wired into assertions later.


1760-1791: XDG cache directory failure behavior is clearly specified.

TestPreserveProvisionedIdentityCase_XDGCacheDirError correctly simulates a file blocking directory creation and asserts that an error is returned, which ensures we don’t silently ignore fundamental cache-dir setup failures. If you later introduce a sentinel error for this path, consider switching to assert.ErrorIs to align with the repo’s preferred error-checking pattern.

pkg/auth/manager.go (1)

492-504: Consider normalizing the key inside GetIdentityDisplayName for robustness.

Today callers pass lowercase identity keys, so the lookup works. To make this more future-proof if a caller ever passes a mixed-case name, you could normalize inside the helper and still return the original input as a fallback:

-func (m *manager) GetIdentityDisplayName(lowercaseKey string) string {
-	defer perf.Track(nil, "auth.Manager.GetIdentityDisplayName")()
-
-	if m.config.IdentityCaseMap != nil {
-		if originalName, exists := m.config.IdentityCaseMap[lowercaseKey]; exists {
-			return originalName
-		}
-	}
-	return lowercaseKey
-}
+func (m *manager) GetIdentityDisplayName(identityKey string) string {
+	defer perf.Track(nil, "auth.Manager.GetIdentityDisplayName")()
+
+	key := strings.ToLower(identityKey)
+	if m.config.IdentityCaseMap != nil {
+		if originalName, exists := m.config.IdentityCaseMap[key]; exists {
+			return originalName
+		}
+	}
+	return identityKey
+}

This keeps current behavior while relaxing assumptions about caller input.

pkg/auth/list/formatter_tree.go (1)

440-445: Using displayName from AuthManager is a good improvement; consider a tiny fallback.

Pulling displayName via authManager.GetIdentityDisplayName(name) and using it consistently in the title keeps UI aligned with original identity casing while preserving behavior when authManager is nil. If GetIdentityDisplayName can ever return "", you might optionally fall back to name here to avoid blank titles, but that is purely defensive.

Also applies to: 460-463

📜 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 e2c1a6b and 42fbc93.

📒 Files selected for processing (12)
  • cmd/auth_console_test.go (2 hunks)
  • internal/exec/terraform_output_utils.go (1 hunks)
  • pkg/auth/hooks_test.go (1 hunks)
  • pkg/auth/list/formatter_table.go (2 hunks)
  • pkg/auth/list/formatter_tree.go (2 hunks)
  • pkg/auth/manager.go (1 hunks)
  • pkg/auth/manager_case_test.go (2 hunks)
  • pkg/auth/providers/aws/saml_test.go (1 hunks)
  • pkg/auth/types/interfaces.go (1 hunks)
  • pkg/auth/types/mock_interfaces.go (2 hunks)
  • pkg/config/load_test.go (4 hunks)
  • pkg/config/provisioned_identity_case.go (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • pkg/auth/manager_case_test.go
🧰 Additional context used
📓 Path-based instructions (4)
**/*.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: Comment style: All comments must end with periods (enforced by godot linter)
Import organization: Three groups separated by blank lines (stdlib, 3rd-party, Atmos packages), sorted alphabetically within groups, maintain aliases: cfg, log, u, errUtils
Performance tracking: Add defer perf.Track(atmosConfig, "pkg.FuncName")() + blank line to all public functions. Use nil if no atmosConfig param
Error handling: ALL user-facing errors MUST use ErrorBuilder with sentinel errors from errors/errors.go. ALWAYS use errors.Is() for checking, NEVER string comparison. ALWAYS use assert.ErrorIs() in tests, NEVER assert.Contains(err.Error(), ...)
Mock generation: Use go.uber.org/mock/mockgen with //go:generate directives. Never manual mocks
File organization: Keep files small and focused (<600 lines). One cmd/impl per file. Co-locate tests. Never use `//revive:disable:file-lengt...

Files:

  • pkg/auth/hooks_test.go
  • internal/exec/terraform_output_utils.go
  • pkg/auth/manager.go
  • pkg/auth/list/formatter_table.go
  • pkg/auth/providers/aws/saml_test.go
  • pkg/auth/types/interfaces.go
  • cmd/auth_console_test.go
  • pkg/auth/types/mock_interfaces.go
  • pkg/auth/list/formatter_tree.go
  • pkg/config/provisioned_identity_case.go
  • pkg/config/load_test.go
**/*_test.go

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

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

**/*_test.go: Test skipping conventions: Use t.Skipf("reason") with clear context. CLI tests auto-build temp binaries
Golden snapshots: NEVER manually edit golden snapshot files - Always use -regenerate-snapshots flag. Snapshots capture exact output including invisible formatting (lipgloss padding, ANSI codes, trailing whitespace). Different environments produce different output. Never use pipe redirection (2>&1, | head, | tail) when running tests as piping breaks TTY detection

Files:

  • pkg/auth/hooks_test.go
  • pkg/auth/providers/aws/saml_test.go
  • cmd/auth_console_test.go
  • pkg/config/load_test.go
cmd/**/*.go

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

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

Files:

  • cmd/auth_console_test.go
cmd/**/*_test.go

📄 CodeRabbit inference engine (CLAUDE.md)

cmd/**/*_test.go: Testing: Use cmd.NewTestKit(t) for cmd tests to auto-clean RootCmd state (flags, args)
Test isolation: ALWAYS use cmd.NewTestKit(t) for cmd tests to auto-clean RootCmd state (flags, args). Required for any test touching RootCmd

Files:

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

Applied to files:

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

Applied to files:

  • cmd/auth_console_test.go
📚 Learning: 2025-11-24T17:35:37.209Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: .cursor/rules/atmos-rules.mdc:0-0
Timestamp: 2025-11-24T17:35:37.209Z
Learning: Applies to **/*.go : Use interfaces for external dependencies to facilitate mocking and consider using testify/mock for creating mock implementations

Applied to files:

  • pkg/auth/types/mock_interfaces.go
📚 Learning: 2025-12-13T00:52:18.278Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-13T00:52:18.278Z
Learning: Interface-driven design: Define interfaces for all major functionality. Use dependency injection for testability. Generate mocks with `go.uber.org/mock/mockgen`. Avoid integration tests by mocking external dependencies

Applied to files:

  • pkg/auth/types/mock_interfaces.go
📚 Learning: 2025-12-13T00:52:18.278Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-13T00:52:18.278Z
Learning: Multi-provider registry: Follow registry pattern: 1) Define interface in dedicated package, 2) Implement per provider, 3) Register implementations, 4) Generate mocks. Example: `pkg/store/` with AWS SSM, Azure Key Vault, Google Secret Manager

Applied to files:

  • pkg/auth/types/mock_interfaces.go
📚 Learning: 2025-12-13T00:52:18.278Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-13T00:52:18.278Z
Learning: Testing strategy: 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. Integration tests in `tests/` only when necessary. Target >80% coverage

Applied to files:

  • pkg/auth/types/mock_interfaces.go
  • pkg/config/load_test.go
📚 Learning: 2025-12-13T00:52:18.278Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-13T00:52:18.278Z
Learning: Applies to **/*.go : Mock generation: Use `go.uber.org/mock/mockgen` with `//go:generate` directives. Never manual mocks

Applied to files:

  • pkg/auth/types/mock_interfaces.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:

  • pkg/config/provisioned_identity_case.go
  • pkg/config/load_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:

  • pkg/config/provisioned_identity_case.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: Final XDG Base Directory Specification implementation for atmos toolchain is complete and verified: toolchain/xdg_cache.go provides GetXDGCacheDir() and GetXDGTempCacheDir() functions, all hardcoded ~/.cache/tools-cache paths have been replaced with XDG-compliant paths using ${XDG_CACHE_HOME}/atmos-toolchain (or ~/.cache/atmos-toolchain fallback), and tests have been updated to expect the new path structure.

Applied to files:

  • pkg/config/provisioned_identity_case.go
  • pkg/config/load_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 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:

  • pkg/config/provisioned_identity_case.go
  • pkg/config/load_test.go
📚 Learning: 2024-12-13T15:33:34.159Z
Learnt from: Listener430
Repo: cloudposse/atmos PR: 844
File: pkg/config/cache.go:17-31
Timestamp: 2024-12-13T15:33:34.159Z
Learning: In `pkg/config/cache.go`, when `XDG_CACHE_HOME` is not set, falling back to `.` (current directory) is acceptable and aligns with the requirement to primarily use `XDG_CACHE_HOME` for the cache directory.

Applied to files:

  • pkg/config/provisioned_identity_case.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/provisioned_identity_case.go
  • pkg/config/load_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/config/load_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/config/load_test.go
📚 Learning: 2025-12-13T00:52:18.278Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-13T00:52:18.278Z
Learning: Test quality: Test behavior, not implementation. Never test stub functions - implement or remove. Avoid tautological tests - don't test hardcoded stubs return hardcoded values. Make code testable - use DI to avoid `os.Exit`, `CheckErrorPrintAndExit`, external systems. No coverage theater - validate real behavior. Remove always-skipped tests - fix or delete. Table-driven tests need real scenarios. Use `assert.ErrorIs(err, ErrSentinel)` for our/stdlib errors. String matching OK for third-party errors

Applied to files:

  • pkg/config/load_test.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_test.go
📚 Learning: 2025-03-12T21:38:42.699Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 1139
File: pkg/config/go-homedir/homedir.go:183-196
Timestamp: 2025-03-12T21:38:42.699Z
Learning: The code in pkg/config/go-homedir is a direct fork of the mitchellh/go-homedir package and was intentionally imported as-is without modifications to maintain consistency with the original source. Security concerns or other improvements may be addressed in future PRs.

Applied to files:

  • pkg/config/load_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:

  • pkg/config/load_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/config/load_test.go
📚 Learning: 2025-12-13T00:52:18.278Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-13T00:52:18.278Z
Learning: Applies to **/*.go : Cross-platform compatibility: Linux/macOS/Windows compatible. Use SDKs over binaries. Use `filepath.Join()`, not hardcoded separators

Applied to files:

  • pkg/config/load_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/config/load_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:

  • pkg/config/load_test.go
📚 Learning: 2025-11-10T23:23:39.771Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 1686
File: toolchain/registry/aqua/aqua_test.go:417-442
Timestamp: 2025-11-10T23:23:39.771Z
Learning: In Atmos toolchain AquaRegistry, tests should not hit real GitHub. Use the options pattern via WithGitHubBaseURL to inject an httptest server URL and make GetLatestVersion/GetAvailableVersions deterministic.

Applied to files:

  • pkg/config/load_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:

  • pkg/config/load_test.go
📚 Learning: 2025-12-13T03:21:27.620Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 1813
File: cmd/terraform/shell.go:28-73
Timestamp: 2025-12-13T03:21:27.620Z
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_test.go
📚 Learning: 2025-11-11T03:47:59.576Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 1686
File: toolchain/which_test.go:166-223
Timestamp: 2025-11-11T03:47:59.576Z
Learning: In the cloudposse/atmos repo, tests that manipulate environment variables should use testing.T.Setenv for automatic setup/teardown instead of os.Setenv/Unsetenv.

Applied to files:

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

Applied to files:

  • pkg/config/load_test.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_test.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_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/config/load_test.go
🧬 Code graph analysis (3)
pkg/auth/manager.go (1)
pkg/perf/perf.go (1)
  • Track (121-138)
pkg/config/provisioned_identity_case.go (4)
pkg/schema/schema.go (1)
  • AtmosConfiguration (53-96)
pkg/xdg/xdg.go (1)
  • GetXDGCacheDir (33-35)
pkg/logger/log.go (1)
  • Debug (24-26)
pkg/auth/provisioning/writer.go (1)
  • ProvisionedFileName (26-26)
pkg/config/load_test.go (2)
pkg/schema/schema.go (1)
  • AtmosConfiguration (53-96)
pkg/schema/schema_auth.go (2)
  • AuthConfig (4-12)
  • Provider (21-36)
⏰ 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 (linux)
  • GitHub Check: Acceptance Tests (macos)
  • GitHub Check: Summary
🔇 Additional comments (12)
pkg/config/provisioned_identity_case.go (1)

23-101: Provisioned identity case preservation and XDG usage look correct.

The helper cleanly scans atmos/auth/*/provisioned-identities.yaml, tolerates missing/unreadable files, and only backfills IdentityCaseMap entries that user config hasn’t set, which matches the documented precedence and the tests in load_test.go. No changes needed.

pkg/config/load_test.go (4)

6-7: Runtime import for OS-conditional tests is appropriate.

Using runtime.GOOS to skip the unreadable-file test on Windows is a straightforward way to keep the test portable.


1222-1291: User-vs-provisioned precedence flow is well specified.

TestUserConfigOverridesProvisionedIdentities accurately captures the desired merge order (provisioned then reapply user config) and verifies both overridden and non-overridden identities, which should guard against regressions in precedence handling.


1293-1705: Provisioned identity case-preservation tests are thorough.

The suite around preserveProvisionedIdentityCase and preserveProviderIdentityCase (mixed case identities, user precedence, edge YAML structures, nil/empty maps, multiple providers, nil map initialization, unreadable files, and XDG cache dir failures) gives excellent coverage of the new behavior and matches the implementation in provisioned_identity_case.go.


1793-1947: Helper tests for YAML extraction and provider-level case mapping are solid.

The direct tests of extractIdentitiesFromYAML and preserveProviderIdentityCase cover valid/malformed YAML, presence/absence of auth and identities, empty sections, and user-defined case precedence, which should make refactors to those helpers safe.

pkg/auth/providers/aws/saml_test.go (1)

139-168: stubSamlMgr update correctly tracks the AuthManager interface.

Adding GetIdentityDisplayName with a pass-through implementation keeps the stub compiling against the expanded interface without changing test behavior.

pkg/auth/list/formatter_table.go (1)

196-205: Identity table now respects original-case display names.

Using authManager.GetIdentityDisplayName(name) to populate the NAME column, with a nil-safe fallback to name, cleanly wires in the new case-preservation behavior without touching status or other columns.

Also applies to: 247-250

pkg/auth/types/interfaces.go (1)

226-230: AuthManager interface extension for display names is reasonable.

Adding GetIdentityDisplayName(lowercaseKey string) string centralizes identity case-resolution behind a single method, which matches how the manager already owns IdentityCaseMap. Implementations and mocks in this PR appear to have been updated accordingly.

internal/exec/terraform_output_utils.go (1)

69-74: authContextWrapper’s GetIdentityDisplayName implementation is appropriate.

Returning the key unchanged, with perf tracking, is a minimal and correct way to satisfy the extended AuthManager interface for this wrapper, which doesn’t own identity config or case maps.

Also applies to: 197-202

pkg/auth/hooks_test.go (1)

40-48: stubAuthManager update keeps hook tests aligned with AuthManager.

The added GetIdentityDisplayName passthrough matches the new interface contract without affecting existing hook test semantics.

cmd/auth_console_test.go (1)

674-676: New GetIdentityDisplayName stubs look correct.

Both mock implementations simply return the input name, which is a safe default and keeps these focused tests simple while satisfying the expanded AuthManager interface. No changes needed here.

Also applies to: 773-775

pkg/auth/types/mock_interfaces.go (1)

117-129: Generated gomock methods match the updated interfaces.

The added MockProvider.Name and MockAuthManager.GetIdentityDisplayName methods (and recorders) follow the same pattern as existing mocks and correctly mirror likely interface signatures. Regenerating via mockgen for future interface changes will keep this in sync.

Also applies to: 554-566

coderabbitai[bot]
coderabbitai bot previously approved these changes Dec 15, 2025
@mergify
Copy link

mergify bot commented Dec 16, 2025

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

@osterman osterman force-pushed the osterman/fix-identity-import branch from 23af48c to 6c4b2f5 Compare January 3, 2026 01:39
@mergify mergify bot removed the conflict This PR has conflicts label Jan 3, 2026
osterman and others added 13 commits January 16, 2026 08:23
Fix two related issues preventing provisioned identities from working:

1. Add injectProvisionedIdentitiesPostLoad() that runs after profiles are
   loaded, ensuring auth.providers (which may be defined in profiles) is
   available before checking for provisioned identity cache files.

2. Add processFileImportsIfPresent() to enable import: directives in profile
   files, which were previously silently ignored. Profile files are now
   processed for imports just like main config files.

This allows auth.providers defined in profiles to properly auto-discover
and load provisioned identities from the cache without manual import entries.

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

Co-Authored-By: Claude <noreply@anthropic.com>
Re-apply user config and profiles after provisioned identities are
injected, ensuring manually configured identities override
auto-provisioned ones. This allows users to customize or override
identities that were auto-provisioned from IAM Identity Center.

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

Co-Authored-By: Claude <noreply@anthropic.com>
The Debug-level log messages for provisioned identity operations
were appearing in test snapshots. These are internal implementation
details that should be Trace-level to avoid cluttering normal debug
output.

Also fix rangeValCopy linter warning by accessing map values by key.

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

Co-Authored-By: Claude <noreply@anthropic.com>
- Respect AutoProvisionIdentities setting when loading cached identities
  Only load cached provisioned identities when the provider has
  auto_provision_identities: true enabled. This ensures cached
  identities are only used when the feature is currently enabled.

- Use mergeConfig in reapplyUserConfigForPrecedence to process imports
  Changed from mergeConfigFile to mergeConfig so user config imports
  are also re-processed, ensuring user overrides in imported files
  take precedence over provisioned identities.

- Fix import precedence test to reflect correct semantics
  Updated test to verify "importing file takes precedence over imported
  files" rather than the reverse. Moved import files to subdirectory
  to prevent double-loading via directory scan.

- Update loadAtmosConfigsFromDirectory for correct precedence
  Process imports FIRST, then merge main file on top, aligning with
  mergeConfig() semantics.

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Provisioned identity names were being displayed in lowercase (e.g.,
"core-artifacts/administratoraccess") instead of their original case
(e.g., "core-artifacts/AdministratorAccess").

Root cause: The preserveIdentityCase function only read identity names
from the main config file, not from provisioned identity cache files.
When provisioned identities were loaded via Viper, their keys were
automatically lowercased, and the original case was lost.

Changes:
- Add preserveProvisionedIdentityCase() function to read provisioned
  identity cache files and populate IdentityCaseMap
- Respect user config precedence (user-defined case is not overwritten)
- Add unit tests for case preservation
- Add test cases for --identity flag case insensitivity

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The test for invalid YAML handling wasn't actually exercising the
invalid YAML path because the provider didn't have auto_provision_identities
enabled. Without this flag, the provider is skipped entirely and the
invalid YAML is never parsed.

Added auto_provision_identities: true to ensure the test actually
exercises the code path it's designed to test.

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
… preservation

Added table-driven tests for edge cases:
- auto_provision_identities disabled
- invalid YAML structure in cache file
- missing auth section in cache file
- missing identities section in cache file
- non-existent cache file
- empty identities section
- nil AutoProvisionIdentities (treated as disabled)

Also added tests for:
- Multiple providers (enabled, disabled, no cache)
- Nil IdentityCaseMap initialization

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add comprehensive tests to achieve 100% coverage for provisioned_identity_case.go:

- Extended TestPreserveProvisionedIdentityCase_EdgeCases with additional cases:
  - malformed_yaml_syntax: completely invalid YAML that fails parsing
  - auth_section_is_string: type assertion failure for auth section
  - identities_section_is_list: type assertion failure for identities

- TestPreserveProvisionedIdentityCase_UnreadableFile: file permission errors
- TestPreserveProvisionedIdentityCase_XDGCacheDirError: XDG directory errors
- TestExtractIdentitiesFromYAML: direct function tests for all branches
- TestPreserveProviderIdentityCase: direct function tests

Coverage improved to 100% for all three functions:
- preserveProvisionedIdentityCase: 100%
- preserveProviderIdentityCase: 100%
- extractIdentitiesFromYAML: 100%

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
File permissions work differently on Windows - setting 0o000 doesn't
prevent reading files like it does on Unix systems. Skip the test
on Windows since the behavior being tested is Unix-specific.

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Update the snapshot to include the new git root .atmos.d discovery
trace messages that were added by the parent directory search feature.

The snapshot now includes:
- "Using test Git root override" trace messages
- "Checking for .atmos.d in git root" trace messages
- "Checking for .atmos.d in config directory" trace messages
- path= suffixes on atmos.d loading failure messages

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Scan cache directory for all provider subdirectories instead of only
processing providers with auto_provision_identities: true. This ensures
identity case is preserved from cache files created by `auth login`
regardless of current config flags.

The IdentityCaseMap is only used for display purposes - this change
does not affect how identities are loaded or merged into config.

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The auth list command was showing provisioned identities in lowercase
(e.g., "core-artifacts/terraformapplyaccess") instead of preserving
the original case from AWS (e.g., "core-artifacts/TerraformApplyAccess").

This fix:
- Adds GetIdentityDisplayName() method to AuthManager interface
- Implements the method in manager.go to lookup original case from
  IdentityCaseMap
- Updates formatter_tree.go and formatter_table.go to use display names
- Adds test coverage for the display name functionality

The IdentityCaseMap is populated during config loading from the
provisioned identities cache file, which preserves the original case
from AWS SSO.

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Update the "Zero-config AWS SSO identity management" milestone to include
case preservation feature: identities now display with original case
(e.g., "TerraformApplyAccess") while supporting case-insensitive resolution.

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
coderabbitai[bot]
coderabbitai bot previously approved these changes Jan 16, 2026
Updates three golden snapshot files to reflect log message changes:
- New "Found atmos.yaml in current directory" trace message
- Log level change from DEBUG to TRACE for "Found config ENV"
- Additional "Preserved case-sensitive map keys" trace messages

These changes are expected from the identity case preservation feature
and rebase onto main.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
@mergify
Copy link

mergify bot commented Jan 21, 2026

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

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

Labels

conflict This PR has conflicts patch A minor, backward compatible change size/xl Extra large size PR

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant