Skip to content

atmos list vendor #1192

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

Open
wants to merge 29 commits into
base: main
Choose a base branch
from
Open

atmos list vendor #1192

wants to merge 29 commits into from

Conversation

Cerebrovinny
Copy link
Collaborator

@Cerebrovinny Cerebrovinny commented Apr 7, 2025

what

  • atmos list vendor command to list all vendor configurations in multiple formats (table, json, yaml, csv, tsv).
  • Implements filtering, custom columns.

why

  • Provides a way to view and audit all vendor configurations.

Evidence:
Screenshot 2025-04-15 at 18 34 00

references

Summary by CodeRabbit

  • New Features

    • Introduced a new CLI command to list vendor configurations with customizable output formats, filtering by stack, and delimiter options.
    • Added support for displaying vendor configuration details in table, JSON, CSV, and TSV formats with customizable columns and headers.
  • Documentation

    • Added detailed usage documentation with examples for the new vendor listing command.
  • Bug Fixes

    • Enhanced error handling and validation during vendor configuration discovery and listing.
  • Tests

    • Added comprehensive tests covering vendor listing, filtering, formatting, manifest discovery, and error scenarios.
  • Refactor

    • Extended configuration schema and formatting options to support advanced vendor listing features.

This commit introduces the `list vendor` command to list vendor configurations, including component and vendor manifests.

It also adds:
- Filtering by stack
- Support for JSON, YAML, CSV, TSV, and table output formats
- Custom column configuration
Copy link

mergify bot commented Apr 7, 2025

Warning

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

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

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

@Cerebrovinny Cerebrovinny added the minor New features that do not break anything label Apr 9, 2025
Copy link

codecov bot commented Apr 9, 2025

Codecov Report

Attention: Patch coverage is 48.46416% with 302 lines in your changes missing coverage. Please review.

Project coverage is 33.26%. Comparing base (c87cd51) to head (6dd4ec6).

Files with missing lines Patch % Lines
pkg/list/list_vendor.go 43.82% 236 Missing and 14 partials ⚠️
cmd/list_vendor.go 12.50% 49 Missing ⚠️
pkg/list/format/table.go 62.50% 2 Missing and 1 partial ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #1192      +/-   ##
==========================================
+ Coverage   32.89%   33.26%   +0.36%     
==========================================
  Files         223      226       +3     
  Lines       23791    24373     +582     
==========================================
+ Hits         7827     8107     +280     
- Misses      14798    15085     +287     
- Partials     1166     1181      +15     
Flag Coverage Δ
unittests 33.26% <48.46%> (+0.36%) ⬆️

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

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

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

@Cerebrovinny Cerebrovinny changed the title Feat/list vendor atmos list vendor Apr 15, 2025
@Cerebrovinny Cerebrovinny marked this pull request as ready for review April 20, 2025 07:02
@Cerebrovinny Cerebrovinny requested a review from a team as a code owner April 20, 2025 07:02
Copy link
Contributor

coderabbitai bot commented Apr 20, 2025

📝 Walkthrough

Walkthrough

This change introduces a new list vendor CLI command to enumerate vendor configurations in the Atmos project. Supporting code is added to discover, filter, and format vendor manifest and component manifest data, with output options including table, JSON, CSV, and TSV. The schema is extended to include a ComponentManifest struct and a list configuration under vendor. Documentation and comprehensive tests are included to validate manifest discovery, filtering, and output formatting. Formatting logic is updated to allow custom headers and a new template output format is defined.

Changes

File(s) Change Summary
cmd/list_vendor.go, pkg/list/list_vendor.go, pkg/list/list_vendor_format.go Introduced the list vendor command, vendor configuration discovery, filtering, and output formatting logic.
cmd/markdown/atmos_list_vendor_usage.md Added documentation for the new atmos list vendor command with usage examples.
pkg/list/format/formatter.go, pkg/list/format/table.go Added support for custom headers, a new template format, and exported the styled table creation function.
pkg/list/list_vendor_test.go Added extensive tests for vendor listing, filtering, formatting, and manifest discovery logic.
pkg/schema/schema.go Added ComponentManifest struct and extended Vendor struct to include a list field.
tests/snapshots/TestCLICommands_atmos_describe_config.stdout.golden Updated snapshot to reflect new list field under vendor in configuration output.

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant CLI
    participant Config
    participant ListVendor
    participant Formatter

    User->>CLI: Run 'atmos list vendor' [with flags]
    CLI->>Config: Initialize and validate configuration
    CLI->>ListVendor: FilterAndListVendor(config, options)
    ListVendor->>ListVendor: Discover component/vendor manifests
    ListVendor->>ListVendor: Apply filters (e.g., stack pattern)
    ListVendor->>Formatter: Format output (table/JSON/CSV/TSV)
    Formatter-->>ListVendor: Formatted output string
    ListVendor-->>CLI: Output string
    CLI-->>User: Prints formatted vendor configuration list
Loading

Possibly related PRs

Suggested reviewers

  • aknysh

📜 Recent review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 858828a and 6dd4ec6.

📒 Files selected for processing (1)
  • pkg/schema/schema.go (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • pkg/schema/schema.go
⏰ Context from checks skipped due to timeout of 90000ms (2)
  • GitHub Check: Build (windows-latest, windows)
  • GitHub Check: Summary
✨ Finishing Touches
  • 📝 Generate Docstrings

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share
🪧 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.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

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.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @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: 6

♻️ Duplicate comments (1)
pkg/list/list_vendor.go (1)

71-111: 🛠️ Refactor suggestion

High cyclomatic complexity – pull common branches into helpers

formatVendorOutput now weighs in at 12 decision points (same number flagged by Advanced‑Security). Most of that stems from three separate switches that partially duplicate each other. You can shave the complexity and make the intent clearer by:

  1. Creating a small helper that returns the data map for a given format.
  2. Moving the CSV/TSV special‑casing into its own formatter.
  3. Leaning on format.NewFormatter for everything else.
-func formatVendorOutput(rows []map[string]interface{}, customHeaders []string, options *FilterOptions) (string, error) {
-    ...
-	switch options.FormatStr {
-	case "table":
-		if formatOpts.TTY {
-			return renderVendorTableOutput(customHeaders, rows), nil
-		}
-	case "csv":
-		return buildVendorCSVTSV(customHeaders, rows, ","), nil
-	case "tsv":
-		return buildVendorCSVTSV(customHeaders, rows, "\t"), nil
-	}
-
-	output, err := formatter.Format(data, formatOpts)
-	...
-}
+func formatVendorOutput(rows []map[string]interface{}, headers []string, opt *FilterOptions) (string, error) {
+    getData := func() map[string]interface{} {
+        withHeader := opt.FormatStr == "table" || opt.FormatStr == "json"
+        return buildVendorDataMap(rows, withHeader)
+    }
+
+    switch opt.FormatStr {
+    case "csv":
+        return buildVendorCSVTSV(headers, rows, ","), nil
+    case "tsv":
+        return buildVendorCSVTSV(headers, rows, "\t"), nil
+    case "table":
+        if term.IsTerminal(int(os.Stdout.Fd())) {
+            return renderVendorTableOutput(headers, rows), nil
+        }
+    }
+
+    formatter, err := format.NewFormatter(format.Format(opt.FormatStr))
+    if err != nil {
+        return "", err
+    }
+    return formatter.Format(getData(), format.FormatOptions{
+        Format:        format.Format(opt.FormatStr),
+        Delimiter:     opt.Delimiter,
+        TTY:           term.IsTerminal(int(os.Stdout.Fd())),
+        CustomHeaders: headers,
+    })
+}

This drops cyclomatic complexity to ~6, satisfying the linter and making later maintenance painless.

🧹 Nitpick comments (8)
cmd/markdown/atmos_list_vendor_usage.md (1)

1-30: Documentation needs formatting improvements.

The documentation provides good examples for the new command but has formatting issues:

  1. Use proper markdown list syntax (e.g., - or *) instead of en-dashes
  2. Add language specifiers to code blocks (e.g., ```bash)
  3. Remove dollar signs from command examples or show output according to markdown best practices
-– List all vendor configurations
-```
- $ atmos list vendor
-```
+- List all vendor configurations
+```bash
+atmos list vendor
+```

-– List vendor configurations with a specific output format
-```
- $ atmos list vendor --format json
-```
+- List vendor configurations with a specific output format
+```bash
+atmos list vendor --format json
+```
🧰 Tools
🪛 LanguageTool

[typographical] ~1-~1: Consider using an em dash in dialogues and enumerations.
Context: – List all vendor configurations ``` $ a...

(DASH_RULE)


[typographical] ~5-~5: Consider using an em dash in dialogues and enumerations.
Context: ...gurations $ atmos list vendor – List vendor configurations with a speci...

(DASH_RULE)


[typographical] ~10-~10: Consider using an em dash in dialogues and enumerations.
Context: ... $ atmos list vendor --format json ``` – List vendor configurations filtered by ...

(DASH_RULE)


[typographical] ~15-~15: Consider using an em dash in dialogues and enumerations.
Context: ...$ atmos list vendor --stack "vpc*" ``` – List vendor configurations with comma-s...

(DASH_RULE)


[typographical] ~20-~20: Consider using an em dash in dialogues and enumerations.
Context: ... $ atmos list vendor --format csv ``` – List vendor configurations with tab-sep...

(DASH_RULE)


[typographical] ~25-~25: Consider using an em dash in dialogues and enumerations.
Context: ... $ atmos list vendor --format tsv ``` – List vendor configurations with a custo...

(DASH_RULE)

🪛 markdownlint-cli2 (0.17.2)

2-2: Fenced code blocks should have a language specified
null

(MD040, fenced-code-language)


3-3: Dollar signs used before commands without showing output
null

(MD014, commands-show-output)


7-7: Fenced code blocks should have a language specified
null

(MD040, fenced-code-language)


8-8: Dollar signs used before commands without showing output
null

(MD014, commands-show-output)


12-12: Fenced code blocks should have a language specified
null

(MD040, fenced-code-language)


13-13: Dollar signs used before commands without showing output
null

(MD014, commands-show-output)


17-17: Fenced code blocks should have a language specified
null

(MD040, fenced-code-language)


18-18: Dollar signs used before commands without showing output
null

(MD014, commands-show-output)


22-22: Fenced code blocks should have a language specified
null

(MD040, fenced-code-language)


23-23: Dollar signs used before commands without showing output
null

(MD014, commands-show-output)


27-27: Fenced code blocks should have a language specified
null

(MD040, fenced-code-language)


28-28: Dollar signs used before commands without showing output
null

(MD014, commands-show-output)

pkg/list/format/table.go (2)

172-174: Exported function comment should match the function name

The doc comment still says createStyledTable but the exported symbol is now CreateStyledTable.
Please update the comment to start with the exact function name to satisfy golint and improve godoc.

-// createStyledTable creates a styled table with headers and rows.
+// CreateStyledTable creates a styled table with headers and rows.

173-173: Public helper could live in a dedicated format package

Exporting CreateStyledTable from this file is handy, but it slightly blurs the boundary between “table helpers” and the higher‑level formatter types.
If you foresee re‑use across packages, consider moving it (and maybe the constants) into a tiny pkg/ui/table or pkg/list/format/tableutil package to keep the API surface tight.

Purely optional, leaving here for future consideration.

cmd/list_vendor.go (1)

43-50: Delimiter flag is accepted even for non‑delimited formats

Right now a user can run atmos list vendor --format json --delimiter "|", and the flag is silently ignored.
You might want to validate that --delimiter is only provided when --format is csv or tsv, otherwise return a helpful error.

if delimiterFlag != "" && formatFlag != "csv" && formatFlag != "tsv" {
    cmd.PrintErrln("The --delimiter flag is only valid with --format csv|tsv")
    return
}
pkg/list/list_vendor_format.go (1)

12-19: Duplicate sizing constants—consider centralising

DefaultTerminalWidth and MaxColumnWidth already exist (or very similar ones do) in pkg/list/format/table.go.
Keeping two separate definitions risks them diverging. Importing the original constants (or exposing them in a shared package) will avoid magic numbers and keep behaviour consistent.

pkg/list/list_vendor_test.go (1)

125-141: Minor duplication in assertions

The table‑format test checks for "Component" twice (lines 132 and 137).
Harmless, but you can drop one of them to keep the test lean.

pkg/list/list_vendor.go (2)

113-132: Early‑return opportunity & duplicated validation

FilterAndListVendor validates options.FormatStr twice (once implicitly through ValidateFormat, and again when constructing the formatter inside formatVendorOutput). You can:

  1. Return early on invalid format right here.
  2. Skip the second validation (or make formatVendorOutput assume it got a valid enum).

Additionally, the linter report mentions an early‑return suggestion – replacing

if options.FormatStr == "" {
    options.FormatStr = string(format.FormatTable)
}
if err := format.ValidateFormat(options.FormatStr); err != nil {
    return "", err
}

with:

if options.FormatStr == "" {
    options.FormatStr = string(format.FormatTable)
} else if err := format.ValidateFormat(options.FormatStr); err != nil {
    return "", err
}

eliminates the else branch entirely and silences that finding.


460-501: Avoid round‑tripping through YAML – unmarshal directly

readComponentManifest converts a map[string]interface{} back to YAML only to unmarshal it again into a struct. That incurs extra allocations and loses the benefit of yaml.UnmarshalStrict.

Since filetype.DetectFormatAndParseFile already gives you a typed map, decode straight into ComponentManifest:

-var manifest schema.ComponentManifest
-
-yamlData, err := yaml.Marshal(mapData)
-
-if err := yaml.Unmarshal(yamlData, &manifest); err != nil {
-
-}
+var manifest schema.ComponentManifest
+if err := mapstructure.Decode(mapData, &manifest); err != nil {
+    return nil, fmt.Errorf("error decoding component manifest: %w", err)
+}

(The mapstructure package is already a transitive dependency in Atmos; if not, it’s lightweight.)
This halves the function’s CPU time and removes unnecessary imports.

📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 29577d8 and 858828a.

📒 Files selected for processing (9)
  • cmd/list_vendor.go (1 hunks)
  • cmd/markdown/atmos_list_vendor_usage.md (1 hunks)
  • pkg/list/format/formatter.go (1 hunks)
  • pkg/list/format/table.go (3 hunks)
  • pkg/list/list_vendor.go (1 hunks)
  • pkg/list/list_vendor_format.go (1 hunks)
  • pkg/list/list_vendor_test.go (1 hunks)
  • pkg/schema/schema.go (1 hunks)
  • tests/snapshots/TestCLICommands_atmos_describe_config.stdout.golden (1 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (1)
cmd/list_vendor.go (5)
pkg/schema/schema.go (2)
  • Command (527-537)
  • ConfigAndStacksInfo (372-442)
pkg/config/config.go (1)
  • InitCliConfig (25-62)
pkg/list/list_values.go (1)
  • FilterOptions (55-64)
pkg/list/list_vendor.go (1)
  • FilterAndListVendor (114-132)
cmd/cmd_utils.go (1)
  • AddStackCompletion (715-720)
🪛 LanguageTool
cmd/markdown/atmos_list_vendor_usage.md

[typographical] ~1-~1: Consider using an em dash in dialogues and enumerations.
Context: – List all vendor configurations ``` $ a...

(DASH_RULE)


[typographical] ~5-~5: Consider using an em dash in dialogues and enumerations.
Context: ...gurations $ atmos list vendor – List vendor configurations with a speci...

(DASH_RULE)


[typographical] ~10-~10: Consider using an em dash in dialogues and enumerations.
Context: ... $ atmos list vendor --format json ``` – List vendor configurations filtered by ...

(DASH_RULE)


[typographical] ~15-~15: Consider using an em dash in dialogues and enumerations.
Context: ...$ atmos list vendor --stack "vpc*" ``` – List vendor configurations with comma-s...

(DASH_RULE)


[typographical] ~20-~20: Consider using an em dash in dialogues and enumerations.
Context: ... $ atmos list vendor --format csv ``` – List vendor configurations with tab-sep...

(DASH_RULE)


[typographical] ~25-~25: Consider using an em dash in dialogues and enumerations.
Context: ... $ atmos list vendor --format tsv ``` – List vendor configurations with a custo...

(DASH_RULE)

🪛 markdownlint-cli2 (0.17.2)
cmd/markdown/atmos_list_vendor_usage.md

2-2: Fenced code blocks should have a language specified
null

(MD040, fenced-code-language)


3-3: Dollar signs used before commands without showing output
null

(MD014, commands-show-output)


7-7: Fenced code blocks should have a language specified
null

(MD040, fenced-code-language)


8-8: Dollar signs used before commands without showing output
null

(MD014, commands-show-output)


12-12: Fenced code blocks should have a language specified
null

(MD040, fenced-code-language)


13-13: Dollar signs used before commands without showing output
null

(MD014, commands-show-output)


17-17: Fenced code blocks should have a language specified
null

(MD040, fenced-code-language)


18-18: Dollar signs used before commands without showing output
null

(MD014, commands-show-output)


22-22: Fenced code blocks should have a language specified
null

(MD040, fenced-code-language)


23-23: Dollar signs used before commands without showing output
null

(MD014, commands-show-output)


27-27: Fenced code blocks should have a language specified
null

(MD040, fenced-code-language)


28-28: Dollar signs used before commands without showing output
null

(MD014, commands-show-output)

⏰ Context from checks skipped due to timeout of 90000ms (2)
  • GitHub Check: Build (windows-latest, windows)
  • GitHub Check: Summary
🔇 Additional comments (7)
pkg/schema/schema.go (2)

770-777: Well-designed component manifest struct.

The new ComponentManifest struct has a clean Kubernetes-like schema with appropriate YAML/JSON tags. The use of generic maps for metadata, spec, and vars fields provides flexibility for different component configurations.


783-783: Good extension of Vendor struct.

The addition of the List field to the Vendor struct properly supports the new vendor listing configuration capabilities. The omitempty tag is appropriate for this optional field.

tests/snapshots/TestCLICommands_atmos_describe_config.stdout.golden (1)

129-133: Snapshot correctly updated with new vendor list configuration.

The test snapshot has been properly updated to reflect the schema changes, showing the new list structure with default empty values.

pkg/list/format/formatter.go (1)

25-25: Good addition of CustomHeaders support.

The new CustomHeaders field in FormatOptions allows for flexible table header customization, which enhances the vendor listing capabilities.

pkg/list/format/table.go (1)

72-82: Make sure customHeaders keep the first “Key” column in sync with the row builder

createRows always places the key (or KeyValue) as the first element of every row, but createHeader now forwards customHeaders verbatim.
If a caller supplies a header slice that does not start with the “Key” column or whose length doesn’t match len(stackKeys)+1, the printed table will be mis‑aligned (data shifted under the wrong headings).

Consider adding a sanity check such as:

+if len(customHeaders) != len(stackKeys)+1 || customHeaders[0] != "Key" {
+    return nil, errors.Errorf("customHeaders must start with \"Key\" and contain exactly %d elements", len(stackKeys)+1)
+}

so that the function fails fast instead of silently producing a garbled table.

pkg/list/list_vendor_format.go (1)

68-85: buildVendorDataMap lower‑cases all keys, not just column names

When capitalizeKeys is false, you apply strings.ToLower to every key in the row map—including custom column names that might already be lowercase, creating duplicates such as typetype (unchanged) but folderfolder (unchanged) while losing original case information.

If the intent is only to lowercase the column names (ColumnNameComponent, etc.), that’s fine, but please document it.
Otherwise, consider a more selective rule or leave the keys untouched and let downstream formatters handle casing.

pkg/list/list_vendor.go (1)

549-558: relativeManifestPath may mislead when source.File is relative

When source.File is set, you keep it as‑is:

relativeManifestPath := source.File

If the vendor manifest lives in a nested directory, the resulting path will be relative to that directory, not to atmosConfig.BasePath, causing confusing output.

Consider normalising:

if !filepath.IsAbs(relativeManifestPath) {
    relativeManifestPath = filepath.Join(filepath.Dir(path), relativeManifestPath)
}
relativeManifestPath, _ = filepath.Rel(atmosConfig.BasePath, relativeManifestPath)

This aligns the column with component manifests and prevents duplicate entries.

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 size/xl
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant