-
-
Notifications
You must be signed in to change notification settings - Fork 132
feat: add !store.get
YAML function for arbitrary key retrieval
#1352
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
- Add GetKey method to Store interface for retrieving arbitrary keys - Implement GetKey method in all store implementations (Azure Key Vault, AWS SSM, Redis, Google Secret Manager, Artifactory) - Add !store.getkey YAML function constant and processor - Create comprehensive tests with table-driven test cases - Add RedisClient() method for testing arbitrary keys in Redis - Update documentation with usage examples and key differences from !store - Follow Atmos project rules for code quality, testing, and documentation
📝 WalkthroughWalkthroughAdds a new YAML function tag Changes
Sequence Diagram(s)sequenceDiagram
participant UserYAML as User YAML
participant Parser
participant Exec as processCustomTags
participant Handler as processTagStoreGet
participant Registry as StoreRegistry
participant Store as Store.GetKey
participant Backend as Backend Provider
UserYAML->>Parser: contains !store.get <store> <key> [| default | query]
Parser->>Exec: detect custom tag
Exec->>Handler: dispatch !store.get payload
Handler->>Registry: lookup <store> by name
Registry-->>Handler: store instance
Handler->>Store: GetKey(key)
Store->>Backend: fetch value
Backend-->>Store: raw value or error
Store-->>Handler: value (decoded JSON or raw) or error
alt query provided
Handler->>Handler: evaluate yq expression on value
end
Handler-->>Parser: resolved value or default/error
Parser-->>UserYAML: final resolved YAML value
Estimated code review effort🎯 4 (Complex) | ⏱️ ~35 minutes Possibly related PRs
Suggested labels
Suggested reviewers
Tip 🔌 Remote MCP (Model Context Protocol) integration is now available!Pro plan users can now connect to remote MCP servers from the Integrations page. Connect with popular remote MCPs such as Notion and Linear to add more context to your reviews and chats. 📜 Recent review detailsConfiguration used: .coderabbit.yaml 💡 Knowledge Base configuration:
You can enable these sources in your CodeRabbit configuration. 📒 Files selected for processing (1)
🚧 Files skipped from review as they are similar to previous changes (1)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (22)
✨ Finishing Touches
🧪 Generate unit tests
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. 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
SupportNeed help? Create a ticket on our support page for assistance with any issues or questions. CodeRabbit Commands (Invoked using PR/Issue comments)Type Other keywords and placeholders
Status, Documentation and Community
|
- Refactor processTagStoreGetKey function to reduce length (78 -> 45 lines) - Replace log.Fatal calls with proper error handling - Split function into smaller, focused functions - Restore .golangci.yml from main branch to fix configuration
a3a6334
to
c8f118d
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 4
♻️ Duplicate comments (2)
pkg/store/artifactory_store.go (1)
297-297
: Use compound assignment for string concatenation.For consistency with Go best practices, consider using compound assignment.
- filePath = filePath + ".json" + filePath += ".json"internal/exec/yaml_func_store_getkey.go (1)
64-107
: Address function length concern from static analysis.This function exceeds the 60-line limit flagged in past reviews. Consider extracting helper functions to improve maintainability.
Extract the store retrieval and value processing into separate functions:
func getStoreFromConfig(atmosConfig schema.AtmosConfiguration, storeName string) (schema.Store, error) { store := atmosConfig.Stores[storeName] if store == nil { return nil, fmt.Errorf("store not found: %s", storeName) } return store, nil } func processStoreValue(value interface{}, query string, atmosConfig *schema.AtmosConfiguration) (interface{}, error) { if query == "" { return value, nil } return u.EvaluateYqExpression(atmosConfig, value, query) }
🧹 Nitpick comments (1)
internal/exec/yaml_func_store_getkey.go (1)
32-46
: Improve quote handling in parameter parsing.The current quote removal approach could strip legitimate quotes from values. Consider using a more robust parsing method.
- v1 := strings.Trim(pipeParts[0], `"'`) // Remove surrounding quotes if present - v2 := strings.Trim(pipeParts[1], `"'`) + v1 := strings.TrimSpace(pipeParts[0]) + v2 := strings.TrimSpace(pipeParts[1]) + // Only remove quotes if they wrap the entire value + if (strings.HasPrefix(v2, `"`) && strings.HasSuffix(v2, `"`)) || + (strings.HasPrefix(v2, `'`) && strings.HasSuffix(v2, `'`)) { + v2 = v2[1 : len(v2)-1] + }
📜 Review details
Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (12)
.cursor/.cursor
(1 hunks)internal/exec/yaml_func_store_getkey.go
(1 hunks)internal/exec/yaml_func_store_getkey_test.go
(1 hunks)internal/exec/yaml_func_utils.go
(1 hunks)pkg/store/artifactory_store.go
(1 hunks)pkg/store/aws_ssm_param_store.go
(2 hunks)pkg/store/azure_keyvault_store.go
(1 hunks)pkg/store/google_secret_manager_store.go
(1 hunks)pkg/store/redis_store.go
(1 hunks)pkg/store/store.go
(1 hunks)pkg/utils/yaml_utils.go
(2 hunks)website/docs/core-concepts/stacks/yaml-functions/store.mdx
(1 hunks)
🧰 Additional context used
📓 Path-based instructions (2)
`website/**`: Keep website code in the website/ directory and follow the existing website architecture and style. Update website documentation in the website/ directory when adding...
website/**
: Keep website code in the website/ directory and follow the existing website architecture and style.
Update website documentation in the website/ directory when adding new features.
website/docs/core-concepts/stacks/yaml-functions/store.mdx
`pkg/*/*.go`: Organize feature implementations in subdirectories under pkg/ with separate files for each feature.
pkg/*/*.go
: Organize feature implementations in subdirectories under pkg/ with separate files for each feature.
pkg/utils/yaml_utils.go
pkg/store/store.go
pkg/store/aws_ssm_param_store.go
pkg/store/azure_keyvault_store.go
pkg/store/artifactory_store.go
pkg/store/redis_store.go
pkg/store/google_secret_manager_store.go
🪛 LanguageTool
website/docs/core-concepts/stacks/yaml-functions/store.mdx
[style] ~269-~269: Using many exclamation marks might seem excessive (in this case: 14 exclamation marks for a text that’s 4899 characters long)
Context: .../component/key pattern, use the regular [!store
](/core-concepts/stacks/yaml-funct...
(EN_EXCESSIVE_EXCLAMATION)
🪛 golangci-lint (1.64.8)
pkg/store/aws_ssm_param_store.go
[error] 300-300: error is not nil (line 298) but it returns nil
(nilerr)
pkg/store/azure_keyvault_store.go
[error] 226-226: error is not nil (line 224) but it returns nil
(nilerr)
pkg/store/redis_store.go
[error] 187-187: error is not nil (line 185) but it returns nil
(nilerr)
⏰ Context from checks skipped due to timeout of 90000ms (5)
- GitHub Check: Build (windows-latest, windows)
- GitHub Check: Analyze (go)
- GitHub Check: website-deploy-preview
- GitHub Check: Lint (golangci)
- GitHub Check: Summary
🔇 Additional comments (18)
pkg/store/store.go (1)
9-9
: Clean interface extension.The new
GetKey
method provides a clear contract for direct key retrieval across all store implementations. The method signature is well-designed and maintains consistency with existing patterns.pkg/utils/yaml_utils.go (2)
23-23
: YAML tag constant follows established conventions.The new constant is properly named and consistent with existing Atmos YAML function patterns.
37-37
: Proper tag registration.Adding the new tag to the global slice ensures it's recognized during YAML processing.
internal/exec/yaml_func_utils.go (1)
78-79
: Consistent integration with existing YAML function processing.The new case follows the established pattern exactly, maintaining code consistency and proper function delegation.
pkg/store/aws_ssm_param_store.go (3)
261-264
: Good input validation.Proper validation of the key parameter prevents downstream errors.
265-277
: Correct SSM parameter name construction.The logic properly handles prefix concatenation and ensures the parameter name starts with "/" as required by SSM.
296-302
: Correct JSON unmarshaling with string fallback.The error handling for JSON unmarshaling is appropriate - returning the raw string when JSON parsing fails is the intended behavior. The static analysis warning about this is a false positive.
pkg/store/artifactory_store.go (3)
282-285
: Good input validation.Proper validation prevents downstream errors in file operations.
287-302
: Clean file path construction logic.The path building with prefix handling and automatic .json extension addition is well-implemented.
333-340
: Consistent JSON unmarshaling pattern.The JSON unmarshaling with string fallback matches the pattern used in other store implementations, ensuring consistent behavior across backends.
website/docs/core-concepts/stacks/yaml-functions/store.mdx (1)
208-269
: Excellent documentation for the new!store.getkey
function!The documentation is comprehensive and well-structured. It clearly explains the key differences from the existing
!store
function, provides practical examples across different store types, and includes important considerations for users. The examples effectively demonstrate real-world usage patterns.pkg/store/azure_keyvault_store.go (1)
196-229
: Solid implementation of GetKey for Azure Key Vault store.The method follows the established patterns from other store implementations and handles Azure Key Vault-specific requirements well, including key normalization and proper error handling for different HTTP status codes. The JSON unmarshaling with string fallback is consistent with other stores.
internal/exec/yaml_func_store_getkey_test.go (1)
1-129
: Comprehensive test coverage for the new!store.getkey
function.The test implementation is excellent with good coverage of success cases, error scenarios, and edge cases. Using miniredis for realistic testing and the table-driven approach makes the tests maintainable and clear. The test data setup covers both store API usage and direct Redis access patterns.
pkg/store/google_secret_manager_store.go (1)
283-324
: Well-implemented GetKey method for Google Secret Manager.The implementation correctly handles Google Secret Manager specifics including proper secret name construction, timeout contexts for API calls, and appropriate gRPC error code handling. The pattern is consistent with other store implementations and follows established conventions.
pkg/store/redis_store.go (2)
156-190
: Good implementation of GetKey for Redis store.The method follows established patterns and handles Redis-specific conventions well, including the colon separator for prefixes and proper handling of "redis: nil" responses. The JSON unmarshaling with string fallback is consistent with other store implementations.
192-195
: Useful addition of RedisClient accessor for testing.This method enables direct access to the Redis client for test scenarios, as demonstrated in the test file. Clean and straightforward implementation.
internal/exec/yaml_func_store_getkey.go (2)
1-11
: Imports look solid.Clean package structure and appropriate dependencies for the functionality.
13-18
: Good struct design.The
storeGetKeyParams
struct is well-structured with appropriate field types. Using a pointer fordefaultValue
correctly handles the optional nature of this parameter.
Codecov Report❌ Patch coverage is Additional details and impacted files@@ Coverage Diff @@
## main #1352 +/- ##
==========================================
+ Coverage 55.16% 55.28% +0.11%
==========================================
Files 271 272 +1
Lines 28185 28444 +259
==========================================
+ Hits 15548 15725 +177
- Misses 10874 10943 +69
- Partials 1763 1776 +13
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
- Fix assignOp in artifactory store (filePath += ".json") - Fix error variable naming in AWS SSM store (unmarshalErr) - Fix error variable naming in Redis store (unmarshalErr) - Ensure proper error handling in JSON unmarshaling
fe0a390
to
470f51b
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 3
♻️ Duplicate comments (3)
pkg/store/aws_ssm_param_store.go (2)
280-290
: Implement role assumption for security consistency.The GetKey method bypasses role assumption unlike the existing Get method, creating a security inconsistency. Both methods should follow the same authentication pattern.
Apply the same role assumption pattern used in the Get method:
+ // Assume read role if specified + cfg, err := s.assumeRole(ctx, s.readRoleArn) + if err != nil { + return nil, fmt.Errorf("failed to assume read role: %w", err) + } + + // Use the same client if no role was assumed + client := s.client + if s.readRoleArn != nil { + // Create SSM client with assumed role if applicable + if s.newSSMClient != nil { + client = s.newSSMClient(*cfg) + } else { + client = ssm.NewFromConfig(*cfg) + } + } + - resp, err := s.client.GetParameter(context.TODO(), &ssm.GetParameterInput{ + resp, err := client.GetParameter(context.TODO(), &ssm.GetParameterInput{
298-300
: Fix the nilerr static analysis issue.The linter correctly identifies that when JSON unmarshaling fails, the error is not nil but you're returning nil instead of the error.
Apply this fix to properly handle the unmarshaling error:
- if unmarshalErr := json.Unmarshal([]byte(*resp.Parameter.Value), &result); unmarshalErr != nil { - // If JSON unmarshaling fails, return as string. - return *resp.Parameter.Value, nil - } + if err := json.Unmarshal([]byte(*resp.Parameter.Value), &result); err != nil { + // If JSON unmarshaling fails, return as string. + return *resp.Parameter.Value, nil + }internal/exec/yaml_func_store_getkey.go (1)
64-107
: Fix undefined variable causing compilation errors.The
function
variable is referenced multiple times but never defined, causing compilation failures.Define the function variable at the start of the method:
func processTagStoreGetKey(atmosConfig schema.AtmosConfiguration, input string, currentStack string) any { + function := u.AtmosYamlFuncStoreGetKey log.Debug("Executing Atmos YAML function", function, input)
🧹 Nitpick comments (2)
internal/exec/yaml_func_store_getkey.go (2)
20-20
: Fix comment formatting.Comment should end with a period per style guidelines.
-// parseStoreGetKeyInput parses the input string and returns storeGetKeyParams +// parseStoreGetKeyInput parses the input string and returns storeGetKeyParams.
64-64
: Pass heavy parameter by pointer.The
atmosConfig
parameter is 6KB+ and should be passed by pointer for performance.-func processTagStoreGetKey(atmosConfig schema.AtmosConfiguration, input string, currentStack string) any { +func processTagStoreGetKey(atmosConfig *schema.AtmosConfiguration, input string, currentStack string) any {Update the method body to use pointer dereferencing:
- store := atmosConfig.Stores[retParams.storeName] + store := atmosConfig.Stores[retParams.storeName] - res, err = u.EvaluateYqExpression(&atmosConfig, value, retParams.query) + res, err = u.EvaluateYqExpression(atmosConfig, value, retParams.query)
📜 Review details
Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (5)
internal/exec/yaml_func_store_getkey.go
(1 hunks)internal/exec/yaml_func_store_getkey_test.go
(1 hunks)pkg/store/artifactory_store.go
(1 hunks)pkg/store/aws_ssm_param_store.go
(2 hunks)pkg/store/redis_store.go
(1 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
- internal/exec/yaml_func_store_getkey_test.go
- pkg/store/artifactory_store.go
🧰 Additional context used
📓 Path-based instructions (1)
`pkg/*/*.go`: Organize feature implementations in subdirectories under pkg/ with separate files for each feature.
pkg/*/*.go
: Organize feature implementations in subdirectories under pkg/ with separate files for each feature.
pkg/store/aws_ssm_param_store.go
pkg/store/redis_store.go
🪛 GitHub Check: golangci-lint
internal/exec/yaml_func_store_getkey.go
[failure] 20-20:
Comment should end in a period
[failure] 34-34:
do not define dynamic errors, use wrapped static errors instead: "fmt.Errorf("invalid number of parameters after the pipe: %d", len(pipeParts))"
[failure] 44-44:
do not define dynamic errors, use wrapped static errors instead: "fmt.Errorf("invalid identifier after the pipe: %s", v1)"
[failure] 53-53:
do not define dynamic errors, use wrapped static errors instead: "fmt.Errorf("invalid number of parameters: %d", partsLength)"
[failure] 64-64:
hugeParam: atmosConfig is heavy (6072 bytes); consider passing it by pointer
pkg/store/aws_ssm_param_store.go
[failure] 300-300:
error is not nil (line 298) but it returns nil
pkg/store/redis_store.go
[failure] 187-187:
error is not nil (line 185) but it returns nil
🪛 golangci-lint (1.64.8)
pkg/store/aws_ssm_param_store.go
[error] 300-300: error is not nil (line 298) but it returns nil
(nilerr)
pkg/store/redis_store.go
[error] 187-187: error is not nil (line 185) but it returns nil
(nilerr)
⏰ Context from checks skipped due to timeout of 90000ms (2)
- GitHub Check: Build (windows-latest, windows)
- GitHub Check: Summary
🔇 Additional comments (1)
pkg/store/redis_store.go (1)
192-195
: Solid addition for testing support.The RedisClient method cleanly exposes the underlying client for test setup - good approach for enabling test scenarios with arbitrary keys.
…tation - Add period to comment in parseStoreGetKeyInput function - Replace dynamic errors with static errors for better error handling - Pass atmosConfig by pointer to avoid hugeParam warning - Add nolint comments for intentional JSON unmarshal error handling - Update function call signature in yaml_func_utils.go
6655161
to
113f804
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 2
♻️ Duplicate comments (2)
internal/exec/yaml_func_store_getkey.go (2)
72-73
: Fix undefined variable causing compilation errorThe variable
function
is undefined, causing compilation failures as noted in past reviews.Define the missing variable at the function start:
func processTagStoreGetKey(atmosConfig *schema.AtmosConfiguration, input string, currentStack string) any { + function := u.AtmosYamlFuncStoreGetKey log.Debug("Executing Atmos YAML function", function, input)
76-85
: Fix additional undefined variablesThe variable
invalidYamlFuncMsg
is also undefined and needs to be defined or replaced with a string literal.str, err := getStringAfterTag(input, u.AtmosYamlFuncStoreGetKey) if err != nil { - return fmt.Sprintf("%s: %s", invalidYamlFuncMsg, input) + return fmt.Sprintf("invalid YAML function: %s", input) } // Parse the input parameters. retParams, err := parseStoreGetKeyInput(str) if err != nil { - log.Error(invalidYamlFuncMsg, function, input, "error", err) - return fmt.Sprintf("%s: %s", invalidYamlFuncMsg, input) + log.Error("invalid YAML function", "function", function, "input", input, "error", err) + return fmt.Sprintf("invalid YAML function: %s", input) }Apply similar fixes to lines 90, 100, and 109 where
function
is used without the undefined variable fix.
📜 Review details
Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (5)
internal/exec/yaml_func_store_getkey.go
(1 hunks)internal/exec/yaml_func_store_getkey_test.go
(1 hunks)internal/exec/yaml_func_utils.go
(1 hunks)pkg/store/aws_ssm_param_store.go
(2 hunks)pkg/store/redis_store.go
(1 hunks)
🚧 Files skipped from review as they are similar to previous changes (3)
- internal/exec/yaml_func_utils.go
- pkg/store/aws_ssm_param_store.go
- pkg/store/redis_store.go
🧰 Additional context used
🪛 GitHub Check: Acceptance Tests (ubuntu-latest, linux)
internal/exec/yaml_func_store_getkey_test.go
[failure] 123-123:
cannot use atmosConfig (variable of struct type schema.AtmosConfiguration) as *schema.AtmosConfiguration value in argument to processTagStoreGetKey
[failure] 120-120:
cannot use atmosConfig (variable of struct type schema.AtmosConfiguration) as *schema.AtmosConfiguration value in argument to processTagStoreGetKey
⏰ Context from checks skipped due to timeout of 90000ms (3)
- GitHub Check: Acceptance Tests (macos-latest, macos)
- GitHub Check: Acceptance Tests (windows-latest, windows)
- GitHub Check: Summary
🔇 Additional comments (4)
internal/exec/yaml_func_store_getkey_test.go (1)
46-58
: Good test data setup approachThe approach of using the RedisClient() method to set arbitrary keys directly is solid and aligns well with testing the new
GetKey
functionality that retrieves keys by exact name rather than the stack/component/key pattern.internal/exec/yaml_func_store_getkey.go (3)
14-26
: Well-structured parameter handling and error definitionsGood use of static errors following Go best practices. The
storeGetKeyParams
struct clearly encapsulates all the necessary parameters for the operation.
28-70
: Solid parsing logic with comprehensive error handlingThe
parseStoreGetKeyInput
function handles the pipe-separated syntax well, supporting bothdefault
andquery
parameters. The validation logic properly catches malformed inputs.
94-114
: Excellent handling of store operations and YQ queriesThe core retrieval logic properly integrates with the new
GetKey
method and handles the optional YQ query processing. The fallback to default values when keys aren't found is well implemented.
- Fix test call to processTagStoreGetKey to pass pointer to atmosConfig - Match the updated function signature that accepts *schema.AtmosConfiguration - Ensure all tests pass with the new function signature
5e58bc0
to
fed8335
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
♻️ Duplicate comments (1)
internal/exec/yaml_func_store_getkey.go (1)
73-115
: Fix undefined variables causing compilation errors.The variables
function
andinvalidYamlFuncMsg
are used but not defined, which will cause compilation failures.Define these variables at the function level:
func processTagStoreGetKey(atmosConfig *schema.AtmosConfiguration, input string, currentStack string) any { + function := u.AtmosYamlFuncStoreGetKey + invalidYamlFuncMsg := "invalid YAML function" + log.Debug("Executing Atmos YAML function", function, input)
🧹 Nitpick comments (1)
internal/exec/yaml_func_store_getkey.go (1)
72-72
: Remove unused parameter.The
currentStack
parameter is not used in this function and should be removed for cleaner code.-func processTagStoreGetKey(atmosConfig *schema.AtmosConfiguration, input string, currentStack string) any { +func processTagStoreGetKey(atmosConfig *schema.AtmosConfiguration, input string) any {
📜 Review details
Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (2)
internal/exec/yaml_func_store_getkey.go
(1 hunks)internal/exec/yaml_func_store_getkey_test.go
(1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
- internal/exec/yaml_func_store_getkey_test.go
🧰 Additional context used
🪛 GitHub Check: golangci-lint
internal/exec/yaml_func_store_getkey.go
[failure] 72-72:
processTagStoreGetKey
- currentStack
is unused
⏰ Context from checks skipped due to timeout of 90000ms (14)
- GitHub Check: [mock-macos] tests/fixtures/scenarios/complete
- GitHub Check: [mock-windows] examples/demo-vendoring
- GitHub Check: [mock-windows] examples/demo-atlantis
- GitHub Check: [mock-windows] tests/fixtures/scenarios/complete
- GitHub Check: [mock-windows] examples/demo-context
- GitHub Check: [mock-linux] tests/fixtures/scenarios/complete
- GitHub Check: [mock-windows] examples/demo-component-versions
- GitHub Check: Acceptance Tests (windows-latest, windows)
- GitHub Check: Acceptance Tests (macos-latest, macos)
- GitHub Check: Acceptance Tests (ubuntu-latest, linux)
- GitHub Check: [k3s] demo-helmfile
- GitHub Check: [lint] Dockerfile
- GitHub Check: [localstack] demo-localstack
- GitHub Check: Summary
🔇 Additional comments (3)
internal/exec/yaml_func_store_getkey.go (3)
1-12
: Package structure looks solid.Clean imports and proper package organization. The aliased imports for log and utils follow good conventions.
14-26
: Good improvement on error handling.The struct design is clean and the static error variables properly address the previous feedback about avoiding dynamic error creation.
28-70
: Parser implementation is well-structured.The input parsing logic correctly handles the pipe-separated syntax and applies proper validation. Good use of the static errors with wrapping.
…ns and naming patterns
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
🔭 Outside diff range comments (1)
pkg/store/artifactory_store_test.go (1)
34-69
: Critical: Mock content writer can override test-provided file content.MockArtifactoryClient.DownloadFiles writes a default JSON payload on success, regardless of any file created in test-run hooks. In TestArtifactoryStore_GetKeyDirect you write custom content via .Run(), but it will be overwritten by this default write, causing false negatives.
Guard against overwriting if the file already exists.
Apply this diff:
func (m *MockArtifactoryClient) DownloadFiles(params ...services.DownloadParams) (int, int, error) { args := m.Called(params[0]) totalDownloaded := args.Int(0) totalFailed := args.Int(1) err := args.Error(2) // First check: if there's an error, return immediately. if err != nil { return totalDownloaded, totalFailed, err } // Second check: if there are failures, return without creating files. if totalFailed > 0 { return totalDownloaded, totalFailed, nil } // Third check: if no downloads, return without creating files. if totalDownloaded == 0 { return totalDownloaded, totalFailed, nil } // Only proceed with file creation for successful cases targetDir := params[0].Target filename := filepath.Base(params[0].Pattern) if err := os.MkdirAll(targetDir, 0o755); err != nil { return 0, 0, err } - data := []byte(`{"test":"value"}`) fullPath := filepath.Join(targetDir, filename) - if err := os.WriteFile(fullPath, data, 0o600); err != nil { - return 0, 0, err - } + // If test code already created the file (e.g., via .Run()), don't overwrite it. + if _, statErr := os.Stat(fullPath); os.IsNotExist(statErr) { + data := []byte(`{"test":"value"}`) + if err := os.WriteFile(fullPath, data, 0o600); err != nil { + return 0, 0, err + } + } return totalDownloaded, totalFailed, nil }
🧹 Nitpick comments (4)
pkg/store/google_secret_manager_store_test.go (2)
695-706
: Use a matcher for proto requests to avoid brittle equality on pointer/struct internals.Proto messages often carry hidden fields; matching the request by Name is more robust and mirrors earlier tests in this file.
Apply this diff to both branches:
- if tt.mockError != nil { - mockClient.On("AccessSecretVersion", mock.Anything, &secretmanagerpb.AccessSecretVersionRequest{ - Name: expectedFullPath, - }).Return(nil, tt.mockError) - } else { - mockClient.On("AccessSecretVersion", mock.Anything, &secretmanagerpb.AccessSecretVersionRequest{ - Name: expectedFullPath, - }).Return(&secretmanagerpb.AccessSecretVersionResponse{ - Payload: &secretmanagerpb.SecretPayload{ - Data: tt.mockPayload, - }, - }, nil) - } + if tt.mockError != nil { + mockClient.On("AccessSecretVersion", mock.Anything, + mock.MatchedBy(func(req *secretmanagerpb.AccessSecretVersionRequest) bool { + return req.GetName() == expectedFullPath + }), + ).Return(nil, tt.mockError) + } else { + mockClient.On("AccessSecretVersion", mock.Anything, + mock.MatchedBy(func(req *secretmanagerpb.AccessSecretVersionRequest) bool { + return req.GetName() == expectedFullPath + }), + ).Return(&secretmanagerpb.AccessSecretVersionResponse{ + Payload: &secretmanagerpb.SecretPayload{ + Data: tt.mockPayload, + }, + }, nil) + }
639-647
: Minor: Align error message expectation with the mapping behavior.You’re setting the gRPC error message to "secret not found" while asserting "resource not found". If the implementation normalizes NotFound to "resource not found", this is fine. If not, consider asserting with errors.Is against a sentinel (e.g., ErrResourceNotFound) for stability, similar to other tests in this package.
pkg/store/azure_keyvault_store_test.go (1)
380-389
: Prefer sentinel error checks over substring matches.To keep tests resilient to message changes, assert with errors.Is against domain errors (e.g., ErrResourceNotFound, ErrPermissionDenied) if GetKey maps SDK errors to sentinels (as done in Get tests).
pkg/store/artifactory_store_test.go (1)
417-562
: Optional: Add a case for "downloads=1, fails>0" to assert failure handling.You already cover "error != nil" and "downloads=0". Adding "downloads>0, fails>0, err=nil" helps validate the fails path.
📜 Review details
Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
💡 Knowledge Base configuration:
- MCP integration is disabled by default for public repositories
- Jira integration is disabled by default for public repositories
- Linear integration is disabled by default for public repositories
You can enable these settings in your CodeRabbit configuration.
📒 Files selected for processing (3)
pkg/store/artifactory_store_test.go
(1 hunks)pkg/store/azure_keyvault_store_test.go
(1 hunks)pkg/store/google_secret_manager_store_test.go
(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
Use interfaces for external dependencies to facilitate mocking
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)
Consider using a custom error type for domain-specific errors
Follow standard Go coding style
Use gofmt and goimports to format code
Prefer short, descriptive variable names
Use snake_case for environment variables
Document all exported functions, types, and methods
Document complex logic with inline comments
Follow Go's documentation conventions
Use Viper for configuration management
Support configuration via files, environment variables, and flags
Follow the precedence order: flags > environment variables > config file > defaults
Files:
pkg/store/azure_keyvault_store_test.go
pkg/store/google_secret_manager_store_test.go
pkg/store/artifactory_store_test.go
**/*_test.go
📄 CodeRabbit Inference Engine (.cursor/rules/atmos-rules.mdc)
**/*_test.go
: Every new feature must include comprehensive unit tests
Test both happy paths and error conditions
Use table-driven tests for testing multiple scenarios
Include integration tests for command flows
Test CLI end-to-end when possible
Use test fixtures for complex inputs
Consider using testify/mock for creating mock implementations
Files:
pkg/store/azure_keyvault_store_test.go
pkg/store/google_secret_manager_store_test.go
pkg/store/artifactory_store_test.go
🧠 Learnings (2)
📚 Learning: 2025-07-01T02:22:25.901Z
Learnt from: CR
PR: cloudposse/atmos#0
File: .cursor/rules/atmos-rules.mdc:0-0
Timestamp: 2025-07-01T02:22:25.901Z
Learning: Applies to **/*_test.go : Test both happy paths and error conditions
Applied to files:
pkg/store/azure_keyvault_store_test.go
pkg/store/google_secret_manager_store_test.go
pkg/store/artifactory_store_test.go
📚 Learning: 2025-07-01T02:22:25.901Z
Learnt from: CR
PR: cloudposse/atmos#0
File: .cursor/rules/atmos-rules.mdc:0-0
Timestamp: 2025-07-01T02:22:25.901Z
Learning: Applies to **/*_test.go : Use table-driven tests for testing multiple scenarios
Applied to files:
pkg/store/google_secret_manager_store_test.go
pkg/store/artifactory_store_test.go
🧬 Code Graph Analysis (3)
pkg/store/azure_keyvault_store_test.go (1)
pkg/store/azure_keyvault_store.go (1)
AzureKeyVaultStore
(33-38)
pkg/store/google_secret_manager_store_test.go (1)
pkg/store/google_secret_manager_store.go (1)
GSMStore
(32-38)
pkg/store/artifactory_store_test.go (1)
pkg/store/artifactory_store.go (1)
ArtifactoryStore
(25-30)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (4)
- GitHub Check: Build (windows-latest, windows)
- GitHub Check: Lint (golangci)
- GitHub Check: website-deploy-preview
- GitHub Check: Summary
🔇 Additional comments (3)
pkg/store/google_secret_manager_store_test.go (1)
604-725
: Nice, comprehensive table-driven coverage for direct key retrieval (GSM).Covers string, JSON object/array, empty, malformed JSON, and error mappings (NotFound, PermissionDenied, Internal). Clear assertions and good use of payload bytes.
pkg/store/azure_keyvault_store_test.go (1)
280-392
: Solid direct-key coverage for Azure Key Vault.Thorough scenarios (string, JSON object/array, empty, malformed JSON, 404/403). The name normalization assertion is a nice touch.
pkg/store/artifactory_store_test.go (1)
523-544
: Good: Verifies download pattern precisely and injects custom content per case.The MatchedBy on services.DownloadParams keeps the test decoupled from internal struct fields while validating the path construction logic.
- Create MockArtifactoryClientForGetKey with configurable file content - Fixes test failures where hardcoded mock data was interfering with test cases - All GetKey tests now pass across all store implementations
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
🧹 Nitpick comments (6)
pkg/store/artifactory_store_test.go (6)
417-417
: Fix lint: comment should end with a period.golangci-lint flagged this. Add a trailing period.
-// Custom mock client for GetKey tests that can return different file contents +// Custom mock client for GetKey tests that can return different file contents.
423-451
: Solid mock; add a small guard to avoid potential panic on empty variadic args.Defensive check to prevent params[0] panics if the signature is ever invoked without args. Purely a test helper, so low risk.
func (m *MockArtifactoryClientForGetKey) DownloadFiles(params ...services.DownloadParams) (int, int, error) { + if len(params) == 0 { + return 0, 0, fmt.Errorf("no download params provided") + } args := m.Called(params[0]) totalDownloaded := args.Int(0) totalFailed := args.Int(1) err := args.Error(2) if err != nil { return totalDownloaded, totalFailed, err }
457-457
: Rename test to reflect the method under test.The test calls
store.GetKey(...)
, notGetKeyDirect
. Rename for clarity.-func TestArtifactoryStore_GetKeyDirect(t *testing.T) { +func TestArtifactoryStore_GetKey(t *testing.T) {
457-459
: Optionally run the parent test in parallel.This can speed up CI if file targets are isolated by the implementation.
If you adopt subtest parallelization (see next comment), also parallelize the parent:
-func TestArtifactoryStore_GetKey(t *testing.T) { +func TestArtifactoryStore_GetKey(t *testing.T) { + t.Parallel()Please verify that
ArtifactoryStore.GetKey
uses unique temp directories (e.g.,os.MkdirTemp
) to avoid cross-test interference before enabling this.
458-469
: Preferany
overinterface{}
in tests.Go 1.18+ alias improves readability.
- expectedValue interface{} + expectedValue any
551-554
: Parallelize subtests safely.To avoid subtest data races when using
t.Parallel()
, rebind the loop variable and parallelize inside eacht.Run
.- for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { + for _, tt := range tests { + tt := tt + t.Run(tt.name, func(t *testing.T) { + t.Parallel()
📜 Review details
Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
💡 Knowledge Base configuration:
- MCP integration is disabled by default for public repositories
- Jira integration is disabled by default for public repositories
- Linear integration is disabled by default for public repositories
You can enable these sources in your CodeRabbit configuration.
📒 Files selected for processing (1)
pkg/store/artifactory_store_test.go
(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
Use interfaces for external dependencies to facilitate mocking
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)
Consider using a custom error type for domain-specific errors
Follow standard Go coding style
Use gofmt and goimports to format code
Prefer short, descriptive variable names
Use snake_case for environment variables
Document all exported functions, types, and methods
Document complex logic with inline comments
Follow Go's documentation conventions
Use Viper for configuration management
Support configuration via files, environment variables, and flags
Follow the precedence order: flags > environment variables > config file > defaults
Files:
pkg/store/artifactory_store_test.go
**/*_test.go
📄 CodeRabbit Inference Engine (.cursor/rules/atmos-rules.mdc)
**/*_test.go
: Every new feature must include comprehensive unit tests
Test both happy paths and error conditions
Use table-driven tests for testing multiple scenarios
Include integration tests for command flows
Test CLI end-to-end when possible
Use test fixtures for complex inputs
Consider using testify/mock for creating mock implementations
Files:
pkg/store/artifactory_store_test.go
🧬 Code Graph Analysis (1)
pkg/store/artifactory_store_test.go (1)
pkg/store/artifactory_store.go (1)
ArtifactoryStore
(25-30)
🪛 GitHub Check: golangci-lint
pkg/store/artifactory_store_test.go
[failure] 417-417:
Comment should end in a period
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
- GitHub Check: Build (windows-latest, windows)
- GitHub Check: Summary
🔇 Additional comments (1)
pkg/store/artifactory_store_test.go (1)
565-571
: Confirmed — test pattern matches implementationGetKey in pkg/store/artifactory_store.go appends ".json" when missing, builds repoPath with filepath.Join(s.repoName, filePath), and sets downloadParams.Pattern = repoPath. The test's expectedPattern (fmt.Sprintf("test-repo/%s/%s.json", tt.prefix, tt.key) in pkg/store/artifactory_store_test.go) matches that behavior.
- Checked: pkg/store/artifactory_store.go — func (s *ArtifactoryStore) GetKey
- Checked: pkg/store/artifactory_store_test.go — expectedPattern and mock for DownloadFiles
No change required.
- Fix errcheck issues by properly handling ignored errors with underscore assignment - Fix staticcheck issue by replacing if-else chain with tagged switch - All linting issues now resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 2
♻️ Duplicate comments (1)
pkg/store/artifactory_store_test.go (1)
417-417
: Doc comment should start with the type name and end with a period.Keeps golangci-lint happy and matches Go doc conventions.
-// Custom mock client for GetKey tests that can return different file contents +// MockArtifactoryClientForGetKey is a test mock that can return different file contents.
🧹 Nitpick comments (7)
pkg/store/artifactory_store_test.go (2)
423-451
: Defensive guard against empty params to avoid potential panic in mock.Future changes could call DownloadFiles with no params; this avoids an index out-of-range.
func (m *MockArtifactoryClientForGetKey) DownloadFiles(params ...services.DownloadParams) (int, int, error) { + if len(params) == 0 { + return 0, 0, fmt.Errorf("no download params provided") + } args := m.Called(params[0]) totalDownloaded := args.Int(0) totalFailed := args.Int(1) err := args.Error(2) if err != nil { return totalDownloaded, totalFailed, err }
457-590
: Strengthen test coverage for edge cases and enable parallel subtests.
- Add a case for “fails > 0 with nil error” to ensure we still surface a “failed to download file” error.
- Run subtests in parallel for speed (this table test doesn’t mutate globals).
Add the missing test case:
@@ { name: "download error", key: "error-config", prefix: "configs", mockDownloads: 0, mockFails: 1, mockError: fmt.Errorf("network error"), fileContent: nil, expectedValue: nil, expectError: true, errorContains: "failed to download file", }, + { + name: "failed download without error", + key: "partial-failure", + prefix: "configs", + mockDownloads: 0, + mockFails: 1, + mockError: nil, + fileContent: nil, + expectedValue: nil, + expectError: true, + errorContains: "failed to download file", + },Run each subtest in parallel:
@@ for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { + t.Parallel()
Optional: you can also add a “no downloads, no error” case (mockDownloads=0, mockFails=0, mockError=nil) to assert a consistent error message.
pkg/store/google_secret_manager_store.go (5)
65-72
: Drop redundant Close() after NewClient errorNewClient returns a nil client on error. The guard makes it safe, but the Close() adds noise and no value here.
client, err := secretmanager.NewClient(ctx, clientOpts...) if err != nil { - // Close the client to prevent resource leaks - if client != nil { - _ = client.Close() - } return nil, fmt.Errorf(errWrapFormat, ErrCreateClient, err) }
282-285
: Add doc comment for exported method GetKeyExported methods must be documented (golangci-lint). Add a short docstring.
+// GetKey retrieves a value by secret ID or full resource name from Google Secret Manager. +// If a prefix is configured and the key is a bare secret ID, the prefix is prepended. func (s *GSMStore) GetKey(key string) (interface{}, error) {
291-294
: Use the existing separator constant instead of hardcoding "_"Avoid magic strings. Use gsmKeySeparator for consistency.
- if s.prefix != "" { - secretName = s.prefix + "_" + key - } + if s.prefix != "" { + secretName = s.prefix + gsmKeySeparator + key + }
288-299
: Support full resource names and sanitize secret IDsAllow passing a full GSM resource name (projects/.../secrets/.../versions/...), and normalize secret IDs by replacing "/" with the GSM separator when a bare ID is provided to prevent malformed paths.
- // Use the key directly as the secret name - secretName := key - - // If prefix is set, prepend it to the key - if s.prefix != "" { - secretName = s.prefix + "_" + key - } - - // Construct the full secret name - fullSecretName := fmt.Sprintf("projects/%s/secrets/%s/versions/latest", s.projectID, secretName) + var fullSecretName string + // If key is a full resource name, use it verbatim + if strings.HasPrefix(key, "projects/") { + fullSecretName = key + } else { + // Treat key as a secret ID, optionally prefixed + secretName := key + if s.prefix != "" { + secretName = s.prefix + gsmKeySeparator + key + } + // Normalize illegal path separators in secret IDs + secretName = strings.ReplaceAll(secretName, "/", gsmKeySeparator) + // Construct the full secret resource name + fullSecretName = fmt.Sprintf("projects/%s/secrets/%s/versions/latest", s.projectID, secretName) + }
283-324
: Add tests for full resource names and PermissionDenied mappingEdge paths: full resource names (“projects/.../secrets/.../versions/...”) and permission-denied errors. Add table entries to assert both behaviors for GetKey.
I can draft test cases for these, including mocking GSMClient.AccessSecretVersion to return codes.PermissionDenied, and a success path with a full resource name. Want me to open a PR to augment pkg/store/google_secret_manager_store_test.go?
📜 Review details
Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
💡 Knowledge Base configuration:
- MCP integration is disabled by default for public repositories
- Jira integration is disabled by default for public repositories
- Linear integration is disabled by default for public repositories
You can enable these sources in your CodeRabbit configuration.
📒 Files selected for processing (4)
pkg/store/artifactory_store.go
(3 hunks)pkg/store/artifactory_store_test.go
(2 hunks)pkg/store/google_secret_manager_store.go
(2 hunks)pkg/store/google_secret_manager_store_test.go
(2 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
- pkg/store/google_secret_manager_store_test.go
- pkg/store/artifactory_store.go
🧰 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
Use interfaces for external dependencies to facilitate mocking
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)
Consider using a custom error type for domain-specific errors
Follow standard Go coding style
Use gofmt and goimports to format code
Prefer short, descriptive variable names
Use snake_case for environment variables
Document all exported functions, types, and methods
Document complex logic with inline comments
Follow Go's documentation conventions
Use Viper for configuration management
Support configuration via files, environment variables, and flags
Follow the precedence order: flags > environment variables > config file > defaults
Files:
pkg/store/google_secret_manager_store.go
pkg/store/artifactory_store_test.go
**/*_test.go
📄 CodeRabbit Inference Engine (.cursor/rules/atmos-rules.mdc)
**/*_test.go
: Every new feature must include comprehensive unit tests
Test both happy paths and error conditions
Use table-driven tests for testing multiple scenarios
Include integration tests for command flows
Test CLI end-to-end when possible
Use test fixtures for complex inputs
Consider using testify/mock for creating mock implementations
Files:
pkg/store/artifactory_store_test.go
🧬 Code Graph Analysis (2)
pkg/store/google_secret_manager_store.go (1)
pkg/store/errors.go (3)
ErrEmptyKey
(10-10)ErrResourceNotFound
(24-24)ErrAccessSecret
(23-23)
pkg/store/artifactory_store_test.go (1)
pkg/store/artifactory_store.go (1)
ArtifactoryStore
(25-30)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (5)
- GitHub Check: Build (macos-latest, macos)
- GitHub Check: Build (windows-latest, windows)
- GitHub Check: Lint (golangci)
- GitHub Check: Analyze (go)
- GitHub Check: website-deploy-preview
🔇 Additional comments (1)
pkg/store/google_secret_manager_store.go (1)
283-324
: Keep GetKey signature as (interface{}, error) — Store interface uses interface{}Store interface and all current GetKey implementations use interface{}, so change should not be made only in GSMStore. If you want to switch to any, update the Store interface and every implementation together.
Files to note:
- pkg/store/store.go — type Store interface (GetKey returns (interface{}, error))
- pkg/store/redis_store.go — GetKey(...)
- pkg/store/google_secret_manager_store.go — GetKey(...)
- pkg/store/aws_ssm_param_store.go — GetKey(...)
- pkg/store/artifactory_store.go — GetKey(...)
- pkg/store/azure_keyvault_store.go — GetKey(...)
Ignore the suggested diff in the original comment; keep the signature as-is or change it project-wide.
Likely an incorrect or invalid review comment.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 1
🔭 Outside diff range comments (1)
internal/exec/yaml_func_store.go (1)
41-54
: Fix undefined identifiers in logging; use literal keys and message.References to invalidYamlFuncMsg and variable function will not compile. Use a literal message and "function" as the key consistently.
Apply this diff:
- if len(pipeParts) != 2 { - log.Error(invalidYamlFuncMsg, function, input, "invalid number of parameters after the pipe", len(pipeParts)) - return fmt.Sprintf("%s: %s", invalidYamlFuncMsg, input) - } + if len(pipeParts) != 2 { + log.Error("invalid YAML function", "function", input, "reason", "invalid number of parameters after the pipe", "count", len(pipeParts)) + return fmt.Sprintf("invalid YAML function: %s", input) + } @@ - default: - log.Error(invalidYamlFuncMsg, function, input, "invalid identifier after the pipe", v1) - return fmt.Sprintf("%s: %s", invalidYamlFuncMsg, input) + default: + log.Error("invalid YAML function", "function", input, "reason", "invalid identifier after the pipe", "identifier", v1) + return fmt.Sprintf("invalid YAML function: %s", input) @@ - if partsLength != 3 && partsLength != 4 { - log.Error(invalidYamlFuncMsg, function, input, "invalid number of parameters", partsLength) - return fmt.Sprintf("%s: %s", invalidYamlFuncMsg, input) - } + if partsLength != 3 && partsLength != 4 { + log.Error("invalid YAML function", "function", input, "reason", "invalid number of parameters", "count", partsLength) + return fmt.Sprintf("invalid YAML function: %s", input) + }Also applies to: 62-64
♻️ Duplicate comments (1)
internal/exec/yaml_func_store.go (1)
23-109
: Function length exceeds linter threshold; consider extracting helpers.processTagStore is lengthy and handles parsing, validation, store lookup, defaulting, and querying. Extracting parsing into helpers will drop complexity and satisfy function-length checks.
Happy to propose a small refactor if you want it in this PR.
🧹 Nitpick comments (5)
internal/exec/yaml_func_store.go (1)
33-56
: Optional: make pipe parsing robust to values with spaces (default/query).strings.Fields forces exactly two tokens; quoted values with spaces (e.g., default "hello world") will be rejected. Consider parsing by prefix and capturing the remainder.
Apply this diff to the pipe parsing block:
- // Default value and query - var defaultValue *string - var query string - if len(parts) > 1 { - // Expecting the format: default <value> or query <yq-expression> - for _, p := range parts[1:] { - pipeParts := strings.Fields(strings.TrimSpace(p)) - if len(pipeParts) != 2 { - log.Error("invalid YAML function", "function", input, "reason", "invalid number of parameters after the pipe", "count", len(pipeParts)) - return fmt.Sprintf("invalid YAML function: %s", input) - } - v1 := strings.Trim(pipeParts[0], `"'`) - v2 := strings.Trim(pipeParts[1], `"'`) - switch v1 { - case "default": - defaultValue = &v2 - case "query": - query = v2 - default: - log.Error("invalid YAML function", "function", input, "reason", "invalid identifier after the pipe", "identifier", v1) - return fmt.Sprintf("invalid YAML function: %s", input) - } - } - } + // Default value and query + var defaultValue *string + var query string + if len(parts) > 1 { + for _, raw := range parts[1:] { + p := strings.TrimSpace(raw) + switch { + case strings.HasPrefix(p, "default "): + v := strings.TrimSpace(strings.TrimPrefix(p, "default ")) + v = strings.Trim(v, `"'`) + dv := v + defaultValue = &dv + case strings.HasPrefix(p, "query "): + v := strings.TrimSpace(strings.TrimPrefix(p, "query ")) + v = strings.Trim(v, `"'`) + query = v + default: + log.Error("invalid YAML function", "function", input, "reason", "invalid pipe identifier", "payload", p) + return fmt.Sprintf("invalid YAML function: %s", input) + } + } + }internal/exec/yaml_func_store_get.go (4)
63-67
: Align error behavior on invalid pipe params with other YAML funcs.Returning err.Error() emits internal sentinel text to the user and diverges from processTagStore which returns a stable "invalid YAML function: " string. Prefer consistent UX.
Apply this diff:
- if err != nil { - return err.Error() - } + if err != nil { + // Keep UX consistent with other YAML functions. + return fmt.Sprintf("invalid YAML function: %s", input) + }
21-42
: Optional: support spaces in default and query values.extractPipeParams uses strings.Fields and enforces two tokens, which breaks for values with spaces (e.g., default "hello world" or complex YQ). Parse by prefix and capture the remainder.
Apply this diff:
-func extractPipeParams(parts []string, input string) (defaultValue *string, query string, err error) { - for _, p := range parts[1:] { - pipeParts := strings.Fields(strings.TrimSpace(p)) - if len(pipeParts) != 2 { - log.Error("invalid YAML function", "function", input, "reason", "invalid number of parameters after the pipe", "count", len(pipeParts)) - return nil, "", fmt.Errorf("%w: %s", ErrInvalidPipeParams, input) - } - v1 := strings.Trim(pipeParts[0], `"'`) // Remove surrounding quotes if present. - v2 := strings.Trim(pipeParts[1], `"'`) - switch v1 { - case "default": - defaultValue = &v2 - case "query": - query = v2 - default: - log.Error("invalid YAML function", "function", input, "reason", "invalid identifier after the pipe", "identifier", v1) - return nil, "", fmt.Errorf("%w: %s", ErrInvalidPipeIdentifier, input) - } - } - return defaultValue, query, nil -} +func extractPipeParams(parts []string, input string) (defaultValue *string, query string, err error) { + for _, raw := range parts[1:] { + p := strings.TrimSpace(raw) + switch { + case strings.HasPrefix(p, "default "): + v := strings.TrimSpace(strings.TrimPrefix(p, "default ")) + v = strings.Trim(v, `"'`) + dv := v + defaultValue = &dv + case strings.HasPrefix(p, "query "): + v := strings.TrimSpace(strings.TrimPrefix(p, "query ")) + v = strings.Trim(v, `"'`) + query = v + default: + log.Error("invalid YAML function", "function", input, "reason", "invalid pipe identifier", "payload", p) + return nil, "", fmt.Errorf("%w: %s", ErrInvalidPipeIdentifier, input) + } + } + return defaultValue, query, nil +}
45-47
: Nit: include the tag in the first debug line for symmetry.Small consistency polish with other handlers.
Apply this diff:
- log.Debug("Executing Atmos YAML function", "function", input) + log.Debug("Executing Atmos YAML function", "function", u.AtmosYamlFuncStoreGet, "input", input)
44-114
: Coverage: add tests for invalid pipe cases and values with spaces.Good happy-path flow. Add table tests covering:
- Unknown pipe identifier (e.g., | foo bar) -> returns "invalid YAML function: ..."
- default "value with spaces" and query with spaces or special chars
- partsLength != 2 (missing key) and missing store -> ErrStoreNotFound path
I can draft tests mirroring internal/exec/yaml_func_store_test.go’s table style targeting processTagStoreGet with miniredis.
📜 Review details
Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
💡 Knowledge Base configuration:
- MCP integration is disabled by default for public repositories
- Jira integration is disabled by default for public repositories
- Linear integration is disabled by default for public repositories
You can enable these sources in your CodeRabbit configuration.
⛔ Files ignored due to path filters (1)
go.sum
is excluded by!**/*.sum
📒 Files selected for processing (3)
go.mod
(1 hunks)internal/exec/yaml_func_store.go
(1 hunks)internal/exec/yaml_func_store_get.go
(1 hunks)
🧰 Additional context used
📓 Path-based instructions (2)
go.mod
📄 CodeRabbit Inference Engine (.cursor/rules/atmos-rules.mdc)
Manage dependencies with Go modules
Files:
go.mod
**/*.go
📄 CodeRabbit Inference Engine (.cursor/rules/atmos-rules.mdc)
**/*.go
: Use Viper for managing configuration, environment variables, and flags
Use interfaces for external dependencies to facilitate mocking
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)
Consider using a custom error type for domain-specific errors
Follow standard Go coding style
Use gofmt and goimports to format code
Prefer short, descriptive variable names
Use snake_case for environment variables
Document all exported functions, types, and methods
Document complex logic with inline comments
Follow Go's documentation conventions
Use Viper for configuration management
Support configuration via files, environment variables, and flags
Follow the precedence order: flags > environment variables > config file > defaults
Files:
internal/exec/yaml_func_store.go
internal/exec/yaml_func_store_get.go
🧠 Learnings (13)
📚 Learning: 2025-07-01T02:22:25.901Z
Learnt from: CR
PR: cloudposse/atmos#0
File: .cursor/rules/atmos-rules.mdc:0-0
Timestamp: 2025-07-01T02:22:25.901Z
Learning: Applies to go.mod : Manage dependencies with Go modules
Applied to files:
go.mod
📚 Learning: 2024-11-30T22:07:08.610Z
Learnt from: aknysh
PR: cloudposse/atmos#810
File: internal/exec/yaml_func_terraform_output.go:35-40
Timestamp: 2024-11-30T22:07:08.610Z
Learning: In the Go function `processTagTerraformOutput` in `internal/exec/yaml_func_terraform_output.go`, parameters cannot contain spaces. The code splits the input by spaces, and if the parameters contain spaces, `len(parts) != 3` will fail and show an error to the user.
Applied to files:
internal/exec/yaml_func_store.go
internal/exec/yaml_func_store_get.go
📚 Learning: 2024-12-17T07:08:41.288Z
Learnt from: aknysh
PR: cloudposse/atmos#863
File: internal/exec/yaml_func_terraform_output.go:34-38
Timestamp: 2024-12-17T07:08:41.288Z
Learning: In the `processTagTerraformOutput` function within `internal/exec/yaml_func_terraform_output.go`, parameters are separated by spaces and do not contain spaces. Therefore, using `strings.Fields()` for parsing is acceptable, and there's no need to handle parameters with spaces.
Applied to files:
internal/exec/yaml_func_store.go
internal/exec/yaml_func_store_get.go
📚 Learning: 2024-12-05T22:33:40.955Z
Learnt from: aknysh
PR: cloudposse/atmos#820
File: cmd/list_components.go:53-54
Timestamp: 2024-12-05T22:33:40.955Z
Learning: In the Atmos CLI Go codebase, using `u.LogErrorAndExit` within completion functions is acceptable because it logs the error and exits the command execution.
Applied to files:
internal/exec/yaml_func_store_get.go
📚 Learning: 2025-04-04T02:03:23.676Z
Learnt from: aknysh
PR: cloudposse/atmos#1185
File: internal/exec/yaml_func_store.go:26-26
Timestamp: 2025-04-04T02:03:23.676Z
Learning: The Atmos codebase currently uses `log.Fatal` for error handling in multiple places. The maintainers are aware this isn't an ideal pattern (should only be used in main() or init() functions) and plan to address it comprehensively in a separate PR. CodeRabbit should not flag these issues or push for immediate changes until that refactoring is complete.
Applied to files:
internal/exec/yaml_func_store_get.go
📚 Learning: 2025-04-04T02:03:21.906Z
Learnt from: aknysh
PR: cloudposse/atmos#1185
File: internal/exec/yaml_func_store.go:71-72
Timestamp: 2025-04-04T02:03:21.906Z
Learning: The codebase currently uses `log.Fatal` for error handling in library functions, which terminates the program. There is a plan to refactor this approach in a separate PR to improve API design by returning error messages instead of terminating execution.
Applied to files:
internal/exec/yaml_func_store_get.go
📚 Learning: 2024-12-05T22:33:54.807Z
Learnt from: aknysh
PR: cloudposse/atmos#820
File: cmd/list_stacks.go:55-56
Timestamp: 2024-12-05T22:33:54.807Z
Learning: In the atmos project, the `u.LogErrorAndExit` function logs the error and exits the command execution appropriately within flag completion functions.
Applied to files:
internal/exec/yaml_func_store_get.go
📚 Learning: 2024-10-23T21:36:40.262Z
Learnt from: osterman
PR: cloudposse/atmos#740
File: cmd/cmd_utils.go:340-359
Timestamp: 2024-10-23T21:36:40.262Z
Learning: In the Go codebase for Atmos, when reviewing functions like `checkAtmosConfig` in `cmd/cmd_utils.go`, avoid suggesting refactoring to return errors instead of calling `os.Exit` if such changes would significantly increase the scope due to the need to update multiple call sites.
Applied to files:
internal/exec/yaml_func_store_get.go
📚 Learning: 2025-04-11T22:06:46.999Z
Learnt from: samtholiya
PR: cloudposse/atmos#1147
File: internal/exec/validate_schema.go:42-57
Timestamp: 2025-04-11T22:06:46.999Z
Learning: The "ExecuteAtmosValidateSchemaCmd" function in internal/exec/validate_schema.go has been reviewed and confirmed to have acceptable cognitive complexity despite static analysis warnings. The function uses a clean structure with only three if statements for error handling and delegates complex operations to helper methods.
Applied to files:
internal/exec/yaml_func_store_get.go
📚 Learning: 2024-11-13T21:37:07.852Z
Learnt from: Cerebrovinny
PR: cloudposse/atmos#764
File: internal/exec/describe_stacks.go:289-295
Timestamp: 2024-11-13T21:37:07.852Z
Learning: In the `internal/exec/describe_stacks.go` file of the `atmos` project written in Go, avoid extracting the stack name handling logic into a helper function within the `ExecuteDescribeStacks` method, even if the logic appears duplicated.
Applied to files:
internal/exec/yaml_func_store_get.go
📚 Learning: 2025-01-25T04:01:58.095Z
Learnt from: Listener430
PR: cloudposse/atmos#934
File: internal/exec/docs_generate.go:98-101
Timestamp: 2025-01-25T04:01:58.095Z
Learning: In the `generateSingleReadme` function of the docs generation feature (internal/exec/docs_generate.go), errors from `fetchAndParseYAML` should be logged and skipped rather than causing early returns. This is by design to process all inputs and collect all errors, instead of failing fast on the first error.
Applied to files:
internal/exec/yaml_func_store_get.go
📚 Learning: 2025-07-01T02:22:25.901Z
Learnt from: CR
PR: cloudposse/atmos#0
File: .cursor/rules/atmos-rules.mdc:0-0
Timestamp: 2025-07-01T02:22:25.901Z
Learning: Applies to **/*.go : Use meaningful error messages
Applied to files:
internal/exec/yaml_func_store_get.go
📚 Learning: 2025-07-01T02:22:25.901Z
Learnt from: CR
PR: cloudposse/atmos#0
File: .cursor/rules/atmos-rules.mdc:0-0
Timestamp: 2025-07-01T02:22:25.901Z
Learning: Applies to **/*.go : Provide clear error messages to users
Applied to files:
internal/exec/yaml_func_store_get.go
🧬 Code Graph Analysis (2)
internal/exec/yaml_func_store.go (2)
internal/exec/yaml_func_store_test.go (1)
TestProcessTagStore
(16-120)internal/exec/yaml_func_utils.go (2)
processNodes
(21-59)processCustomTags
(61-88)
internal/exec/yaml_func_store_get.go (6)
internal/exec/yaml_func_errors.go (4)
ErrInvalidPipeParams
(15-15)ErrInvalidPipeIdentifier
(16-16)ErrStoreNotFound
(13-13)ErrGetKeyFailed
(14-14)pkg/schema/schema.go (1)
AtmosConfiguration
(25-60)pkg/utils/yaml_utils.go (1)
AtmosYamlFuncStoreGet
(23-23)errors/error_funcs.go (1)
CheckErrorPrintAndExit
(55-72)pkg/utils/yq_utils.go (1)
EvaluateYqExpression
(48-98)internal/exec/yaml_func_store_test.go (1)
TestProcessTagStore
(16-120)
🪛 GitHub Actions: Dependency Review
go.mod
[error] 1-1: Dependency review detected incompatible licenses for dependency github.com/redis/go-redis/v9@9.12.1 (License: BSD-2-Clause) referenced in go.mod.
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (7)
- GitHub Check: Build (windows-latest, windows)
- GitHub Check: Build (ubuntu-latest, linux)
- GitHub Check: Build (macos-latest, macos)
- GitHub Check: Lint (golangci)
- GitHub Check: Analyze (go)
- GitHub Check: website-deploy-preview
- GitHub Check: Summary
🔇 Additional comments (3)
go.mod (1)
70-71
: Action: dependency-review flagged github.com/redis/go-redis/v9 v9.12.1 (BSD-2-Clause) — repo config not foundI ran the requested checks. I couldn't find a local dependency-review config, and go.mod contains the bumped redis dependency.
Files/locations to inspect:
- go.mod (lines shown):
github.com/posthog/posthog-go v1.6.3 github.com/redis/go-redis/v9 v9.12.1 github.com/samber/lo v1.51.0
- .github/dependency-review-config.yml — not present in the repo search. Also check .github/workflows/* for dependency-review action configuration or any org-level policy that could enforce a stricter allowlist.
Suggested short-term actions:
- Revert the bump to github.com/redis/go-redis/v9 v9.12.0 (if that version was previously allowed).
Preferred actions:- Update dependency-review config to allow BSD-2-Clause or add an explicit exception for this module/version.
Alternative:- Remove or avoid the bump if the new version isn't required for this PR.
I can't confirm the exact policy used by Actions from the repo contents alone — please verify the dependency-review config in workflows or org settings, or tell me if you want me to search workflows for the action configuration.
internal/exec/yaml_func_store_get.go (2)
84-90
: Docs and API naming: verify !store.get vs docs and store.GetKey vs Get.PR summary mentions docs refer to !store.getkey and the interface adding Get(key string), while code uses !store.get and Store.GetKey. Ensure docs and interface naming are consistent to avoid confusion.
Please confirm:
- website/docs reference the function as !store.get (not !store.getkey).
- pkg/store/store.go defines GetKey and all implementations embed it; or, if the API intended is Get(key), align the handler accordingly.
1-114
: Verified: !store.get is routed before !store; no undefined identifiersNo action required — processCustomTags already matches u.AtmosYamlFuncStoreGet before u.AtmosYamlFuncStore, and the log keys are defined.
- internal/exec/yaml_func_utils.go — case for AtmosYamlFuncStoreGet precedes AtmosYamlFuncStore (processTagStoreGet then processTagStore).
- internal/exec/yaml_func_store_get.go — handler: processTagStoreGet.
- internal/exec/yaml_func_errors.go — defines invalidYamlFuncMsg and function constant.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 1
🔭 Outside diff range comments (1)
pkg/store/aws_ssm_param_store.go (1)
292-299
: Mirror decryption semantics in GetKey()Same issue here; ensure decryption for SecureString parameters retrieved by arbitrary key.
Apply:
- output, err := client.GetParameter(ctx, &ssm.GetParameterInput{ - Name: aws.String(paramName), - }) + output, err := client.GetParameter(ctx, &ssm.GetParameterInput{ + Name: aws.String(paramName), + WithDecryption: aws.Bool(true), + })
♻️ Duplicate comments (1)
pkg/store/aws_ssm_param_store.go (1)
235-242
: Always decrypt SecureString in Get()Without WithDecryption=true, SecureString values won’t be returned in plaintext. This breaks parity with other stores and surprises users of !store.get.
Apply:
- output, err := client.GetParameter(ctx, &ssm.GetParameterInput{ - Name: aws.String(paramName), - }) + output, err := client.GetParameter(ctx, &ssm.GetParameterInput{ + Name: aws.String(paramName), + WithDecryption: aws.Bool(true), + })
🧹 Nitpick comments (2)
pkg/store/aws_ssm_param_store_test.go (1)
681-911
: Add test cases for leading-slash keys and prefix joiningCover edge cases to prevent accidental "//" in paths and to ensure we always start with "/".
Suggested additions:
- key starts with "/" and prefix set (expect "/prefix/your/key" without double slash)
- key starts with "/" and no prefix (expect "/your/key")
- key without "/" and no prefix (expect "/your/key")
pkg/store/aws_ssm_param_store.go (1)
265-273
: Normalize prefix/key joining to avoid double slashesIf prefix ends with "/" and/or key starts with "/", current logic can yield "//". Normalize both ends before constructing the path.
Apply:
- // If the prefix is set, prepend it to the key - if s.prefix != "" { - paramName = s.prefix + "/" + key - } - - // Ensure the parameter name starts with "/" for SSM - if !strings.HasPrefix(paramName, "/") { - paramName = "/" + paramName - } + // Normalize and join prefix/key, ensure it starts with "/" + k := strings.TrimPrefix(key, "/") + if s.prefix != "" { + p := strings.TrimSuffix(s.prefix, "/") + paramName = "/" + p + "/" + k + } else { + paramName = "/" + k + }
📜 Review details
Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
💡 Knowledge Base configuration:
- MCP integration is disabled by default for public repositories
- Jira integration is disabled by default for public repositories
- Linear integration is disabled by default for public repositories
You can enable these sources in your CodeRabbit configuration.
📒 Files selected for processing (3)
pkg/store/artifactory_store_test.go
(5 hunks)pkg/store/aws_ssm_param_store.go
(6 hunks)pkg/store/aws_ssm_param_store_test.go
(1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
- pkg/store/artifactory_store_test.go
🧰 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
Use interfaces for external dependencies to facilitate mocking
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)
Consider using a custom error type for domain-specific errors
Follow standard Go coding style
Use gofmt and goimports to format code
Prefer short, descriptive variable names
Use snake_case for environment variables
Document all exported functions, types, and methods
Document complex logic with inline comments
Follow Go's documentation conventions
Use Viper for configuration management
Support configuration via files, environment variables, and flags
Follow the precedence order: flags > environment variables > config file > defaults
Files:
pkg/store/aws_ssm_param_store_test.go
pkg/store/aws_ssm_param_store.go
**/*_test.go
📄 CodeRabbit Inference Engine (.cursor/rules/atmos-rules.mdc)
**/*_test.go
: Every new feature must include comprehensive unit tests
Test both happy paths and error conditions
Use table-driven tests for testing multiple scenarios
Include integration tests for command flows
Test CLI end-to-end when possible
Use test fixtures for complex inputs
Consider using testify/mock for creating mock implementations
Files:
pkg/store/aws_ssm_param_store_test.go
🧠 Learnings (2)
📚 Learning: 2024-10-23T21:36:40.262Z
Learnt from: osterman
PR: cloudposse/atmos#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/store/aws_ssm_param_store.go
📚 Learning: 2025-01-30T19:30:59.120Z
Learnt from: samtholiya
PR: cloudposse/atmos#959
File: cmd/workflow.go:74-74
Timestamp: 2025-01-30T19:30:59.120Z
Learning: Error handling for `cmd.Usage()` is not required in the Atmos CLI codebase, as confirmed by the maintainer.
Applied to files:
pkg/store/aws_ssm_param_store.go
🧬 Code Graph Analysis (1)
pkg/store/aws_ssm_param_store.go (1)
pkg/store/errors.go (2)
ErrGetParameter
(25-25)ErrEmptyKey
(17-17)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (12)
- GitHub Check: Analyze (javascript-typescript)
- GitHub Check: Analyze (javascript-typescript)
- GitHub Check: Analyze (go)
- GitHub Check: Lint (golangci)
- GitHub Check: Lint (golangci)
- GitHub Check: Analyze (go)
- GitHub Check: Analyze (go)
- GitHub Check: Lint (golangci)
- GitHub Check: Build (windows-latest, windows)
- GitHub Check: Build (ubuntu-latest, linux)
- GitHub Check: website-deploy-preview
- GitHub Check: Summary
🔇 Additional comments (6)
pkg/store/aws_ssm_param_store_test.go (1)
681-911
: Nice breadth of value-shape coverageGood coverage across string, array, map, numeric, malformed JSON, AWS errors, and role-assumption paths.
pkg/store/aws_ssm_param_store.go (5)
140-196
: Set(): LGTMJSON-encode values (including primitives), derive full SSM path, and overwrite by default; role-assumption is consistent with write path expectations.
110-138
: assumeRole: sensible, testable designGood use of injectable STS/SSM constructors and static credentials provider; session name is constant and discoverable in logs.
243-252
: Intentional nil error on JSON parse failureThe nolint:nilerr directive and fallback to raw string are appropriate to support legacy non-JSON values.
300-309
: Same JSON fallback behavior for GetKeyConsistent handling with Get(); good.
55-99
: errWrapFormat & errWrapFormatWithID are present — no action neededVerified: the constants are defined and in use.
- Definition: pkg/store/errors.go — const block defines errFormat, errWrapFormat, errWrapFormatWithID (e.g. errWrapFormat = "%w: %w", errWrapFormatWithID = "%w '%s': %w").
- Usages: referenced in pkg/store/aws_ssm_param_store.go and other store implementations (google_secret_manager_store.go, azure_keyvault_store.go, redis_store.go, etc.).
No rename/move detected; the code will compile with these symbols as-is.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
🔭 Outside diff range comments (1)
website/docs/core-concepts/stacks/yaml-functions/store.mdx (1)
119-121
: Fix incorrect reference to the function nameThis section is for the
!store
YAML function but references!terraform.output
.Apply this diff:
-There are multiple ways you can specify the Atmos stack parameter in the `!terraform.output` function. +There are multiple ways you can specify the Atmos stack parameter in the `!store` function.
♻️ Duplicate comments (1)
website/docs/core-concepts/stacks/yaml-functions/store.get.mdx (1)
19-24
: Nice: usage phrasing matches prior suggestionThe usage statement clearly communicates two parameters plus optional default and query, aligning with earlier feedback.
🧹 Nitpick comments (5)
website/docs/core-concepts/stacks/yaml-functions/store.mdx (1)
13-13
: Tighten grammar and flow in the intro sentenceThe phrasing is awkward. Suggest reordering and adding a comma after e.g.
Apply this diff:
- (e.g. SSM Parameter Store, Artifactory, Redis, etc.) for an Atmos component in a stack into Atmos stack manifests. + (e.g., SSM Parameter Store, Artifactory, Redis, etc.) and inject them into Atmos stack manifests for an Atmos component in a stack.website/docs/core-concepts/stacks/yaml-functions/yaml-functions.mdx (2)
41-41
: End the bullet sentence with a periodMinor formatting/punctuation polish for consistency with other bullets.
- - The [__`!terraform.state`__](/core-concepts/stacks/yaml-functions/terraform.state) YAML function reads outputs **directly from the configured Terraform or OpenTofu backend**, without initializing providers or running Terraform — it's **very fast** and currently supports [S3 and local backends](/core-concepts/components/terraform/backends) for accessing [remote state](/core-concepts/share-data/remote-state) + - The [__`!terraform.state`__](/core-concepts/stacks/yaml-functions/terraform.state) YAML function reads outputs **directly from the configured Terraform or OpenTofu backend**, without initializing providers or running Terraform — it's **very fast** and currently supports [S3 and local backends](/core-concepts/components/terraform/backends) for accessing [remote state](/core-concepts/share-data/remote-state).
47-52
: Add terminal punctuation to the new!store.get
bulletKeeps list style consistent and improves readability.
- - The [__`!store.get`__](/core-concepts/stacks/yaml-functions/store.get) YAML function allows retrieving arbitrary keys - directly from a [store](/core-concepts/projects/configuration/stores) - without following the Atmos stack/component/key naming convention. - This is useful for accessing values stored by external systems - or for retrieving global configuration that doesn't belong to a specific component + - The [__`!store.get`__](/core-concepts/stacks/yaml-functions/store.get) YAML function allows retrieving arbitrary keys + directly from a [store](/core-concepts/projects/configuration/stores) + without following the Atmos stack/component/key naming convention. + This is useful for accessing values stored by external systems + or for retrieving global configuration that doesn't belong to a specific component.website/docs/core-concepts/stacks/yaml-functions/store.get.mdx (2)
51-51
: Add a period to complete the sentenceMinor punctuation fix.
- <dd>The exact key name or path to retrieve from the store. This is the literal key as it exists in the store, not constructed from stack/component/key patterns</dd> + <dd>The exact key name or path to retrieve from the store. This is the literal key as it exists in the store, not constructed from stack/component/key patterns.</dd>
100-114
: Consider adding an Artifactory example for parity with other storesYou cover Redis, SSM, Azure KV, GSM. An Artifactory example would round out the set and help users unfamiliar with its key conventions.
I can draft an Artifactory example snippet if you share the common key/path patterns you expect users to retrieve.
📜 Review details
Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
💡 Knowledge Base configuration:
- MCP integration is disabled by default for public repositories
- Jira integration is disabled by default for public repositories
- Linear integration is disabled by default for public repositories
You can enable these sources in your CodeRabbit configuration.
📒 Files selected for processing (8)
website/docs/core-concepts/stacks/yaml-functions/env.mdx
(1 hunks)website/docs/core-concepts/stacks/yaml-functions/exec.mdx
(1 hunks)website/docs/core-concepts/stacks/yaml-functions/include.mdx
(1 hunks)website/docs/core-concepts/stacks/yaml-functions/repo-root.mdx
(1 hunks)website/docs/core-concepts/stacks/yaml-functions/store.get.mdx
(1 hunks)website/docs/core-concepts/stacks/yaml-functions/store.mdx
(1 hunks)website/docs/core-concepts/stacks/yaml-functions/template.mdx
(1 hunks)website/docs/core-concepts/stacks/yaml-functions/yaml-functions.mdx
(1 hunks)
✅ Files skipped from review due to trivial changes (5)
- website/docs/core-concepts/stacks/yaml-functions/env.mdx
- website/docs/core-concepts/stacks/yaml-functions/include.mdx
- website/docs/core-concepts/stacks/yaml-functions/repo-root.mdx
- website/docs/core-concepts/stacks/yaml-functions/template.mdx
- website/docs/core-concepts/stacks/yaml-functions/exec.mdx
🧰 Additional context used
📓 Path-based instructions (1)
website/**
📄 CodeRabbit Inference Engine (.cursor/rules/atmos-rules.mdc)
website/**
: Update website documentation in the website/ directory when adding new features
Follow the website's documentation structure and style
Keep website code in the website/ directory
Follow the existing website architecture and style
Document new features on the website
Include examples and use cases in website documentation
Files:
website/docs/core-concepts/stacks/yaml-functions/yaml-functions.mdx
website/docs/core-concepts/stacks/yaml-functions/store.get.mdx
website/docs/core-concepts/stacks/yaml-functions/store.mdx
🧠 Learnings (5)
📚 Learning: 2024-12-03T04:01:16.446Z
Learnt from: aknysh
PR: cloudposse/atmos#810
File: website/docs/core-concepts/stacks/yaml-functions/terraform.output.mdx:0-0
Timestamp: 2024-12-03T04:01:16.446Z
Learning: In the `terraform.output.mdx` documentation file (`website/docs/core-concepts/stacks/yaml-functions/terraform.output.mdx`), the cache invalidation and cache scope behavior for the `!terraform.output` function are already described.
Applied to files:
website/docs/core-concepts/stacks/yaml-functions/yaml-functions.mdx
📚 Learning: 2025-01-19T22:30:27.600Z
Learnt from: aknysh
PR: cloudposse/atmos#0
File: :0-0
Timestamp: 2025-01-19T22:30:27.600Z
Learning: The Atmos YAML function `!include` allows downloading local or remote files from different sources and assigning their contents to sections in stack manifests. It supports various protocols (file, http, git, s3, etc.) and can filter content using YQ expressions.
Applied to files:
website/docs/core-concepts/stacks/yaml-functions/yaml-functions.mdx
website/docs/core-concepts/stacks/yaml-functions/store.mdx
📚 Learning: 2024-12-01T00:33:20.298Z
Learnt from: aknysh
PR: cloudposse/atmos#810
File: examples/tests/stacks/catalog/terraform/template-functions-test2/defaults.yaml:28-32
Timestamp: 2024-12-01T00:33:20.298Z
Learning: In `examples/tests/stacks/catalog/terraform/template-functions-test2/defaults.yaml`, `!exec atmos terraform output` is used in examples to demonstrate its usage, even though `!terraform.output` is the recommended approach according to the documentation.
Applied to files:
website/docs/core-concepts/stacks/yaml-functions/yaml-functions.mdx
website/docs/core-concepts/stacks/yaml-functions/store.mdx
📚 Learning: 2025-01-19T22:30:27.600Z
Learnt from: aknysh
PR: cloudposse/atmos#0
File: :0-0
Timestamp: 2025-01-19T22:30:27.600Z
Learning: The Atmos YAML function `!env` is used to retrieve environment variables and assign them to sections in stack manifests. It supports both simple types (string, number, boolean) and complex types (JSON-encoded lists, maps, objects).
Applied to files:
website/docs/core-concepts/stacks/yaml-functions/yaml-functions.mdx
website/docs/core-concepts/stacks/yaml-functions/store.get.mdx
website/docs/core-concepts/stacks/yaml-functions/store.mdx
📚 Learning: 2025-02-11T08:21:33.143Z
Learnt from: shirkevich
PR: cloudposse/atmos#1034
File: website/docs/core-concepts/projects/configuration/stores.mdx:173-177
Timestamp: 2025-02-11T08:21:33.143Z
Learning: The parameter for configuring stack path delimiter in store configurations is consistently named `stack_delimiter` (not `stacks_delimiter`) across all store types in Atmos.
Applied to files:
website/docs/core-concepts/stacks/yaml-functions/store.mdx
🧬 Code Graph Analysis (2)
website/docs/core-concepts/stacks/yaml-functions/yaml-functions.mdx (2)
internal/exec/yaml_func_store.go (1)
processTagStore
(28-114)internal/exec/yaml_func_terraform_state.go (1)
processTagTerraformState
(15-58)
website/docs/core-concepts/stacks/yaml-functions/store.get.mdx (1)
internal/exec/yaml_func_store.go (1)
processTagStore
(28-114)
🪛 LanguageTool
website/docs/core-concepts/stacks/yaml-functions/yaml-functions.mdx
[grammar] ~45-~45: Please add a punctuation mark at the end of paragraph.
Context: ... Artifactory, etc.) into Atmos stack manifests - The [!store.get
](/core-concep...
(PUNCTUATION_PARAGRAPH_END)
[grammar] ~51-~51: Please add a punctuation mark at the end of paragraph.
Context: ...ation that doesn't belong to a specific component - The [!include
](/core-concepts...
(PUNCTUATION_PARAGRAPH_END)
website/docs/core-concepts/stacks/yaml-functions/store.get.mdx
[grammar] ~8-~8: There might be a mistake here.
Context: ... Intro from '@site/src/components/Intro' import File from '@site/src/components/F...
(QB_NEW_EN)
[grammar] ~19-~19: There might be a mistake here.
Context: ...ters, and optionally a default value and a YQ ...
(QB_NEW_EN)
[typographical] ~40-~40: Consider using a typographic opening quote here.
Context: ...!store.get <store_name> | default "{}" | query .field ``` ### Argu...
(EN_QUOTES)
[typographical] ~112-~112: Consider using a typographic opening quote here.
Context: ...lly regional_config: !store.get redis "config-{{ .vars.region }}" ``` ...
(EN_QUOTES)
[typographical] ~138-~138: Consider using a typographic opening quote here.
Context: ...zure-keyvault ssl-certificate | default "" ``` #### Google Secret Manage...
(EN_QUOTES)
[grammar] ~157-~157: There might be a mistake here.
Context: ...d in the backend, including any required prefix, path, or normalization specific ...
(QB_NEW_EN)
[grammar] ~159-~159: There might be a mistake here.
Context: ...s written by external systems that don't follow Atmos naming conventions - **Perf...
(QB_NEW_EN)
[style] ~162-~162: Using many exclamation marks might seem excessive (in this case: 9 exclamation marks for a text that’s 1695 characters long)
Context: ...truction is needed - Security: Like !store
, using !store.get
with secrets will expose them...
(EN_EXCESSIVE_EXCLAMATION)
website/docs/core-concepts/stacks/yaml-functions/store.mdx
[grammar] ~7-~7: There might be a mistake here.
Context: ...rt File from '@site/src/components/File' import Intro from '@site/src/components/...
(QB_NEW_EN)
[grammar] ~8-~8: There might be a mistake here.
Context: ... Intro from '@site/src/components/Intro' import Terminal from '@site/src/componen...
(QB_NEW_EN)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (7)
- GitHub Check: Build (windows-latest, windows)
- GitHub Check: Build (ubuntu-latest, linux)
- GitHub Check: Build (macos-latest, macos)
- GitHub Check: Analyze (go)
- GitHub Check: Lint (golangci)
- GitHub Check: website-deploy-preview
- GitHub Check: Summary
🔇 Additional comments (1)
website/docs/core-concepts/stacks/yaml-functions/yaml-functions.mdx (1)
47-47
: Confirm PR title/description use the canonical tag!store.get
Docs consistently use
!store.get
. The PR summary mentions!store.getkey
. Please align the PR text with the canonical tag.Would you update the PR title/description to use
!store.get
everywhere?
These changes were released in v1.187.0. |
This PR introduces the
!store.get
YAML function, enabling retrieval of arbitrary keys from any supported store (Azure Key Vault, AWS SSM, Redis, Google Secret Manager, Artifactory). Unlike the existing!store
function,!store.get
does not require keys to follow the Atmos stack/component/key naming pattern. Users can retrieve any key by specifying its exact name or path.Key Features
Adds
Get(key string) (interface{}, error)
to theStore
interface for arbitrary key retrieval.Implements
Get
in all supported stores, handling prefixes and store-specific key/path conventions.Adds the
!store.get
YAML function and its processor, allowing direct key/path access in YAML.Comprehensive, table-driven unit tests for the new function, including happy paths and error conditions.
Adds a
RedisClient()
method to the Redis store for direct test setup of arbitrary keys.Updates website documentation with a new section for
!store.getkey
, including usage, arguments, and clear examples.Explicitly documents that this function does not follow the stack/component/key pattern.
Usage Example
Notable Differences from
!store
!store.get
does not construct keys using stack/component/key; it expects the full key or path.Compliance
Summary by CodeRabbit
New Features
Documentation
Tests
Chores
Breaking Changes