Skip to content

Conversation

@osterman
Copy link
Member

@osterman osterman commented Nov 17, 2025

what

  • Implement reusable renderer pipeline infrastructure for list commands (filter, sort, column selection, format)
  • Apply renderer pipeline to all list commands: stacks, components, instances, metadata, vendor, workflows
  • Add configurable column output via atmos.yaml and --columns CLI flag with Go template support
  • Add tree-view visualization with --format=tree and --provenance flags for import hierarchy display
  • Add comprehensive test coverage for list infrastructure packages

why

  • Enable users to customize list command output with template-based columns (e.g., --columns "Name={{ .component }}")
  • Provide consistent filtering, sorting, and formatting across all list commands
  • Support multiple output formats (JSON, YAML, CSV, TSV, table, tree) for different use cases
  • Improve developer experience with smart TTY detection and automatic color degradation
  • Achieve high test coverage (>88%) for reliability and maintainability

references

Key Features

Configurable Columns

# atmos.yaml
stacks:
  list:
    columns:
      - name: Stack
        value: "{{ .stack }}"
      - name: Component  
        value: "{{ .component }}"

CLI Flags

  • --columns - Custom column definitions with Go templates
  • --format - Output format (table, json, yaml, csv, tsv, tree)
  • --sort - Sort specification (e.g., Stack:asc,Component:desc)
  • --provenance - Show import hierarchy in tree format

Test Coverage

Package Coverage
pkg/list/column 88.5%
pkg/list/filter 96.8%
pkg/list/sort 96.2%
pkg/list/output 100%
pkg/list/renderer 91.5%
pkg/list/list_metadata.go 100% (unit functions)
pkg/list/list_instances.go 100% (unit functions)

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features

    • List commands now support customizable template-driven columns, dynamic column completion, filtering, multi-column sorting, and multiple output formats (table, JSON, YAML, CSV, TSV, tree) including provenance-aware tree views.
  • UX / Bug Fixes

    • Improved table rendering (semantic styling, multiline/inline markdown), robust TTY detection with graceful non‑TTY output, clearer UI messages, and a telemetry notice.
  • Documentation

    • New guides, PRD, examples, and command docs for configurable list output and migration.

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

…ipeline

- Implement reusable renderer pipeline (filter, sort, column, format, output)
- Create 5 pkg/list packages with >88% test coverage each
- Add extraction functions for components, stacks, vendor
- Update Priority Tier 1 commands: components (DEV-2805), stacks, vendor (DEV-2806)
- Add schema support for List config in Stacks and Components
- Create 17 standardized flag wrappers using With* naming convention
- Enable universal filtering, sorting, column selection, and format options

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

Co-Authored-By: Claude <[email protected]>
@osterman osterman requested a review from a team as a code owner November 17, 2025 06:27
@github-actions github-actions bot added the size/xl Extra large size PR label Nov 17, 2025
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Nov 17, 2025

Warning

Rate limit exceeded

@osterman has exceeded the limit for the number of commits or files that can be reviewed per hour. Please wait 25 minutes and 10 seconds before requesting another review.

⌛ How to resolve this issue?

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

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

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

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

Please see our FAQ for further information.

📥 Commits

Reviewing files that changed from the base of the PR and between 82ed911 and 658b6d9.

📒 Files selected for processing (3)
  • cmd/root.go (4 hunks)
  • cmd/root_test.go (1 hunks)
  • internal/exec/validate_stacks.go (1 hunks)
📝 Walkthrough

Walkthrough

Refactors the list subsystem into a pipeline-driven renderer: adds composable flag wrappers and NewListParser, column templates, filters, sorters, extractors, Renderer and Output manager, provenance-aware import resolution and tree renderers, schema/config additions, many CLI adapters, tests, docs, and tooling for CLAUDE/agent size checks.

Changes

Cohort / File(s) Summary
Flag wrapper infra
cmd/list/flag_wrappers.go, cmd/list/flag_wrappers_test.go, docs/list-flag-wrappers.md, docs/list-implementation-guide.md
Add With*Flag builders and NewListParser; tests and docs for composing reusable CLI flags.
Command wiring & CLI adapters
cmd/list/*.go (e.g., components.go, instances.go, metadata.go, stacks.go, vendor.go, workflows.go, values.go, settings.go, corresponding *_test.go)
Move commands to parser/options structs, register expanded flags (format/columns/sort/provenance/etc.), add dynamic --columns completion, and delegate execution to pkg/list pipeline; update/adapt many tests.
Renderer & output manager
pkg/list/renderer/renderer.go, pkg/list/renderer/*_test.go, pkg/list/output/output.go, pkg/list/output/output_test.go
New Renderer orchestrates filters→columns→sort→format→output; Output Manager routes writes; TTY-aware table/plain fallback and structured formats implemented.
Column templating
pkg/list/column/column.go, pkg/list/column/column_test.go
New column Config/Selector with pre-parsed Go templates, TemplateContext, BuildColumnFuncMap and extraction APIs.
Filtering framework
pkg/list/filter/filter.go, pkg/list/filter/filter_test.go
Add Filter interface, GlobFilter, ColumnValueFilter, BoolFilter and Chain composition with robust validation.
Sorting subsystem
pkg/list/sort/sort.go, pkg/list/sort/sort_test.go
Type-aware Sorter and MultiSorter, ParseSortSpec, numeric/boolean/string comparisons and stable multi-column sorting.
Formatting & table rendering
pkg/list/format/*.go, pkg/list/format/*_test.go
Enhanced table formatter (multi-line expansion, content-type styling, inline markdown, width logic, ErrTableTooWide) plus tree renderers for stacks/instances and styling helpers.
Extractors (domain data)
pkg/list/extract/*.go, pkg/list/extract/*_test.go
New extractors that convert domain data into []map[string]any for components, instances, metadata, stacks, vendor, workflows (with tests).
Import resolver & provenance
pkg/list/importresolver/*.go, pkg/list/importresolver/*_test.go, pkg/list/tree/types.go
Heuristic and provenance-based import-tree resolution, ImportNode type, circular detection, caching, ResolveImportTree/ResolveImportTreeFromProvenance and tests.
List command implementations (pkg/list)
pkg/list/list_*.go, pkg/list/list_*_test.go
New Execute*Cmd flows and Options structs using extractors, filters, column selector, sorters, and Renderer; vendor uses extract.VendorInfo.
Stack processing & provenance plumbing
internal/exec/*
ProcessYAMLConfigFileWithContext extended to return MergeContext, merge-context propagation, GetAllMergeContexts, and cache clearing.
Errors & schema
errors/errors.go, pkg/schema/schema.go
Add sentinels (ErrTemplateEvaluation, ErrInvalidConfig, ErrNoStacksFound) and schema additions for list config in components/stacks/workflows.
Root/terminal
cmd/root.go, cmd/root_test.go
Add termenv color-profile mapping and minor args-parser refactor; tests updated.
Docs, examples, tests, tooling
website/docs/**, website/blog/**, docs/prd/**, examples/**, tests/**, .pre-commit-config.yaml, scripts/check-claude-md-size.sh, .claude/agents/*
Extensive docs and examples for configurable list output; many tests and snapshots added/updated; add CLAUDE/agent size-check pre-commit hook and script.

Sequence Diagram(s)

%% Primary render pipeline (high-level)
sequenceDiagram
    participant CLI as CLI
    participant Parser as NewListParser
    participant Cmd as Command.RunE
    participant Extract as Extractor
    participant Filter as FilterChain
    participant Col as ColumnSelector
    participant Sort as MultiSorter
    participant Renderer as Renderer
    participant Output as OutputManager

    CLI->>Parser: parse flags (With*Flag)
    Parser-->>CLI: options struct
    CLI->>Cmd: invoke RunE with options
    Cmd->>Extract: fetch domain data
    Extract-->>Cmd: []map[string]any
    Cmd->>Filter: build filters from options
    Cmd->>Col: resolve columns (flag > config > defaults)
    Cmd->>Sort: build sorters from spec
    Cmd->>Renderer: New(filters, selector, sorters, format, delimiter)
    Cmd->>Renderer: Render(data)
    Renderer->>Filter: Apply(data)
    Filter-->>Renderer: filtered data
    Renderer->>Col: Extract(headers, rows)
    Renderer->>Sort: Sort(rows, headers)
    Renderer->>Renderer: formatTable(headers, rows)
    Renderer->>Output: Write(formatted)
Loading
%% Provenance import-resolution flow
sequenceDiagram
    participant StackProc as ProcessYAMLConfigFileWithContext
    participant Store as MergeContextStore
    participant Cache as GetAllMergeContexts
    participant Resolver as ResolveImportTreeFromProvenance
    participant TreeFmt as RenderStacksTree/RenderInstancesTree

    StackProc->>Store: create and persist MergeContext (with ImportChain)
    Store-->>Cache: available contexts
    Resolver->>Cache: GetAllMergeContexts()
    Cache-->>Resolver: contexts w/ import chains
    Resolver->>Resolver: build per-stack import trees (detect circular)
    Resolver-->>TreeFmt: trees for rendering
    TreeFmt->>TreeFmt: render styled tree (spacers, colors)
Loading

Estimated code review effort

🎯 5 (Critical) | ⏱️ ~120 minutes

  • Areas requiring extra attention:
    • pkg/list/column: template parsing, BuildColumnFuncMap correctness, and error handling paths (ErrTemplateEvaluation / ErrInvalidConfig).
    • pkg/list/renderer & pkg/list/output: end-to-end pipeline behavior, TTY detection/fallback, and structured vs plain output routing.
    • pkg/list/importresolver and provenance: path resolution heuristics, caching correctness, and circular-detection logic.
    • internal/exec: updated ProcessYAMLConfigFileWithContext signature — ensure all call-sites are updated and MergeContext propagation is correct.
    • pkg/list/format/table.go: width calculations, inline markdown rendering, and ErrTableTooWide handling.
    • CLI flag wrappers and Viper bindings across cmd/list/*: consistency of env bindings, shorthand usage, and completion hooks.
    • Deleted/removed tests (metadata, instances formatting) vs new tests: confirm coverage gaps or intentional removals.

Possibly related PRs

Suggested reviewers

  • aknysh

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 67.87% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'feat: Implement configurable output for list commands' accurately and concisely describes the main objective of the PR, which implements configurable output across all list commands.
Linked Issues check ✅ Passed The PR fully implements requirements from DEV-2805 and DEV-2806: configurable columns via atmos.yaml templates, CLI flags (--columns, --format, --sort, --type, --enabled, --locked, --provenance), multiple output formats, tree views, filtering, TTY detection, and styling.
Out of Scope Changes check ✅ Passed All changes are scoped to list command infrastructure and configuration. Minor changes to root.go and stack processor for terminal profiling and provenance tracking directly support list rendering requirements.

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

❤️ Share

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

@mergify
Copy link

mergify bot commented Nov 17, 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.

@github-actions
Copy link

github-actions bot commented Nov 17, 2025

Dependency Review

✅ No vulnerabilities or license issues found.

Scanned Files

None

Claude (via Conductor) and others added 6 commits November 17, 2025 00:38
Migrate workflows, values, and instances commands to use the new renderer
pipeline and flag wrapper pattern for consistent flag handling.

## Changes

### cmd/list/workflows.go
- Migrate to full renderer pipeline (filter → column → sort → format)
- Replace custom flag parsing with NewListParser flag wrappers
- Add buildWorkflowFilters(), getWorkflowColumns(), buildWorkflowSorters()
- Update return type from string to error
- Add support for --columns and --sort flags
- Maintain backward compatibility with --file filter
- Use static errors from errors/errors.go

### pkg/list/extract_workflows.go (NEW)
- Create ExtractWorkflows() to transform workflow manifests into []map[string]any
- Extract workflow data with file, workflow name, description, and step count
- Support file filtering via --file flag
- Handle workflow directory traversal and YAML parsing
- Use static errors (ErrParseFile, ErrWorkflowDirectoryDoesNotExist)

### pkg/list/extract_workflows_test.go (NEW)
- Add comprehensive tests for workflow extraction
- Test empty workflows, single workflow, multiple workflows
- Test nil workflows handling

### cmd/list/values.go
- Replace newCommonListParser with NewListParser using flag wrappers
- Use WithFormatFlag, WithDelimiterFlag, WithStackFlag, WithQueryFlag
- Use WithMaxColumnsFlag, WithAbstractFlag, WithProcessTemplatesFlag
- Use WithProcessFunctionsFlag
- Maintain existing FilterAndListValues logic (already using reusables)
- Update both valuesCmd and varsCmd parsers

### cmd/list/instances.go
- Replace newCommonListParser with NewListParser using flag wrappers
- Use WithFormatFlag, WithDelimiterFlag, WithMaxColumnsFlag
- Use WithStackFlag, WithQueryFlag, WithUploadFlag
- Maintain existing ExecuteListInstancesCmd logic

## Testing

All tests pass:
- go test ./cmd/list/... ./pkg/list/... ✓
- All flag wrapper tests pass ✓
- All extraction tests pass ✓

## Impact

- Workflows command now supports universal --columns and --sort flags
- Values and instances commands use consistent flag wrapper pattern
- All Tier 2 commands follow same architectural pattern as Tier 1
- Maintains backward compatibility with existing flags

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

Co-Authored-By: Claude <[email protected]>
Fix critical bug where empty format string caused "unsupported format:" error
when running list commands without explicit --format flag.

## Changes

### pkg/list/renderer/renderer.go
- Add default handling in formatTable() to use table format when empty
- Prevents "unsupported format:" error on commands like `atmos list stacks`

### pkg/list/renderer/renderer_integration_test.go (NEW)
- Add comprehensive integration tests for all format types
- Test empty format string (should default to table)
- Test invalid format string (should error)
- Test rendering with sorting
- Test rendering with empty data
- All tests initialize I/O context properly

## Testing

- All renderer tests pass (91.8% coverage)
- Fixed user-reported issue: `atmos list stacks` now works
- Test all formats: table, json, yaml, csv, tsv, empty

## Impact

- Fixes critical regression where basic list commands failed
- Empty format now correctly defaults to table format
- Maintains backward compatibility

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

Co-Authored-By: Claude <[email protected]>
- Replace thick bordered table with clean header-only underline
- Use simple local styles (bold header, plain cells) like version list
- Change border to gray (color 8) for consistency
- Remove unused theme import

This gives list commands the same polished look as atmos version list.
…support

- Add ExtractInstances() to convert schema.Instance to renderer format
- Add getInstanceColumns() to read column config from atmos.yaml
- Update ExecuteListInstancesCmd to use renderer pipeline
- Remove obsolete formatInstances() function and related tests
- Add custom column configuration to quick-start-advanced example
- Support all output formats (table, json, yaml, csv, tsv)

Custom columns configured in atmos.yaml (components.list.columns):
- Component, Stack, Tenant, Environment, Stage, Region

All existing list instances tests pass with renderer migration.
- Move Component column to the end for better readability
- Add Description column from metadata.description field
- Add description metadata to vpc and vpc-flow-logs-bucket components

Column order: Stack → Tenant → Environment → Stage → Region → Description → Component

This makes the output more readable by grouping organizational fields (tenant,
environment, stage, region) before the descriptive and component fields.
…data to renderer pipeline

This change fixes an anti-pattern where list commands were using log.Info()
for user-facing messages instead of proper UI output methods. It also migrates
the list metadata command to use the renderer pipeline for consistent table
output with customizable columns.

## Changes

### Anti-pattern fixes
- **cmd/list/settings.go**: Replace `log.Info()` with `ui.Info()` for "No settings found" messages
- **cmd/list/values.go**: Replace `log.Info()` with `ui.Info()` for "No vars/values found" messages
- **pkg/list/list_metadata.go**: Remove `log.Error()` calls; errors are now properly returned
- **cmd/list/settings_test.go**: Update tests for renamed function `displayNoSettingsFoundMessage()`
- **cmd/list/values_test.go**: Update tests for renamed function `displayNoValuesFoundMessage()`

### List metadata migration to renderer pipeline
- **cmd/list/metadata.go**: Migrate to renderer pipeline (91 lines, down from 161)
- **cmd/list/metadata_test.go**: Delete obsolete tests for old flag structure
- **pkg/list/extract_metadata.go**: Create metadata extractor for renderer
- **pkg/list/extract_metadata_test.go**: Add comprehensive tests (5 test cases)
- **pkg/list/list_metadata.go**: Implement renderer integration with default columns

### Documentation updates
- **website/docs/cli/commands/list/list-metadata.mdx**: Complete rewrite for table view with column configuration examples
- **website/docs/cli/commands/list/list-instances.mdx**: New comprehensive documentation
- **website/docs/cli/commands/list/list-vendor.mdx**: New comprehensive documentation
- **website/docs/cli/commands/list/list-components.mdx**: Enhanced with column examples
- **website/docs/cli/commands/list/list-stacks.mdx**: Add column configuration
- **website/docs/cli/commands/list/list-workflows.mdx**: Fix duplicate sections
- **website/blog/2025-11-17-customizable-list-command-output.mdx**: Feature announcement blog post

### Breaking changes for list metadata
- Removed `--query` flag (use `--filter` with YQ syntax instead)
- Removed `--max-columns` flag (use renderer table formatting)
- Removed `--delimiter` flag (renderer handles formatting)
- Removed positional component argument (use `--filter` for filtering)

## Resolution

Fixes issue where `atmos list metadata` displayed "INFO No metadata found"
instead of proper UI output. Now uses `ui.Info()` for user-facing messages
and renderer pipeline for consistent table formatting.

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

Co-Authored-By: Claude <[email protected]>
@mergify
Copy link

mergify bot commented Nov 17, 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.

Apply theme-aware color styling to table cells based on content type:
- Booleans: Green (Success) for 'true', Red (Error) for 'false'
- Numbers: Cyan (Info) for numeric values
- Placeholders: Darker gray (Muted) for {...} and [...] placeholders
- Default text: No color styling (uses base table cell style)

Implementation details:
- Add detectContentType() to identify cell content (boolean, number, placeholder)
- Add getCellStyle() to apply appropriate theme style based on content type
- Update CreateStyledTable() StyleFunc to apply semantic styling
- Use theme.GetCurrentStyles() for theme-aware color consistency
- Add regex pattern matching for placeholder detection ({...}, [...])
- Pass baseStyle by pointer to avoid copying heavy struct (552 bytes)

This enhances readability by visually distinguishing different data types
in list command table output (instances, metadata, workflows, etc.)
Claude (via Conductor) added 2 commits November 17, 2025 08:28
Tables now expand arrays of scalar values (strings, numbers, booleans)
into multi-row cells with one value per line, making array data readable
without needing to expand placeholders.

Changes:
- Add tryExpandScalarArray() to detect and expand scalar arrays
- Arrays with non-scalar elements still show placeholder format
- Add joinItems() helper to join array items with newlines
- Respect MaxColumnWidth for individual array items
- Maps continue to show {...} (N keys) placeholder format

Benefits:
- availability_zones: us-east-1a, us-east-1b, us-east-1c (multi-line)
- Complex arrays: [...] (N items) (placeholder for non-scalar)
- Improves readability for common scalar array fields

Tests:
- Add comprehensive tests for scalar array expansion
- Test mixed types, nested arrays, empty arrays
- Verify placeholder fallback for complex structures
Replace byte-based len() with lipgloss.Width() for proper handling of:
- ANSI escape codes (colors, styles)
- Multi-byte Unicode characters
- Multi-line cell content (expanded arrays)

Changes:
- Replace len() with lipgloss.Width() in width calculations
- Add getMaxLineWidth() to handle multi-line cells correctly
- Add splitLines() helper for line-by-line width calculation
- Update calculateMaxKeyWidth() to use visual width
- Update calculateStackColumnWidth() to use visual width
- Update getMaxValueWidth() to find widest line in multi-line values

Benefits:
- Tables now size columns based on actual visual width
- Colored text no longer causes incorrect column sizing
- Multi-line array expansions properly measured
- More efficient use of terminal space

Tests:
- Add tests for getMaxLineWidth with ANSI codes
- Add tests for splitLines with various inputs
- Verify ANSI-aware width calculation
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: 11

♻️ Duplicate comments (1)
cmd/list/vendor.go (1)

145-171: --columns for vendor shares the same stub implementation

getVendorColumns also calls parseColumnsFlag(columnsFlag) when --columns is set, but that helper is currently a TODO that always returns default columns. So for vendor:

  • --columns / ATMOS_LIST_COLUMNS do not actually influence the output today.

Once parseColumnsFlag is implemented for components, it would be good to hook vendor into the same real implementation so behavior is consistent.

🧹 Nitpick comments (20)
CLAUDE.md (1)

39-74: Good addition - consider fixing the markdownlint issue.

This section provides clear guidance on when to consult specialized agents. The examples and rationale are helpful.

One minor issue: The fenced code block at line 57 is missing a language identifier. Consider adding one for proper syntax highlighting:

-```
+```text
 Task(
   subagent_type: "flag-handler",
   prompt: "Help design named wrapper functions for list command flags"
 )

</blockquote></details>
<details>
<summary>website/docs/cli/commands/list/list-vendor.mdx (1)</summary><blockquote>

`24-37`: **Minor style nit in description paragraph**

The “Target destination path” / “Vendor configuration file” bullets read a bit abruptly after “information about:”. If you care about polish, consider making the last bullet a full phrase like “Vendor configuration file path.” or similar, but the content is otherwise clear.

</blockquote></details>
<details>
<summary>cmd/list/instances.go (1)</summary><blockquote>

`15-26`: **InstancesOptions is built but not used downstream**

`InstancesOptions` (including the new `Filter` and `Sort` fields) is populated in `RunE` and passed into `executeListInstancesCmd`, but `executeListInstancesCmd` ignores `opts` and just calls `list.ExecuteListInstancesCmd(&configAndStacksInfo, cmd, args)`.

If the list package is still reading values directly from Cobra/Viper, this options struct isn’t buying you anything right now and may confuse future readers. I’d either:

- Wire `opts` through into `list.ExecuteListInstancesCmd` (if you’re moving instances onto the same options-based renderer pipeline as other list commands), or
- Drop `InstancesOptions` / the `opts` parameter for now and reintroduce it when instances actually consume these fields.




Also applies to: 47-57, 85-95

</blockquote></details>
<details>
<summary>cmd/list/settings.go (1)</summary><blockquote>

`116-123`: **Consider handling ui.Info errors.**

The error returns from `ui.Info` are discarded. While this may be acceptable for informational messages, consider whether these errors should be logged or returned, especially if UI output failures could impact user experience.



```diff
 func displayNoSettingsFoundMessage(componentFilter string) {
 	if componentFilter != "" {
-		_ = ui.Info("No settings found for component: " + componentFilter)
+		if err := ui.Info("No settings found for component: " + componentFilter); err != nil {
+			log.Debug("Failed to display no settings message", "error", err)
+		}
 	} else {
-		_ = ui.Info("No settings found")
+		if err := ui.Info("No settings found"); err != nil {
+			log.Debug("Failed to display no settings message", "error", err)
+		}
 	}
 }
pkg/list/extract_metadata.go (1)

34-50: Simplify string concatenation with strings.Join.

The manual string building for inherits can be streamlined using strings.Join, making the code more concise and idiomatic.

 		if val, ok := instance.Metadata["inherits"].([]interface{}); ok {
-			// Convert []interface{} to comma-separated string.
 			inheritsSlice := make([]string, 0, len(val))
 			for _, v := range val {
 				if str, ok := v.(string); ok {
 					inheritsSlice = append(inheritsSlice, str)
 				}
 			}
-			if len(inheritsSlice) > 0 {
-				for i, s := range inheritsSlice {
-					if i > 0 {
-						inherits += ", "
-					}
-					inherits += s
-				}
-			}
+			inherits = strings.Join(inheritsSlice, ", ")
 		}

Don't forget to import strings if not already imported.

pkg/list/list_metadata.go (1)

48-85: Consider adding filter and sort support.

The renderer is created with nil filters and sorters (line 77), but other list commands support filtering and sorting via CLI flags. Consider whether metadata listing should also support these features for consistency.

If filtering and sorting are needed, you could add flags and build filters/sorters similar to other list commands:

 func ExecuteListMetadataCmd(info *schema.ConfigAndStacksInfo, cmd *cobra.Command, args []string) error {
 	// Initialize CLI config.
 	atmosConfig, err := cfg.InitCliConfig(*info, true)
 	if err != nil {
 		return errors.Join(errUtils.ErrFailedToInitConfig, err)
 	}
 
-	// Get flags.
+	// Get flags
 	formatFlag, _ := cmd.Flags().GetString("format")
+	filterFlag, _ := cmd.Flags().GetString("filter")
+	sortFlag, _ := cmd.Flags().GetString("sort")
 
 	// Process instances (same as list instances, but we'll extract metadata).
 	instances, err := processInstances(&atmosConfig)
 	if err != nil {
 		return errors.Join(errUtils.ErrProcessInstances, err)
 	}
 
 	// Extract metadata into renderer-compatible format.
 	data := ExtractMetadata(instances)
 
 	// Get column configuration.
 	columns := getMetadataColumns(&atmosConfig)
+
+	// Build filters and sorters
+	filters := buildMetadataFilters(filterFlag)
+	sorters := buildMetadataSorters(sortFlag)
 
 	// Create column selector.
 	selector, err := column.NewSelector(columns, column.BuildColumnFuncMap())
 	if err != nil {
 		return fmt.Errorf("failed to create column selector: %w", err)
 	}
 
 	// Create renderer.
-	r := renderer.New(nil, selector, nil, format.Format(formatFlag))
+	r := renderer.New(filters, selector, sorters, format.Format(formatFlag))
 
 	// Render output.
 	if err := r.Render(data); err != nil {
 		return fmt.Errorf("failed to render metadata: %w", err)
 	}
 
 	return nil
 }
cmd/list/flag_wrappers_test.go (1)

377-414: Tighten env var binding test or drop unused envVarName

TestFlagEnvironmentVariableBinding currently only asserts that BindToViper succeeds; the envVarName field is never used, so the test doesn’t actually confirm the binding name.

Either:

  • Use envVarName (e.g., t.Setenv(tt.envVarName, "x"), call BindToViper, then assert v.GetString(tt.flagName) == "x"), or
  • Remove envVarName from the table to avoid implying stronger coverage than is present.
pkg/list/extract_stacks.go (1)

9-73: Consider whether deterministic stack ordering is needed

Both extractors iterate over stacksMap directly, so the output order is whatever Go’s map iteration yields. If the downstream renderer doesn’t always apply an explicit sort (e.g., default sort by stack), CLI output may appear in a non‑deterministic order between runs.

If you want stable default ordering, consider sorting the stack names (or ensure callers always run the sort pipeline on these results). Otherwise, the current implementation is straightforward and matches the tests.

pkg/list/renderer/renderer_test.go (1)

38-237: Consider factoring I/O initialization into a helper

Most tests duplicate the NewContext/InitWriter/InitFormatter setup. Extracting a small helper like initTestRendererIO(t) would cut repetition and make future tweaks to the IO/UI wiring cheaper.

pkg/list/extract_components.go (1)

9-17: Unused exported ComponentData struct

ComponentData isn’t used in this file. If there’s no external consumer yet, consider either wiring it into the API (e.g., returning strongly‑typed slices instead of []map[string]any) or dropping it for now to avoid a “blessed but unused” public type.

pkg/list/extract_components_test.go (1)

11-245: Nice coverage; consider asserting component_type semantics explicitly

The tests do a good job exercising success and failure paths. To lock in the intended meaning of metadata fields, you might add a couple of assertions that:

  • For an abstract component (like ingress in TestExtractComponents), comp["component_type"] == "abstract".
  • For a normal TF component, comp["type"] == "terraform" and comp["component_type"] == "real".

That would make future refactors around .type vs .component_type safer.

cmd/list/stacks.go (1)

29-31: Columns flag type vs parsing helper may not line up

StacksOptions.Columns is a string populated via v.GetString("columns"), but WithColumnsFlag registers columns as a StringSlice flag. Depending on how StandardParser binds to Viper, GetString("columns") may see something like "[stack,component]" rather than the raw stack,component string that parseColumnsFlag expects.

If the intent is “comma‑separated single value”, you might either:

  • Change the flag to a simple string flag; or
  • Keep it as a slice and update StacksOptions + parseColumnsFlag to work with []string.

Worth a quick manual check of --columns stack,component and the env var form to confirm the value that reaches parseColumnsFlag.

Also applies to: 150-154

website/docs/cli/commands/list/list-stacks.mdx (1)

119-142: Clarify that the listed template functions are a subset of what’s available

The “Available functions” list here is a subset of what BuildColumnFuncMap exposes (pad, get, getOr, has, split, toInt, toBool, etc. are also supported). To avoid confusing folks who read the code, consider either:

  • Renaming this to “Common functions” and noting it’s not exhaustive, or
  • Expanding the list to match the actual func map.
pkg/list/renderer/renderer.go (1)

151-159: Use a CSV/TSV writer to handle escaping correctly

formatDelimited currently does a raw strings.Join for CSV/TSV. That means fields containing the delimiter, quotes, or newlines won’t be escaped and can break consumers.

Consider switching to Go’s encoding/csv (with the delimiter configurable for TSV) so quoting and escaping are handled correctly, e.g., by writing into a bytes.Buffer and returning the buffer string.

cmd/list/components.go (1)

142-177: Revisit interaction between type and abstract filters

buildComponentFilters currently combines:

  • Type flag → filter.NewColumnFilter("type", opts.Type) (default "real" from WithTypeFlag), and
  • Abstract flag → when !opts.Abstract, always adds filter.NewColumnFilter("component_type", "real").

This can make it hard to express some combinations:

  • With no flags you filter on both type=real and component_type=real.
  • With --abstract but no explicit --type, you still filter type=real, so abstract-only components may never show.
  • With --type=all but --abstract omitted, you still filter component_type to real, so “all” doesn’t actually include abstract.

Might be worth clarifying which field (type vs component_type) is the canonical “real/abstract/all” dimension and simplifying defaults around that (e.g., let Type default to "" and derive the “real-only by default” behavior solely from Abstract).

cmd/list/vendor.go (2)

130-143: Confirm intent of using --stack to glob on the component field

buildVendorFilters treats the --stack flag as a glob on the "component" field:

globFilter, err := filter.NewGlobFilter("component", opts.Stack)

Given WithStackFlag’s help text (“Filter by stack pattern”) this is a bit surprising. If vendor rows don’t have a stack field and the goal is to filter by component name, it might be clearer to either:

  • Introduce a dedicated --component filter for vendor, or
  • Rename/update the --stack help text for this command.

At minimum, worth double-checking that this aligns with how users expect to filter vendor entries.


185-256: Unused home-dir obfuscation helpers after renderer refactor

After switching vendor listing to the renderer pipeline, obfuscateHomeDirInOutput, shouldReplaceHomeDir, and isPathChar are no longer used in this file.

If the renderer-based output is intentionally allowed to show absolute paths now, these helpers can probably be removed. If you still want to avoid leaking $HOME in vendor paths, you may want to integrate this behavior into the data extraction step or the renderer instead.

pkg/list/sort/sort.go (1)

110-133: Numeric and multi-column sort behavior is good; tighten comments around edge cases

The type-aware sorting and stable multi-column precedence look solid. Two small nits:

  • compareNumeric’s comment says “Non-numeric values sort last”, but when both values are non-numeric you fall back to strings.Compare(a, b). That’s fine behavior, just worth reflecting in the comment so future readers don’t assume “always last”.
  • In Sorter.Sort, rows where colIdx >= len(row) are effectively treated as “equal” to everything else (you always return false from the comparator). That’s a reasonable choice; consider documenting that missing-column rows preserve original order and don’t participate in the sort.

No functional changes required; this is just about making the behavior explicit.

Also applies to: 161-185

pkg/list/filter/filter.go (1)

39-86: Filter primitives and chaining look solid

The glob/column/boolean filters and the Chain combinator are straightforward and type-safe, with good validation and error messages. The permissive string handling in BoolFilter (treating non-true strings as false) is fine for the intended enabled/locked use cases; if you later apply it to arbitrary fields you might want stricter validation, but nothing blocking here.

Nice foundation for composing filters into the renderer pipeline.

Also applies to: 119-160, 167-178

pkg/list/column/column.go (1)

27-47: TemplateContext struct is unused; current implementation relies on a generic map-based context

Right now, templates are evaluated against the map[string]any produced by buildTemplateContext, and the TemplateContext struct isn’t used anywhere. That’s not wrong, but it’s a bit misleading for readers who might assume templates see a strongly-typed context with the JSON-tagged field names.

You can either:

  • Remove TemplateContext until you actually switch to using it, or
  • Update buildTemplateContext to construct and return a TemplateContext (plus maybe embed Raw separately) so the declared API matches the real context shape.

Low priority, but it’ll reduce cognitive overhead for anyone extending the column templating later.

Also applies to: 190-272

Claude (via Conductor) added 2 commits November 17, 2025 08:35
Tables now expand maps with scalar values (like tags) into readable
multi-line format with one key-value pair per line.

Before:
  tags    {...} (7 keys)

After:
  tags    Environment: production
          Name: vpc
          Team: platform
          ...

Implementation:
- Add tryExpandScalarMap() to detect and expand scalar maps
- Sort keys alphabetically for consistent ordering
- Format as 'key: value' pairs, one per line
- Maps with non-scalar values still show {...} (N keys) placeholder
- Shares joinItems() helper with array expansion

Behavior:
- Scalar maps (string, number, bool values) → Expanded multi-line
- Complex maps (nested objects, arrays) → Placeholder {...} (N keys)
- Empty maps → Empty string
- Keys sorted alphabetically for consistency

Benefits:
- Tags and metadata now readable without expanding
- Consistent with array expansion behavior
- Maintains compact placeholder for complex structures

Tests:
- Add comprehensive tests for scalar map expansion
- Test mixed scalar types, empty maps
- Verify placeholder fallback for nested structures
- Update existing tests to match new behavior
Prevent scalar arrays and maps from being expanded if their items
exceed a reasonable width threshold. This avoids creating impossibly
wide tables that trigger "table too wide" errors.

Problem:
- Expanding arrays/maps with long values caused tables to exceed terminal width
- Users saw: "Error: the table is too wide to display properly (width: 418 > 185)"
- No fallback to compact placeholder format for wide values

Solution:
- Track maximum item width during expansion
- Reject expansion if any item exceeds maxReasonableItemWidth (20 chars)
- Fall back to compact placeholder format: [...] (N items) or {...} (N keys)
- Threshold set to ~1/3 of MaxColumnWidth for reasonable table display

Changes:
- Add width tracking to tryExpandScalarArray()
- Add width tracking to tryExpandScalarMap()
- Use lipgloss.Width() for ANSI-aware measurement
- Set maxReasonableItemWidth constant to 20 characters

Benefits:
- Tables stay within terminal width limits
- Short values still expand (availability_zones, tags with short values)
- Long values gracefully degrade to placeholders
- No more "table too wide" errors from expansion

Tests:
- Add test for arrays with very long strings
- Add test for maps with very long values
- Verify both fall back to placeholder format
- Add renderInlineMarkdown() function to render markdown in table cells
- Uses glamour library with theme-aware styling for terminals
- Automatically detects color support and degrades gracefully
- Collapses multi-line markdown into single line for table cells
- Applies to Description column specifically when present in headers
- Preserves inline markdown (bold, italic, code) while removing blocks
- Includes comprehensive tests for markdown rendering edge cases

Resolves markdown rendering for description fields in metadata tables.
…data

**Enhancement 1: Style <no value> in Dark Gray**
- Add contentTypeNoValue enum to cell content type detection
- Update detectContentType() to identify <no value> from Go templates
- Apply styles.Muted (dark gray) styling to <no value> cells
- Consistent with placeholder styling ({...}, [...])
- Theme-aware and zero-config

**Enhancement 2: Support Vars in List Metadata**
- Expose vars, settings, and env in ExtractMetadata()
- Enables column templates to access component variables
- Users can now use {{ .vars.region }}, {{ .vars.environment }}, etc.
- Follows same pattern as ExtractInstances()

**Testing:**
- Add TestDetectContentType_NoValue with comprehensive test cases
- Add TestExtractMetadata_IncludesVarsSettingsEnv to verify exposure
- Update existing metadata tests to include new fields
- All tests passing

**Impact:**
- list metadata now displays actual var values instead of <no value>
- Improves readability with dark gray styling for missing values
- Enables custom column configuration using vars/settings/env

Closes user request for dark gray <no value> styling and vars support.
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 (2)
pkg/list/list_metadata_test.go (1)

285-309: Placeholder test for future filter implementation.

This tests a stub function that currently returns nil. When filter functionality is implemented, these test cases should be expanded to validate actual filtering behavior.

pkg/list/list_instances_coverage_test.go (1)

61-67: Consider I/O initialization consistency across test variants.

This test properly initializes I/O and UI contexts, but the error-path tests (TestExecuteListInstancesCmd_InvalidConfig and TestExecuteListInstancesCmd_UploadPath) don't. If those tests fail early before reaching code that needs the I/O context, this is fine. However, this pattern is fragile—if error handling changes, tests could fail unexpectedly.

Consider either:

  1. Adding a comment explaining why error-path tests don't need I/O initialization
  2. Extracting I/O setup to a test helper and using it consistently
  3. Initializing I/O in all ExecuteListInstancesCmd tests for consistency
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 5091be1 and 551d868.

📒 Files selected for processing (3)
  • cmd/list/stacks_test.go (2 hunks)
  • pkg/list/list_instances_coverage_test.go (4 hunks)
  • pkg/list/list_metadata_test.go (1 hunks)
🧰 Additional context used
🧠 Learnings (13)
📓 Common learnings
Learnt from: osterman
Repo: cloudposse/atmos PR: 1533
File: pkg/config/load.go:585-637
Timestamp: 2025-09-27T20:50:20.564Z
Learning: In the cloudposse/atmos repository, command merging prioritizes precedence over display ordering. Help commands are displayed lexicographically regardless of internal array order, so the mergeCommandArrays function focuses on ensuring the correct precedence chain (top-level file wins) rather than maintaining specific display order.
Learnt from: Listener430
Repo: cloudposse/atmos PR: 934
File: tests/fixtures/scenarios/docs-generate/README.md.gotmpl:99-118
Timestamp: 2025-01-25T03:51:57.689Z
Learning: For the cloudposse/atmos repository, changes to template contents should be handled in dedicated PRs and are typically considered out of scope for PRs focused on other objectives.
Learnt from: samtholiya
Repo: cloudposse/atmos PR: 1466
File: cmd/markdown/atmos_toolchain_aliases.md:2-4
Timestamp: 2025-09-13T16:39:20.007Z
Learning: In the cloudposse/atmos repository, CLI documentation files in cmd/markdown/ follow a specific format that uses " $ atmos command" (with leading space and dollar sign prompt) in code blocks. This is the established project convention and should not be changed to comply with standard markdownlint rules MD040 and MD014.
Learnt from: RoseSecurity
Repo: cloudposse/atmos PR: 797
File: pkg/list/atmos.yaml:213-214
Timestamp: 2024-11-25T17:17:15.703Z
Learning: The file `pkg/list/atmos.yaml` is primarily intended for testing purposes.
📚 Learning: 2024-12-08T14:26:16.972Z
Learnt from: pkbhowmick
Repo: cloudposse/atmos PR: 828
File: pkg/schema/schema.go:98-100
Timestamp: 2024-12-08T14:26:16.972Z
Learning: The `ListConfig` columns array in the `Components` struct can be empty.

Applied to files:

  • pkg/list/list_metadata_test.go
  • pkg/list/list_instances_coverage_test.go
📚 Learning: 2025-11-11T03:47:45.878Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 1686
File: toolchain/add_test.go:67-77
Timestamp: 2025-11-11T03:47:45.878Z
Learning: In the cloudposse/atmos codebase, tests should prefer t.Setenv for environment variable setup/teardown instead of os.Setenv/Unsetenv to ensure test-scoped isolation.

Applied to files:

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

Applied to files:

  • pkg/list/list_metadata_test.go
  • cmd/list/stacks_test.go
📚 Learning: 2025-01-30T19:30:59.120Z
Learnt from: samtholiya
Repo: cloudposse/atmos PR: 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/list/list_instances_coverage_test.go
📚 Learning: 2024-12-07T16:16:13.038Z
Learnt from: Listener430
Repo: cloudposse/atmos PR: 825
File: internal/exec/helmfile_generate_varfile.go:28-31
Timestamp: 2024-12-07T16:16:13.038Z
Learning: In `internal/exec/helmfile_generate_varfile.go`, the `--help` command (`./atmos helmfile generate varfile --help`) works correctly without requiring stack configurations, and the only change needed was to make `ProcessCommandLineArgs` exportable by capitalizing its name.

Applied to files:

  • pkg/list/list_instances_coverage_test.go
  • cmd/list/stacks_test.go
📚 Learning: 2025-02-19T05:50:35.853Z
Learnt from: samtholiya
Repo: cloudposse/atmos PR: 1068
File: tests/snapshots/TestCLICommands_atmos_terraform_apply_--help.stdout.golden:0-0
Timestamp: 2025-02-19T05:50:35.853Z
Learning: Backtick formatting should only be applied to flag descriptions in Go source files, not in golden test files (test snapshots) as they are meant to capture the raw command output.

Applied to files:

  • pkg/list/list_instances_coverage_test.go
📚 Learning: 2024-10-20T00:41:57.135Z
Learnt from: haitham911
Repo: cloudposse/atmos PR: 731
File: internal/exec/validate_stacks.go:93-98
Timestamp: 2024-10-20T00:41:57.135Z
Learning: When downloading schema files in `internal/exec/validate_stacks.go`, use a consistent temporary file name to overwrite the file each time and avoid creating multiple temporary files.

Applied to files:

  • cmd/list/stacks_test.go
📚 Learning: 2025-04-11T22:06:46.999Z
Learnt from: samtholiya
Repo: cloudposse/atmos PR: 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:

  • cmd/list/stacks_test.go
📚 Learning: 2024-10-20T00:57:53.500Z
Learnt from: haitham911
Repo: cloudposse/atmos PR: 731
File: internal/exec/validate_stacks.go:0-0
Timestamp: 2024-10-20T00:57:53.500Z
Learning: In `internal/exec/validate_stacks.go`, when downloading the Atmos JSON Schema file to the temp directory, the temporary file is overwritten each time, so explicit removal is not necessary.

Applied to files:

  • cmd/list/stacks_test.go
📚 Learning: 2024-11-13T21:37:07.852Z
Learnt from: Cerebrovinny
Repo: cloudposse/atmos PR: 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:

  • cmd/list/stacks_test.go
📚 Learning: 2025-01-09T22:27:25.538Z
Learnt from: samtholiya
Repo: cloudposse/atmos PR: 914
File: cmd/validate_stacks.go:20-23
Timestamp: 2025-01-09T22:27:25.538Z
Learning: The validate commands in Atmos can have different help handling implementations. Specifically, validate_component.go and validate_stacks.go are designed to handle help requests differently, with validate_stacks.go including positional argument checks while validate_component.go does not.

Applied to files:

  • cmd/list/stacks_test.go
📚 Learning: 2025-08-15T14:43:41.030Z
Learnt from: aknysh
Repo: cloudposse/atmos PR: 1352
File: pkg/store/artifactory_store_test.go:108-113
Timestamp: 2025-08-15T14:43:41.030Z
Learning: In test files for the atmos project, it's acceptable to ignore errors from os.Setenv/Unsetenv operations during test environment setup and teardown, as these are controlled test scenarios.

Applied to files:

  • cmd/list/stacks_test.go
🧬 Code graph analysis (3)
pkg/list/list_metadata_test.go (4)
errors/errors.go (1)
  • ErrInvalidConfig (43-43)
pkg/schema/schema.go (3)
  • AtmosConfiguration (53-94)
  • ListConfig (947-952)
  • ListColumnConfig (954-957)
pkg/list/sort/sort.go (5)
  • Sorter (35-39)
  • NewSorter (48-54)
  • Ascending (17-17)
  • Descending (19-19)
  • Order (13-13)
pkg/list/filter/filter.go (1)
  • Filter (12-14)
pkg/list/list_instances_coverage_test.go (6)
pkg/io/context.go (1)
  • NewContext (22-46)
pkg/ui/formatter.go (1)
  • InitFormatter (36-54)
pkg/data/data.go (1)
  • InitWriter (29-35)
pkg/list/sort/sort.go (6)
  • String (27-27)
  • Sorter (35-39)
  • NewSorter (48-54)
  • Ascending (17-17)
  • Descending (19-19)
  • Order (13-13)
pkg/list/list_instances.go (2)
  • ExecuteListInstancesCmd (349-456)
  • InstancesCommandOptions (37-47)
errors/errors.go (1)
  • ErrInvalidConfig (43-43)
cmd/list/stacks_test.go (2)
cmd/list/stacks.go (1)
  • StacksOptions (30-37)
pkg/schema/schema.go (3)
  • AtmosConfiguration (53-94)
  • ListConfig (947-952)
  • ListColumnConfig (954-957)
⏰ Context from checks skipped due to timeout of 900000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
  • GitHub Check: Acceptance Tests (linux)
  • GitHub Check: Acceptance Tests (windows)
  • GitHub Check: Summary
🔇 Additional comments (20)
pkg/list/list_metadata_test.go (6)

1-14: LGTM!

Clean test setup with appropriate imports and justified nolint directive.


16-124: Excellent test coverage for column flag parsing.

Comprehensive test cases covering happy paths, edge cases (multiple equals signs, whitespace), and error conditions with proper error type checking.


126-211: Solid test coverage for column resolution precedence.

Tests correctly validate the CLI flag → config → defaults hierarchy and handle edge cases like empty config columns.


213-283: Thorough testing of sorter construction.

Covers default behavior, single/multiple columns, ordering directions, and error cases.


311-331: Good validation of default metadata columns.

The hardcoded count and name list act as a safeguard against unintentional changes to the default columns configuration.


333-350: Basic struct validation test.

While this only tests simple field assignment (which Go guarantees), it serves to document the MetadataOptions interface.

pkg/list/list_instances_coverage_test.go (7)

1-19: LGTM!

The nolint directive is well-justified, and the new imports properly support the expanded test coverage for the rendering pipeline.


21-57: LGTM!

These wrapper coverage tests are well-documented and appropriately scoped to verify execution without panics.


97-148: LGTM!

Error path tests are appropriately structured and verify graceful failure handling for invalid configurations.


150-233: Excellent test coverage!

This table-driven test thoroughly covers parsing edge cases including multiple equals signs in templates, empty values, and proper error wrapping. The use of ErrorIs for error type checking is spot-on.


235-321: LGTM!

This test thoroughly validates the configuration precedence hierarchy and properly handles the empty-columns edge case. The fallback logic to defaults is well-tested.


323-408: LGTM!

Comprehensive sorter test with good coverage of default behavior, explicit specifications, and error cases. The logic for returning nil when columns don't match the default Component/Stack convention is correctly tested.


410-416: Placeholder test acknowledged.

This test correctly validates the current placeholder behavior of buildInstanceFilters. Remember to expand this test when the real filter implementation is added.

cmd/list/stacks_test.go (7)

5-12: Clean imports for the new test coverage.

The strings and schema packages support the new test functions appropriately.


110-176: Solid coverage of all StacksOptions fields.

The test cases cover meaningful combinations—fully populated, empty, and partial configurations. Structure is clear and aligns with the StacksOptions definition.


178-205: Test correctly validates filter construction.

The expectation of 0 filters for the component case is well-documented—component filtering happens during extraction, not in the filter pipeline. This is clear from the comment.


207-281: Thorough testing of column resolution logic.

Cases cover defaults (with/without component), CLI flags, and config-driven columns. The schema types align correctly with the codebase, and assertions validate both count and content.


283-330: Well-structured sorter tests.

Covers empty (default), single field (both directions), multiple fields, and invalid specs. Error handling is verified alongside success cases.


332-347: Pragmatic approach to completion testing.

The test acknowledges that full integration needs valid config, so it validates signature and directive behavior. The unused suggestions assignment is appropriately documented.


349-427: Thoughtful provenance validation testing.

The test correctly differentiates between config loading errors and provenance validation failures. Smart use of t.Skipf prevents false negatives when config issues occur before validation. The logic validates that provenance requires tree format while other formats should reject it.

- Fix doc comments in extract/components.go to start with symbol names
- Remove unused ComponentData struct from extract/components.go
- Fix stripBasePath to return relative, extensionless, forward-slash paths
- Update provenance and resolver tests to use t.TempDir() and filepath.Join
- Use strconv.Itoa for proper number formatting in long chain tests
- Refactor list_instances.go tree format to avoid double stack processing
- Add error for --upload with --format=tree combination
- Fix stacks.go to call ProcessCommandLineArgs like other list subcommands
- Add Width field to ListColumnConfig schema
- Include Width in column config mapping across all list commands
- Replace undefined contains() with u.SliceContainsString
- Use canonical gopkg.in/yaml.v3 import instead of deprecated go.yaml.in

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

Co-Authored-By: Claude <[email protected]>
Add early validation for --provenance flag before config loading to
prevent nil pointer dereference when cmd is nil. Skip test cases that
require config loading since they cannot be tested without a real cmd.

Add nolint directives to suppress complexity warnings in pkg/list/
and internal/exec/ files where functions have unavoidable complexity
from nested logic patterns.

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

Co-Authored-By: Claude <[email protected]>
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: 5

♻️ Duplicate comments (2)
pkg/list/importresolver/provenance.go (1)

404-415: Fix relative import resolution to honor the importing file path

resolveImportPath currently ignores parentFilePath and always resolves imports relative to StacksBaseAbsolutePath. For relative imports like ./foo or ../common/vars, this produces incorrect absolute paths (e.g., escaping the stacks directory) and diverges from the stack processor’s behavior.

Use parentFilePath for ./.. imports and keep base-path resolution for “rooted” stack imports; also handle absolute import paths explicitly.

-// resolveImportPath converts a relative import path to an absolute file path.
-func resolveImportPath(importPath, _ string, atmosConfig *schema.AtmosConfiguration) string {
-	// Import paths are relative to the stacks base path.
-	basePath := atmosConfig.StacksBaseAbsolutePath
-
-	// Add .yaml extension if not present.
-	if !strings.HasSuffix(importPath, yamlExt) && !strings.HasSuffix(importPath, ymlExt) {
-		importPath += yamlExt
-	}
-
-	return filepath.Join(basePath, importPath)
-}
+// resolveImportPath converts an import path to an absolute file path.
+// - Absolute paths are returned as-is (cleaned).
+// - Relative paths starting with "." or ".." are resolved relative to the parent file directory.
+// - All other paths are resolved relative to the stacks base path.
+func resolveImportPath(importPath, parentFilePath string, atmosConfig *schema.AtmosConfiguration) string {
+	// Add .yaml extension if not present.
+	if !strings.HasSuffix(importPath, yamlExt) && !strings.HasSuffix(importPath, ymlExt) {
+		importPath += yamlExt
+	}
+
+	// Absolute import: return cleaned path directly.
+	if filepath.IsAbs(importPath) {
+		return filepath.Clean(importPath)
+	}
+
+	// Relative import (./ or ../): resolve from parent file directory when available.
+	if strings.HasPrefix(importPath, ".") && parentFilePath != "" {
+		parentDir := filepath.Dir(parentFilePath)
+		return filepath.Join(parentDir, importPath)
+	}
+
+	// Fallback: resolve from stacks base path.
+	basePath := atmosConfig.StacksBaseAbsolutePath
+	return filepath.Join(basePath, importPath)
+}
cmd/list/components.go (1)

224-276: --columns flag is effectively ignored (parseColumnsFlag is still a stub)

getComponentColumns treats any non-empty columnsFlag as “use CLI columns”, but parseColumnsFlag ignores the flag value and always returns the same default Component/Stack/Type set. That means:

  • --columns and ATMOS_LIST_COLUMNS do not affect the output at all.
  • This contradicts the PR goal of configurable columns via CLI and atmos.yaml.

You should either make --columns functional now or fail fast when it’s used:

  • Preferred: Implement real parsing that maps the requested column names to column.Config entries (likely starting from atmosConfig.Components.List.Columns or a known default set), or
  • Interim: Detect non-empty columnsFlag and return an error explaining that CLI column selection is not yet supported, rather than silently ignoring user input.

For example, a conservative interim behavior:

func getComponentColumns(atmosConfig *schema.AtmosConfiguration, columnsFlag []string) []column.Config {
	// If --columns flag is provided, parse it and return.
	if len(columnsFlag) > 0 {
-		return parseColumnsFlag(columnsFlag)
+		// TODO: Implement full parsing of column specs.
+		// For now, fail fast instead of silently ignoring the flag.
+		panic("list components: --columns is wired but parsing is not yet implemented")
	}

and then follow up with a real implementation that interprets columnsFlag into a filtered or reordered slice of column.Config.

🧹 Nitpick comments (1)
internal/exec/stack_processor_utils.go (1)

1056-1087: Provenance tracking logic works correctly.

The import chain building logic is functional and the use of u.SliceContainsString is correct. The nested structure is acknowledged with the nolint directive.

If you want to reduce duplication, the two branches (lines 1072-1077 and 1078-1084) could be consolidated since they perform identical operations:

-					if len(result.mergeContext.ImportChain) > 0 && importedFile == result.mergeContext.ImportChain[0] {
-						// This is the imported file itself, add it only once.
-						if !u.SliceContainsString(mergeContext.ImportChain, importedFile) {
-							mergeContext.ImportChain = append(mergeContext.ImportChain, importedFile)
-							log.Trace("Added import to parent import chain", "file", importedFile)
-						}
-					} else {
-						// This is a nested import from the imported file.
-						if !u.SliceContainsString(mergeContext.ImportChain, importedFile) {
-							mergeContext.ImportChain = append(mergeContext.ImportChain, importedFile)
-							log.Trace("Added nested import to parent import chain", "file", importedFile)
-						}
-					}
+					if !u.SliceContainsString(mergeContext.ImportChain, importedFile) {
+						mergeContext.ImportChain = append(mergeContext.ImportChain, importedFile)
+						if len(result.mergeContext.ImportChain) > 0 && importedFile == result.mergeContext.ImportChain[0] {
+							log.Trace("Added import to parent import chain", "file", importedFile)
+						} else {
+							log.Trace("Added nested import to parent import chain", "file", importedFile)
+						}
+					}

That said, the current structure makes the distinction between direct and nested imports clear, so this is purely a style preference.

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 551d868 and 74f6a77.

📒 Files selected for processing (13)
  • cmd/list/components.go (1 hunks)
  • cmd/list/stacks.go (1 hunks)
  • cmd/list/stacks_test.go (2 hunks)
  • cmd/list/vendor.go (1 hunks)
  • cmd/list/workflows.go (1 hunks)
  • internal/exec/stack_processor_utils.go (31 hunks)
  • pkg/list/column/column.go (1 hunks)
  • pkg/list/extract/components.go (1 hunks)
  • pkg/list/extract/workflows.go (1 hunks)
  • pkg/list/importresolver/provenance.go (1 hunks)
  • pkg/list/importresolver/provenance_test.go (1 hunks)
  • pkg/list/importresolver/resolver_test.go (1 hunks)
  • pkg/list/list_instances.go (3 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • pkg/list/importresolver/provenance_test.go
  • cmd/list/stacks_test.go
🧰 Additional context used
🧠 Learnings (60)
📓 Common learnings
Learnt from: Listener430
Repo: cloudposse/atmos PR: 934
File: tests/fixtures/scenarios/docs-generate/README.md.gotmpl:99-118
Timestamp: 2025-01-25T03:51:57.689Z
Learning: For the cloudposse/atmos repository, changes to template contents should be handled in dedicated PRs and are typically considered out of scope for PRs focused on other objectives.
Learnt from: osterman
Repo: cloudposse/atmos PR: 1036
File: cmd/list_settings.go:46-50
Timestamp: 2025-02-20T13:57:36.326Z
Learning: The max-columns flag in Atmos list commands supports -1 for unlimited width, which bypasses terminal width restrictions and may require horizontal scrolling. The default is 10 columns if not specified.
Learnt from: samtholiya
Repo: cloudposse/atmos PR: 1466
File: cmd/markdown/atmos_toolchain_aliases.md:2-4
Timestamp: 2025-09-13T16:39:20.007Z
Learning: In the cloudposse/atmos repository, CLI documentation files in cmd/markdown/ follow a specific format that uses " $ atmos command" (with leading space and dollar sign prompt) in code blocks. This is the established project convention and should not be changed to comply with standard markdownlint rules MD040 and MD014.
Learnt from: osterman
Repo: cloudposse/atmos PR: 1533
File: pkg/config/load.go:585-637
Timestamp: 2025-09-27T20:50:20.564Z
Learning: In the cloudposse/atmos repository, command merging prioritizes precedence over display ordering. Help commands are displayed lexicographically regardless of internal array order, so the mergeCommandArrays function focuses on ensuring the correct precedence chain (top-level file wins) rather than maintaining specific display order.
Learnt from: RoseSecurity
Repo: cloudposse/atmos PR: 797
File: pkg/list/atmos.yaml:213-214
Timestamp: 2024-11-25T17:17:15.703Z
Learning: The file `pkg/list/atmos.yaml` is primarily intended for testing purposes.
📚 Learning: 2024-12-25T20:28:47.526Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 887
File: internal/exec/stack_processor_utils.go:380-380
Timestamp: 2024-12-25T20:28:47.526Z
Learning: Windows path handling often requires `filepath.Join` to ensure correct separators and comparisons. Insufficient tests can break cross-platform compatibility, so migrating from `path.Join` to `filepath.Join` needs thorough testing on Windows before merging.

Applied to files:

  • pkg/list/importresolver/resolver_test.go
📚 Learning: 2024-12-25T20:28:19.618Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 887
File: internal/exec/workflow_utils.go:167-169
Timestamp: 2024-12-25T20:28:19.618Z
Learning: The user plans to revert the change from `path.Join` to `filepath.Join` in this PR due to testing gaps and will open a new PR to safely handle the migration without breaking `main`.

Applied to files:

  • pkg/list/importresolver/resolver_test.go
📚 Learning: 2024-11-19T23:00:45.899Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 795
File: internal/exec/stack_processor_utils.go:378-386
Timestamp: 2024-11-19T23:00:45.899Z
Learning: In the `ProcessYAMLConfigFile` function within `internal/exec/stack_processor_utils.go`, directory traversal in stack imports is acceptable and should not be restricted.

Applied to files:

  • pkg/list/importresolver/resolver_test.go
  • pkg/list/extract/workflows.go
  • internal/exec/stack_processor_utils.go
  • pkg/list/importresolver/provenance.go
📚 Learning: 2024-10-28T01:51:30.811Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 727
File: internal/exec/terraform_clean.go:329-332
Timestamp: 2024-10-28T01:51:30.811Z
Learning: In the Atmos Go code, when deleting directories or handling file paths (e.g., in `terraform_clean.go`), always resolve the absolute path using `filepath.Abs` and use the logger `u.LogWarning` for logging messages instead of using `fmt.Printf`.

Applied to files:

  • pkg/list/importresolver/resolver_test.go
  • internal/exec/stack_processor_utils.go
  • pkg/list/importresolver/provenance.go
📚 Learning: 2024-12-02T21:26:32.337Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 808
File: pkg/config/config.go:478-483
Timestamp: 2024-12-02T21:26:32.337Z
Learning: In the 'atmos' project, when reviewing Go code like `pkg/config/config.go`, avoid suggesting file size checks after downloading remote configs if such checks aren't implemented elsewhere in the codebase.

Applied to files:

  • pkg/list/importresolver/resolver_test.go
  • cmd/list/workflows.go
  • internal/exec/stack_processor_utils.go
  • pkg/list/importresolver/provenance.go
  • cmd/list/vendor.go
  • cmd/list/stacks.go
📚 Learning: 2024-10-20T00:41:57.135Z
Learnt from: haitham911
Repo: cloudposse/atmos PR: 731
File: internal/exec/validate_stacks.go:93-98
Timestamp: 2024-10-20T00:41:57.135Z
Learning: When downloading schema files in `internal/exec/validate_stacks.go`, use a consistent temporary file name to overwrite the file each time and avoid creating multiple temporary files.

Applied to files:

  • pkg/list/importresolver/resolver_test.go
📚 Learning: 2025-05-23T19:51:47.091Z
Learnt from: samtholiya
Repo: cloudposse/atmos PR: 1255
File: cmd/describe_affected_test.go:15-15
Timestamp: 2025-05-23T19:51:47.091Z
Learning: The atmos codebase has a custom extension to *testing.T that provides a Chdir method, allowing test functions to call t.Chdir() to change working directories during tests. This is used consistently across test files in the codebase.

Applied to files:

  • pkg/list/importresolver/resolver_test.go
📚 Learning: 2025-02-05T11:10:51.031Z
Learnt from: mss
Repo: cloudposse/atmos PR: 1024
File: internal/exec/go_getter_utils.go:31-33
Timestamp: 2025-02-05T11:10:51.031Z
Learning: The path traversal check in `ValidateURI` function in `internal/exec/go_getter_utils.go` is intentionally kept despite potentially blocking valid Git URLs, as this validation is planned to be addressed in a separate ticket.

Applied to files:

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

Applied to files:

  • pkg/list/importresolver/resolver_test.go
📚 Learning: 2025-09-24T20:45:40.401Z
Learnt from: Benbentwo
Repo: cloudposse/atmos PR: 1475
File: tests/fixtures/scenarios/atmos-auth/stacks/deploy/nonprod.yaml:3-4
Timestamp: 2025-09-24T20:45:40.401Z
Learning: In Atmos stack files, the correct syntax for importing other stack files is `import:` (singular), not `imports:` (plural). All stack files in the Atmos codebase consistently use `import:` followed by a list of paths to import.

Applied to files:

  • pkg/list/importresolver/resolver_test.go
  • pkg/list/importresolver/provenance.go
📚 Learning: 2025-07-05T20:59:02.914Z
Learnt from: aknysh
Repo: cloudposse/atmos PR: 1363
File: internal/exec/template_utils.go:18-18
Timestamp: 2025-07-05T20:59:02.914Z
Learning: In the Atmos project, gomplate v4 is imported with a blank import (`_ "github.com/hairyhenderson/gomplate/v4"`) alongside v3 imports to resolve AWS SDK version conflicts. V3 uses older AWS SDK versions that conflict with newer AWS modules used by Atmos. A full migration to v4 requires extensive refactoring due to API changes and should be handled in a separate PR.

Applied to files:

  • pkg/list/importresolver/resolver_test.go
  • pkg/list/extract/workflows.go
  • internal/exec/stack_processor_utils.go
  • pkg/list/importresolver/provenance.go
📚 Learning: 2025-09-10T22:38:42.212Z
Learnt from: Benbentwo
Repo: cloudposse/atmos PR: 1475
File: pkg/auth/identities/aws/user.go:141-145
Timestamp: 2025-09-10T22:38:42.212Z
Learning: The user confirmed that the errors package has an error string wrapping format, contradicting the previous learning about ErrWrappingFormat being invalid. The current usage of fmt.Errorf(errUtils.ErrWrappingFormat, errUtils.ErrAuthAwsFileManagerFailed, err) appears to be the correct pattern.

Applied to files:

  • pkg/list/list_instances.go
📚 Learning: 2025-06-07T19:28:21.289Z
Learnt from: samtholiya
Repo: cloudposse/atmos PR: 1266
File: cmd/describe_affected.go:0-0
Timestamp: 2025-06-07T19:28:21.289Z
Learning: In the Atmos codebase, using panic for unsupported flag types in flag processing functions like setDescribeAffectedFlagValueInCliArgs is the expected behavior rather than returning errors. This pattern is preferred for developer errors when unsupported types are added to the flagsKeyValue map.

Applied to files:

  • pkg/list/list_instances.go
  • cmd/list/components.go
📚 Learning: 2025-01-07T20:38:09.618Z
Learnt from: samtholiya
Repo: cloudposse/atmos PR: 896
File: cmd/editor_config.go:37-40
Timestamp: 2025-01-07T20:38:09.618Z
Learning: Error handling suggestion for `cmd.Help()` in `cmd/editor_config.go` was deferred as the code is planned for future modifications.

Applied to files:

  • pkg/list/list_instances.go
  • cmd/list/workflows.go
  • cmd/list/components.go
📚 Learning: 2025-02-19T05:50:35.853Z
Learnt from: samtholiya
Repo: cloudposse/atmos PR: 1068
File: tests/snapshots/TestCLICommands_atmos_terraform_apply_--help.stdout.golden:0-0
Timestamp: 2025-02-19T05:50:35.853Z
Learning: Backtick formatting should only be applied to flag descriptions in Go source files, not in golden test files (test snapshots) as they are meant to capture the raw command output.

Applied to files:

  • pkg/list/list_instances.go
  • cmd/list/components.go
📚 Learning: 2024-12-13T15:28:13.630Z
Learnt from: Listener430
Repo: cloudposse/atmos PR: 844
File: cmd/version.go:34-44
Timestamp: 2024-12-13T15:28:13.630Z
Learning: In `cmd/version.go`, when handling the `--check` flag in the `versionCmd`, avoid using `CheckForAtmosUpdateAndPrintMessage(cliConfig)` as it updates the cache timestamp, which may not be desired in this context.

Applied to files:

  • pkg/list/list_instances.go
  • cmd/list/stacks.go
📚 Learning: 2025-10-10T23:51:36.597Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 1599
File: internal/exec/terraform.go:394-402
Timestamp: 2025-10-10T23:51:36.597Z
Learning: In Atmos (internal/exec/terraform.go), when adding OpenTofu-specific flags like `--var-file` for `init`, do not gate them based on command name (e.g., checking if `info.Command == "tofu"` or `info.Command == "opentofu"`) because command names don't reliably indicate the actual binary being executed (symlinks, aliases). Instead, document the OpenTofu requirement in code comments and documentation, trusting users who enable the feature (e.g., `PassVars`) to ensure their terraform command points to an OpenTofu binary.

Applied to files:

  • pkg/list/list_instances.go
  • cmd/list/workflows.go
  • cmd/list/components.go
  • cmd/list/vendor.go
  • cmd/list/stacks.go
📚 Learning: 2025-06-23T02:14:30.937Z
Learnt from: aknysh
Repo: cloudposse/atmos PR: 1327
File: cmd/terraform.go:111-117
Timestamp: 2025-06-23T02:14:30.937Z
Learning: In cmd/terraform.go, flags for the DescribeAffected function are added dynamically at runtime when info.Affected is true. This is intentional to avoid exposing internal flags like "file", "format", "verbose", "include-spacelift-admin-stacks", "include-settings", and "upload" in the terraform command interface, while still providing them for the shared DescribeAffected function used by both `atmos describe affected` and `atmos terraform apply --affected`.

Applied to files:

  • pkg/list/list_instances.go
  • cmd/list/stacks.go
📚 Learning: 2025-02-18T13:18:53.146Z
Learnt from: samtholiya
Repo: cloudposse/atmos PR: 1068
File: cmd/vendor_pull.go:31-31
Timestamp: 2025-02-18T13:18:53.146Z
Learning: Error checking is not required for cobra.Command.RegisterFlagCompletionFunc calls as these are static configurations done at init time.

Applied to files:

  • pkg/list/list_instances.go
  • cmd/list/components.go
📚 Learning: 2025-02-03T06:00:11.419Z
Learnt from: samtholiya
Repo: cloudposse/atmos PR: 959
File: cmd/describe_config.go:20-20
Timestamp: 2025-02-03T06:00:11.419Z
Learning: Commands should use `PrintErrorMarkdownAndExit` with empty title and suggestion (`"", err, ""`) for general error handling. Specific titles like "Invalid Usage" or "File Not Found" should only be used for validation or specific error scenarios.

Applied to files:

  • pkg/list/list_instances.go
📚 Learning: 2025-09-10T22:38:42.212Z
Learnt from: Benbentwo
Repo: cloudposse/atmos PR: 1475
File: pkg/auth/identities/aws/user.go:141-145
Timestamp: 2025-09-10T22:38:42.212Z
Learning: ErrWrappingFormat is correctly defined as "%w: %w" in the errors package and is used throughout the codebase to wrap two error types together. The usage fmt.Errorf(errUtils.ErrWrappingFormat, errUtils.ErrAuthAwsFileManagerFailed, err) is the correct pattern when both arguments are error types.

Applied to files:

  • pkg/list/list_instances.go
  • internal/exec/stack_processor_utils.go
📚 Learning: 2025-02-20T13:57:36.326Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 1036
File: cmd/list_settings.go:46-50
Timestamp: 2025-02-20T13:57:36.326Z
Learning: The max-columns flag in Atmos list commands (values, settings, metadata) supports -1 as a special value to display unlimited columns in table outputs. The default is 10 columns if not specified.

Applied to files:

  • pkg/list/list_instances.go
📚 Learning: 2025-02-20T13:57:36.326Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 1036
File: cmd/list_settings.go:46-50
Timestamp: 2025-02-20T13:57:36.326Z
Learning: The max-columns flag in Atmos list commands supports -1 for unlimited width, which bypasses terminal width restrictions and may require horizontal scrolling. The default is 10 columns if not specified.

Applied to files:

  • pkg/list/list_instances.go
  • cmd/list/vendor.go
📚 Learning: 2025-02-20T13:57:36.326Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 1036
File: cmd/list_settings.go:46-50
Timestamp: 2025-02-20T13:57:36.326Z
Learning: The max-columns flag in Atmos list commands (values, settings, metadata) supports -1 as a special value to display unlimited columns in table outputs, with a default of 10 columns.

Applied to files:

  • pkg/list/list_instances.go
📚 Learning: 2025-02-20T13:57:36.326Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 1036
File: cmd/list_settings.go:46-50
Timestamp: 2025-02-20T13:57:36.326Z
Learning: The max-columns flag in Atmos list commands supports -1 as a special value to display unlimited columns in table outputs.

Applied to files:

  • pkg/list/list_instances.go
📚 Learning: 2024-11-13T21:37:07.852Z
Learnt from: Cerebrovinny
Repo: cloudposse/atmos PR: 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:

  • pkg/list/list_instances.go
  • internal/exec/stack_processor_utils.go
  • pkg/list/importresolver/provenance.go
  • cmd/list/vendor.go
  • cmd/list/stacks.go
📚 Learning: 2024-12-07T16:19:01.683Z
Learnt from: aknysh
Repo: cloudposse/atmos PR: 825
File: internal/exec/terraform.go:30-30
Timestamp: 2024-12-07T16:19:01.683Z
Learning: In `internal/exec/terraform.go`, skipping stack validation when help flags are present is not necessary.

Applied to files:

  • pkg/list/list_instances.go
  • cmd/list/vendor.go
  • cmd/list/stacks.go
📚 Learning: 2024-12-08T14:26:16.972Z
Learnt from: pkbhowmick
Repo: cloudposse/atmos PR: 828
File: pkg/schema/schema.go:98-100
Timestamp: 2024-12-08T14:26:16.972Z
Learning: The `ListConfig` columns array in the `Components` struct can be empty.

Applied to files:

  • pkg/list/list_instances.go
  • cmd/list/components.go
  • cmd/list/vendor.go
  • pkg/list/column/column.go
📚 Learning: 2025-06-02T14:12:02.710Z
Learnt from: milldr
Repo: cloudposse/atmos PR: 1229
File: internal/exec/workflow_test.go:0-0
Timestamp: 2025-06-02T14:12:02.710Z
Learning: In the atmos codebase, workflow error handling was refactored to use `PrintErrorMarkdown` followed by returning specific error variables (like `ErrWorkflowNoSteps`, `ErrInvalidFromStep`, `ErrInvalidWorkflowStepType`, `ErrWorkflowStepFailed`) instead of `PrintErrorMarkdownAndExit`. This pattern allows proper error testing without the function terminating the process with `os.Exit`, enabling unit tests to assert on error conditions while maintaining excellent user-facing error formatting.

Applied to files:

  • cmd/list/workflows.go
  • pkg/list/extract/workflows.go
📚 Learning: 2024-12-07T16:16:13.038Z
Learnt from: Listener430
Repo: cloudposse/atmos PR: 825
File: internal/exec/helmfile_generate_varfile.go:28-31
Timestamp: 2024-12-07T16:16:13.038Z
Learning: In `internal/exec/helmfile_generate_varfile.go`, the `--help` command (`./atmos helmfile generate varfile --help`) works correctly without requiring stack configurations, and the only change needed was to make `ProcessCommandLineArgs` exportable by capitalizing its name.

Applied to files:

  • cmd/list/workflows.go
  • cmd/list/components.go
  • internal/exec/stack_processor_utils.go
  • cmd/list/vendor.go
  • cmd/list/stacks.go
📚 Learning: 2025-01-09T22:37:01.004Z
Learnt from: samtholiya
Repo: cloudposse/atmos PR: 914
File: cmd/terraform_commands.go:260-265
Timestamp: 2025-01-09T22:37:01.004Z
Learning: In the terraform commands implementation (cmd/terraform_commands.go), the direct use of `os.Args[2:]` for argument handling is intentionally preserved to avoid extensive refactoring. While it could be improved to use cobra's argument parsing, such changes should be handled in a dedicated PR to maintain focus and minimize risk.

Applied to files:

  • cmd/list/workflows.go
  • cmd/list/components.go
  • cmd/list/stacks.go
📚 Learning: 2025-11-08T19:56:18.660Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 1697
File: internal/exec/oci_utils.go:0-0
Timestamp: 2025-11-08T19:56:18.660Z
Learning: In the Atmos codebase, when a function receives an `*schema.AtmosConfiguration` parameter, it should read configuration values from `atmosConfig.Settings` fields rather than using direct `os.Getenv()` or `viper.GetString()` calls. The Atmos pattern is: viper.BindEnv in cmd/root.go binds environment variables → Viper unmarshals into atmosConfig.Settings via mapstructure → business logic reads from the Settings struct. This provides centralized config management, respects precedence, and enables testability. Example: `atmosConfig.Settings.AtmosGithubToken` instead of `os.Getenv("ATMOS_GITHUB_TOKEN")` in functions like `getGHCRAuth` in internal/exec/oci_utils.go.

Applied to files:

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

Applied to files:

  • cmd/list/workflows.go
  • internal/exec/stack_processor_utils.go
  • pkg/list/importresolver/provenance.go
  • cmd/list/stacks.go
📚 Learning: 2024-12-11T18:40:12.808Z
Learnt from: Listener430
Repo: cloudposse/atmos PR: 844
File: cmd/helmfile.go:37-37
Timestamp: 2024-12-11T18:40:12.808Z
Learning: In the atmos project, `cliConfig` is initialized within the `cmd` package in `root.go` and can be used in other command files.

Applied to files:

  • cmd/list/workflows.go
  • internal/exec/stack_processor_utils.go
📚 Learning: 2025-08-16T23:32:40.412Z
Learnt from: aknysh
Repo: cloudposse/atmos PR: 1405
File: internal/exec/describe_dependents_test.go:455-456
Timestamp: 2025-08-16T23:32:40.412Z
Learning: In the cloudposse/atmos Go codebase, `InitCliConfig` returns a `schema.AtmosConfiguration` value (not a pointer), while `ExecuteDescribeDependents` expects a `*schema.AtmosConfiguration` pointer parameter. Therefore, when passing the result of `InitCliConfig` to `ExecuteDescribeDependents`, use `&atmosConfig` to pass the address of the value.

Applied to files:

  • cmd/list/workflows.go
  • cmd/list/stacks.go
📚 Learning: 2024-10-20T13:12:46.499Z
Learnt from: haitham911
Repo: cloudposse/atmos PR: 736
File: pkg/config/const.go:6-6
Timestamp: 2024-10-20T13:12:46.499Z
Learning: In `cmd/cmd_utils.go`, it's acceptable to have hardcoded references to `atmos.yaml` in logs, and it's not necessary to update them to use the `CliConfigFileName` constant.

Applied to files:

  • cmd/list/workflows.go
  • internal/exec/stack_processor_utils.go
📚 Learning: 2025-06-02T14:12:02.710Z
Learnt from: milldr
Repo: cloudposse/atmos PR: 1229
File: internal/exec/workflow_test.go:0-0
Timestamp: 2025-06-02T14:12:02.710Z
Learning: In the atmos codebase, workflow error handling was refactored to use `PrintErrorMarkdown` followed by returning the error instead of `PrintErrorMarkdownAndExit`. This pattern allows proper error testing without the function terminating the process with `os.Exit`, enabling unit tests to assert on error conditions.

Applied to files:

  • pkg/list/extract/workflows.go
📚 Learning: 2025-09-29T02:20:11.636Z
Learnt from: aknysh
Repo: cloudposse/atmos PR: 1540
File: internal/exec/validate_component.go:117-118
Timestamp: 2025-09-29T02:20:11.636Z
Learning: The ValidateComponent function in internal/exec/validate_component.go had its componentSection parameter type refined from `any` to `map[string]any` without adding new parameters. This is a type safety improvement, not a signature change requiring call site updates.

Applied to files:

  • cmd/list/components.go
  • internal/exec/stack_processor_utils.go
  • pkg/list/extract/components.go
  • cmd/list/stacks.go
📚 Learning: 2025-11-10T03:03:31.505Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 0
File: :0-0
Timestamp: 2025-11-10T03:03:31.505Z
Learning: In the Atmos codebase, commands using the `StandardParser` flag pattern (from pkg/flags) do NOT need explicit `viper.BindPFlag()` calls in their code. The StandardParser encapsulates flag binding internally: flags are registered via `parser.RegisterFlags(cmd)` in init(), and bound via `parser.BindFlagsToViper(cmd, v)` in RunE, which internally calls viper.BindPFlag for each flag. This pattern is used throughout Atmos (e.g., cmd/toolchain/get.go, cmd/toolchain/info.go, cmd/toolchain/install.go, cmd/toolchain/path.go). Do not flag missing viper.BindPFlag calls when StandardParser is used.

Applied to files:

  • cmd/list/components.go
📚 Learning: 2024-10-31T07:09:31.983Z
Learnt from: Cerebrovinny
Repo: cloudposse/atmos PR: 737
File: internal/exec/vendor_utils.go:181-182
Timestamp: 2024-10-31T07:09:31.983Z
Learning: In `internal/exec/vendor_utils.go`, the variables `mergedSources` and `mergedImports` are declared and used later in the code. Do not suggest removing them as unused variables.

Applied to files:

  • internal/exec/stack_processor_utils.go
  • pkg/list/importresolver/provenance.go
📚 Learning: 2025-10-16T05:26:31.892Z
Learnt from: aknysh
Repo: cloudposse/atmos PR: 1639
File: pkg/merge/merge.go:392-430
Timestamp: 2025-10-16T05:26:31.892Z
Learning: In Atmos merge operations (pkg/merge/merge.go), context.Positions is a PositionMap (map[string]*schema.Position) keyed by JSONPath strings, not a slice indexed by input array position. Position lookups are path-based, making them independent of input array reorganization or filtering. This design allows filtering empty inputs without affecting provenance tracking correctness.

Applied to files:

  • internal/exec/stack_processor_utils.go
  • pkg/list/importresolver/provenance.go
📚 Learning: 2024-10-30T13:25:45.965Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 727
File: internal/exec/terraform_clean.go:405-412
Timestamp: 2024-10-30T13:25:45.965Z
Learning: In `internal/exec/terraform_clean.go`, when appending `stackFolders` to `folders` in the `handleCleanSubCommand` function, it's unnecessary to check if `stackFolders` is nil before appending, because in Go, appending a nil slice is safe and does not cause a panic.

Applied to files:

  • internal/exec/stack_processor_utils.go
📚 Learning: 2025-05-22T15:42:10.906Z
Learnt from: aknysh
Repo: cloudposse/atmos PR: 1261
File: internal/exec/utils.go:639-640
Timestamp: 2025-05-22T15:42:10.906Z
Learning: In the Atmos codebase, when appending slices with `args := append(configAndStacksInfo.CliArgs, configAndStacksInfo.AdditionalArgsAndFlags...)`, it's intentional that the result is not stored back in the original slice. This pattern is used when the merged result serves a different purpose than the original slices, such as when creating a filtered version for component section assignments.

Applied to files:

  • internal/exec/stack_processor_utils.go
  • cmd/list/stacks.go
📚 Learning: 2025-10-08T06:48:07.499Z
Learnt from: aknysh
Repo: cloudposse/atmos PR: 1602
File: internal/exec/stack_processor_utils.go:968-1003
Timestamp: 2025-10-08T06:48:07.499Z
Learning: The `FindComponentDependenciesLegacy` function in `internal/exec/stack_processor_utils.go` is legacy code that is not actively used and is kept only for backward compatibility purposes.

Applied to files:

  • internal/exec/stack_processor_utils.go
  • pkg/list/extract/components.go
📚 Learning: 2025-04-04T02:03:23.676Z
Learnt from: aknysh
Repo: cloudposse/atmos PR: 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/stack_processor_utils.go
  • pkg/list/importresolver/provenance.go
  • cmd/list/stacks.go
📚 Learning: 2025-09-13T18:06:07.674Z
Learnt from: samtholiya
Repo: cloudposse/atmos PR: 1466
File: toolchain/list.go:39-42
Timestamp: 2025-09-13T18:06:07.674Z
Learning: In the cloudposse/atmos repository, for UI messages in the toolchain package, use utils.PrintfMessageToTUI instead of log.Error or fmt.Fprintln(os.Stderr, ...). Import pkg/utils with alias "u" to follow the established pattern.

Applied to files:

  • internal/exec/stack_processor_utils.go
📚 Learning: 2025-02-06T13:38:07.216Z
Learnt from: Listener430
Repo: cloudposse/atmos PR: 984
File: internal/exec/copy_glob.go:0-0
Timestamp: 2025-02-06T13:38:07.216Z
Learning: The `u.LogTrace` function in the `cloudposse/atmos` repository accepts `atmosConfig` as its first parameter, followed by the message string.

Applied to files:

  • internal/exec/stack_processor_utils.go
📚 Learning: 2025-11-09T19:06:58.470Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 1752
File: pkg/profile/list/formatter_table.go:27-29
Timestamp: 2025-11-09T19:06:58.470Z
Learning: In the cloudposse/atmos repository, performance tracking with `defer perf.Track()` is enforced on all functions via linting, including high-frequency utility functions, formatters, and renderers. This is a repository-wide policy to maintain consistency and avoid making case-by-case judgment calls about which functions should have profiling.

Applied to files:

  • internal/exec/stack_processor_utils.go
  • pkg/list/importresolver/provenance.go
📚 Learning: 2025-10-22T14:55:44.014Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 1695
File: pkg/auth/manager.go:169-171
Timestamp: 2025-10-22T14:55:44.014Z
Learning: Go 1.20+ supports multiple %w verbs in fmt.Errorf, which returns an error implementing Unwrap() []error. This is valid and does not panic. Atmos uses Go 1.24.8 and configures errorlint with errorf-multi: true to validate this pattern.

Applied to files:

  • internal/exec/stack_processor_utils.go
📚 Learning: 2024-10-20T00:57:53.500Z
Learnt from: haitham911
Repo: cloudposse/atmos PR: 731
File: internal/exec/validate_stacks.go:0-0
Timestamp: 2024-10-20T00:57:53.500Z
Learning: In `internal/exec/validate_stacks.go`, when downloading the Atmos JSON Schema file to the temp directory, the temporary file is overwritten each time, so explicit removal is not necessary.

Applied to files:

  • internal/exec/stack_processor_utils.go
📚 Learning: 2025-04-11T22:06:46.999Z
Learnt from: samtholiya
Repo: cloudposse/atmos PR: 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/stack_processor_utils.go
📚 Learning: 2025-03-17T18:41:08.831Z
Learnt from: haitham911
Repo: cloudposse/atmos PR: 1085
File: pkg/config/imports.go:68-75
Timestamp: 2025-03-17T18:41:08.831Z
Learning: In the Atmos configuration import system, errors during config file merging are logged at debug level and the process continues with other imports rather than failing completely, prioritizing resilience over strict correctness.

Applied to files:

  • internal/exec/stack_processor_utils.go
📚 Learning: 2025-04-03T10:57:04.602Z
Learnt from: haitham911
Repo: cloudposse/atmos PR: 1091
File: pkg/config/load_config_args.go:61-82
Timestamp: 2025-04-03T10:57:04.602Z
Learning: In the Atmos configuration system, errors in `mergeDefaultImports` and `mergeImports` functions are intentionally only logged as debug messages without returning errors, as they are considered non-critical. Only errors in critical functions like `mergeConfigFile` are returned to halt execution.

Applied to files:

  • internal/exec/stack_processor_utils.go
📚 Learning: 2025-09-10T21:17:55.273Z
Learnt from: samtholiya
Repo: cloudposse/atmos PR: 1466
File: toolchain/http_client_test.go:3-10
Timestamp: 2025-09-10T21:17:55.273Z
Learning: In the cloudposse/atmos repository, imports should never be changed as per samtholiya's coding guidelines.

Applied to files:

  • pkg/list/importresolver/provenance.go
📚 Learning: 2025-10-13T18:13:54.020Z
Learnt from: aknysh
Repo: cloudposse/atmos PR: 1622
File: pkg/perf/perf.go:140-184
Timestamp: 2025-10-13T18:13:54.020Z
Learning: In pkg/perf/perf.go, the `trackWithSimpleStack` function intentionally skips ownership checks at call stack depth > 1 to avoid expensive `getGoroutineID()` calls on every nested function. This is a performance optimization for the common single-goroutine execution case (most Atmos commands), accepting the rare edge case of potential metric corruption if multi-goroutine execution occurs at depth > 1. The ~19× performance improvement justifies this trade-off.

Applied to files:

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

Applied to files:

  • pkg/list/importresolver/provenance.go
📚 Learning: 2024-11-01T15:44:12.617Z
Learnt from: RoseSecurity
Repo: cloudposse/atmos PR: 757
File: cmd/docs.go:42-59
Timestamp: 2024-11-01T15:44:12.617Z
Learning: In `cmd/docs.go`, when implementing width detection for the `docsCmd` command, it's acceptable to keep the code inline without extracting it into a separate function, as per the user's preference for compact readability and maintainability in Go code.

Applied to files:

  • cmd/list/vendor.go
📚 Learning: 2025-01-09T22:27:25.538Z
Learnt from: samtholiya
Repo: cloudposse/atmos PR: 914
File: cmd/validate_stacks.go:20-23
Timestamp: 2025-01-09T22:27:25.538Z
Learning: The validate commands in Atmos can have different help handling implementations. Specifically, validate_component.go and validate_stacks.go are designed to handle help requests differently, with validate_stacks.go including positional argument checks while validate_component.go does not.

Applied to files:

  • cmd/list/stacks.go
📚 Learning: 2025-01-19T15:49:15.593Z
Learnt from: samtholiya
Repo: cloudposse/atmos PR: 955
File: tests/snapshots/TestCLICommands_atmos_validate_editorconfig_--help.stdout.golden:0-0
Timestamp: 2025-01-19T15:49:15.593Z
Learning: In future commits, the help text for Atmos CLI commands should be limited to only show component and stack parameters for commands that actually use them. This applies to the example usage section in command help text.

Applied to files:

  • cmd/list/stacks.go
🧬 Code graph analysis (11)
pkg/list/importresolver/resolver_test.go (3)
pkg/schema/schema.go (1)
  • AtmosConfiguration (53-94)
pkg/list/importresolver/resolver.go (1)
  • ResolveImportTree (20-46)
errors/errors.go (1)
  • ErrStackManifestFileNotFound (223-223)
pkg/list/list_instances.go (10)
pkg/list/column/column.go (3)
  • Config (13-17)
  • NewSelector (52-79)
  • BuildColumnFuncMap (278-304)
pkg/schema/schema.go (3)
  • ConfigAndStacksInfo (624-718)
  • AtmosConfiguration (53-94)
  • Components (404-417)
pkg/config/config.go (1)
  • InitCliConfig (28-67)
pkg/list/format/formatter.go (2)
  • FormatTree (17-17)
  • Format (8-8)
internal/exec/stack_processor_utils.go (1)
  • ClearMergeContexts (74-80)
internal/exec/utils.go (1)
  • ClearFindStacksMapCache (263-270)
pkg/list/importresolver/provenance.go (1)
  • ResolveImportTreeFromProvenance (32-108)
pkg/list/extract/metadata.go (1)
  • Metadata (43-53)
pkg/list/renderer/renderer.go (1)
  • New (31-46)
pkg/list/sort/sort.go (4)
  • Sorter (35-39)
  • ParseSortSpec (195-237)
  • NewSorter (48-54)
  • Ascending (17-17)
cmd/list/workflows.go (8)
internal/exec/cli_utils.go (1)
  • ProcessCommandLineArgs (79-199)
pkg/config/config.go (1)
  • InitCliConfig (28-67)
pkg/list/extract/workflows.go (1)
  • Workflows (20-92)
cmd/list/flag_wrappers.go (5)
  • NewListParser (304-315)
  • WithFormatFlag (32-40)
  • WithWorkflowsColumnsFlag (103-110)
  • WithSortFlag (149-156)
  • WithFileFlag (208-215)
pkg/list/column/column.go (2)
  • NewSelector (52-79)
  • BuildColumnFuncMap (278-304)
pkg/list/renderer/renderer.go (1)
  • New (31-46)
pkg/list/output/output.go (1)
  • New (14-16)
pkg/list/sort/sort.go (4)
  • Sorter (35-39)
  • NewSorter (48-54)
  • Ascending (17-17)
  • ParseSortSpec (195-237)
pkg/list/extract/workflows.go (4)
pkg/schema/schema.go (2)
  • Workflows (450-453)
  • AtmosConfiguration (53-94)
pkg/utils/file_utils.go (4)
  • IsYaml (48-59)
  • IsPathAbsolute (100-102)
  • IsDirectory (20-28)
  • GetAllYamlFilesInDir (238-255)
errors/errors.go (2)
  • ErrParseFile (12-12)
  • ErrWorkflowDirectoryDoesNotExist (398-398)
pkg/schema/workflow.go (1)
  • WorkflowManifest (24-28)
cmd/list/components.go (10)
pkg/flags/global_registry.go (1)
  • ParseGlobalFlags (33-74)
pkg/config/config.go (1)
  • InitCliConfig (28-67)
pkg/list/extract/components.go (1)
  • Components (17-44)
cmd/list/flag_wrappers.go (9)
  • NewListParser (304-315)
  • WithFormatFlag (32-40)
  • WithComponentsColumnsFlag (81-86)
  • WithSortFlag (149-156)
  • WithStackFlag (126-133)
  • WithTypeFlag (185-193)
  • WithEnabledFlag (161-168)
  • WithLockedFlag (173-180)
  • WithAbstractFlag (241-248)
errors/errors.go (2)
  • ErrInitializingCLIConfig (283-283)
  • ErrExecuteDescribeStacks (404-404)
pkg/list/column/column.go (3)
  • NewSelector (52-79)
  • BuildColumnFuncMap (278-304)
  • Config (13-17)
pkg/list/renderer/renderer.go (1)
  • New (31-46)
pkg/list/output/output.go (1)
  • New (14-16)
pkg/list/filter/filter.go (4)
  • Filter (12-14)
  • NewGlobFilter (40-58)
  • NewColumnFilter (89-94)
  • NewBoolFilter (121-126)
pkg/list/sort/sort.go (4)
  • Sorter (35-39)
  • NewSorter (48-54)
  • Ascending (17-17)
  • ParseSortSpec (195-237)
internal/exec/stack_processor_utils.go (8)
pkg/merge/merge_context.go (1)
  • MergeContext (16-36)
pkg/perf/perf.go (1)
  • Track (121-138)
pkg/logger/log.go (1)
  • Trace (14-16)
pkg/utils/file_utils.go (1)
  • TrimBasePathFromPath (93-97)
errors/errors.go (7)
  • ErrInvalidStackManifest (224-224)
  • ErrInvalidOverridesSection (314-314)
  • ErrInvalidTerraformSection (307-307)
  • ErrInvalidTerraformOverridesSection (315-315)
  • ErrInvalidHelmfileSection (308-308)
  • ErrInvalidHelmfileOverridesSection (316-316)
  • ErrInvalidImport (313-313)
pkg/utils/json_utils.go (1)
  • ConvertFromJSON (170-187)
pkg/config/const.go (3)
  • TerraformSectionName (79-79)
  • OverridesSectionName (65-65)
  • HelmfileSectionName (80-80)
pkg/utils/slice_utils.go (1)
  • SliceContainsString (12-21)
pkg/list/importresolver/provenance.go (3)
pkg/schema/schema.go (1)
  • AtmosConfiguration (53-94)
pkg/list/tree/types.go (1)
  • ImportNode (4-9)
internal/exec/stack_processor_utils.go (1)
  • GetAllMergeContexts (84-96)
pkg/list/extract/components.go (2)
pkg/schema/schema.go (1)
  • Components (404-417)
errors/errors.go (4)
  • ErrStackNotFound (412-412)
  • ErrParseStacks (408-408)
  • ErrParseComponents (409-409)
  • ErrNoComponentsFound (410-410)
cmd/list/vendor.go (9)
pkg/flags/global_registry.go (1)
  • ParseGlobalFlags (33-74)
pkg/config/config.go (1)
  • InitCliConfig (28-67)
pkg/list/extract/vendor.go (1)
  • Vendor (24-44)
cmd/list/flag_wrappers.go (5)
  • NewListParser (304-315)
  • WithFormatFlag (32-40)
  • WithVendorColumnsFlag (115-122)
  • WithSortFlag (149-156)
  • WithStackFlag (126-133)
pkg/list/list_vendor.go (1)
  • GetVendorInfos (128-156)
pkg/list/column/column.go (3)
  • NewSelector (52-79)
  • BuildColumnFuncMap (278-304)
  • Config (13-17)
pkg/list/renderer/renderer.go (1)
  • New (31-46)
pkg/list/filter/filter.go (2)
  • Filter (12-14)
  • NewGlobFilter (40-58)
pkg/list/sort/sort.go (4)
  • Sorter (35-39)
  • NewSorter (48-54)
  • Ascending (17-17)
  • ParseSortSpec (195-237)
cmd/list/stacks.go (12)
internal/exec/cli_utils.go (1)
  • ProcessCommandLineArgs (79-199)
pkg/config/config.go (1)
  • InitCliConfig (28-67)
pkg/schema/schema.go (2)
  • Stacks (441-448)
  • AtmosConfiguration (53-94)
pkg/list/extract/stacks.go (2)
  • Stacks (11-27)
  • StacksForComponent (30-73)
cmd/list/flag_wrappers.go (6)
  • NewListParser (304-315)
  • WithFormatFlag (32-40)
  • WithStacksColumnsFlag (91-98)
  • WithSortFlag (149-156)
  • WithComponentFlag (197-204)
  • WithProvenanceFlag (285-292)
errors/errors.go (3)
  • ErrInvalidFlag (147-147)
  • ErrInitializingCLIConfig (283-283)
  • ErrExecuteDescribeStacks (404-404)
pkg/list/importresolver/provenance.go (1)
  • ResolveImportTreeFromProvenance (32-108)
pkg/list/tree/types.go (1)
  • ImportNode (4-9)
pkg/list/format/tree_stacks.go (1)
  • RenderStacksTree (14-25)
pkg/list/column/column.go (3)
  • NewSelector (52-79)
  • BuildColumnFuncMap (278-304)
  • Config (13-17)
pkg/list/renderer/renderer.go (1)
  • New (31-46)
pkg/list/sort/sort.go (4)
  • Sorter (35-39)
  • NewSorter (48-54)
  • Ascending (17-17)
  • ParseSortSpec (195-237)
pkg/list/column/column.go (4)
pkg/list/extract/metadata.go (1)
  • Metadata (43-53)
internal/exec/template_funcs.go (1)
  • FuncMap (21-34)
errors/errors.go (2)
  • ErrInvalidConfig (43-43)
  • ErrTemplateEvaluation (42-42)
pkg/list/renderer/renderer.go (1)
  • New (31-46)
⏰ Context from checks skipped due to timeout of 900000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: Acceptance Tests (windows)
  • GitHub Check: Summary
🔇 Additional comments (8)
internal/exec/stack_processor_utils.go (2)

82-96: LGTM! Clean defensive copy pattern.

The new function properly locks for thread safety and returns a defensive copy to prevent external modifications. The implementation aligns well with the existing merge context API.


19-19: Good provenance tracking instrumentation.

The trace logging additions provide helpful visibility into merge context propagation and import chain building. The logger alias is used correctly throughout.

Also applies to: 616-627, 877-878

pkg/list/importresolver/resolver_test.go (1)

16-912: Tests look solid and cross‑platform friendly

The resolver tests cover the key behaviors (empty stacks, nested imports, circular detection, caching, path resolution, and error paths) and use filepath.Join/t.TempDir() correctly, so they should behave well on all platforms.

cmd/list/workflows.go (1)

114-217: Workflows command implementation looks solid.

The renderer pipeline integration is clean: ProcessCommandLineArgs properly flows CLI config through to InitCliConfig, columns are handled as a string slice matching the flag definition, and the default columns use correct template variables (.file, .name, .description, .steps). All past review concerns have been addressed.

The pattern here—dynamic completion, flag wrappers, column/filter/sorter builders, and renderer delegation—matches the broader list command refactor nicely.

pkg/list/column/column.go (1)

52-79: Column selector architecture is well-designed.

Pre-parsing templates at selector creation (with validation) and deferring evaluation until Extract keeps the happy path fast while catching config errors early. The comprehensive field mapping in buildTemplateContext and safe template function set make this a solid foundation for the rendering pipeline.

pkg/list/list_instances.go (1)

352-464: Instance listing execution flow is clean.

The tree format branch now processes stacks exactly once (line 390), enables provenance correctly, and returns early (line 406) before the upload path—fixing the double-processing concern from past reviews. Format and upload flag error handling is consistent, and the renderer wiring (filters/selector/sorters) sets up the pipeline correctly even though filters are currently a no-op.

cmd/list/vendor.go (1)

185-212: Column width preservation looks good.

getVendorColumns now correctly copies the Width field from atmosConfig.Vendor.List.Columns at line 199, addressing the past review concern about dropped width settings.

cmd/list/stacks.go (1)

122-252: Stacks command correctly integrates CLI config and provenance.

The two-stage provenance validation (lines 125-127 and 145-148) catches misuse early when --format is explicit while still respecting config defaults. ProcessCommandLineArgs at line 130 ensures CLI flags like --base-path are honored, matching the pattern in other list commands. The tree format correctly filters by component (lines 198-220), preventing the "show all stacks" issue from past reviews.

Clean implementation that addresses all previous concerns.

The stackComponents map was being built but never read or used in the
ResolveImportTreeFromProvenance function. This removes the dead code.

Also updated nolint directive since function is now shorter.

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

Co-Authored-By: Claude <[email protected]>
- Add perf.Track instrumentation to all list extraction and resolver functions
  - pkg/list/extract/workflows.go: Workflows, extractFromManifest
  - pkg/list/extract/components.go: Components, ComponentsForStack, extractComponentType, enrichComponentWithMetadata
  - cmd/list/components.go: All helper functions (columnsCompletionForComponents, listComponentsWithOptions, buildComponentFilters, getComponentColumns, buildComponentSorters, parseColumnsFlag)
  - pkg/list/importresolver/provenance.go: All functions (ResolveImportTreeFromProvenance, findStacksForFilePath, extractComponentFolders, extractComponentsFromStackData, buildImportTreeFromChain, resolveImportFileImports, buildNodesFromImportPaths, resolveImportPath, readImportsFromYAMLFile, extractImportStringsHelper)

- Fix vendor stack filter to target correct column
  - Changed from "stack" to "component" since vendor rows contain component, type, manifest, folder fields

- Fix Type filter in components command
  - Changed filter target from "type" to "component_type"
  - Made Type filter authoritative: when --type is provided, no default abstract filter is added
  - Only applies default abstract filter when Type is not set and Abstract is false

- Fix relative import path resolution in provenance resolver
  - resolveImportPath now detects relative imports (starting with . or ..)
  - Relative imports resolve against parent file's directory
  - Non-relative imports continue to resolve against stacks base path

- Update component filter tests to match new Type filter behavior

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

Co-Authored-By: Claude <[email protected]>
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: 4

🧹 Nitpick comments (5)
cmd/list/components.go (1)

273-287: Consider implementing column parsing or document the deferral.

The parseColumnsFlag stub always returns defaults despite the --columns flag being wired. The TODO comment and nolint:unparam indicate this is intentionally deferred, but users expecting custom columns via CLI will still get the default set. Either implement the parsing logic to map flag values to column specs, or add a temporary user-facing warning when the flag is passed.

cmd/list/vendor.go (1)

170-184: Consider renaming opts.Stack to clarify vendor filtering.

While the implementation correctly filters the "component" field (line 177), the parameter name opts.Stack is misleading since vendor rows don't contain stack data. This could confuse future maintainers. Consider either renaming VendorOptions.Stack to Component or Filter, or adding a comment explaining the field repurposing. The comment already clarifies the intent ("Component filter"), but the field name doesn't match.

pkg/list/extract/workflows.go (1)

55-59: Consider extracting path construction logic.

The absolute path check and join pattern appears in both locations. A small helper would reduce duplication and make the intent clearer.

Something like:

func resolveWorkflowPath(atmosConfig *schema.AtmosConfiguration, relativePath string) string {
	if utils.IsPathAbsolute(atmosConfig.Workflows.BasePath) {
		return filepath.Join(atmosConfig.Workflows.BasePath, relativePath)
	}
	return filepath.Join(atmosConfig.BasePath, atmosConfig.Workflows.BasePath, relativePath)
}

Then use it at lines 55-59 and 74-78. No pressure though—the current approach works fine.

Also applies to: 74-78

pkg/list/extract/components.go (2)

78-95: Preserve metadata invariants when componentData has an unexpected shape

Right now, if componentData isn’t a map[string]any, enrichComponentWithMetadata returns immediately, leaving the component without enabled, locked, or component_type fields and without a data field. That can make list filters/columns behave inconsistently for malformed components.

You can at least apply default metadata before bailing out so callers always see a consistent shape:

 func enrichComponentWithMetadata(comp map[string]any, componentData any) {
 	defer perf.Track(nil, "list.extract.enrichComponentWithMetadata")()
 
 	compMap, ok := componentData.(map[string]any)
 	if !ok {
-		return
+		// Ensure callers still see default metadata fields even for malformed components.
+		setDefaultMetadataFields(comp)
+		return
 	}

This keeps the “always have enabled/locked/component_type” invariant without changing error semantics.


21-47: Confirm intentional difference in “no components” behavior between aggregate and per-stack paths

Components returns an empty slice and nil error when no components are found across all stacks, while ComponentsForStack returns ErrNoComponentsFound when a specific stack has zero components.

If that distinction is intentional (aggregate listing treats “nothing to list” as success, targeted listing treats “nothing for this stack” as an error), it might be worth making that explicit in the doc comments so callers don’t misinterpret a nil,nil from Components as an error/edge case.

If you intended uniform behavior instead, you could either:

  • have Components also return ErrNoComponentsFound when len(components) == 0, or
  • relax ComponentsForStack to match the aggregate behavior and just return an empty slice.

Given the surrounding pipeline, I suspect the current behavior is fine; mostly asking you to double-check it’s by design.

Also applies to: 147-153

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 37e9c20 and be74995.

📒 Files selected for processing (6)
  • cmd/list/components.go (1 hunks)
  • cmd/list/components_test.go (2 hunks)
  • cmd/list/vendor.go (1 hunks)
  • pkg/list/extract/components.go (1 hunks)
  • pkg/list/extract/workflows.go (1 hunks)
  • pkg/list/importresolver/provenance.go (1 hunks)
🧰 Additional context used
🧠 Learnings (36)
📓 Common learnings
Learnt from: Listener430
Repo: cloudposse/atmos PR: 934
File: tests/fixtures/scenarios/docs-generate/README.md.gotmpl:99-118
Timestamp: 2025-01-25T03:51:57.689Z
Learning: For the cloudposse/atmos repository, changes to template contents should be handled in dedicated PRs and are typically considered out of scope for PRs focused on other objectives.
Learnt from: osterman
Repo: cloudposse/atmos PR: 1036
File: cmd/list_settings.go:46-50
Timestamp: 2025-02-20T13:57:36.326Z
Learning: The max-columns flag in Atmos list commands supports -1 for unlimited width, which bypasses terminal width restrictions and may require horizontal scrolling. The default is 10 columns if not specified.
Learnt from: samtholiya
Repo: cloudposse/atmos PR: 1466
File: cmd/markdown/atmos_toolchain_aliases.md:2-4
Timestamp: 2025-09-13T16:39:20.007Z
Learning: In the cloudposse/atmos repository, CLI documentation files in cmd/markdown/ follow a specific format that uses " $ atmos command" (with leading space and dollar sign prompt) in code blocks. This is the established project convention and should not be changed to comply with standard markdownlint rules MD040 and MD014.
Learnt from: osterman
Repo: cloudposse/atmos PR: 1533
File: pkg/config/load.go:585-637
Timestamp: 2025-09-27T20:50:20.564Z
Learning: In the cloudposse/atmos repository, command merging prioritizes precedence over display ordering. Help commands are displayed lexicographically regardless of internal array order, so the mergeCommandArrays function focuses on ensuring the correct precedence chain (top-level file wins) rather than maintaining specific display order.
📚 Learning: 2025-06-02T14:12:02.710Z
Learnt from: milldr
Repo: cloudposse/atmos PR: 1229
File: internal/exec/workflow_test.go:0-0
Timestamp: 2025-06-02T14:12:02.710Z
Learning: In the atmos codebase, workflow error handling was refactored to use `PrintErrorMarkdown` followed by returning specific error variables (like `ErrWorkflowNoSteps`, `ErrInvalidFromStep`, `ErrInvalidWorkflowStepType`, `ErrWorkflowStepFailed`) instead of `PrintErrorMarkdownAndExit`. This pattern allows proper error testing without the function terminating the process with `os.Exit`, enabling unit tests to assert on error conditions while maintaining excellent user-facing error formatting.

Applied to files:

  • pkg/list/extract/workflows.go
📚 Learning: 2025-06-02T14:12:02.710Z
Learnt from: milldr
Repo: cloudposse/atmos PR: 1229
File: internal/exec/workflow_test.go:0-0
Timestamp: 2025-06-02T14:12:02.710Z
Learning: In the atmos codebase, workflow error handling was refactored to use `PrintErrorMarkdown` followed by returning the error instead of `PrintErrorMarkdownAndExit`. This pattern allows proper error testing without the function terminating the process with `os.Exit`, enabling unit tests to assert on error conditions.

Applied to files:

  • pkg/list/extract/workflows.go
📚 Learning: 2025-07-05T20:59:02.914Z
Learnt from: aknysh
Repo: cloudposse/atmos PR: 1363
File: internal/exec/template_utils.go:18-18
Timestamp: 2025-07-05T20:59:02.914Z
Learning: In the Atmos project, gomplate v4 is imported with a blank import (`_ "github.com/hairyhenderson/gomplate/v4"`) alongside v3 imports to resolve AWS SDK version conflicts. V3 uses older AWS SDK versions that conflict with newer AWS modules used by Atmos. A full migration to v4 requires extensive refactoring due to API changes and should be handled in a separate PR.

Applied to files:

  • pkg/list/extract/workflows.go
  • pkg/list/importresolver/provenance.go
📚 Learning: 2024-11-19T23:00:45.899Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 795
File: internal/exec/stack_processor_utils.go:378-386
Timestamp: 2024-11-19T23:00:45.899Z
Learning: In the `ProcessYAMLConfigFile` function within `internal/exec/stack_processor_utils.go`, directory traversal in stack imports is acceptable and should not be restricted.

Applied to files:

  • pkg/list/extract/workflows.go
  • pkg/list/importresolver/provenance.go
  • cmd/list/vendor.go
📚 Learning: 2025-11-09T19:06:58.470Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 1752
File: pkg/profile/list/formatter_table.go:27-29
Timestamp: 2025-11-09T19:06:58.470Z
Learning: In the cloudposse/atmos repository, performance tracking with `defer perf.Track()` is enforced on all functions via linting, including high-frequency utility functions, formatters, and renderers. This is a repository-wide policy to maintain consistency and avoid making case-by-case judgment calls about which functions should have profiling.

Applied to files:

  • pkg/list/extract/workflows.go
  • cmd/list/components.go
  • pkg/list/importresolver/provenance.go
  • pkg/list/extract/components.go
📚 Learning: 2025-10-13T18:13:54.020Z
Learnt from: aknysh
Repo: cloudposse/atmos PR: 1622
File: pkg/perf/perf.go:140-184
Timestamp: 2025-10-13T18:13:54.020Z
Learning: In pkg/perf/perf.go, the `trackWithSimpleStack` function intentionally skips ownership checks at call stack depth > 1 to avoid expensive `getGoroutineID()` calls on every nested function. This is a performance optimization for the common single-goroutine execution case (most Atmos commands), accepting the rare edge case of potential metric corruption if multi-goroutine execution occurs at depth > 1. The ~19× performance improvement justifies this trade-off.

Applied to files:

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

Applied to files:

  • pkg/list/extract/workflows.go
  • pkg/list/importresolver/provenance.go
  • pkg/list/extract/components.go
📚 Learning: 2025-09-29T02:20:11.636Z
Learnt from: aknysh
Repo: cloudposse/atmos PR: 1540
File: internal/exec/validate_component.go:117-118
Timestamp: 2025-09-29T02:20:11.636Z
Learning: The ValidateComponent function in internal/exec/validate_component.go had its componentSection parameter type refined from `any` to `map[string]any` without adding new parameters. This is a type safety improvement, not a signature change requiring call site updates.

Applied to files:

  • cmd/list/components.go
  • pkg/list/extract/components.go
  • cmd/list/components_test.go
📚 Learning: 2024-12-08T14:26:16.972Z
Learnt from: pkbhowmick
Repo: cloudposse/atmos PR: 828
File: pkg/schema/schema.go:98-100
Timestamp: 2024-12-08T14:26:16.972Z
Learning: The `ListConfig` columns array in the `Components` struct can be empty.

Applied to files:

  • cmd/list/components.go
  • cmd/list/vendor.go
  • cmd/list/components_test.go
📚 Learning: 2024-12-07T16:16:13.038Z
Learnt from: Listener430
Repo: cloudposse/atmos PR: 825
File: internal/exec/helmfile_generate_varfile.go:28-31
Timestamp: 2024-12-07T16:16:13.038Z
Learning: In `internal/exec/helmfile_generate_varfile.go`, the `--help` command (`./atmos helmfile generate varfile --help`) works correctly without requiring stack configurations, and the only change needed was to make `ProcessCommandLineArgs` exportable by capitalizing its name.

Applied to files:

  • cmd/list/components.go
  • cmd/list/vendor.go
📚 Learning: 2025-01-09T22:37:01.004Z
Learnt from: samtholiya
Repo: cloudposse/atmos PR: 914
File: cmd/terraform_commands.go:260-265
Timestamp: 2025-01-09T22:37:01.004Z
Learning: In the terraform commands implementation (cmd/terraform_commands.go), the direct use of `os.Args[2:]` for argument handling is intentionally preserved to avoid extensive refactoring. While it could be improved to use cobra's argument parsing, such changes should be handled in a dedicated PR to maintain focus and minimize risk.

Applied to files:

  • cmd/list/components.go
📚 Learning: 2025-10-10T23:51:36.597Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 1599
File: internal/exec/terraform.go:394-402
Timestamp: 2025-10-10T23:51:36.597Z
Learning: In Atmos (internal/exec/terraform.go), when adding OpenTofu-specific flags like `--var-file` for `init`, do not gate them based on command name (e.g., checking if `info.Command == "tofu"` or `info.Command == "opentofu"`) because command names don't reliably indicate the actual binary being executed (symlinks, aliases). Instead, document the OpenTofu requirement in code comments and documentation, trusting users who enable the feature (e.g., `PassVars`) to ensure their terraform command points to an OpenTofu binary.

Applied to files:

  • cmd/list/components.go
  • cmd/list/vendor.go
📚 Learning: 2025-01-07T20:38:09.618Z
Learnt from: samtholiya
Repo: cloudposse/atmos PR: 896
File: cmd/editor_config.go:37-40
Timestamp: 2025-01-07T20:38:09.618Z
Learning: Error handling suggestion for `cmd.Help()` in `cmd/editor_config.go` was deferred as the code is planned for future modifications.

Applied to files:

  • cmd/list/components.go
📚 Learning: 2025-06-07T19:28:21.289Z
Learnt from: samtholiya
Repo: cloudposse/atmos PR: 1266
File: cmd/describe_affected.go:0-0
Timestamp: 2025-06-07T19:28:21.289Z
Learning: In the Atmos codebase, using panic for unsupported flag types in flag processing functions like setDescribeAffectedFlagValueInCliArgs is the expected behavior rather than returning errors. This pattern is preferred for developer errors when unsupported types are added to the flagsKeyValue map.

Applied to files:

  • cmd/list/components.go
📚 Learning: 2025-11-10T03:03:31.505Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 0
File: :0-0
Timestamp: 2025-11-10T03:03:31.505Z
Learning: In the Atmos codebase, commands using the `StandardParser` flag pattern (from pkg/flags) do NOT need explicit `viper.BindPFlag()` calls in their code. The StandardParser encapsulates flag binding internally: flags are registered via `parser.RegisterFlags(cmd)` in init(), and bound via `parser.BindFlagsToViper(cmd, v)` in RunE, which internally calls viper.BindPFlag for each flag. This pattern is used throughout Atmos (e.g., cmd/toolchain/get.go, cmd/toolchain/info.go, cmd/toolchain/install.go, cmd/toolchain/path.go). Do not flag missing viper.BindPFlag calls when StandardParser is used.

Applied to files:

  • cmd/list/components.go
📚 Learning: 2025-02-19T05:50:35.853Z
Learnt from: samtholiya
Repo: cloudposse/atmos PR: 1068
File: tests/snapshots/TestCLICommands_atmos_terraform_apply_--help.stdout.golden:0-0
Timestamp: 2025-02-19T05:50:35.853Z
Learning: Backtick formatting should only be applied to flag descriptions in Go source files, not in golden test files (test snapshots) as they are meant to capture the raw command output.

Applied to files:

  • cmd/list/components.go
📚 Learning: 2025-02-18T13:18:53.146Z
Learnt from: samtholiya
Repo: cloudposse/atmos PR: 1068
File: cmd/vendor_pull.go:31-31
Timestamp: 2025-02-18T13:18:53.146Z
Learning: Error checking is not required for cobra.Command.RegisterFlagCompletionFunc calls as these are static configurations done at init time.

Applied to files:

  • cmd/list/components.go
  • cmd/list/components_test.go
📚 Learning: 2024-12-02T21:26:32.337Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 808
File: pkg/config/config.go:478-483
Timestamp: 2024-12-02T21:26:32.337Z
Learning: In the 'atmos' project, when reviewing Go code like `pkg/config/config.go`, avoid suggesting file size checks after downloading remote configs if such checks aren't implemented elsewhere in the codebase.

Applied to files:

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

Applied to files:

  • pkg/list/importresolver/provenance.go
📚 Learning: 2025-04-04T02:03:23.676Z
Learnt from: aknysh
Repo: cloudposse/atmos PR: 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:

  • pkg/list/importresolver/provenance.go
📚 Learning: 2025-09-10T21:17:55.273Z
Learnt from: samtholiya
Repo: cloudposse/atmos PR: 1466
File: toolchain/http_client_test.go:3-10
Timestamp: 2025-09-10T21:17:55.273Z
Learning: In the cloudposse/atmos repository, imports should never be changed as per samtholiya's coding guidelines.

Applied to files:

  • pkg/list/importresolver/provenance.go
📚 Learning: 2024-11-13T21:37:07.852Z
Learnt from: Cerebrovinny
Repo: cloudposse/atmos PR: 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:

  • pkg/list/importresolver/provenance.go
  • cmd/list/vendor.go
📚 Learning: 2024-10-28T01:51:30.811Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 727
File: internal/exec/terraform_clean.go:329-332
Timestamp: 2024-10-28T01:51:30.811Z
Learning: In the Atmos Go code, when deleting directories or handling file paths (e.g., in `terraform_clean.go`), always resolve the absolute path using `filepath.Abs` and use the logger `u.LogWarning` for logging messages instead of using `fmt.Printf`.

Applied to files:

  • pkg/list/importresolver/provenance.go
📚 Learning: 2025-09-24T20:45:40.401Z
Learnt from: Benbentwo
Repo: cloudposse/atmos PR: 1475
File: tests/fixtures/scenarios/atmos-auth/stacks/deploy/nonprod.yaml:3-4
Timestamp: 2025-09-24T20:45:40.401Z
Learning: In Atmos stack files, the correct syntax for importing other stack files is `import:` (singular), not `imports:` (plural). All stack files in the Atmos codebase consistently use `import:` followed by a list of paths to import.

Applied to files:

  • pkg/list/importresolver/provenance.go
📚 Learning: 2025-10-16T05:26:31.892Z
Learnt from: aknysh
Repo: cloudposse/atmos PR: 1639
File: pkg/merge/merge.go:392-430
Timestamp: 2025-10-16T05:26:31.892Z
Learning: In Atmos merge operations (pkg/merge/merge.go), context.Positions is a PositionMap (map[string]*schema.Position) keyed by JSONPath strings, not a slice indexed by input array position. Position lookups are path-based, making them independent of input array reorganization or filtering. This design allows filtering empty inputs without affecting provenance tracking correctness.

Applied to files:

  • pkg/list/importresolver/provenance.go
📚 Learning: 2024-12-07T16:19:01.683Z
Learnt from: aknysh
Repo: cloudposse/atmos PR: 825
File: internal/exec/terraform.go:30-30
Timestamp: 2024-12-07T16:19:01.683Z
Learning: In `internal/exec/terraform.go`, skipping stack validation when help flags are present is not necessary.

Applied to files:

  • cmd/list/vendor.go
📚 Learning: 2025-02-20T13:57:36.326Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 1036
File: cmd/list_settings.go:46-50
Timestamp: 2025-02-20T13:57:36.326Z
Learning: The max-columns flag in Atmos list commands supports -1 for unlimited width, which bypasses terminal width restrictions and may require horizontal scrolling. The default is 10 columns if not specified.

Applied to files:

  • cmd/list/vendor.go
📚 Learning: 2024-11-01T15:44:12.617Z
Learnt from: RoseSecurity
Repo: cloudposse/atmos PR: 757
File: cmd/docs.go:42-59
Timestamp: 2024-11-01T15:44:12.617Z
Learning: In `cmd/docs.go`, when implementing width detection for the `docsCmd` command, it's acceptable to keep the code inline without extracting it into a separate function, as per the user's preference for compact readability and maintainability in Go code.

Applied to files:

  • cmd/list/vendor.go
📚 Learning: 2024-10-22T23:00:20.627Z
Learnt from: Cerebrovinny
Repo: cloudposse/atmos PR: 737
File: internal/exec/vendor_utils.go:131-141
Timestamp: 2024-10-22T23:00:20.627Z
Learning: In the `ReadAndProcessVendorConfigFile` function in `internal/exec/vendor_utils.go`, the existence of the vendor config file is already checked, so additional file existence checks may be unnecessary.

Applied to files:

  • cmd/list/vendor.go
📚 Learning: 2025-06-23T02:14:30.937Z
Learnt from: aknysh
Repo: cloudposse/atmos PR: 1327
File: cmd/terraform.go:111-117
Timestamp: 2025-06-23T02:14:30.937Z
Learning: In cmd/terraform.go, flags for the DescribeAffected function are added dynamically at runtime when info.Affected is true. This is intentional to avoid exposing internal flags like "file", "format", "verbose", "include-spacelift-admin-stacks", "include-settings", and "upload" in the terraform command interface, while still providing them for the shared DescribeAffected function used by both `atmos describe affected` and `atmos terraform apply --affected`.

Applied to files:

  • cmd/list/vendor.go
📚 Learning: 2025-01-09T22:27:25.538Z
Learnt from: samtholiya
Repo: cloudposse/atmos PR: 914
File: cmd/validate_stacks.go:20-23
Timestamp: 2025-01-09T22:27:25.538Z
Learning: The validate commands in Atmos can have different help handling implementations. Specifically, validate_component.go and validate_stacks.go are designed to handle help requests differently, with validate_stacks.go including positional argument checks while validate_component.go does not.

Applied to files:

  • cmd/list/vendor.go
📚 Learning: 2024-10-30T13:25:45.965Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 727
File: internal/exec/terraform_clean.go:405-412
Timestamp: 2024-10-30T13:25:45.965Z
Learning: In `internal/exec/terraform_clean.go`, when appending `stackFolders` to `folders` in the `handleCleanSubCommand` function, it's unnecessary to check if `stackFolders` is nil before appending, because in Go, appending a nil slice is safe and does not cause a panic.

Applied to files:

  • cmd/list/vendor.go
📚 Learning: 2025-10-08T06:48:07.499Z
Learnt from: aknysh
Repo: cloudposse/atmos PR: 1602
File: internal/exec/stack_processor_utils.go:968-1003
Timestamp: 2025-10-08T06:48:07.499Z
Learning: The `FindComponentDependenciesLegacy` function in `internal/exec/stack_processor_utils.go` is legacy code that is not actively used and is kept only for backward compatibility purposes.

Applied to files:

  • pkg/list/extract/components.go
📚 Learning: 2025-04-11T22:06:46.999Z
Learnt from: samtholiya
Repo: cloudposse/atmos PR: 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:

  • cmd/list/components_test.go
📚 Learning: 2025-02-09T14:38:53.443Z
Learnt from: samtholiya
Repo: cloudposse/atmos PR: 992
File: cmd/cmd_utils.go:0-0
Timestamp: 2025-02-09T14:38:53.443Z
Learning: Error handling for RegisterFlagCompletionFunc in AddStackCompletion is not required as the errors are non-critical for tab completion functionality.

Applied to files:

  • cmd/list/components_test.go
🧬 Code graph analysis (3)
pkg/list/extract/workflows.go (4)
pkg/perf/perf.go (1)
  • Track (121-138)
pkg/utils/file_utils.go (3)
  • IsYaml (48-59)
  • IsPathAbsolute (100-102)
  • GetAllYamlFilesInDir (238-255)
errors/errors.go (2)
  • ErrParseFile (19-19)
  • ErrWorkflowDirectoryDoesNotExist (405-405)
pkg/schema/workflow.go (1)
  • WorkflowManifest (24-28)
pkg/list/importresolver/provenance.go (4)
pkg/list/tree/types.go (1)
  • ImportNode (4-9)
pkg/perf/perf.go (1)
  • Track (121-138)
internal/exec/stack_processor_utils.go (1)
  • GetAllMergeContexts (84-96)
pkg/logger/log.go (1)
  • Trace (14-16)
pkg/list/extract/components.go (3)
pkg/schema/schema.go (1)
  • Components (404-417)
pkg/perf/perf.go (1)
  • Track (121-138)
errors/errors.go (4)
  • ErrStackNotFound (419-419)
  • ErrParseStacks (415-415)
  • ErrParseComponents (416-416)
  • ErrNoComponentsFound (417-417)
⏰ Context from checks skipped due to timeout of 900000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
  • GitHub Check: Acceptance Tests (macos)
  • GitHub Check: Acceptance Tests (windows)
  • GitHub Check: Summary
🔇 Additional comments (4)
pkg/list/importresolver/provenance.go (3)

33-101: Import tree resolution logic is solid.

The provenance-based resolution correctly handles circular imports with backtracking, implements per-call caching to optimize repeated file reads, and properly attaches component folder metadata to first-level import nodes. The fixed relative path handling (using parent directory for paths starting with ".") aligns with standard Atmos import semantics.

Also applies to: 273-315, 371-407


107-187: File path matching handles multiple representations correctly.

The multi-strategy approach (absolute, relative, extension-agnostic) at lines 172-176 provides good flexibility for matching atmos_stack_file values that may be stored in different formats. The normalization and type-safety checks throughout are appropriate.


240-271: Function is actively tested—no removal needed.

The search shows extractComponentsFromStackData is called in pkg/list/importresolver/provenance_test.go:353. It has dedicated test coverage and proper instrumentation. No changes required.

Likely an incorrect or invalid review comment.

pkg/list/extract/workflows.go (1)

21-22: Performance tracking properly implemented.

Both entry points now have perf.Track instrumentation as requested in the previous review. The use of atmosConfig in Workflows and nil in extractFromManifest is appropriate given their respective signatures.

Also applies to: 98-99

@osterman
Copy link
Member Author

@coderabbitai full review

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Nov 23, 2025

✅ Actions performed

Full review triggered.

Add perf.Track instrumentation to all helper functions in vendor command
and list extract packages to satisfy repository performance tracking policy.

Changes:
- cmd/list/vendor.go: Add perf tracking to columnsCompletionForVendor,
  listVendorWithOptions, buildVendorFilters, getVendorColumns, and
  buildVendorSorters functions
- pkg/list/extract/components.go: Add perf tracking to buildBaseComponent,
  extractMetadataFields, setDefaultMetadataFields, getBoolWithDefault,
  and getStringWithDefault helper functions
- pkg/list/extract/workflows.go: Fix cleanPath usage to ensure normalized
  path is used consistently for all file operations and error messages
- pkg/list/importresolver/provenance.go: Add perf tracking to stripBasePath
  function

All functions now have defer perf.Track(nil, "package.functionName")()
as the first statement, matching the repository's mandatory performance
tracking pattern.

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

Co-Authored-By: Claude <[email protected]>
The stripBasePath function was removing file extensions before converting
path separators to forward slashes, which caused inconsistent behavior
across different operating systems.

Changes:
- Reorder operations to convert to forward slashes first (via filepath.ToSlash)
- Then remove .yaml/.yml extensions using string literals instead of constants
- This ensures consistent relative, extensionless paths regardless of OS

The fix ensures that stripBasePath returns paths like "catalog/base" rather
than OS-specific separator formats, making the import tree rendering consistent
across Windows, macOS, and Linux.

All tests now pass, including TestStripBasePath which validates:
- Simple paths
- Paths with trailing slashes
- Both .yaml and .yml extensions
- Relative paths
- Nested directory structures

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

Co-Authored-By: Claude <[email protected]>
coderabbitai[bot]
coderabbitai bot previously approved these changes Nov 24, 2025
osterman and others added 2 commits November 23, 2025 20:27
…omponent

- Replace outdated `:::note Purpose` pattern in CLAUDE.md documentation template with modern `<Intro>` component
- Add Intro import to template example
- Update terminology from "purpose note" to "intro" for consistency
- Improve list-stacks intro to describe specific user actions (filtering, format options, understanding inheritance) instead of generic "list stacks"
- Follows pattern from auth commands: concrete actions users can accomplish

This fixes the root cause of documentation hallucinations where new docs were being written with deprecated :::note syntax.

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

Co-Authored-By: Claude <[email protected]>
Replace deprecated `:::note Purpose` admonitions with modern `<Intro>` component across all list command documentation files. Update intros to describe specific user actions and benefits following pattern from auth commands.

Changes:
- list-components.mdx: Add Intro describing filtering and output formats
- list-instances.mdx: Add Intro explaining component-stack combinations and Atmos Pro upload
- list-metadata.mdx: Add Intro about filtering and sorting metadata fields
- list-vendor.mdx: Add Intro describing vendor sources and dependencies
- themes.mdx: Add Intro about color schemes and syntax highlighting
- list-workflows.mdx: Add Intro, Screengrab, and description field
- list-settings.mdx: Add Intro about cross-stack comparison tables
- list-values.mdx: Add Intro about configuration value comparison
- list-vars.mdx: Add Intro about Terraform variable comparison

All intros now:
- Use action-oriented language (what users can accomplish)
- Describe specific capabilities (filtering, formats, comparison)
- Follow modern documentation pattern with <Intro> component
- Include Screengrab components where missing

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

Co-Authored-By: Claude <[email protected]>
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 (2)
pkg/list/extract/workflows.go (1)

72-78: Consider extracting path construction helper

The logic here duplicates lines 55-59. Both blocks check IsPathAbsolute and construct paths accordingly. A small helper function could reduce repetition:

func buildWorkflowPath(atmosConfig *schema.AtmosConfiguration, relPath string) string {
    if utils.IsPathAbsolute(atmosConfig.Workflows.BasePath) {
        return filepath.Join(atmosConfig.Workflows.BasePath, relPath)
    }
    return filepath.Join(atmosConfig.BasePath, atmosConfig.Workflows.BasePath, relPath)
}

Then both call sites become simpler. Optional cleanup—the current approach works fine.

pkg/list/importresolver/provenance.go (1)

346-371: Consider tracing YAML read/parse failures in resolveImportFileImports

Right now, any error from readImportsFromYAMLFile is silently treated as “no imports”, which can make it harder to debug missing branches in the provenance tree when a path is wrong or a file is malformed. A low-noise Trace log would help operators understand why parts of the tree disappear without impacting normal runs.

For example:

 func resolveImportFileImports(
   importFilePath string,
   atmosConfig *schema.AtmosConfiguration,
   visited map[string]bool,
   cache map[string][]string,
 ) []*tree.ImportNode {
@@
-  // Read imports from the file.
-  imports, err := readImportsFromYAMLFile(importFilePath)
-  if err != nil {
-    // File can't be read or has no imports.
-    return nil
-  }
+  // Read imports from the file.
+  imports, err := readImportsFromYAMLFile(importFilePath)
+  if err != nil {
+    // Trace-level log so provenance debugging can see why a branch is missing.
+    log.Trace("Failed to read imports from YAML file", "file", importFilePath, "error", err)
+    return nil
+  }
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between be74995 and 82ed911.

📒 Files selected for processing (5)
  • CLAUDE.md (4 hunks)
  • cmd/list/vendor.go (1 hunks)
  • pkg/list/extract/components.go (1 hunks)
  • pkg/list/extract/workflows.go (1 hunks)
  • pkg/list/importresolver/provenance.go (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • pkg/list/extract/components.go
🧰 Additional context used
🧠 Learnings (41)
📓 Common learnings
Learnt from: Listener430
Repo: cloudposse/atmos PR: 934
File: tests/fixtures/scenarios/docs-generate/README.md.gotmpl:99-118
Timestamp: 2025-01-25T03:51:57.689Z
Learning: For the cloudposse/atmos repository, changes to template contents should be handled in dedicated PRs and are typically considered out of scope for PRs focused on other objectives.
Learnt from: samtholiya
Repo: cloudposse/atmos PR: 1466
File: cmd/markdown/atmos_toolchain_aliases.md:2-4
Timestamp: 2025-09-13T16:39:20.007Z
Learning: In the cloudposse/atmos repository, CLI documentation files in cmd/markdown/ follow a specific format that uses " $ atmos command" (with leading space and dollar sign prompt) in code blocks. This is the established project convention and should not be changed to comply with standard markdownlint rules MD040 and MD014.
📚 Learning: 2025-06-02T14:12:02.710Z
Learnt from: milldr
Repo: cloudposse/atmos PR: 1229
File: internal/exec/workflow_test.go:0-0
Timestamp: 2025-06-02T14:12:02.710Z
Learning: In the atmos codebase, workflow error handling was refactored to use `PrintErrorMarkdown` followed by returning specific error variables (like `ErrWorkflowNoSteps`, `ErrInvalidFromStep`, `ErrInvalidWorkflowStepType`, `ErrWorkflowStepFailed`) instead of `PrintErrorMarkdownAndExit`. This pattern allows proper error testing without the function terminating the process with `os.Exit`, enabling unit tests to assert on error conditions while maintaining excellent user-facing error formatting.

Applied to files:

  • pkg/list/extract/workflows.go
📚 Learning: 2025-07-05T20:59:02.914Z
Learnt from: aknysh
Repo: cloudposse/atmos PR: 1363
File: internal/exec/template_utils.go:18-18
Timestamp: 2025-07-05T20:59:02.914Z
Learning: In the Atmos project, gomplate v4 is imported with a blank import (`_ "github.com/hairyhenderson/gomplate/v4"`) alongside v3 imports to resolve AWS SDK version conflicts. V3 uses older AWS SDK versions that conflict with newer AWS modules used by Atmos. A full migration to v4 requires extensive refactoring due to API changes and should be handled in a separate PR.

Applied to files:

  • pkg/list/extract/workflows.go
  • pkg/list/importresolver/provenance.go
📚 Learning: 2024-11-19T23:00:45.899Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 795
File: internal/exec/stack_processor_utils.go:378-386
Timestamp: 2024-11-19T23:00:45.899Z
Learning: In the `ProcessYAMLConfigFile` function within `internal/exec/stack_processor_utils.go`, directory traversal in stack imports is acceptable and should not be restricted.

Applied to files:

  • pkg/list/extract/workflows.go
  • pkg/list/importresolver/provenance.go
  • cmd/list/vendor.go
📚 Learning: 2025-11-09T19:06:58.470Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 1752
File: pkg/profile/list/formatter_table.go:27-29
Timestamp: 2025-11-09T19:06:58.470Z
Learning: In the cloudposse/atmos repository, performance tracking with `defer perf.Track()` is enforced on all functions via linting, including high-frequency utility functions, formatters, and renderers. This is a repository-wide policy to maintain consistency and avoid making case-by-case judgment calls about which functions should have profiling.

Applied to files:

  • pkg/list/extract/workflows.go
  • pkg/list/importresolver/provenance.go
  • cmd/list/vendor.go
📚 Learning: 2025-10-13T18:13:54.020Z
Learnt from: aknysh
Repo: cloudposse/atmos PR: 1622
File: pkg/perf/perf.go:140-184
Timestamp: 2025-10-13T18:13:54.020Z
Learning: In pkg/perf/perf.go, the `trackWithSimpleStack` function intentionally skips ownership checks at call stack depth > 1 to avoid expensive `getGoroutineID()` calls on every nested function. This is a performance optimization for the common single-goroutine execution case (most Atmos commands), accepting the rare edge case of potential metric corruption if multi-goroutine execution occurs at depth > 1. The ~19× performance improvement justifies this trade-off.

Applied to files:

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

Applied to files:

  • pkg/list/extract/workflows.go
  • pkg/list/importresolver/provenance.go
📚 Learning: 2024-10-28T01:51:30.811Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 727
File: internal/exec/terraform_clean.go:329-332
Timestamp: 2024-10-28T01:51:30.811Z
Learning: In the Atmos Go code, when deleting directories or handling file paths (e.g., in `terraform_clean.go`), always resolve the absolute path using `filepath.Abs` and use the logger `u.LogWarning` for logging messages instead of using `fmt.Printf`.

Applied to files:

  • pkg/list/extract/workflows.go
  • pkg/list/importresolver/provenance.go
📚 Learning: 2024-11-02T15:35:09.958Z
Learnt from: aknysh
Repo: cloudposse/atmos PR: 759
File: internal/exec/terraform.go:366-368
Timestamp: 2024-11-02T15:35:09.958Z
Learning: In `internal/exec/terraform.go`, the workspace cleaning code under both the general execution path and within the `case "init":` block is intentionally duplicated because the code execution paths are different. The `.terraform/environment` file should be deleted before executing `terraform init` in both scenarios to ensure a clean state.

Applied to files:

  • pkg/list/extract/workflows.go
📚 Learning: 2025-04-26T15:54:10.506Z
Learnt from: haitham911
Repo: cloudposse/atmos PR: 1195
File: internal/exec/terraform_clean.go:99-99
Timestamp: 2025-04-26T15:54:10.506Z
Learning: The error variable `ErrRelPath` is defined in `internal/exec/terraform_clean_util.go` and is used across files in the `exec` package, including in `terraform_clean.go`. This is part of an approach to standardize error handling in the codebase.

Applied to files:

  • pkg/list/extract/workflows.go
📚 Learning: 2024-10-27T04:41:49.199Z
Learnt from: haitham911
Repo: cloudposse/atmos PR: 727
File: internal/exec/terraform_clean.go:215-223
Timestamp: 2024-10-27T04:41:49.199Z
Learning: In `internal/exec/terraform_clean.go`, the function `determineCleanPath` is necessary and should not be removed.

Applied to files:

  • pkg/list/extract/workflows.go
📚 Learning: 2024-12-25T20:28:47.526Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 887
File: internal/exec/stack_processor_utils.go:380-380
Timestamp: 2024-12-25T20:28:47.526Z
Learning: Windows path handling often requires `filepath.Join` to ensure correct separators and comparisons. Insufficient tests can break cross-platform compatibility, so migrating from `path.Join` to `filepath.Join` needs thorough testing on Windows before merging.

Applied to files:

  • pkg/list/extract/workflows.go
📚 Learning: 2024-12-25T20:28:19.618Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 887
File: internal/exec/workflow_utils.go:167-169
Timestamp: 2024-12-25T20:28:19.618Z
Learning: The user plans to revert the change from `path.Join` to `filepath.Join` in this PR due to testing gaps and will open a new PR to safely handle the migration without breaking `main`.

Applied to files:

  • pkg/list/extract/workflows.go
📚 Learning: 2024-11-12T03:16:02.910Z
Learnt from: aknysh
Repo: cloudposse/atmos PR: 775
File: internal/exec/template_funcs_component.go:157-159
Timestamp: 2024-11-12T03:16:02.910Z
Learning: In the Go code for `componentFunc` in `internal/exec/template_funcs_component.go`, the function `cleanTerraformWorkspace` does not return errors, and it's acceptable if the file does not exist. Therefore, error handling for `cleanTerraformWorkspace` is not needed.

Applied to files:

  • pkg/list/extract/workflows.go
📚 Learning: 2024-12-02T21:26:32.337Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 808
File: pkg/config/config.go:478-483
Timestamp: 2024-12-02T21:26:32.337Z
Learning: In the 'atmos' project, when reviewing Go code like `pkg/config/config.go`, avoid suggesting file size checks after downloading remote configs if such checks aren't implemented elsewhere in the codebase.

Applied to files:

  • pkg/list/extract/workflows.go
  • pkg/list/importresolver/provenance.go
  • cmd/list/vendor.go
📚 Learning: 2025-11-07T14:52:55.217Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 1761
File: docs/prd/claude-agent-architecture.md:331-439
Timestamp: 2025-11-07T14:52:55.217Z
Learning: In the cloudposse/atmos repository, Claude agents are used as interactive tools, not in automated/headless CI/CD contexts. Agent documentation and patterns should assume synchronous human interaction.

Applied to files:

  • CLAUDE.md
📚 Learning: 2024-10-31T19:25:41.298Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 727
File: internal/exec/terraform_clean.go:233-235
Timestamp: 2024-10-31T19:25:41.298Z
Learning: When specifying color values in functions like `confirmDeleteTerraformLocal` in `internal/exec/terraform_clean.go`, avoid hardcoding color values. Instead, use predefined color constants or allow customization through configuration settings to improve accessibility and user experience across different terminals and themes.

Applied to files:

  • CLAUDE.md
📚 Learning: 2024-11-10T19:28:17.365Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 768
File: internal/exec/vendor_utils.go:0-0
Timestamp: 2024-11-10T19:28:17.365Z
Learning: When TTY is not supported, log the downgrade message at the Warn level using `u.LogWarning(cliConfig, ...)` instead of `fmt.Println`.

Applied to files:

  • CLAUDE.md
📚 Learning: 2025-09-13T18:06:07.674Z
Learnt from: samtholiya
Repo: cloudposse/atmos PR: 1466
File: toolchain/list.go:39-42
Timestamp: 2025-09-13T18:06:07.674Z
Learning: In the cloudposse/atmos repository, for UI messages in the toolchain package, use utils.PrintfMessageToTUI instead of log.Error or fmt.Fprintln(os.Stderr, ...). Import pkg/utils with alias "u" to follow the established pattern.

Applied to files:

  • CLAUDE.md
📚 Learning: 2024-11-01T14:45:32.417Z
Learnt from: RoseSecurity
Repo: cloudposse/atmos PR: 757
File: cmd/docs.go:52-54
Timestamp: 2024-11-01T14:45:32.417Z
Learning: In `cmd/docs.go`, capping the terminal width at 120 columns is considered acceptable and preferred after testing.

Applied to files:

  • CLAUDE.md
📚 Learning: 2025-10-11T19:11:58.965Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 1599
File: internal/exec/terraform.go:0-0
Timestamp: 2025-10-11T19:11:58.965Z
Learning: For terraform apply interactivity checks in Atmos (internal/exec/terraform.go), use stdin TTY detection (e.g., `IsTTYSupportForStdin()` or checking `os.Stdin`) to determine if user prompts are possible. This is distinct from stdout/stderr TTY checks used for output display (like TUI rendering). User input requires stdin to be a TTY; output display requires stdout/stderr to be a TTY.

Applied to files:

  • CLAUDE.md
📚 Learning: 2024-11-10T18:37:10.032Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 768
File: internal/exec/vendor_component_utils.go:354-360
Timestamp: 2024-11-10T18:37:10.032Z
Learning: In the vendoring process, a TTY can exist without being interactive. If the process does not prompt the user, we should not require interactive mode to display the TUI. The `CheckTTYSupport` function should check TTY support on stdout rather than stdin.

Applied to files:

  • CLAUDE.md
📚 Learning: 2025-10-14T01:54:48.410Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 1498
File: website/src/components/Screengrabs/atmos-completion--help.html:2-7
Timestamp: 2025-10-14T01:54:48.410Z
Learning: Screengrab HTML files in website/src/components/Screengrabs/ are generated from actual Atmos CLI output converted to HTML. The ANSI-art headers and formatting in these files are intentional and reflect the real CLI user experience, so they should not be suggested for removal or modification.

Applied to files:

  • CLAUDE.md
📚 Learning: 2025-09-13T16:39:20.007Z
Learnt from: samtholiya
Repo: cloudposse/atmos PR: 1466
File: cmd/markdown/atmos_toolchain_aliases.md:2-4
Timestamp: 2025-09-13T16:39:20.007Z
Learning: In the cloudposse/atmos repository, CLI documentation files in cmd/markdown/ follow a specific format that uses " $ atmos command" (with leading space and dollar sign prompt) in code blocks. This is the established project convention and should not be changed to comply with standard markdownlint rules MD040 and MD014.

Applied to files:

  • CLAUDE.md
📚 Learning: 2025-10-07T00:25:16.333Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 1498
File: website/src/components/Screengrabs/atmos-terraform-metadata--help.html:25-55
Timestamp: 2025-10-07T00:25:16.333Z
Learning: In Atmos CLI, subcommands inherit flags from their parent commands via Cobra's command inheritance. For example, `atmos terraform metadata --help` shows `--affected` and related flags inherited from the parent `terraform` command (defined in cmd/terraform.go), even though the metadata subcommand doesn't explicitly define these flags. This is expected Cobra behavior and auto-generated help screengrabs accurately reflect this inheritance.

Applied to files:

  • CLAUDE.md
📚 Learning: 2025-01-19T15:49:15.593Z
Learnt from: samtholiya
Repo: cloudposse/atmos PR: 955
File: tests/snapshots/TestCLICommands_atmos_validate_editorconfig_--help.stdout.golden:0-0
Timestamp: 2025-01-19T15:49:15.593Z
Learning: In future commits, the help text for Atmos CLI commands should be limited to only show component and stack parameters for commands that actually use them. This applies to the example usage section in command help text.

Applied to files:

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

Applied to files:

  • pkg/list/importresolver/provenance.go
📚 Learning: 2025-09-10T21:17:55.273Z
Learnt from: samtholiya
Repo: cloudposse/atmos PR: 1466
File: toolchain/http_client_test.go:3-10
Timestamp: 2025-09-10T21:17:55.273Z
Learning: In the cloudposse/atmos repository, imports should never be changed as per samtholiya's coding guidelines.

Applied to files:

  • pkg/list/importresolver/provenance.go
📚 Learning: 2025-04-04T02:03:23.676Z
Learnt from: aknysh
Repo: cloudposse/atmos PR: 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:

  • pkg/list/importresolver/provenance.go
📚 Learning: 2024-11-13T21:37:07.852Z
Learnt from: Cerebrovinny
Repo: cloudposse/atmos PR: 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:

  • pkg/list/importresolver/provenance.go
  • cmd/list/vendor.go
📚 Learning: 2025-09-24T20:45:40.401Z
Learnt from: Benbentwo
Repo: cloudposse/atmos PR: 1475
File: tests/fixtures/scenarios/atmos-auth/stacks/deploy/nonprod.yaml:3-4
Timestamp: 2025-09-24T20:45:40.401Z
Learning: In Atmos stack files, the correct syntax for importing other stack files is `import:` (singular), not `imports:` (plural). All stack files in the Atmos codebase consistently use `import:` followed by a list of paths to import.

Applied to files:

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

Applied to files:

  • pkg/list/importresolver/provenance.go
📚 Learning: 2025-01-17T00:18:57.769Z
Learnt from: aknysh
Repo: cloudposse/atmos PR: 944
File: go.mod:206-206
Timestamp: 2025-01-17T00:18:57.769Z
Learning: For indirect dependencies with license compliance issues in the cloudposse/atmos repository, the team prefers to handle them in follow-up PRs rather than blocking the current changes, as these issues often require deeper investigation of the dependency tree.

Applied to files:

  • pkg/list/importresolver/provenance.go
📚 Learning: 2025-10-16T05:26:31.892Z
Learnt from: aknysh
Repo: cloudposse/atmos PR: 1639
File: pkg/merge/merge.go:392-430
Timestamp: 2025-10-16T05:26:31.892Z
Learning: In Atmos merge operations (pkg/merge/merge.go), context.Positions is a PositionMap (map[string]*schema.Position) keyed by JSONPath strings, not a slice indexed by input array position. Position lookups are path-based, making them independent of input array reorganization or filtering. This design allows filtering empty inputs without affecting provenance tracking correctness.

Applied to files:

  • pkg/list/importresolver/provenance.go
📚 Learning: 2024-12-07T16:16:13.038Z
Learnt from: Listener430
Repo: cloudposse/atmos PR: 825
File: internal/exec/helmfile_generate_varfile.go:28-31
Timestamp: 2024-12-07T16:16:13.038Z
Learning: In `internal/exec/helmfile_generate_varfile.go`, the `--help` command (`./atmos helmfile generate varfile --help`) works correctly without requiring stack configurations, and the only change needed was to make `ProcessCommandLineArgs` exportable by capitalizing its name.

Applied to files:

  • cmd/list/vendor.go
📚 Learning: 2024-12-07T16:19:01.683Z
Learnt from: aknysh
Repo: cloudposse/atmos PR: 825
File: internal/exec/terraform.go:30-30
Timestamp: 2024-12-07T16:19:01.683Z
Learning: In `internal/exec/terraform.go`, skipping stack validation when help flags are present is not necessary.

Applied to files:

  • cmd/list/vendor.go
📚 Learning: 2025-10-10T23:51:36.597Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 1599
File: internal/exec/terraform.go:394-402
Timestamp: 2025-10-10T23:51:36.597Z
Learning: In Atmos (internal/exec/terraform.go), when adding OpenTofu-specific flags like `--var-file` for `init`, do not gate them based on command name (e.g., checking if `info.Command == "tofu"` or `info.Command == "opentofu"`) because command names don't reliably indicate the actual binary being executed (symlinks, aliases). Instead, document the OpenTofu requirement in code comments and documentation, trusting users who enable the feature (e.g., `PassVars`) to ensure their terraform command points to an OpenTofu binary.

Applied to files:

  • cmd/list/vendor.go
📚 Learning: 2024-12-08T14:26:16.972Z
Learnt from: pkbhowmick
Repo: cloudposse/atmos PR: 828
File: pkg/schema/schema.go:98-100
Timestamp: 2024-12-08T14:26:16.972Z
Learning: The `ListConfig` columns array in the `Components` struct can be empty.

Applied to files:

  • cmd/list/vendor.go
📚 Learning: 2025-02-20T13:57:36.326Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 1036
File: cmd/list_settings.go:46-50
Timestamp: 2025-02-20T13:57:36.326Z
Learning: The max-columns flag in Atmos list commands supports -1 for unlimited width, which bypasses terminal width restrictions and may require horizontal scrolling. The default is 10 columns if not specified.

Applied to files:

  • cmd/list/vendor.go
📚 Learning: 2024-10-22T23:00:20.627Z
Learnt from: Cerebrovinny
Repo: cloudposse/atmos PR: 737
File: internal/exec/vendor_utils.go:131-141
Timestamp: 2024-10-22T23:00:20.627Z
Learning: In the `ReadAndProcessVendorConfigFile` function in `internal/exec/vendor_utils.go`, the existence of the vendor config file is already checked, so additional file existence checks may be unnecessary.

Applied to files:

  • cmd/list/vendor.go
📚 Learning: 2025-06-23T02:14:30.937Z
Learnt from: aknysh
Repo: cloudposse/atmos PR: 1327
File: cmd/terraform.go:111-117
Timestamp: 2025-06-23T02:14:30.937Z
Learning: In cmd/terraform.go, flags for the DescribeAffected function are added dynamically at runtime when info.Affected is true. This is intentional to avoid exposing internal flags like "file", "format", "verbose", "include-spacelift-admin-stacks", "include-settings", and "upload" in the terraform command interface, while still providing them for the shared DescribeAffected function used by both `atmos describe affected` and `atmos terraform apply --affected`.

Applied to files:

  • cmd/list/vendor.go
🧬 Code graph analysis (1)
cmd/list/vendor.go (11)
pkg/flags/standard_parser.go (1)
  • StandardParser (18-22)
pkg/flags/global_registry.go (1)
  • ParseGlobalFlags (33-74)
pkg/schema/schema.go (3)
  • ConfigAndStacksInfo (624-718)
  • Vendor (936-941)
  • AtmosConfiguration (53-94)
pkg/config/config.go (1)
  • InitCliConfig (28-67)
pkg/list/extract/vendor.go (1)
  • Vendor (24-44)
cmd/list/flag_wrappers.go (2)
  • NewListParser (304-315)
  • WithFormatFlag (32-40)
pkg/list/list_vendor.go (1)
  • GetVendorInfos (128-156)
pkg/list/column/column.go (2)
  • NewSelector (52-79)
  • Config (13-17)
pkg/list/renderer/renderer.go (1)
  • New (31-46)
pkg/list/output/output.go (1)
  • New (14-16)
pkg/list/sort/sort.go (4)
  • Sorter (35-39)
  • NewSorter (48-54)
  • Ascending (17-17)
  • ParseSortSpec (195-237)
🪛 LanguageTool
CLAUDE.md

[typographical] ~40-~40: Consider using a typographic close quote here.
Context: ...i-expert(terminal UI). Use Task tool:Task(subagent_type: "flag-handler", prompt: "...")`. Prevents incorrect patterns and ensu...

(EN_QUOTES)

⏰ Context from checks skipped due to timeout of 900000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (4)
  • GitHub Check: Acceptance Tests (macos)
  • GitHub Check: Acceptance Tests (linux)
  • GitHub Check: Acceptance Tests (windows)
  • GitHub Check: Summary
🔇 Additional comments (20)
CLAUDE.md (3)

39-40: Specialized Agents guidance is clear and actionable.

The new mandatory pattern for consulting specialized agents via the Task tool provides concrete direction. The specific mention of flag-handler aligns well with the PR's list command refactoring and prevents duplicated effort.


767-790: Intro component integration strengthens documentation consistency.

The addition of Intro component usage in the documentation template aligns the guidance with the PR's UI/messaging improvements across list commands. The example clearly shows the intended pattern, and the section ordering (Intro → Screengrab → Usage → Examples) reads naturally.


206-206: Benefits consolidation maintains substance while improving clarity.

Replacing the multi-block rationale with a single concise line ("Auto color/width degradation, TTY detection, secret masking, ...") preserves the key benefits without sacrificing readability. This is especially valuable in a document this size.

pkg/list/extract/workflows.go (2)

3-26: Clean structure and imports

The imports are correct, perf tracking is in place, and the linter suppressions are justified for the file handling complexity. Good start.


97-120: Solid extraction logic

The function is well-structured with perf tracking, nil-checking, and clear mapping from manifest to output format. Works as intended.

pkg/list/importresolver/provenance.go (9)

33-101: Provenance tree assembly and perf instrumentation look solid

The aggregation over merge contexts into map[stackName]map[componentName][]*tree.ImportNode is coherent, and the use of extractComponentFolders to attach ComponentFolder on the first node per component keeps rendering concerns nicely separated. perf.Track is wired in as per policy and there are no obvious correctness issues here.


107-187: Stack/file matching logic in findStacksForFilePath is thorough

The normalization plus multiple match strategies (absolute, relative, and extensionless) give this a good chance of matching atmos_stack_file values across common variants without overcomplicating things. The function is defensive around type assertions and keeps logging at Trace, which is appropriate.


191-238: Component folder derivation aligns with components/{type}/{folder} convention

Using metadata.component when present and falling back to the component name, then composing components/{type}/{folder}, matches Atmos’ component folder semantics and gives renderers the path they need without exposing the full stack structure.


241-271: extractComponentsFromStackData is a simple, reusable helper

This helper cleanly extracts component names across all types and is defensive on shapes. It’s a reasonable internal/test utility to keep component enumeration logic in one place.


273-315: ImportChain → tree conversion is cycle-safe and cached

buildImportTreeFromChain correctly skips the root stack entry, normalizes display paths via stripBasePath, and uses a visited set plus importCache to avoid infinite recursion and redundant file reads. The backtracking of visited per branch looks correct.


319-344: stripBasePath normalization and extension stripping are well-behaved

The combination of filepath.Rel with a TrimPrefix fallback, plus filepath.ToSlash and .yaml/.yml stripping, gives consistent, cross-platform, extensionless display paths. The added perf.Track keeps it aligned with repo profiling rules.


373-409: Child-node Path values intentionally preserve original import strings

Top-level nodes are normalized via stripBasePath, while child nodes use the raw importPath from YAML for Path. That gives users what they actually wrote in nested imports, at the expense of inconsistent normalization between levels. If that’s the intended UX for --provenance output, this implementation supports it cleanly.


411-439: Import path resolution correctly handles relative vs base-path imports

The split between ./..-prefixed paths resolved against parentFilePath and other imports resolved against StacksBaseAbsolutePath matches expected stack import semantics and keeps cycle detection keyed on absolute paths. Path cleaning and extension handling look correct, and directory traversal for legitimate .. imports is preserved as intended.
Based on learnings, directory traversal in stack imports is acceptable here.


441-492: YAML import extraction is flexible and defensive

readImportsFromYAMLFile plus extractImportStringsHelper handle both import and imports, and accept either a single string or a slice, returning an empty slice instead of nil when no imports are found. That makes the callers simpler and keeps provenance resolution tolerant of optional import fields. The perf tracking is in place on both helpers.

cmd/list/vendor.go (6)

68-91: LGTM!

Dynamic completion properly loads config and extracts vendor column names. Performance tracking is in place and error handling is graceful.


93-117: Clean flag setup with modular wrappers.

Flag configuration uses composable wrappers and properly registers completions and Viper bindings. Follows established patterns.


119-173: Solid renderer pipeline implementation.

The flow is clean: config → vendor data → filters/columns/sorters → renderer → output. Format fallback from config and graceful handling of empty vendors are good touches. Error handling is comprehensive.


175-191: Filter implementation correctly targets component field.

The filter logic and inline comment clearly document that --stack is applied to the "component" field (vendor rows don't contain stack context). This design was reviewed in past comments and accepted.


193-222: Column configuration properly preserves width settings.

Flag precedence is correct (flag → config → defaults), and the Width field is now carried through from atmos.yaml configuration as intended. Default columns align with vendor data structure.


224-236: Sorter configuration with sensible defaults.

Default sort by Component ascending is appropriate, and the implementation delegates to the shared ParseSortSpec validation. Clean and correct.

coderabbitai[bot]
coderabbitai bot previously approved these changes Nov 24, 2025
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 needs-cloudposse Needs Cloud Posse assistance size/xl Extra large size PR

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants