-
-
Notifications
You must be signed in to change notification settings - Fork 135
feat: Implement configurable output for list commands #1798
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
…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]>
📝 WalkthroughWalkthroughRefactors Atmos "list" commands into a unified, pipeline-driven system: new column templates, filters, sorters, renderer, provenance-driven import resolution, dynamic flag wrappers, and extensive tests/docs supporting configurable, multi-format list outputs. Changes
Sequence Diagram(s)sequenceDiagram
actor User
participant CLI as CLI Command
participant Parser as Flag Parser
participant Extract as Extractor
participant Filters as Filter Chain
participant Selector as Column Selector
participant Sorter as Sorters
participant Renderer as Renderer
participant Formatter as Formatter
participant Output as Output Manager
User->>CLI: run "atmos list instances --columns Stack,Comp --sort stack:asc"
CLI->>Parser: parse flags (NewListParser)
CLI->>Extract: extract instances (extract.Instances)
Extract-->>CLI: []map[string]any
CLI->>Filters: build/apply filters
Filters-->>CLI: filtered data
CLI->>Selector: select columns & compile templates
Selector-->>CLI: headers, rows
CLI->>Sorter: sort rows
Sorter-->>CLI: sorted rows
CLI->>Renderer: render(format)
Renderer->>Formatter: format(headers, rows)
Formatter-->>Renderer: formatted string
Renderer->>Output: write(formatted)
Output-->>User: stdout
sequenceDiagram
participant StackProc as ProcessYAMLConfigFileWithContext
participant MergeCtx as MergeContext
participant ProvResolver as ResolveImportTreeFromProvenance
participant ImportBuilder as buildImportTreeFromChain
participant Renderer as RenderStacksTree
StackProc->>MergeCtx: create and populate provenance data
StackProc-->>StackProc: return MergeContext
ProvResolver->>MergeCtx: read all merge contexts
ProvResolver->>ImportBuilder: build import tree per chain
ImportBuilder-->>ProvResolver: ImportNode trees
ProvResolver-->>Renderer: per-stack import trees
Renderer->>Renderer: render styled tree output
Estimated code review effort🎯 5 (Critical) | ⏱️ ~120 minutes Key areas that need careful review:
Possibly related PRs
Suggested reviewers
Pre-merge checks and finishing touches❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing touches
🧪 Generate unit tests (beta)
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. Comment |
|
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. |
Dependency Review✅ No vulnerabilities or license issues found.Scanned FilesNone |
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]>
|
Important Cloud Posse Engineering Team Review RequiredThis 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 |
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.)
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
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 11
♻️ Duplicate comments (1)
cmd/list/vendor.go (1)
145-171:--columnsfor vendor shares the same stub implementation
getVendorColumnsalso callsparseColumnsFlag(columnsFlag)when--columnsis set, but that helper is currently a TODO that always returns default columns. So for vendor:
--columns/ATMOS_LIST_COLUMNSdo not actually influence the output today.Once
parseColumnsFlagis 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
inheritscan be streamlined usingstrings.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
stringsif not already imported.pkg/list/list_metadata.go (1)
48-85: Consider adding filter and sort support.The renderer is created with
nilfilters 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 unusedenvVarName
TestFlagEnvironmentVariableBindingcurrently only asserts thatBindToVipersucceeds; theenvVarNamefield is never used, so the test doesn’t actually confirm the binding name.Either:
- Use
envVarName(e.g.,t.Setenv(tt.envVarName, "x"), callBindToViper, then assertv.GetString(tt.flagName) == "x"), or- Remove
envVarNamefrom the table to avoid implying stronger coverage than is present.pkg/list/extract_stacks.go (1)
9-73: Consider whether deterministic stack ordering is neededBoth extractors iterate over
stacksMapdirectly, 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 bystack), 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 helperMost tests duplicate the
NewContext/InitWriter/InitFormattersetup. Extracting a small helper likeinitTestRendererIO(t)would cut repetition and make future tweaks to the IO/UI wiring cheaper.pkg/list/extract_components.go (1)
9-17: Unused exportedComponentDatastruct
ComponentDataisn’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 assertingcomponent_typesemantics explicitlyThe 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
ingressinTestExtractComponents),comp["component_type"] == "abstract".- For a normal TF component,
comp["type"] == "terraform"andcomp["component_type"] == "real".That would make future refactors around
.typevs.component_typesafer.cmd/list/stacks.go (1)
29-31: Columns flag type vs parsing helper may not line up
StacksOptions.Columnsis astringpopulated viav.GetString("columns"), butWithColumnsFlagregisterscolumnsas aStringSliceflag. Depending on howStandardParserbinds to Viper,GetString("columns")may see something like"[stack,component]"rather than the rawstack,componentstring thatparseColumnsFlagexpects.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+parseColumnsFlagto work with[]string.Worth a quick manual check of
--columns stack,componentand the env var form to confirm the value that reachesparseColumnsFlag.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 availableThe “Available functions” list here is a subset of what
BuildColumnFuncMapexposes (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
formatDelimitedcurrently does a rawstrings.Joinfor 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 abytes.Bufferand returning the buffer string.cmd/list/components.go (1)
142-177: Revisit interaction betweentypeandabstractfilters
buildComponentFilterscurrently combines:
Typeflag →filter.NewColumnFilter("type", opts.Type)(default"real"fromWithTypeFlag), andAbstractflag → when!opts.Abstract, always addsfilter.NewColumnFilter("component_type", "real").This can make it hard to express some combinations:
- With no flags you filter on both
type=realandcomponent_type=real.- With
--abstractbut no explicit--type, you still filtertype=real, so abstract-only components may never show.- With
--type=allbut--abstractomitted, you still filtercomponent_typetoreal, so “all” doesn’t actually include abstract.Might be worth clarifying which field (
typevscomponent_type) is the canonical “real/abstract/all” dimension and simplifying defaults around that (e.g., letTypedefault to""and derive the “real-only by default” behavior solely fromAbstract).cmd/list/vendor.go (2)
130-143: Confirm intent of using--stackto glob on thecomponentfield
buildVendorFilterstreats the--stackflag 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 astackfield and the goal is to filter by component name, it might be clearer to either:
- Introduce a dedicated
--componentfilter for vendor, or- Rename/update the
--stackhelp 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 refactorAfter switching vendor listing to the renderer pipeline,
obfuscateHomeDirInOutput,shouldReplaceHomeDir, andisPathCharare 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
$HOMEin 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 casesThe 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 tostrings.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 wherecolIdx >= len(row)are effectively treated as “equal” to everything else (you always returnfalsefrom 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 solidThe 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 intendedenabled/lockeduse 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 contextRight now, templates are evaluated against the
map[string]anyproduced bybuildTemplateContext, and theTemplateContextstruct 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
TemplateContextuntil you actually switch to using it, or- Update
buildTemplateContextto construct and return aTemplateContext(plus maybe embedRawseparately) 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
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.
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]>
…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]>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
🧹 Nitpick comments (2)
pkg/list/extract/workflows.go (1)
72-78: Consider extracting path construction helperThe logic here duplicates lines 55-59. Both blocks check
IsPathAbsoluteand 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 inresolveImportFileImportsRight now, any error from
readImportsFromYAMLFileis 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-noiseTracelog 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.
📒 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.gopkg/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.gopkg/list/importresolver/provenance.gocmd/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.gopkg/list/importresolver/provenance.gocmd/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.gopkg/list/importresolver/provenance.gocmd/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.gopkg/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.gopkg/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.gopkg/list/importresolver/provenance.gocmd/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.gocmd/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-handleraligns 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 importsThe 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 logicThe 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 solidThe aggregation over merge contexts into
map[stackName]map[componentName][]*tree.ImportNodeis coherent, and the use ofextractComponentFoldersto attachComponentFolderon the first node per component keeps rendering concerns nicely separated.perf.Trackis wired in as per policy and there are no obvious correctness issues here.
107-187: Stack/file matching logic infindStacksForFilePathis thoroughThe normalization plus multiple match strategies (absolute, relative, and extensionless) give this a good chance of matching
atmos_stack_filevalues across common variants without overcomplicating things. The function is defensive around type assertions and keeps logging atTrace, which is appropriate.
191-238: Component folder derivation aligns with components/{type}/{folder} conventionUsing
metadata.componentwhen present and falling back to the component name, then composingcomponents/{type}/{folder}, matches Atmos’ component folder semantics and gives renderers the path they need without exposing the full stack structure.
241-271:extractComponentsFromStackDatais a simple, reusable helperThis 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
buildImportTreeFromChaincorrectly skips the root stack entry, normalizes display paths viastripBasePath, and uses avisitedset plusimportCacheto avoid infinite recursion and redundant file reads. The backtracking ofvisitedper branch looks correct.
319-344:stripBasePathnormalization and extension stripping are well-behavedThe combination of
filepath.Relwith a TrimPrefix fallback, plusfilepath.ToSlashand.yaml/.ymlstripping, gives consistent, cross-platform, extensionless display paths. The addedperf.Trackkeeps it aligned with repo profiling rules.
373-409: Child-nodePathvalues intentionally preserve original import stringsTop-level nodes are normalized via
stripBasePath, while child nodes use the rawimportPathfrom YAML forPath. 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--provenanceoutput, this implementation supports it cleanly.
411-439: Import path resolution correctly handles relative vs base-path importsThe split between
./..-prefixed paths resolved againstparentFilePathand other imports resolved againstStacksBaseAbsolutePathmatches 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
readImportsFromYAMLFileplusextractImportStringsHelperhandle bothimportandimports, and accept either a single string or a slice, returning an empty slice instead ofnilwhen 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
--stackis 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.yamlconfiguration 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
ParseSortSpecvalidation. Clean and correct.
Merged main branch changes including: - Authentication/identity support for list commands - Metadata inheritance feature (StacksInherit) - Devcontainer support - Various bug fixes and improvements Resolved conflicts by: - Keeping new list UI infrastructure (renderer, column selector, filters) - Integrating auth manager support via createAuthManagerForList helper - Merging Stacks schema to include both List and Inherit fields - Combining documentation flags from both branches 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]>
Remove the third argument (nil authManager) from all test calls since the function signature was simplified during the merge conflict resolution. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]>
…ommands During the merge conflict resolution, the authManager parameter was accidentally removed from processInstances and processInstancesWithDeps functions. This regression broke authentication support that was added on main branch. Changes: - Restore auth.AuthManager parameter to processInstancesWithDeps() - Restore auth.AuthManager parameter to processInstances() - Add AuthManager field to InstancesCommandOptions struct - Add AuthManager field to MetadataOptions struct - Update cmd/list/instances.go to create and pass authManager - Update cmd/list/metadata.go to create and pass authManager - Update ExecuteListInstancesCmd to use opts.AuthManager - Pass authManager to ExecuteDescribeStacks calls for both tree and non-tree formats - Update all tests to match new function signatures 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]>
…nance The second ExecuteDescribeStacks call in listStacksWithOptions was passing nil instead of authManager when re-processing stacks with provenance tracking enabled. This would cause authentication to fail for stacks using YAML template functions that require authentication. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]>
Add tests for all ListCommandProvider getter methods which were at 0% coverage. This increases cmd/list package coverage from 43.9% to 44.6%. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 4
♻️ Duplicate comments (1)
cmd/list/components.go (1)
279-293:parseColumnsFlagremains a stub ---columnsflag is effectively ignored.Past review noted this issue and marked it as "addressed in commit c8f61af", but the implementation still returns default columns regardless of input. Users passing
--columnswill see no effect.If this is intentionally deferred, consider either:
- Documenting the deferral more explicitly (e.g., link to tracking issue)
- Emitting a warning when
--columnsis used but not yet implementedThis prevents user confusion when the flag appears functional but isn't.
🧹 Nitpick comments (5)
cmd/list/instances.go (1)
72-97: Missingperf.TrackincolumnsCompletionForInstances.Unlike
columnsCompletionForComponentswhich hasdefer perf.Track(nil, "list.components.columnsCompletionForComponents")(), this function lacks performance tracking. Per repo policy, non-trivial functions should include it.func columnsCompletionForInstances(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { + defer perf.Track(nil, "list.instances.columnsCompletionForInstances")() + // Load atmos configuration.Add the
perfimport if not present.cmd/list/metadata.go (1)
63-88: Missingperf.TrackincolumnsCompletionForMetadata.Same issue as instances.go. This function lacks performance tracking.
func columnsCompletionForMetadata(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { + defer perf.Track(nil, "list.metadata.columnsCompletionForMetadata")() + // Load atmos configuration.cmd/list/values.go (1)
3-23: Import organization needs correction.The
logimport (line 7) is placed between stdlib (errors,fmt) and 3rd-party imports. It should be in the Atmos packages group since it'sgithub.com/cloudposse/atmos/pkg/logger.import ( "errors" "fmt" - log "github.com/cloudposse/atmos/pkg/logger" pkgerrors "github.com/pkg/errors" "github.com/spf13/cobra" "github.com/spf13/viper" e "github.com/cloudposse/atmos/internal/exec" "github.com/cloudposse/atmos/pkg/config" "github.com/cloudposse/atmos/pkg/flags" "github.com/cloudposse/atmos/pkg/flags/global" l "github.com/cloudposse/atmos/pkg/list" listerrors "github.com/cloudposse/atmos/pkg/list/errors" f "github.com/cloudposse/atmos/pkg/list/format" listutils "github.com/cloudposse/atmos/pkg/list/utils" + log "github.com/cloudposse/atmos/pkg/logger" "github.com/cloudposse/atmos/pkg/schema" "github.com/cloudposse/atmos/pkg/ui" u "github.com/cloudposse/atmos/pkg/utils" )cmd/list/stacks.go (2)
70-95: Dynamic--columnscompletion is correct; consider prefix-filteringThe completion helper correctly loads
atmosConfigviaProcessCommandLineArgs+InitCliConfigand surfaces configuredstacks.list.columnsnames, which is exactly what users need.If you want to polish UX a bit, you could optionally filter on
toCompletebefore returning, so shells don’t have to handle very long suggestion lists:var columnNames []string for _, col := range atmosConfig.Stacks.List.Columns { if toComplete == "" || strings.HasPrefix(col.Name, toComplete) { columnNames = append(columnNames, col.Name) } }You’d need a
stringsimport if you go this route.
121-160: Consider aligning new user-facing errors with theErrorBuilderpatternThe new error paths here (invalid
--provenanceusage, CLI config initialization,ExecuteDescribeStacksfailure, sort spec parsing) currently usefmt.Errorfdirectly, sometimes wrapping sentinels likeerrUtils.ErrInvalidFlagorerrUtils.ErrInitializingCLIConfig.To better match the repo’s error-handling conventions, you might want to transition these to the central
ErrorBuilderAPI so you can attach causes, hints, and explanations consistently. For example, the provenance validation could become something along the lines of:return errUtils. NewInvalidFlagError(). WithExplanation("--provenance flag only works with --format=tree"). Error()(Adjusted to whatever concrete builder helpers exist.)
Not urgent for correctness, but it will make CLI error reporting and downstream handling more consistent with the rest of the codebase.
Also applies to: 247-257
📜 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.
📒 Files selected for processing (12)
cmd/list/components.go(1 hunks)cmd/list/instances.go(4 hunks)cmd/list/metadata.go(1 hunks)cmd/list/settings.go(4 hunks)cmd/list/stacks.go(1 hunks)cmd/list/values.go(5 hunks)cmd/root.go(4 hunks)cmd/root_test.go(1 hunks)errors/errors.go(2 hunks)internal/exec/stack_processor_utils.go(31 hunks)internal/exec/utils.go(1 hunks)internal/exec/validate_stacks.go(1 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
- internal/exec/validate_stacks.go
- errors/errors.go
🧰 Additional context used
📓 Path-based instructions (4)
**/*.go
📄 CodeRabbit inference engine (.cursor/rules/atmos-rules.mdc)
**/*.go: Use Viper for managing configuration, environment variables, and flags in CLI commands
Use interfaces for external dependencies to facilitate mocking and consider using testify/mock for creating mock implementations
All code must pass golangci-lint checks
Follow Go's error handling idioms: use meaningful error messages, wrap errors with context usingfmt.Errorf("context: %w", err), and consider using custom error types for domain-specific errors
Follow standard Go coding style: usegofmtandgoimportsto format code, prefer short descriptive variable names, use kebab-case for command-line flags, and snake_case for environment variables
Document all exported functions, types, and methods following Go's documentation conventions
Document complex logic with inline comments in Go code
Support configuration via files, environment variables, and flags following the precedence order: flags > environment variables > config file > defaults
Provide clear error messages to users, include troubleshooting hints when appropriate, and log detailed errors for debugging
**/*.go: All comments must end with periods (enforced bygodotlinter)
Import organization: three groups separated by blank lines, sorted alphabetically: 1) Go stdlib, 2) 3rd-party (NOT cloudposse/atmos), 3) Atmos packages. Maintain aliases:cfg,log,u,errUtils
Adddefer perf.Track(atmosConfig, "pkg.FuncName")()+ blank line to all public functions. Usenilif no atmosConfig param
Keep files small and focused (<600 lines). One cmd/impl per file. Co-locate tests. Never use//revive:disable:file-length-limit
Use sentinel errors fromerrors/errors.gowith ErrorBuilder for all user-facing errors. Useerrors.Is()for checking errors, never string comparison.WithCause()preserves underlying error messages,WithExplanation()adds context,WithHint()provides guidance,WithContext()adds key-value pairs
Usecontext.Contextas first parameter for: cancellation signals (prop...
Files:
internal/exec/utils.gocmd/list/settings.gocmd/list/stacks.gocmd/list/metadata.gocmd/root.gocmd/list/instances.gocmd/list/values.gocmd/root_test.gocmd/list/components.gointernal/exec/stack_processor_utils.go
cmd/**/*.go
📄 CodeRabbit inference engine (.cursor/rules/atmos-rules.mdc)
cmd/**/*.go: Use Cobra's recommended command structure with a root command and subcommands, implementing each command in a separate file undercmd/directory
Provide comprehensive help text for all commands and flags, include examples in command help, and follow Go's documentation conventions in Cobra command definitions
Provide meaningful feedback to users and include progress indicators for long-running operations in CLI commands
cmd/**/*.go: CLI command files must be thin wrappers that only handle CLI concerns (flags, arguments, command registration). All business logic must be delegated topkg/packages
Useflags.NewStandardParser()for command-specific flag parsing. NEVER callviper.BindEnv()orviper.BindPFlag()directly - use the unifiedpkg/flags/infrastructure instead. Register flags with Cobra command and bind to Viper for precedence handling
All CLI commands MUST implement the CommandProvider interface and register via command registry pattern incmd/internal/registry.go
Embed examples fromcmd/markdown/*_usage.mdusing//go:embed. Render withutils.PrintfMarkdown()
Files:
cmd/list/settings.gocmd/list/stacks.gocmd/list/metadata.gocmd/root.gocmd/list/instances.gocmd/list/values.gocmd/root_test.gocmd/list/components.go
**/*_test.go
📄 CodeRabbit inference engine (.cursor/rules/atmos-rules.mdc)
**/*_test.go: Every new feature must include comprehensive unit tests targeting >80% code coverage for all packages
Use table-driven tests for testing multiple scenarios in Go
Include integration tests for command flows and test CLI end-to-end when possible with test fixtures
**/*_test.go: Useassert.ErrorIs(t, err, ErrSentinel)for checking our own errors and stdlib errors. Only use string matching for third-party errors
NEVER useassert.Contains(err.Error(), ...)for error checking. ALWAYS useassert.ErrorIs()instead. NEVER use string comparison:err.Error() == "..."orstrings.Contains(err.Error(), ...)
Test behavior, not implementation. Never test stub functions - implement or remove. Avoid tautological tests. Make code testable using dependency injection to avoidos.Exit,CheckErrorPrintAndExit, external systems. Remove always-skipped tests - fix or delete. Table-driven tests must have real scenarios
Usego.uber.org/mock/mockgenwith//go:generatedirectives for mock generation. Never create manual mocks. Pattern://go:generate go run go.uber.org/mock/mockgen@latest -source=filename.go -destination=mock_filename_test.go
Use table-driven tests for comprehensive coverage. Tests must call actual production code, never duplicate logic. Target >80% test coverage (enforced by CodeCov)
Files:
cmd/root_test.go
cmd/**/*_test.go
📄 CodeRabbit inference engine (CLAUDE.md)
ALWAYS use
cmd.NewTestKit(t)for cmd tests. This auto-cleans RootCmd state (flags, args) and is required for any test touching RootCmd
Files:
cmd/root_test.go
🧠 Learnings (89)
📓 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.
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: 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: 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.
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.
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.
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.
📚 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/utils.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:
internal/exec/utils.gocmd/list/stacks.gointernal/exec/stack_processor_utils.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:
cmd/list/settings.gocmd/root.gocmd/list/values.gointernal/exec/stack_processor_utils.go
📚 Learning: 2025-01-18T15:15:41.645Z
Learnt from: samtholiya
Repo: cloudposse/atmos PR: 914
File: cmd/terraform.go:37-46
Timestamp: 2025-01-18T15:15:41.645Z
Learning: In the atmos CLI, error handling is intentionally structured to use LogErrorAndExit for consistent error display, avoiding Cobra's default error handling to prevent duplicate error messages.
Applied to files:
cmd/list/settings.go
📚 Learning: 2025-11-24T17:35:37.209Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: .cursor/rules/atmos-rules.mdc:0-0
Timestamp: 2025-11-24T17:35:37.209Z
Learning: Applies to **/*.go : Use Viper for managing configuration, environment variables, and flags in CLI commands
Applied to files:
cmd/list/settings.gocmd/list/instances.gocmd/list/values.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/settings.gocmd/list/stacks.gocmd/list/metadata.gocmd/root.gocmd/list/instances.gocmd/list/values.gointernal/exec/stack_processor_utils.go
📚 Learning: 2025-12-06T19:24:49.343Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-06T19:24:49.343Z
Learning: Applies to **/*.go : Import organization: three groups separated by blank lines, sorted alphabetically: 1) Go stdlib, 2) 3rd-party (NOT cloudposse/atmos), 3) Atmos packages. Maintain aliases: `cfg`, `log`, `u`, `errUtils`
Applied to files:
cmd/list/settings.gocmd/root.gocmd/list/instances.gocmd/list/values.gointernal/exec/stack_processor_utils.go
📚 Learning: 2025-08-29T20:57:35.423Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 1433
File: cmd/theme_list.go:33-36
Timestamp: 2025-08-29T20:57:35.423Z
Learning: In the Atmos codebase, avoid using viper.SetEnvPrefix("ATMOS") with viper.AutomaticEnv() because canonical environment variable names are not exclusive to Atmos and could cause conflicts. Instead, use selective environment variable binding through the setEnv function in pkg/config/load.go with bindEnv(v, "config.key", "ENV_VAR_NAME") for specific environment variables.
Applied to files:
cmd/list/settings.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/settings.gocmd/list/instances.gocmd/list/values.gointernal/exec/stack_processor_utils.go
📚 Learning: 2025-12-06T19:24:49.343Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-06T19:24:49.343Z
Learning: Applies to **/*.go : Use `viper.BindEnv("ATMOS_VAR", "ATMOS_VAR", "FALLBACK")` for environment variables - ATMOS_ prefix required. Configuration loading precedence: CLI flags → ENV vars → config files → defaults
Applied to files:
cmd/list/settings.gocmd/list/values.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:
cmd/list/settings.gocmd/root.gocmd/list/values.gointernal/exec/stack_processor_utils.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:
cmd/list/settings.gocmd/list/values.gointernal/exec/stack_processor_utils.go
📚 Learning: 2024-12-05T22:33:54.807Z
Learnt from: aknysh
Repo: cloudposse/atmos PR: 820
File: cmd/list_stacks.go:55-56
Timestamp: 2024-12-05T22:33:54.807Z
Learning: In the atmos project, the `u.LogErrorAndExit` function logs the error and exits the command execution appropriately within flag completion functions.
Applied to files:
cmd/list/settings.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:
cmd/list/settings.gointernal/exec/stack_processor_utils.go
📚 Learning: 2024-12-05T22:33:40.955Z
Learnt from: aknysh
Repo: cloudposse/atmos PR: 820
File: cmd/list_components.go:53-54
Timestamp: 2024-12-05T22:33:40.955Z
Learning: In the Atmos CLI Go codebase, using `u.LogErrorAndExit` within completion functions is acceptable because it logs the error and exits the command execution.
Applied to files:
cmd/list/settings.go
📚 Learning: 2025-02-21T20:56:05.539Z
Learnt from: samtholiya
Repo: cloudposse/atmos PR: 1077
File: pkg/downloader/custom_github_detector.go:0-0
Timestamp: 2025-02-21T20:56:05.539Z
Learning: The `github.com/charmbracelet/log` package should be imported with the alias `log` according to the project's import alias configuration.
Applied to files:
cmd/list/settings.go
📚 Learning: 2025-02-21T20:56:20.761Z
Learnt from: samtholiya
Repo: cloudposse/atmos PR: 1077
File: pkg/downloader/custom_github_detector_test.go:0-0
Timestamp: 2025-02-21T20:56:20.761Z
Learning: The `github.com/charmbracelet/log` package should be imported with the alias `log`, not `clog`.
Applied to files:
cmd/list/settings.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/stacks.gocmd/list/metadata.gocmd/list/components.gointernal/exec/stack_processor_utils.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: 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/stacks.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:
cmd/list/stacks.gocmd/list/metadata.gointernal/exec/stack_processor_utils.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/stacks.gocmd/list/metadata.gocmd/list/instances.gocmd/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:
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/stacks.gocmd/list/instances.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:
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
📚 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/stacks.gocmd/list/components.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/stacks.gocmd/list/metadata.gocmd/list/instances.gocmd/root_test.gocmd/list/components.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:
cmd/list/stacks.gointernal/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/stacks.gocmd/list/instances.go
📚 Learning: 2025-11-24T17:35:37.209Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: .cursor/rules/atmos-rules.mdc:0-0
Timestamp: 2025-11-24T17:35:37.209Z
Learning: Applies to cmd/**/*.go : Provide comprehensive help text for all commands and flags, include examples in command help, and follow Go's documentation conventions in Cobra command definitions
Applied to files:
cmd/list/metadata.gocmd/root.gocmd/list/components.go
📚 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:
cmd/list/metadata.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/metadata.gocmd/list/instances.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:
cmd/list/metadata.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/metadata.gointernal/exec/stack_processor_utils.go
📚 Learning: 2025-09-05T14:57:37.360Z
Learnt from: RoseSecurity
Repo: cloudposse/atmos PR: 1448
File: cmd/ansible.go:26-28
Timestamp: 2025-09-05T14:57:37.360Z
Learning: The Atmos codebase uses a consistent pattern for commands that delegate to external tools: `PersistentFlags().Bool("", false, doubleDashHint)` where doubleDashHint provides help text about using double dashes to separate Atmos options from native command arguments. This pattern is used across terraform, packer, helmfile, atlantis, aws, and ansible commands.
Applied to files:
cmd/list/metadata.gocmd/list/instances.gocmd/list/values.go
📚 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:
cmd/root.gocmd/list/values.go
📚 Learning: 2025-12-06T19:24:49.343Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-06T19:24:49.343Z
Learning: Applies to **/*.go : Use colors from `pkg/ui/theme/colors.go` for consistent theming throughout the codebase
Applied to files:
cmd/root.gocmd/list/values.go
📚 Learning: 2025-06-07T19:27:40.807Z
Learnt from: samtholiya
Repo: cloudposse/atmos PR: 1266
File: pkg/utils/highlight_utils.go:0-0
Timestamp: 2025-06-07T19:27:40.807Z
Learning: In pkg/utils/highlight_utils.go, the global variable `isTermPresent` that caches terminal detection at package initialization is an intentional design choice and should not be changed to per-call detection.
Applied to files:
cmd/root.go
📚 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:
cmd/root.go
📚 Learning: 2025-11-24T17:35:37.209Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: .cursor/rules/atmos-rules.mdc:0-0
Timestamp: 2025-11-24T17:35:37.209Z
Learning: Applies to **/*_test.go : Include integration tests for command flows and test CLI end-to-end when possible with test fixtures
Applied to files:
cmd/root.gocmd/root_test.go
📚 Learning: 2025-12-06T19:24:49.343Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-06T19:24:49.343Z
Learning: Applies to pkg/io/**/*.go : Use I/O layer (`pkg/io/`) for stream access (stdout/stderr/stdin), terminal capabilities, masking. Use UI layer (`pkg/ui/`) for formatting (colors, styles, markdown rendering). Never use `fmt.Fprintf(os.Stdout/Stderr, ...)`, `fmt.Println()`, or direct stream access
Applied to files:
cmd/root.gocmd/list/values.go
📚 Learning: 2025-11-24T17:35:37.209Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: .cursor/rules/atmos-rules.mdc:0-0
Timestamp: 2025-11-24T17:35:37.209Z
Learning: Applies to cmd/**/*.go : Provide meaningful feedback to users and include progress indicators for long-running operations in CLI commands
Applied to files:
cmd/root.gocmd/list/values.go
📚 Learning: 2025-12-06T19:24:49.343Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-06T19:24:49.343Z
Learning: Applies to tests/**/*_test.go : NEVER use pipe redirection (`2>&1`, `| head`, `| tail`) when running tests. Piping breaks TTY detection → ASCII fallback → wrong snapshots. NEVER manually edit golden snapshot files - always use `-regenerate-snapshots` flag. Snapshots capture exact output including invisible formatting (lipgloss padding, ANSI codes, trailing whitespace)
Applied to files:
cmd/root.go
📚 Learning: 2025-12-06T19:24:49.343Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-06T19:24:49.343Z
Learning: Applies to **/*.go : Add `defer perf.Track(atmosConfig, "pkg.FuncName")()` + blank line to all public functions. Use `nil` if no atmosConfig param
Applied to files:
cmd/root.gocmd/list/values.gocmd/list/components.gointernal/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:
cmd/root.gocmd/list/components.gointernal/exec/stack_processor_utils.go
📚 Learning: 2025-12-06T19:24:49.343Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-06T19:24:49.343Z
Learning: Applies to **/*.go : For output: Pipeable data → `data.*` (stdout), Plain UI → `ui.Write*()` (stderr), Status messages → `ui.Success/Error/Warning/Info()` (stderr), Formatted docs → `ui.Markdown*()`. Use `data.Write()`, `data.Writef()`, `data.Writeln()`, `data.WriteJSON()`, `data.WriteYAML()` for data output
Applied to files:
cmd/root.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:
cmd/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 (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:
cmd/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:
cmd/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:
cmd/list/instances.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/instances.gocmd/list/values.gocmd/list/components.go
📚 Learning: 2025-12-06T19:24:49.343Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-06T19:24:49.343Z
Learning: Applies to cmd/**/*.go : Use `flags.NewStandardParser()` for command-specific flag parsing. NEVER call `viper.BindEnv()` or `viper.BindPFlag()` directly - use the unified `pkg/flags/` infrastructure instead. Register flags with Cobra command and bind to Viper for precedence handling
Applied to files:
cmd/list/instances.gocmd/list/values.gocmd/list/components.go
📚 Learning: 2024-11-25T17:17:15.703Z
Learnt from: RoseSecurity
Repo: cloudposse/atmos PR: 797
File: pkg/list/atmos.yaml:213-214
Timestamp: 2024-11-25T17:17:15.703Z
Learning: The file `pkg/list/atmos.yaml` is primarily intended for testing purposes.
Applied to files:
cmd/list/values.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/values.gocmd/list/components.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:
cmd/root_test.go
📚 Learning: 2025-05-23T19:51:47.091Z
Learnt from: samtholiya
Repo: cloudposse/atmos PR: 1255
File: cmd/describe_affected_test.go:15-15
Timestamp: 2025-05-23T19:51:47.091Z
Learning: In the atmos codebase, t.Chdir() is a valid method call on *testing.T objects and works correctly for changing directories in tests. This is implemented through custom testing framework extensions and is used consistently throughout the test suite.
Applied to files:
cmd/root_test.go
📚 Learning: 2025-05-23T19:51:47.091Z
Learnt from: samtholiya
Repo: cloudposse/atmos PR: 1255
File: cmd/describe_affected_test.go:15-15
Timestamp: 2025-05-23T19:51:47.091Z
Learning: In the atmos codebase, t.Chdir() is a valid method that can be called on *testing.T objects. This functionality is implemented through custom testing framework extensions and is used consistently throughout the test suite for changing working directories during tests.
Applied to files:
cmd/root_test.go
📚 Learning: 2025-05-23T19:51:47.091Z
Learnt from: samtholiya
Repo: cloudposse/atmos PR: 1255
File: cmd/describe_affected_test.go:15-15
Timestamp: 2025-05-23T19:51:47.091Z
Learning: In the atmos codebase, t.Chdir() is a valid method call on *testing.T objects and works correctly for changing directories in tests.
Applied to files:
cmd/root_test.go
📚 Learning: 2025-12-06T19:24:49.343Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-06T19:24:49.343Z
Learning: Applies to tests/**/*.go : Use `cmd.NewTestKit(t)` for any test touching RootCmd. This auto-cleans RootCmd state. Tests skip gracefully with helpers from `tests/test_preconditions.go`
Applied to files:
cmd/root_test.go
📚 Learning: 2025-12-06T19:24:49.343Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-06T19:24:49.343Z
Learning: Applies to **/*_test.go : Test behavior, not implementation. Never test stub functions - implement or remove. Avoid tautological tests. Make code testable using dependency injection to avoid `os.Exit`, `CheckErrorPrintAndExit`, external systems. Remove always-skipped tests - fix or delete. Table-driven tests must have real scenarios
Applied to files:
cmd/root_test.go
📚 Learning: 2025-12-06T19:24:49.343Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-06T19:24:49.343Z
Learning: Applies to cmd/**/*_test.go : ALWAYS use `cmd.NewTestKit(t)` for cmd tests. This auto-cleans RootCmd state (flags, args) and is required for any test touching RootCmd
Applied to files:
cmd/root_test.go
📚 Learning: 2025-11-24T17:35:37.209Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: .cursor/rules/atmos-rules.mdc:0-0
Timestamp: 2025-11-24T17:35:37.209Z
Learning: Applies to **/*_test.go : Use table-driven tests for testing multiple scenarios in Go
Applied to files:
cmd/root_test.go
📚 Learning: 2025-12-06T19:24:49.343Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-06T19:24:49.343Z
Learning: Applies to **/*_test.go : Use table-driven tests for comprehensive coverage. Tests must call actual production code, never duplicate logic. Target >80% test coverage (enforced by CodeCov)
Applied to files:
cmd/root_test.go
📚 Learning: 2024-12-25T20:28:47.526Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 887
File: internal/exec/stack_processor_utils.go:380-380
Timestamp: 2024-12-25T20:28:47.526Z
Learning: Windows path handling often requires `filepath.Join` to ensure correct separators and comparisons. Insufficient tests can break cross-platform compatibility, so migrating from `path.Join` to `filepath.Join` needs thorough testing on Windows before merging.
Applied to files:
cmd/root_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
📚 Learning: 2025-12-06T19:24:49.343Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-06T19:24:49.343Z
Learning: Applies to **/*.go : Use functional options pattern for configuration instead of many parameters. Provide defaults and extensibility without breaking changes. Pattern: `type Option func(*Config)`, `func WithName(val) Option { return func(c *Config) { c.Name = val } }`, `func New(opts ...Option) { cfg := &Config{/*defaults*/}; for _, opt := range opts { opt(cfg) }; return &Client{config: cfg} }`
Applied to files:
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:
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-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-11-30T04:16:24.155Z
Learnt from: aknysh
Repo: cloudposse/atmos PR: 1821
File: pkg/merge/deferred.go:34-48
Timestamp: 2025-11-30T04:16:24.155Z
Learning: In the cloudposse/atmos repository, the `defer perf.Track()` guideline applies to functions that perform meaningful work (I/O, computation, external calls), but explicitly excludes trivial accessors/mutators (e.g., simple getters, setters with single integer increments, string joins, or map appends) where the tracking overhead would exceed the actual method cost and provide no actionable performance data. Hot-path methods called in tight loops should especially avoid perf.Track() if they perform only trivial operations.
Applied to files:
cmd/list/components.go
📚 Learning: 2025-11-30T04:16:01.899Z
Learnt from: aknysh
Repo: cloudposse/atmos PR: 1821
File: pkg/merge/deferred.go:50-59
Timestamp: 2025-11-30T04:16:01.899Z
Learning: In the cloudposse/atmos repository, performance tracking with `defer perf.Track()` should NOT be added to trivial O(1) getter methods that only return field references or check map lengths (e.g., `GetDeferredValues()`, `HasDeferredValues()`). The guideline to add perf tracking to "all public functions" applies to functions that do meaningful work (I/O, computation, external calls), not to trivial accessors where the tracking overhead would exceed the operation time and pollute performance reports.
Applied to files:
cmd/list/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:
cmd/list/components.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:
internal/exec/stack_processor_utils.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
📚 Learning: 2025-12-06T19:24:49.343Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-06T19:24:49.343Z
Learning: Applies to **/*.go : New configs support Go templating with `FuncMap()` from `internal/exec/template_funcs.go`. Implement template functions in `internal/exec/template_funcs.go`, register them, add tests, and update documentation
Applied to files:
internal/exec/stack_processor_utils.go
📚 Learning: 2025-12-06T19:24:49.343Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-06T19:24:49.343Z
Learning: Applies to pkg/**/*.go : Create focused purpose-built packages in `pkg/` for new functionality, each with clear responsibility. DO NOT add new functions to `pkg/utils/` or `internal/exec/`. Each package should have focused business logic with tests
Applied to files:
internal/exec/stack_processor_utils.go
📚 Learning: 2025-12-06T19:24:49.343Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-06T19:24:49.343Z
Learning: Applies to **/*.go : Before implementing new functionality, search `internal/exec/` and `pkg/` for existing code. Extend, don't duplicate
Applied to files:
internal/exec/stack_processor_utils.go
📚 Learning: 2025-11-24T17:35:37.209Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: .cursor/rules/atmos-rules.mdc:0-0
Timestamp: 2025-11-24T17:35:37.209Z
Learning: Applies to **/*.go : Document complex logic with inline comments in Go code
Applied to files:
internal/exec/stack_processor_utils.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-12-06T19:24:49.343Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-06T19:24:49.343Z
Learning: Applies to **/*_test.go : NEVER use `assert.Contains(err.Error(), ...)` for error checking. ALWAYS use `assert.ErrorIs()` instead. NEVER use string comparison: `err.Error() == "..."` or `strings.Contains(err.Error(), ...)`
Applied to files:
internal/exec/stack_processor_utils.go
📚 Learning: 2025-12-06T19:24:49.343Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-06T19:24:49.343Z
Learning: Applies to **/*.go : Keep files small and focused (<600 lines). One cmd/impl per file. Co-locate tests. Never use `//revive:disable:file-length-limit`
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-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
📚 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:
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-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
🧬 Code graph analysis (5)
internal/exec/utils.go (2)
pkg/perf/perf.go (1)
Track(121-138)pkg/logger/log.go (1)
Trace(14-16)
cmd/list/settings.go (1)
pkg/list/errors/types.go (1)
NoValuesFoundError(9-12)
cmd/list/metadata.go (3)
internal/exec/cli_utils.go (1)
ProcessCommandLineArgs(80-201)pkg/config/config.go (1)
InitCliConfig(28-67)cmd/list/flag_wrappers.go (6)
NewListParser(304-315)WithFormatFlag(32-40)WithStackFlag(126-133)WithMetadataColumnsFlag(68-75)WithSortFlag(149-156)WithFilterFlag(137-144)
cmd/root.go (2)
pkg/terminal/terminal.go (6)
New(150-190)ColorProfile(89-89)ColorNone(92-92)Color16(93-93)Color256(94-94)ColorTrue(95-95)pkg/ui/formatter.go (1)
SetColorProfile(121-123)
cmd/list/values.go (2)
pkg/list/errors/types.go (1)
NoValuesFoundError(9-12)cmd/list/flag_wrappers.go (5)
NewListParser(304-315)WithFormatFlag(32-40)WithDelimiterFlag(44-51)WithStackFlag(126-133)WithQueryFlag(230-237)
⏰ 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
| // Stack filter (glob pattern). | ||
| if opts.Stack != "" { | ||
| globFilter, err := filter.NewGlobFilter("stack", opts.Stack) | ||
| if err == nil { | ||
| filters = append(filters, globFilter) | ||
| } | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Silently swallowing glob pattern errors could confuse users.
If NewGlobFilter returns an error (e.g., invalid pattern), the filter isn't added but no feedback is provided. Users might think their --stack pattern is being applied when it's silently ignored.
Consider logging a warning or returning the error:
if opts.Stack != "" {
globFilter, err := filter.NewGlobFilter("stack", opts.Stack)
- if err == nil {
+ if err != nil {
+ return nil // or log warning and continue
+ }
+ if globFilter != nil {
filters = append(filters, globFilter)
}
}Committable suggestion skipped: line range outside the PR's diff.
| import ( | ||
| "fmt" | ||
| "strings" | ||
|
|
||
| "github.com/spf13/cobra" | ||
| "github.com/spf13/viper" | ||
|
|
||
| errUtils "github.com/cloudposse/atmos/errors" | ||
| e "github.com/cloudposse/atmos/internal/exec" | ||
| "github.com/cloudposse/atmos/pkg/config" | ||
| "github.com/cloudposse/atmos/pkg/flags" | ||
| "github.com/cloudposse/atmos/pkg/flags/global" | ||
| l "github.com/cloudposse/atmos/pkg/list" | ||
| "github.com/cloudposse/atmos/pkg/list/column" | ||
| "github.com/cloudposse/atmos/pkg/list/extract" | ||
| "github.com/cloudposse/atmos/pkg/list/filter" | ||
| "github.com/cloudposse/atmos/pkg/list/format" | ||
| "github.com/cloudposse/atmos/pkg/list/importresolver" | ||
| "github.com/cloudposse/atmos/pkg/list/renderer" | ||
| listSort "github.com/cloudposse/atmos/pkg/list/sort" | ||
| "github.com/cloudposse/atmos/pkg/list/tree" | ||
| log "github.com/cloudposse/atmos/pkg/logger" | ||
| "github.com/cloudposse/atmos/pkg/schema" | ||
| "github.com/cloudposse/atmos/pkg/ui" | ||
| "github.com/cloudposse/atmos/pkg/ui/theme" | ||
| u "github.com/cloudposse/atmos/pkg/utils" | ||
| ) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Avoid fmt.Println for output; route through data.* instead
Per the project’s I/O guidelines, list output shouldn’t go directly to stdout via fmt.Println; it should go through the data helpers so it stays consistently pipeable and benefits from any future central behavior changes.
You can keep semantics and just swap to data.Writeln (or data.Write) and wire in the import:
-import (
- "fmt"
+import (
+ "fmt"
@@
- "github.com/cloudposse/atmos/pkg/list/tree"
+ "github.com/cloudposse/atmos/pkg/list/tree"
+ "github.com/cloudposse/atmos/pkg/data"
@@
- // Render the tree.
- // Use showImports from --provenance flag.
- output := format.RenderStacksTree(importTrees, opts.Provenance)
- fmt.Println(output)
+ // Render the tree.
+ // Use showImports from --provenance flag.
+ output := format.RenderStacksTree(importTrees, opts.Provenance)
+ data.Writeln(output)This keeps behavior the same while aligning with the global output abstraction.
Also applies to: 228-231
🤖 Prompt for AI Agents
In cmd/list/stacks.go around lines 3-25 (and also update occurrences at
228-231), the code uses fmt.Println to write list output directly to stdout;
replace those direct fmt outputs with the project data helpers (e.g.,
data.Writeln or data.Write) and add the required import for the data package so
output is routed through the central I/O abstraction. Update each fmt.Println
call to the appropriate data.* call preserving the string/format semantics and
ensure the data package is imported at the top of the file.
| //nolint:gocognit,revive,cyclop,funlen // Complexity and length from necessary validation and format branching. | ||
| func listStacksWithOptions(cmd *cobra.Command, args []string, opts *StacksOptions) error { | ||
| // Early validation: --provenance only works with --format=tree. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion | 🟠 Major
New nolint directives conflict with repo linting guidance
You’ve added:
//nolint:gocognit,revive,cyclop,funlenonlistStacksWithOptions.//nolint:nestifin the tree-format branch.
Project guidelines explicitly call out avoiding nolint for gocognit/cyclomatic complexity/nestif and preferring refactors instead, and also ask for explicit approval before adding new nolint comments.
A straightforward way to drop most of these would be to extract the tree-specific logic into a focused helper:
-func listStacksWithOptions(cmd *cobra.Command, args []string, opts *StacksOptions) error {
- ...
- //nolint:nestif // Nesting required for tree format handling.
- if opts.Format == "tree" {
- // provenance + tree rendering
- }
- ...
-}
+func listStacksWithOptions(cmd *cobra.Command, args []string, opts *StacksOptions) error {
+ ...
+ if opts.Format == string(format.FormatTree) {
+ return renderStacksTree(cmd, args, opts, stacks, stacksMap, &atmosConfig, authManager)
+ }
+ ...
+}
+
+func renderStacksTree(
+ cmd *cobra.Command,
+ args []string,
+ opts *StacksOptions,
+ stacks []map[string]any,
+ stacksMap map[string]any,
+ atmosConfig *schema.AtmosConfiguration,
+ authManager AuthManagerType, // adjust to actual type
+) error {
+ // existing tree/provenance logic moved here.
+}That should bring cyclomatic complexity and length down enough to remove most of the nolints while keeping behavior identical.
If you intentionally want to keep the lint suppressions as-is, can you confirm that’s acceptable for this repo so they’re clearly an intentional exception?
Also applies to: 181-182
| //nolint:nestif // Nesting required for provenance tracking. | ||
| // Store merge context for imported files if provenance tracking is enabled. | ||
| if atmosConfig != nil && atmosConfig.TrackProvenance { | ||
| switch { | ||
| case result.mergeContext == nil: | ||
| log.Trace("Import has nil merge context", "import", result.importRelativePathWithoutExt) | ||
| case !result.mergeContext.IsProvenanceEnabled(): | ||
| log.Trace("Import has merge context but provenance not enabled", "import", result.importRelativePathWithoutExt) | ||
| default: | ||
| log.Trace("Storing merge context for import", "import", result.importRelativePathWithoutExt, "chain_length", len(result.mergeContext.ImportChain)) | ||
| SetMergeContextForStack(result.importRelativePathWithoutExt, result.mergeContext) | ||
|
|
||
| // Add imported files to parent merge context's import chain. | ||
| // The imported file's chain includes its own imports, so we take all files from it. | ||
| for _, importedFile := range result.mergeContext.ImportChain { | ||
| // Skip the first file if it's the same as the result's own file path (to avoid duplicates). | ||
| 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) | ||
| } | ||
| } | ||
| } | ||
| } | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Refactor to eliminate nolint:nestif directive.
The coding guidelines explicitly forbid using nolint for nestif complexity: "NEVER add nolint for gocognit, cyclomatic complexity, magic numbers, or nestif - refactor instead." The provenance tracking logic at lines 1056-1087 should be extracted into a helper function to reduce nesting.
Consider extracting the provenance tracking and import chain propagation into a dedicated helper function:
// propagateImportChainToParent adds imported files from the result's merge context
// to the parent merge context's import chain, avoiding duplicates.
func propagateImportChainToParent(parentContext, resultContext *m.MergeContext, importPath string) {
if resultContext == nil || !resultContext.IsProvenanceEnabled() {
log.Trace("Import has nil or disabled merge context", "import", importPath)
return
}
log.Trace("Storing merge context for import", "import", importPath, "chain_length", len(resultContext.ImportChain))
SetMergeContextForStack(importPath, resultContext)
// Add imported files to parent's import chain.
for _, importedFile := range resultContext.ImportChain {
if !u.SliceContainsString(parentContext.ImportChain, importedFile) {
parentContext.ImportChain = append(parentContext.ImportChain, importedFile)
// Log with context about whether this is the direct import or nested.
if len(resultContext.ImportChain) > 0 && importedFile == resultContext.ImportChain[0] {
log.Trace("Added import to parent import chain", "file", importedFile)
} else {
log.Trace("Added nested import to parent import chain", "file", importedFile)
}
}
}
}Then call it from line 1058:
if atmosConfig != nil && atmosConfig.TrackProvenance {
propagateImportChainToParent(mergeContext, result.mergeContext, result.importRelativePathWithoutExt)
}🤖 Prompt for AI Agents
internal/exec/stack_processor_utils.go lines 1056-1087: refactor the provenance
tracking block (which currently uses //nolint:nestif) into a small helper that
handles nil/disabled contexts, stores the merge context, and appends imported
files to the parent import chain without duplicates; remove the nolint comment,
add a function (e.g., propagateImportChainToParent) that accepts the parent
mergeContext, result.mergeContext and import path, move the
logging/SetMergeContextForStack and loop logic into it, and replace the original
nested if/switch with a single call to that helper when atmosConfig != nil &&
atmosConfig.TrackProvenance.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
🧹 Nitpick comments (2)
errors/errors.go (1)
49-49: Consider more specific naming if ambiguity arises.
ErrInvalidConfigis intentionally generic for reusability across the rendering pipeline, but the file already has several specific config errors (ErrInvalidStackConfiguration,ErrInvalidBackendConfig,ErrInvalidAuthConfig). If you find callers wrapping this with similar context repeatedly, consider splitting into more specific sentinels likeErrInvalidColumnConfigorErrInvalidFilterConfig.cmd/list/list_test.go (1)
247-280: Interface contract test looks good.The test correctly verifies that
ListCommandProviderimplements the CommandProvider interface with expected values. Usingrequire.NotNilbefore accessingcmd.Useis appropriate defensive practice.Consider verifying additional command properties if it adds value:
t.Run("GetCommand returns listCmd", func(t *testing.T) { cmd := provider.GetCommand() require.NotNil(t, cmd) assert.Equal(t, "list", cmd.Use) + assert.NotEmpty(t, cmd.Commands(), "Expected list command to have subcommands") })However, the current focused interface contract test is perfectly acceptable for the command registry pattern.
📜 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.
📒 Files selected for processing (2)
cmd/list/list_test.go(2 hunks)errors/errors.go(2 hunks)
🧰 Additional context used
📓 Path-based instructions (4)
cmd/**/*.go
📄 CodeRabbit inference engine (.cursor/rules/atmos-rules.mdc)
cmd/**/*.go: Use Cobra's recommended command structure with a root command and subcommands, implementing each command in a separate file undercmd/directory
Provide comprehensive help text for all commands and flags, include examples in command help, and follow Go's documentation conventions in Cobra command definitions
Provide meaningful feedback to users and include progress indicators for long-running operations in CLI commands
cmd/**/*.go: CLI command files must be thin wrappers that only handle CLI concerns (flags, arguments, command registration). All business logic must be delegated topkg/packages
Useflags.NewStandardParser()for command-specific flag parsing. NEVER callviper.BindEnv()orviper.BindPFlag()directly - use the unifiedpkg/flags/infrastructure instead. Register flags with Cobra command and bind to Viper for precedence handling
All CLI commands MUST implement the CommandProvider interface and register via command registry pattern incmd/internal/registry.go
Embed examples fromcmd/markdown/*_usage.mdusing//go:embed. Render withutils.PrintfMarkdown()
Files:
cmd/list/list_test.go
**/*.go
📄 CodeRabbit inference engine (.cursor/rules/atmos-rules.mdc)
**/*.go: Use Viper for managing configuration, environment variables, and flags in CLI commands
Use interfaces for external dependencies to facilitate mocking and consider using testify/mock for creating mock implementations
All code must pass golangci-lint checks
Follow Go's error handling idioms: use meaningful error messages, wrap errors with context usingfmt.Errorf("context: %w", err), and consider using custom error types for domain-specific errors
Follow standard Go coding style: usegofmtandgoimportsto format code, prefer short descriptive variable names, use kebab-case for command-line flags, and snake_case for environment variables
Document all exported functions, types, and methods following Go's documentation conventions
Document complex logic with inline comments in Go code
Support configuration via files, environment variables, and flags following the precedence order: flags > environment variables > config file > defaults
Provide clear error messages to users, include troubleshooting hints when appropriate, and log detailed errors for debugging
**/*.go: All comments must end with periods (enforced bygodotlinter)
Import organization: three groups separated by blank lines, sorted alphabetically: 1) Go stdlib, 2) 3rd-party (NOT cloudposse/atmos), 3) Atmos packages. Maintain aliases:cfg,log,u,errUtils
Adddefer perf.Track(atmosConfig, "pkg.FuncName")()+ blank line to all public functions. Usenilif no atmosConfig param
Keep files small and focused (<600 lines). One cmd/impl per file. Co-locate tests. Never use//revive:disable:file-length-limit
Use sentinel errors fromerrors/errors.gowith ErrorBuilder for all user-facing errors. Useerrors.Is()for checking errors, never string comparison.WithCause()preserves underlying error messages,WithExplanation()adds context,WithHint()provides guidance,WithContext()adds key-value pairs
Usecontext.Contextas first parameter for: cancellation signals (prop...
Files:
cmd/list/list_test.goerrors/errors.go
**/*_test.go
📄 CodeRabbit inference engine (.cursor/rules/atmos-rules.mdc)
**/*_test.go: Every new feature must include comprehensive unit tests targeting >80% code coverage for all packages
Use table-driven tests for testing multiple scenarios in Go
Include integration tests for command flows and test CLI end-to-end when possible with test fixtures
**/*_test.go: Useassert.ErrorIs(t, err, ErrSentinel)for checking our own errors and stdlib errors. Only use string matching for third-party errors
NEVER useassert.Contains(err.Error(), ...)for error checking. ALWAYS useassert.ErrorIs()instead. NEVER use string comparison:err.Error() == "..."orstrings.Contains(err.Error(), ...)
Test behavior, not implementation. Never test stub functions - implement or remove. Avoid tautological tests. Make code testable using dependency injection to avoidos.Exit,CheckErrorPrintAndExit, external systems. Remove always-skipped tests - fix or delete. Table-driven tests must have real scenarios
Usego.uber.org/mock/mockgenwith//go:generatedirectives for mock generation. Never create manual mocks. Pattern://go:generate go run go.uber.org/mock/mockgen@latest -source=filename.go -destination=mock_filename_test.go
Use table-driven tests for comprehensive coverage. Tests must call actual production code, never duplicate logic. Target >80% test coverage (enforced by CodeCov)
Files:
cmd/list/list_test.go
cmd/**/*_test.go
📄 CodeRabbit inference engine (CLAUDE.md)
ALWAYS use
cmd.NewTestKit(t)for cmd tests. This auto-cleans RootCmd state (flags, args) and is required for any test touching RootCmd
Files:
cmd/list/list_test.go
🧠 Learnings (11)
📓 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.
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: 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: 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.
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.
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.
Learnt from: samtholiya
Repo: cloudposse/atmos PR: 1068
File: tests/snapshots/TestCLICommands_atmos_terraform_help.stdout.golden:59-64
Timestamp: 2025-02-18T13:13:11.497Z
Learning: For Atmos CLI help text, angle brackets in command examples and flag descriptions should be escaped using HTML entities (e.g., `<component>`) rather than converted to backticks or other markdown formatting.
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.
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.
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.
📚 Learning: 2025-11-24T17:35:37.209Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: .cursor/rules/atmos-rules.mdc:0-0
Timestamp: 2025-11-24T17:35:37.209Z
Learning: Applies to **/*_test.go : Include integration tests for command flows and test CLI end-to-end when possible with test fixtures
Applied to files:
cmd/list/list_test.go
📚 Learning: 2025-12-06T19:24:49.343Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-06T19:24:49.343Z
Learning: Applies to cmd/**/*.go : All CLI commands MUST implement the CommandProvider interface and register via command registry pattern in `cmd/internal/registry.go`
Applied to files:
cmd/list/list_test.go
📚 Learning: 2025-11-24T17:35:37.209Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: .cursor/rules/atmos-rules.mdc:0-0
Timestamp: 2025-11-24T17:35:37.209Z
Learning: Applies to cmd/**/*.go : Provide comprehensive help text for all commands and flags, include examples in command help, and follow Go's documentation conventions in Cobra command definitions
Applied to files:
cmd/list/list_test.go
📚 Learning: 2025-12-06T19:24:49.343Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-06T19:24:49.343Z
Learning: Applies to **/*_test.go : Use `assert.ErrorIs(t, err, ErrSentinel)` for checking our own errors and stdlib errors. Only use string matching for third-party errors
Applied to files:
cmd/list/list_test.goerrors/errors.go
📚 Learning: 2025-12-06T19:24:49.343Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-06T19:24:49.343Z
Learning: Applies to **/*_test.go : Test behavior, not implementation. Never test stub functions - implement or remove. Avoid tautological tests. Make code testable using dependency injection to avoid `os.Exit`, `CheckErrorPrintAndExit`, external systems. Remove always-skipped tests - fix or delete. Table-driven tests must have real scenarios
Applied to files:
cmd/list/list_test.go
📚 Learning: 2025-12-06T19:24:49.343Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-06T19:24:49.343Z
Learning: Use dependency injection and interface-driven design to make code testable - avoid `os.Exit`, `CheckErrorPrintAndExit`, and direct external system calls in testable functions
Applied to files:
cmd/list/list_test.go
📚 Learning: 2025-12-06T19:24:49.343Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-06T19:24:49.343Z
Learning: Applies to **/*_test.go : NEVER use `assert.Contains(err.Error(), ...)` for error checking. ALWAYS use `assert.ErrorIs()` instead. NEVER use string comparison: `err.Error() == "..."` or `strings.Contains(err.Error(), ...)`
Applied to files:
cmd/list/list_test.go
📚 Learning: 2025-12-06T19:24:49.343Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-06T19:24:49.343Z
Learning: Applies to **/*.go : Use sentinel errors from `errors/errors.go` with ErrorBuilder for all user-facing errors. Use `errors.Is()` for checking errors, never string comparison. `WithCause()` preserves underlying error messages, `WithExplanation()` adds context, `WithHint()` provides guidance, `WithContext()` adds key-value pairs
Applied to files:
errors/errors.go
📚 Learning: 2025-12-06T19:24:49.343Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-06T19:24:49.343Z
Learning: Applies to **/*.go : New configs support Go templating with `FuncMap()` from `internal/exec/template_funcs.go`. Implement template functions in `internal/exec/template_funcs.go`, register them, add tests, and update documentation
Applied to files:
errors/errors.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:
errors/errors.go
🧬 Code graph analysis (1)
cmd/list/list_test.go (1)
cmd/list/list.go (1)
ListCommandProvider(50-50)
⏰ 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 (2)
errors/errors.go (1)
48-48: LGTM!Both
ErrTemplateEvaluationandErrNoStacksFoundare well-placed within their respective error categories and have clear, actionable messages. The template error sits naturally with other template-related sentinels, and the stack error fits perfectly in the list package section.Also applies to: 453-453
cmd/list/list_test.go (1)
8-8: LGTM – Import properly organized.The
requireimport is correctly placed in the 3rd-party section and used appropriately in the new test for assertions where subsequent code depends on non-nil values.
what
atmos.yamland--columnsCLI flag with Go template support--format=treeand--provenanceflags for import hierarchy displaywhy
--columns "Name={{ .component }}")references
Key Features
Configurable Columns
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 formatTest Coverage
🤖 Generated with Claude Code
Summary by CodeRabbit
New Features
Documentation
UX
✏️ Tip: You can customize this high-level summary in your review settings.