Skip to content
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

Add --query (shorthand -q) flag to all atmos describe <subcommand> commands #920

Merged
merged 41 commits into from
Jan 8, 2025

Conversation

aknysh
Copy link
Member

@aknysh aknysh commented Jan 8, 2025

what

  • Add --query (shorthand -q) flag to all atmos describe <subcommand> commands
  • Update docs

why

  • Query (and filter) the results of atmos describe <subcommand> commands using yq expressions
  • Before, an external yq or jq binary was required to query/filter the results of atmos describe commands. With the yq functionality now embedded in Atmos, installing the yq binary is not required

examples

atmos describe component vpc -s plat-ue2-prod --query .vars
atmos describe component vpc -s plat-ue2-prod -q .vars.tags
atmos describe component vpc -s plat-ue2-prod -q .settings
atmos describe component vpc -s plat-ue2-prod --query .metadata.inherits

atmos describe stacks -q keys  # this produces the same result as the native `atmos list stacks` command

atmos describe config -q .stacks.base_path

atmos describe workflows -q '.0 | keys'

atmos describe affected -q <yq-expression>

atmos describe dependents -q <yq-expression>

references

Summary by CodeRabbit

Release Notes for Atmos v1.140.0

  • New Features

    • Added --query flag across multiple describe commands to filter results using YQ expressions.
    • Enhanced command-line querying capabilities for components, stacks, workflows, and configuration.
  • Improvements

    • Updated error handling in various commands.
    • Improved path resolution and configuration management.
    • Enhanced dependency management.
  • Dependency Updates

    • Added new dependencies including yq/v4 and several indirect dependencies.
    • Updated Go module dependencies.
  • Documentation

    • Updated CLI command documentation to reflect new querying functionality.
    • Added examples for new query-based commands.
  • Chores

    • Updated Atmos version in example configurations.
    • Minor code reorganization and import statement adjustments.

Copy link

mergify bot commented Jan 8, 2025

Important

Cloud Posse Engineering Team Review Required

This pull request modifies files that require Cloud Posse's review. Please be patient, and a core maintainer will review your changes.

To expedite this process, reach out to us on Slack in the #pr-reviews channel.

Copy link
Contributor

coderabbitai bot commented Jan 8, 2025

📝 Walkthrough

Walkthrough

This pull request introduces a comprehensive set of changes to the Atmos CLI, focusing on enhancing command functionality, error handling, and configuration management. The primary additions include a new --query flag across multiple describe commands, improved error handling in various functions, and updates to dependencies and documentation. The changes aim to provide more flexible querying capabilities and robust error management.

Changes

File Change Summary
LICENSE Updated copyright year range from 2020-2024 to 2020-2025
atmos.yaml Changed base_path from "." to ""
cmd/* Added error handling, new query flag in various commands
examples/quick-start-advanced/Dockerfile Updated Atmos version to 1.140.0
go.mod Added new dependencies, including github.com/mikefarah/yq/v4
internal/exec/* Implemented query functionality in describe commands
pkg/utils/yq_utils.go Added new utility for evaluating YQ expressions
website/docs/cli/commands/describe/* Updated documentation for new --query flag

Sequence Diagram

sequenceDiagram
    participant User
    participant CLI
    participant YQProcessor
    participant ConfigManager

    User->>CLI: Run describe command with --query
    CLI->>ConfigManager: Retrieve configuration
    ConfigManager-->>CLI: Return configuration
    CLI->>YQProcessor: Evaluate query expression
    YQProcessor-->>CLI: Return filtered results
    CLI->>User: Display results
Loading

Possibly related PRs

Suggested Reviewers

  • Gowiem
  • osterman

Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media?

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR. (Beta)
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary or @auto-summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai or @auto-title anywhere in the PR title to generate the title automatically.

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

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 (11)
website/docs/cli/commands/describe/describe-stacks.mdx (2)

47-47: Add a concrete example of the query expression.

The example would be more helpful with a real-world yq expression. Consider adding practical examples that users can directly copy and use.

-atmos describe stacks --query <yq-expression>
+atmos describe stacks --query '.components | keys'
+atmos describe stacks --query '.components.[].vars.namespace'

51-51: Enhance the tip with a practical example.

The tip could be more helpful by including a brief example of what the filter can achieve.

-Use the `--query` flag (shorthand `-q`) to filter the output.
+Use the `--query` flag (shorthand `-q`) to filter the output. For example, use `--query '.components | keys'` to list all component names.
internal/exec/describe_config.go (1)

34-44: Well-structured query evaluation logic! ⚔️

The implementation:

  • Cleanly handles both query and non-query cases
  • Maintains the original config when no query is provided
  • Properly propagates evaluation errors

However, consider adding debug logging to help users understand the query evaluation process.

 if query != "" {
+    log.Debug().Msgf("Evaluating query expression: %s", query)
     res, err = u.EvaluateYqExpression(atmosConfig, atmosConfig, query)
     if err != nil {
+        log.Debug().Err(err).Msg("Query evaluation failed")
         return err
     }
+    log.Debug().Msg("Query evaluation successful")
 } else {
     res = atmosConfig
 }
pkg/utils/glob_utils.go (1)

24-24: Excellent cross-platform compatibility enhancement!

Converting the pattern to slash format ensures consistent behavior across different operating systems. Consider adding a brief comment explaining the purpose of this conversion for future maintainers.

+    // Convert to forward slashes for cross-platform compatibility
     pattern = filepath.ToSlash(pattern)
internal/exec/describe_workflows.go (1)

71-76: Solid query evaluation integration!

The implementation aligns perfectly with the PR objective of adding query support. Consider adding a debug log when query processing is active.

     if query != "" {
+        log.Debug().Str("query", query).Msg("Processing query expression")
         res, err = u.EvaluateYqExpression(atmosConfig, res, query)
pkg/utils/yq_utils.go (2)

17-32: Add documentation for the logBackend struct and methods.

While the implementation is correct for a no-op logger, adding documentation would help explain its purpose and usage.

+// logBackend implements a no-op logging backend for yqlib when detailed logging is not required
 type logBackend struct{}

+// Log implements logging.Backend interface with no-op behavior
 func (n logBackend) Log(level logging.Level, i int, record *logging.Record) error {

34-73: Add input validation for the YQ expression.

The function should validate that the YQ expression is not empty before proceeding with evaluation.

 func EvaluateYqExpression(atmosConfig schema.AtmosConfiguration, data any, yq string) (any, error) {
+    if yq == "" {
+        return nil, fmt.Errorf("EvaluateYqExpression: YQ expression cannot be empty")
+    }
+
     // Use the `yqlib` default (chatty) logger only when Atmos Logs Level is set to `Trace`
internal/exec/describe_component.go (1)

46-73: Add documentation for the query flag behavior.

While the implementation is correct, adding a comment would help explain how the query flag affects the output.

+    // If a query is provided, evaluate it against the component section using YQ
+    // Otherwise, return the entire component section
     var res any

     if query != "" {
pkg/utils/yq_test.go (1)

11-168: Consider using table-driven tests for better maintainability.

While the test coverage is excellent, restructuring to use table-driven tests would make it easier to add new test cases and maintain the existing ones.

Example structure:

func TestEvaluateYqExpression(t *testing.T) {
    tests := []struct {
        name     string
        yq       string
        expected any
    }{
        {
            name:     "get settings test value",
            yq:       ".settings.test",
            expected: true,
        },
        // Add more test cases
    }

    for _, tt := range tests {
        t.Run(tt.name, func(t *testing.T) {
            res, err := EvaluateYqExpression(atmosConfig, data, tt.yq)
            assert.Nil(t, err)
            assert.Equal(t, tt.expected, res)
        })
    }
}
internal/exec/describe_affected.go (1)

241-291: Consider adding error handling for empty query results.

The query evaluation logic is well-structured, but it might benefit from additional error handling for cases where the query returns no results.

Consider adding a check:

 res, err := u.EvaluateYqExpression(atmosConfig, affected, query)
 if err != nil {
     return err
 }
+if res == nil {
+    return fmt.Errorf("query returned no results: %s", query)
+}
internal/exec/describe_stacks.go (1)

116-127: Consider adding validation for query syntax.

While the implementation is solid, it might benefit from validating the query syntax before evaluation.

Consider adding basic validation:

+if query != "" {
+    if !strings.Contains(query, ".") && !strings.Contains(query, "[") {
+        return fmt.Errorf("invalid query syntax: %s", query)
+    }
     res, err = u.EvaluateYqExpression(atmosConfig, finalStacksMap, query)
     if err != nil {
         return err
     }
 } else {
📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 23507ab and c01a353.

⛔ Files ignored due to path filters (1)
  • go.sum is excluded by !**/*.sum
📒 Files selected for processing (30)
  • LICENSE (1 hunks)
  • atmos.yaml (1 hunks)
  • cmd/about.go (1 hunks)
  • cmd/describe.go (1 hunks)
  • cmd/list_components.go (2 hunks)
  • cmd/list_stacks.go (1 hunks)
  • cmd/root.go (1 hunks)
  • cmd/support.go (1 hunks)
  • examples/quick-start-advanced/Dockerfile (1 hunks)
  • go.mod (8 hunks)
  • internal/exec/describe_affected.go (4 hunks)
  • internal/exec/describe_component.go (2 hunks)
  • internal/exec/describe_config.go (3 hunks)
  • internal/exec/describe_dependents.go (2 hunks)
  • internal/exec/describe_stacks.go (3 hunks)
  • internal/exec/describe_workflows.go (2 hunks)
  • internal/exec/utils.go (3 hunks)
  • pkg/config/const.go (1 hunks)
  • pkg/schema/schema.go (2 hunks)
  • pkg/utils/file_extensions.go (1 hunks)
  • pkg/utils/glob_utils.go (1 hunks)
  • pkg/utils/yq_test.go (1 hunks)
  • pkg/utils/yq_utils.go (1 hunks)
  • website/docs/cli/commands/describe/describe-affected.mdx (2 hunks)
  • website/docs/cli/commands/describe/describe-component.mdx (2 hunks)
  • website/docs/cli/commands/describe/describe-config.mdx (1 hunks)
  • website/docs/cli/commands/describe/describe-dependents.mdx (2 hunks)
  • website/docs/cli/commands/describe/describe-stacks.mdx (2 hunks)
  • website/docs/cli/commands/describe/describe-workflows.mdx (1 hunks)
  • website/docs/integrations/atlantis.mdx (1 hunks)
✅ Files skipped from review due to trivial changes (3)
  • LICENSE
  • cmd/list_stacks.go
  • website/docs/integrations/atlantis.mdx
👮 Files not reviewed due to content moderation or server errors (3)
  • website/docs/cli/commands/describe/describe-dependents.mdx
  • website/docs/cli/commands/describe/describe-component.mdx
  • website/docs/cli/commands/describe/describe-affected.mdx
🧰 Additional context used
📓 Learnings (1)
examples/quick-start-advanced/Dockerfile (2)
Learnt from: aknysh
PR: cloudposse/atmos#775
File: examples/quick-start-advanced/Dockerfile:9-9
Timestamp: 2024-11-12T05:52:05.088Z
Learning: It is acceptable to set `ARG ATMOS_VERSION` to a future version like `1.105.0` in `examples/quick-start-advanced/Dockerfile` if that will be the next release.
Learnt from: osterman
PR: cloudposse/atmos#801
File: examples/quick-start-advanced/Dockerfile:9-9
Timestamp: 2024-11-23T00:13:22.004Z
Learning: When updating the `ATMOS_VERSION` in Dockerfiles, the team prefers to pin to the next future version when the PR merges, even if the version is not yet released.
⏰ Context from checks skipped due to timeout of 90000ms (2)
  • GitHub Check: Build (windows-latest, windows)
  • GitHub Check: Summary
🔇 Additional comments (30)
website/docs/cli/commands/describe/describe-stacks.mdx (1)

65-65: LGTM! Well-documented flag.

The flag documentation is thorough and includes all necessary information:

  • Clear description
  • Command syntax
  • Shorthand alias
  • Link to detailed documentation
examples/quick-start-advanced/Dockerfile (1)

9-9: LGTM! Version bump aligns with team preferences.

The update to ATMOS_VERSION=1.140.0 follows the team's practice of pinning to the next future version.

Let's confirm this is the next planned version:

✅ Verification successful

Confirmed! Version 1.140.0 is indeed the next version after the latest release.

The version bump from 1.139.0 to 1.140.0 follows a clean progression, with the latest release (v1.139.0) being from 2025-01-08.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify the next planned version
# Check the latest released version and any pending release PRs

# Get latest released version
gh release list -L 1

# Check for pending release PRs
gh pr list --search "release in:title" --state open

Length of output: 275

go.mod (2)

39-39: LGTM! YQ dependency added for query functionality.

The addition of github.com/mikefarah/yq/v4 aligns perfectly with the PR objective of adding the --query flag to atmos describe commands.


72-72: LGTM! Supporting packages added for YQ integration.

All necessary supporting packages have been added:

  • envsubst for variable substitution
  • participle for parsing
  • utfbom for UTF handling
  • orderedmap for maintaining order
  • go-json and go-yaml for data processing
  • copier for data copying
  • gopher-lua for scripting support

These additions provide a robust foundation for the YQ integration.

Also applies to: 76-76, 123-123, 131-131, 143-144, 186-186, 212-212, 246-246

atmos.yaml (1)

18-18: LGTM! Base path configuration updated for flexibility.

Setting base_path to an empty string allows for independent path configurations for components, stacks, and workflows. This change is well-documented and provides more flexibility in path management.

Let's verify that all path configurations are properly set:

✅ Verification successful

Base path configuration verified - all paths properly set!

The empty base path at root level allows for independent path configurations in each section, while all required paths are explicitly configured in their respective sections. This follows the documented patterns and is validated by examples throughout the codebase.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Check if all required path configurations are explicitly set
rg -A 1 "base_path:" | grep -v "^--$" | grep -v "^\s*#"

Length of output: 34548

pkg/utils/file_extensions.go (1)

4-9: Clean and well-organized constants, warrior! 💪

The file extension constants are well-defined and follow proper Go naming conventions. The removal of DefaultVendoringManifestFileExtension keeps the codebase lean.

cmd/describe.go (1)

16-17: Excellent flag implementation, commander! 🎯

The --query flag is well-defined with:

  • Clear description including usage example
  • Proper shorthand -q for quick access
  • Strategic placement before command registration
internal/exec/describe_config.go (1)

19-22: Strong error handling, strategist! 🛡️

Proper error checking for the query flag retrieval. This defensive programming will serve us well in battle!

cmd/about.go (1)

38-41: Fortified error handling, guardian! 🛡️

The addition of error checking for fmt.Fprint strengthens our defenses against I/O failures. A true warrior leaves no error unchecked!

cmd/support.go (1)

38-41: Strong work on error handling improvement!

The addition of error checking for fmt.Fprint operation strengthens the robustness of the command. This is a solid defensive programming practice.

internal/exec/describe_workflows.go (2)

51-54: Clean flag retrieval implementation!

Proper error handling for the new query flag retrieval.


61-69: Well-structured result assignment!

Clear and maintainable approach to handling different output types.

cmd/list_components.go (2)

27-33: Robust flag handling enhancement!

Good improvement in error handling for flag retrieval. The error message is clear and helpful for users.


6-8: Clean import organization!

The reorganization of imports improves code readability.

pkg/utils/yq_utils.go (1)

8-15: LGTM! Clean and focused imports.

The imports are well-organized and include all necessary dependencies for YQ functionality and logging.

pkg/config/const.go (1)

68-69: LGTM! Well-placed constant definition.

The QueryFlag constant follows the established pattern and is appropriately placed within the flags section.

internal/exec/describe_affected.go (2)

35-35: LGTM! Field addition follows the standard pattern.

The Query field addition to DescribeAffectedCmdArgs aligns with the PR objective of adding query support.


157-161: LGTM! Proper flag parsing implementation.

The query flag parsing follows the established error handling pattern used throughout the codebase.

internal/exec/describe_dependents.go (2)

55-59: LGTM! Consistent flag parsing implementation.

The query flag parsing follows the same pattern as other describe commands.


67-77: LGTM! Clean and concise query handling.

The query evaluation logic is well-structured and maintains consistency with other describe commands.

internal/exec/describe_stacks.go (1)

97-101: LGTM! Consistent flag parsing.

The query flag parsing maintains consistency with other describe commands.

pkg/schema/schema.go (2)

192-192: LGTM! Clean struct field addition.

The Query field addition to ArgsAndFlagsInfo follows the established pattern.


257-257: LGTM! Consistent struct field addition.

The Query field addition to ConfigAndStacksInfo maintains consistency with the codebase.

internal/exec/utils.go (2)

53-53: LGTM! The query flag is correctly added to commonFlags.

The addition of cfg.QueryFlag to the commonFlags slice follows the established pattern for flag registration.


968-980: LGTM! The query flag processing logic is well-implemented.

The implementation follows the same pattern as other flags:

  • Handles both standalone (--query value) and assignment-style (--query=value) usage
  • Includes proper error handling for invalid flag formats
  • Stores the query value in the appropriate field
website/docs/cli/commands/describe/describe-config.mdx (2)

38-38: LGTM! Clear example of query flag usage.

The example follows the established pattern of command examples in the documentation.


43-46: LGTM! Well-documented flag description.

The flag documentation:

  • Clearly explains the purpose of the --query flag
  • Includes the -q alias
  • Provides a link to the yq documentation for further details
  • Maintains consistent table formatting
cmd/root.go (1)

113-117: LGTM! Improved error handling for SetCustomUsageFunc.

The addition of error handling ensures that any issues during usage template setup are properly caught and reported, preventing silent failures.

website/docs/cli/commands/describe/describe-workflows.mdx (2)

39-39: LGTM! Clear example of query flag usage.

The example follows the established pattern of command examples in the documentation.


44-48: LGTM! Well-documented flag description.

The flag documentation:

  • Clearly explains the purpose of the --query flag
  • Includes the -q alias
  • Provides a link to the yq documentation for further details
  • Maintains consistent table formatting with other flags

coderabbitai[bot]
coderabbitai bot previously approved these changes Jan 8, 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 (9)
internal/exec/describe_config.go (1)

34-44: Consider enhancing error messages for query evaluation

While the implementation is solid, the error message from query evaluation could be more descriptive to help users debug invalid yq expressions.

Consider wrapping the error with additional context:

 if query != "" {
   res, err = u.EvaluateYqExpression(atmosConfig, atmosConfig, query)
   if err != nil {
-    return err
+    return fmt.Errorf("failed to evaluate query expression '%s': %w", query, err)
   }
pkg/utils/yq_utils.go (1)

34-73: Consider enhancing error messages and optimizing memory usage.

  1. Error messages could be more descriptive by including the actual data that failed to convert.
  2. YAML preferences could be extracted to package-level constants for reusability.
  3. Consider using streaming for large YAML documents to improve memory efficiency.
 func EvaluateYqExpression(atmosConfig schema.AtmosConfiguration, data any, yq string) (any, error) {
+    // Extract YAML preferences to package-level constants
+    const (
+        defaultIndent = 2
+        defaultPrintDocSeparators = true
+        defaultUnwrapScalar = true
+    )

     yaml, err := ConvertToYAML(data)
     if err != nil {
-        return nil, fmt.Errorf("EvaluateYqExpression: failed to convert data to YAML: %w", err)
+        return nil, fmt.Errorf("EvaluateYqExpression: failed to convert data to YAML. Data: %+v, Error: %w", data, err)
     }

     pref := yqlib.YamlPreferences{
-        Indent:                      2,
+        Indent:                      defaultIndent,
         ColorsEnabled:               false,
         LeadingContentPreProcessing: true,
-        PrintDocSeparators:          true,
-        UnwrapScalar:                true,
+        PrintDocSeparators:          defaultPrintDocSeparators,
+        UnwrapScalar:                defaultUnwrapScalar,
         EvaluateTogether:            false,
     }
internal/exec/describe_component.go (1)

46-49: Consider improving error handling and code organization.

  1. Error messages could be more specific about what failed during query evaluation.
  2. Query evaluation logic could be extracted to a helper function for reuse across commands.
+// evaluateQuery evaluates a YQ expression against the given data
+func evaluateQuery(query string, data any) (any, error) {
+    if query == "" {
+        return data, nil
+    }
+
+    atmosConfig, err := cfg.InitCliConfig(schema.ConfigAndStacksInfo{}, true)
+    if err != nil {
+        return nil, fmt.Errorf("failed to initialize CLI config: %w", err)
+    }
+
+    res, err := u.EvaluateYqExpression(atmosConfig, data, query)
+    if err != nil {
+        return nil, fmt.Errorf("failed to evaluate query '%s': %w", query, err)
+    }
+
+    return res, nil
+}

 func ExecuteDescribeComponentCmd(cmd *cobra.Command, args []string) error {
     // ... existing code ...

     query, err := flags.GetString("query")
     if err != nil {
-        return err
+        return fmt.Errorf("failed to get query flag: %w", err)
     }

     component := args[0]
     componentSection, err := ExecuteDescribeComponent(component, stack, processTemplates)
     if err != nil {
         return err
     }

-    var res any
-    if query != "" {
-        atmosConfig, err := cfg.InitCliConfig(schema.ConfigAndStacksInfo{}, true)
-        if err != nil {
-            return err
-        }
-
-        res, err = u.EvaluateYqExpression(atmosConfig, componentSection, query)
-        if err != nil {
-            return err
-        }
-    } else {
-        res = componentSection
-    }
+    res, err := evaluateQuery(query, componentSection)
+    if err != nil {
+        return err
+    }

Also applies to: 58-72

pkg/utils/yq_test.go (1)

11-168: Consider enhancing test coverage and organization.

The test cases are comprehensive but could benefit from:

  1. Using table-driven tests for better organization and maintainability
  2. Adding edge cases (empty input, invalid expressions)
  3. Adding error scenario tests

Here's an example of how to refactor using table-driven tests:

 func TestEvaluateYqExpression(t *testing.T) {
     input := `
     settings:
         test: true
         mode: test
     # ... rest of the input ...
     `

     atmosConfig := schema.AtmosConfiguration{
         Logs: schema.Logs{
             Level: "Trace",
         },
     }

     data, err := UnmarshalYAML[map[string]any](input)
     assert.Nil(t, err)
     assert.NotNil(t, data)

+    tests := []struct {
+        name     string
+        yq       string
+        expected any
+        wantErr  bool
+    }{
+        {
+            name:     "get boolean setting",
+            yq:       ".settings.test",
+            expected: true,
+        },
+        {
+            name:     "get string setting",
+            yq:       ".settings.mode",
+            expected: "test",
+        },
+        // Add more test cases here
+        {
+            name:    "invalid expression",
+            yq:      ".[",
+            wantErr: true,
+        },
+    }
+
+    for _, tt := range tests {
+        t.Run(tt.name, func(t *testing.T) {
+            res, err := EvaluateYqExpression(atmosConfig, data, tt.yq)
+            if tt.wantErr {
+                assert.Error(t, err)
+                return
+            }
+            assert.NoError(t, err)
+            assert.Equal(t, tt.expected, res)
+        })
+    }
website/docs/cli/commands/describe/describe-stacks.mdx (1)

47-47: Documentation looks good, but could be enhanced with an example query!

The documentation for the new --query flag is clear and well-structured. Consider adding a practical example of a yq expression to help users get started.

 atmos describe stacks --query <yq-expression>
+# Example: Filter stacks by environment
+atmos describe stacks --query '.[] | select(.environment == "prod")'

Also applies to: 51-51, 65-65

website/docs/cli/commands/describe/describe-workflows.mdx (1)

39-39: Documentation is consistent and well-formatted!

The documentation follows the same pattern as other commands. Consider adding a practical example query here as well.

 atmos describe workflows --query <yq-expression>
+# Example: Filter workflows by specific file
+atmos describe workflows --query 'select(file == "networking.yaml")'

Also applies to: 44-48

website/docs/cli/commands/describe/describe-dependents.mdx (1)

244-244: Documentation maintains consistency across commands!

The documentation aligns well with other commands. Consider adding a practical example query for filtering dependents.

 atmos describe dependents test/test-component -s tenant1-ue2-test-1 --query <yq-expression>
+# Example: Filter dependents by component type
+atmos describe dependents test/test-component -s tenant1-ue2-test-1 --query 'select(.component_type == "terraform")'

Also applies to: 255-260

website/docs/cli/commands/describe/describe-component.mdx (1)

46-49: Examples look good but could be more descriptive!

The examples demonstrate the usage of the new --query flag well. Consider adding comments to show expected output format.

 atmos describe component vpc -s plat-ue2-prod --query .vars.tags
+# Returns component tags in YAML format
 
 atmos describe component vpc -s plat-ue2-prod -q .settings
+# Returns component settings in YAML format
website/docs/cli/commands/describe/describe-affected.mdx (1)

110-110: Example could be more specific!

While the example shows the basic syntax, it would be more helpful to include a concrete example with an actual yq expression.

-atmos describe affected --query <yq-expression>
+atmos describe affected --query '.[] | select(.affected == "component")'
+# Lists only components affected by direct changes
📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 23507ab and c01a353.

⛔ Files ignored due to path filters (1)
  • go.sum is excluded by !**/*.sum
📒 Files selected for processing (30)
  • LICENSE (1 hunks)
  • atmos.yaml (1 hunks)
  • cmd/about.go (1 hunks)
  • cmd/describe.go (1 hunks)
  • cmd/list_components.go (2 hunks)
  • cmd/list_stacks.go (1 hunks)
  • cmd/root.go (1 hunks)
  • cmd/support.go (1 hunks)
  • examples/quick-start-advanced/Dockerfile (1 hunks)
  • go.mod (8 hunks)
  • internal/exec/describe_affected.go (4 hunks)
  • internal/exec/describe_component.go (2 hunks)
  • internal/exec/describe_config.go (3 hunks)
  • internal/exec/describe_dependents.go (2 hunks)
  • internal/exec/describe_stacks.go (3 hunks)
  • internal/exec/describe_workflows.go (2 hunks)
  • internal/exec/utils.go (3 hunks)
  • pkg/config/const.go (1 hunks)
  • pkg/schema/schema.go (2 hunks)
  • pkg/utils/file_extensions.go (1 hunks)
  • pkg/utils/glob_utils.go (1 hunks)
  • pkg/utils/yq_test.go (1 hunks)
  • pkg/utils/yq_utils.go (1 hunks)
  • website/docs/cli/commands/describe/describe-affected.mdx (2 hunks)
  • website/docs/cli/commands/describe/describe-component.mdx (2 hunks)
  • website/docs/cli/commands/describe/describe-config.mdx (1 hunks)
  • website/docs/cli/commands/describe/describe-dependents.mdx (2 hunks)
  • website/docs/cli/commands/describe/describe-stacks.mdx (2 hunks)
  • website/docs/cli/commands/describe/describe-workflows.mdx (1 hunks)
  • website/docs/integrations/atlantis.mdx (1 hunks)
✅ Files skipped from review due to trivial changes (3)
  • cmd/list_stacks.go
  • website/docs/integrations/atlantis.mdx
  • LICENSE
🧰 Additional context used
📓 Learnings (1)
examples/quick-start-advanced/Dockerfile (2)
Learnt from: aknysh
PR: cloudposse/atmos#775
File: examples/quick-start-advanced/Dockerfile:9-9
Timestamp: 2024-11-12T05:52:05.088Z
Learning: It is acceptable to set `ARG ATMOS_VERSION` to a future version like `1.105.0` in `examples/quick-start-advanced/Dockerfile` if that will be the next release.
Learnt from: osterman
PR: cloudposse/atmos#801
File: examples/quick-start-advanced/Dockerfile:9-9
Timestamp: 2024-11-23T00:13:22.004Z
Learning: When updating the `ATMOS_VERSION` in Dockerfiles, the team prefers to pin to the next future version when the PR merges, even if the version is not yet released.
⏰ Context from checks skipped due to timeout of 90000ms (2)
  • GitHub Check: Acceptance Tests (windows-latest, windows)
  • GitHub Check: Summary
🔇 Additional comments (32)
pkg/utils/file_extensions.go (1)

4-9: Clean and well-organized constants!

The file extension constants are properly maintained, and the removal of redundant constants keeps the code lean. The remaining YAML-related constants will support the new query functionality well.

cmd/describe.go (1)

16-17: Excellent implementation of the query flag!

The persistent flag is well-implemented with:

  • Clear description mentioning yq expressions
  • Proper shorthand -q option
  • Availability across all describe subcommands

This perfectly aligns with the PR objectives.

internal/exec/describe_config.go (1)

19-22: Robust error handling for the query flag!

The error handling follows the established pattern consistently.

cmd/about.go (1)

38-41: Great defensive programming!

Adding error handling for fmt.Fprint improves the robustness of the command output handling. This is a solid improvement to the codebase.

cmd/support.go (1)

38-41: Excellent error handling addition, warrior!

The new error check for stdout write operations strengthens the command's reliability. This is the way.

pkg/utils/glob_utils.go (1)

24-24: Path normalization strengthens cross-platform support!

Converting to slash format ensures consistent glob matching across different operating systems. A worthy enhancement.

internal/exec/describe_workflows.go (4)

5-5: Clean import alias for utils package!

Using u as an alias maintains code clarity while adding the new dependency.


51-54: Strong error handling for the new query flag!

The error check ensures robust command-line argument processing.


61-69: Clean result type handling!

Using any type and clear conditional logic for different output types makes the code maintainable.


71-76: Excellent query processing implementation!

The query evaluation is properly gated and error-handled. This is the core of the new functionality.

cmd/list_components.go (2)

6-8: Clean import organization!

The imports are now properly grouped and organized.


27-33: Strong error handling with user-friendly output!

The addition of colored error messages and proper flag error handling improves the user experience significantly.

pkg/utils/yq_utils.go (1)

17-32: LGTM! Clean and focused no-op logging implementation.

The logBackend struct provides a clean implementation of the logging interface, effectively suppressing logs when not in trace mode.

pkg/config/const.go (1)

68-68: LGTM! Well-placed constant definition.

The QueryFlag constant follows the established pattern and is logically placed among other flag constants.

cmd/root.go (1)

113-116: Great addition of error handling!

The error handling for SetCustomUsageFunc ensures that any template setup failures are properly caught and reported.

internal/exec/describe_affected.go (2)

35-35: LGTM! Clean implementation of the query flag.

The Query field is properly added to the struct and initialized through the command-line flags.

Also applies to: 157-160, 179-179


241-292: Well-structured control flow for query evaluation!

The implementation:

  1. Correctly handles the empty query case
  2. Properly evaluates the query using EvaluateYqExpression
  3. Ensures upload logic is only executed when no query is provided

This maintains a clean separation of concerns between querying and uploading functionality.

internal/exec/describe_dependents.go (2)

5-5: LGTM! Clean import and flag parsing.

The utils package is properly imported and the query flag is correctly retrieved with error handling.

Also applies to: 55-58


67-78: Well-structured query evaluation logic!

The implementation follows a clean pattern:

  1. Declares a result variable of type any
  2. Evaluates the query only when provided
  3. Falls back to the original dependents when no query is specified
internal/exec/describe_stacks.go (2)

58-58: Good refactoring for consistency!

Changed to use the already retrieved flags variable instead of calling cmd.Flags() again.


97-100: Clean implementation of query evaluation!

The implementation follows the same consistent pattern as other describe commands:

  1. Proper query flag parsing with error handling
  2. Clear conditional logic for query evaluation
  3. Consistent use of EvaluateYqExpression

Also applies to: 116-127

pkg/schema/schema.go (1)

192-192: Clean and consistent struct field additions!

The Query field is appropriately added to both info structs with consistent tagging.

Also applies to: 257-257

internal/exec/utils.go (3)

53-53: Good addition to commonFlags!

The QueryFlag is properly added to the commonFlags slice, maintaining consistency with other flag declarations.


223-223: Clean field propagation!

The Query field is correctly propagated from argsAndFlagsInfo to configAndStacksInfo.


968-980: Well-structured query flag handling!

The implementation follows the established pattern for flag processing with proper error handling.

examples/quick-start-advanced/Dockerfile (1)

9-9: Version bump looks good!

The update to ATMOS_VERSION=1.140.0 follows the team's convention of pinning to future versions.

website/docs/cli/commands/describe/describe-config.mdx (2)

38-38: Clear example addition!

The example clearly demonstrates the usage of the new query flag.


43-46: Well-documented flag!

The query flag documentation is comprehensive, including:

  • Clear description
  • Example usage
  • Link to yq documentation
  • Consistent table formatting
go.mod (1)

39-39: Dependencies look good, verify compatibility!

The addition of yq and its dependencies is appropriate for the new query functionality. All versions appear to be stable releases.

Run this script to verify the dependencies:

Also applies to: 72-72, 76-76, 131-131, 143-144, 186-186, 212-212, 246-246

✅ Verification successful

This is a secure dependency, warrior! 🛡️

No vulnerabilities found in the GitHub Security Advisory Database for github.com/mikefarah/yq/v4. The version v4.44.6 is battle-tested and safe to use.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check for any known vulnerabilities in the new dependencies

# Check the yq library for any security advisories
gh api graphql -f query='
{
  securityVulnerabilities(first: 5, ecosystem: GO, package: "github.com/mikefarah/yq") {
    nodes {
      advisory {
        summary
        severity
        publishedAt
      }
      vulnerableVersionRange
      firstPatchedVersion {
        identifier
      }
    }
  }
}'

Length of output: 355

atmos.yaml (1)

18-18: Configuration change provides more flexibility!

Setting base_path to an empty string allows for independent path configurations, which is well-documented in the comments above. This change enhances flexibility in path management.

website/docs/cli/commands/describe/describe-component.mdx (1)

66-66: Flag documentation is clear and well-referenced!

The --query flag documentation provides good context with examples and links to the yq documentation.

website/docs/cli/commands/describe/describe-affected.mdx (1)

214-214: Flag documentation is consistent with other commands!

The --query flag documentation follows the same pattern as in other commands, providing clear examples and referencing yq documentation.

Copy link

mergify bot commented Jan 8, 2025

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

@mergify mergify bot added the conflict This PR has conflicts label Jan 8, 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 (1)
internal/exec/describe_stacks.go (1)

116-126: Consider using a more descriptive variable name than 'res'.

While the logic is solid, consider renaming res to something more descriptive like queryResult or stacksMapResult to better convey its purpose.

-	var res any
+	var queryResult any

	if query != "" {
-		res, err = u.EvaluateYqExpression(atmosConfig, finalStacksMap, query)
+		queryResult, err = u.EvaluateYqExpression(atmosConfig, finalStacksMap, query)
		if err != nil {
			return err
		}
	} else {
-		res = finalStacksMap
+		queryResult = finalStacksMap
	}

-	err = printOrWriteToFile(format, file, res)
+	err = printOrWriteToFile(format, file, queryResult)
📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between c01a353 and a8a66f1.

📒 Files selected for processing (4)
  • go.mod (8 hunks)
  • internal/exec/describe_stacks.go (3 hunks)
  • internal/exec/utils.go (3 hunks)
  • pkg/config/const.go (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • pkg/config/const.go
  • go.mod
⏰ Context from checks skipped due to timeout of 90000ms (2)
  • GitHub Check: Build (windows-latest, windows)
  • GitHub Check: Summary
🔇 Additional comments (6)
internal/exec/describe_stacks.go (2)

58-58: LGTM! Flag retrieval changes are consistent.

The changes maintain consistency in flag retrieval patterns across the function, with proper error handling.

Also applies to: 97-100


127-127: LGTM! Clean integration with existing output handling.

The query evaluation is well-integrated into the existing flow, maintaining backward compatibility while adding the new query functionality.

internal/exec/utils.go (4)

53-53: LGTM! The query flag is correctly added to commonFlags.

The placement ensures the flag will be properly handled and removed before passing arguments to underlying tools.


990-1001: LGTM! Query flag processing follows established patterns.

The implementation correctly handles both flag formats and includes proper error handling.


245-245: LGTM! Query field is properly integrated.

The field is correctly populated in the ConfigAndStacksInfo struct, maintaining consistency with other command-line arguments.


53-53: Verify query flag integration with describe commands.

Let's ensure the query flag is properly integrated across all describe commands.

Run this script to verify the integration:

Also applies to: 245-245, 990-1001

✅ Verification successful

Query flag integration verified successfully across describe commands

The query flag is properly implemented and consistently integrated across all describe commands, with proper parsing and execution flow.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify query flag integration in describe commands

# Test 1: Find all describe commands that should support the query flag
echo "Checking describe commands for query flag support..."
ast-grep --pattern 'func.*Cmd.*describe.*\(.*\).*{
  $$$
}'

# Test 2: Verify query flag processing in these commands
echo "Checking query flag processing..."
rg -A 5 'Query.*=.*argsAndFlagsInfo\.Query'

Length of output: 585


Script:

#!/bin/bash
# Find query flag definition and describe commands
echo "=== Query flag definition ==="
rg -A 3 'Query.*string.*[`"]query[`"]'

echo -e "\n=== Describe command implementations ==="
ast-grep --pattern 'func.*describe.*Command.*\(.*\).*{
  $$$
}'

echo -e "\n=== Query value usage ==="
rg -A 5 'configAndStacksInfo.*Query'

Length of output: 664


Script:

#!/bin/bash
# Broader search for query-related code
echo "=== Query flag definitions (broader search) ==="
rg -i "query.*flag" -A 3

echo -e "\n=== Describe command implementations (alternative pattern) ==="
rg "func.*[Dd]escribe" -A 5

echo -e "\n=== Query parameter flow ==="
rg -i "query" internal/exec/utils.go -A 3

Length of output: 21277

@aknysh aknysh merged commit 66badb5 into main Jan 8, 2025
45 checks passed
@aknysh aknysh deleted the add-vars-parameter branch January 8, 2025 20:47
@mergify mergify bot removed the needs-cloudposse Needs Cloud Posse assistance label Jan 8, 2025
Copy link

github-actions bot commented Jan 8, 2025

These changes were released in v1.140.0.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
minor New features that do not break anything
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants