Skip to content

feat: Improve source provisioner UX with spinners and interactive delete#1965

Merged
aknysh merged 10 commits intomainfrom
osterman/source-ux-spinner
Jan 14, 2026
Merged

feat: Improve source provisioner UX with spinners and interactive delete#1965
aknysh merged 10 commits intomainfrom
osterman/source-ux-spinner

Conversation

@osterman
Copy link
Member

@osterman osterman commented Jan 14, 2026

what

  • Added spinner feedback during auto-provisioning in vendorToTarget()
  • Introduced PromptForConfirmation() to pkg/flags/interactive.go for reusable destructive action confirmation prompts
  • Updated delete command to prompt interactively instead of requiring --force flag
  • Delete operation now shows spinner during deletion with consistent visual feedback
  • Added blog post and roadmap milestone documenting the enhancement

why

These changes improve UX consistency across the CLI by providing:

  • Better visual feedback during vendoring operations with spinners matching other long-running operations
  • Interactive confirmation prompts for destructive actions that gracefully degrade in non-TTY environments
  • A reusable pattern for other commands that need confirmation prompts

references

Related to source provisioner improvements for better developer experience with JIT vendoring.

Summary by CodeRabbit

  • New Features

    • Interactive confirmation for destructive actions (requires TTY unless --force).
    • Interactive component/stack selection added to pull, delete, describe, and list; positional args now optional.
    • Shell completion for component and stack names.
    • Progress spinners for vendoring, provisioning and deletion flows; clearer interactive/error messaging.
  • Tests

    • Expanded coverage for prompts, confirmations, non‑TTY flows, provisioning detection, and completion helpers.
  • Documentation

    • UX docs updated with TTY vs non‑TTY guidance and force behavior.

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

- Add spinner to auto-provisioning in provision_hook.go
- Add PromptForConfirmation() to pkg/flags/interactive.go for reusable
  destructive action confirmation prompts
- Update delete command to prompt interactively instead of requiring --force
- Delete operation now shows spinner during deletion
- Add blog post and roadmap milestone for the enhancement

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
@osterman osterman requested a review from a team as a code owner January 14, 2026 05:40
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Jan 14, 2026

📝 Walkthrough

Walkthrough

Adds interactive prompting for missing component/stack across source provisioner commands, a TTY-guarded destructive confirmation helper, spinner-wrapped vendoring/deletion UX, shell completion helpers, and extensive tests and docs updates.

Changes

Cohort / File(s) Summary
Interactive Confirmation Infrastructure
pkg/flags/interactive.go, pkg/flags/interactive_test.go
Add PromptForConfirmation(title string, force bool) requiring TTY unless force==true; tests for force and non-TTY behaviors.
Prompting & Completion Utilities
pkg/provisioner/source/cmd/prompt.go, pkg/provisioner/source/cmd/prompt_test.go
New prompt subsystem: PromptForComponent, PromptForStack, HandlePromptError, shell completions (ComponentArgCompletion, StackFlagCompletion), and helpers to enumerate stacks/components with source; comprehensive unit tests and test hooks.
Commands — Delete / Pull / Describe / List
pkg/provisioner/source/cmd/delete.go, pkg/provisioner/source/cmd/delete_test.go, pkg/provisioner/source/cmd/pull.go, pkg/provisioner/source/cmd/pull_test.go, pkg/provisioner/source/cmd/describe.go, pkg/provisioner/source/cmd/describe_test.go, pkg/provisioner/source/cmd/list.go
Make component arg optional ([component]), add interactive prompts for missing inputs, propagate --force for destructive ops, add confirmation before deletion, update usage/help text and tests.
Provisioning UX / Spinner
pkg/provisioner/source/provision_hook.go, pkg/provisioner/source/provision_hook_test.go
Replace direct UI messages with spinner-wrapped execution for vendoring; adjust tests for provisioning detection and workdir behavior.
Test Infrastructure Updates
tests/cli_source_provisioner_test.go, tests/cli_source_provisioner_workdir_test.go
Add Viper reset helpers to avoid global flag state leakage, create/delete temp target dirs for delete tests, and relax assertions to include interactive-not-available cases.
Filesystem Deletion Path
pkg/provisioner/source/cmd/delete.go, pkg/provisioner/source/cmd/delete_test.go
Delete flow updated to require confirmation (TTY) unless --force; pass force into directory removal; wrap deletion in spinner and provide contextual error messages.
Docs / Roadmap
website/blog/2026-01-14-source-provisioner-ux.mdx, website/src/data/roadmap.js
Document UX changes (spinners, interactive prompts, TTY guidance) and update roadmap/vendoring progress.
Additional Tests
pkg/provisioner/source/cmd/prompt_test.go, pkg/provisioner/source/provision_hook_test.go, pkg/flags/interactive_test.go
New and expanded tests covering prompt utilities, interactive error handling, provisioning detection, and confirmation behavior.

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant CLI as Source CLI (delete/pull/describe/list)
    participant Prompt as Prompt subsystem
    participant Config as Atmos Config / DescribeStacks
    participant Spinner as Spinner/UI
    participant FS as Filesystem

    User->>CLI: invoke command (no component/stack)
    CLI->>Prompt: PromptForComponent()
    Prompt->>Config: listComponentsWithSource()
    Config-->>Prompt: components
    Prompt->>User: show component selector
    User-->>Prompt: select component
    Prompt-->>CLI: component

    CLI->>Prompt: PromptForStack(component)
    Prompt->>Config: listStacksWithSourceForComponent(component)
    Config-->>Prompt: stacks
    Prompt->>User: show stack selector
    User-->>Prompt: select stack
    Prompt-->>CLI: stack

    CLI->>Prompt: PromptForConfirmation(title, force)
    alt force == true
        Prompt-->>CLI: confirmed
    else
        Prompt->>User: show yes/no prompt (TTY required)
        User-->>Prompt: confirm/decline
        Prompt-->>CLI: result
    end

    alt confirmed
        CLI->>Spinner: start operation spinner
        Spinner->>FS: perform os.RemoveAll / vendor
        FS-->>Spinner: success/failure
        Spinner->>User: show completion
    else declined
        CLI->>User: operation cancelled
    end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Suggested reviewers

  • osterman
  • milldr
🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the main changes: adding spinners for visual feedback and making the delete command interactive, which aligns with the primary objectives of improving source provisioner UX.
Docstring Coverage ✅ Passed Docstring coverage is 91.36% which is sufficient. The required threshold is 80.00%.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch osterman/source-ux-spinner

🧹 Recent nitpick comments
tests/cli_source_provisioner_workdir_test.go (1)

85-91: Use filepath.Join for cross-platform compatibility.

Hardcoded forward slashes may cause issues on Windows. As per coding guidelines, use filepath.Join() instead of hardcoded path separators.

Proposed fix
+	"path/filepath"

Then update the path construction:

-	targetDir := ".workdir/terraform/dev-vpc-remote-workdir"
+	targetDir := filepath.Join(".workdir", "terraform", "dev-vpc-remote-workdir")
pkg/provisioner/source/cmd/prompt.go (1)

109-134: TODO worth tracking.

The TODO about caching ExecuteDescribeStacks results is valid. Repeated calls during tab completion could impact UX. Consider creating an issue to track this optimization.

Want me to open an issue to track the shell completion caching optimization?


📜 Recent review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between f46e68a and ed9bfea.

📒 Files selected for processing (4)
  • pkg/provisioner/source/cmd/prompt.go
  • pkg/provisioner/source/cmd/prompt_test.go
  • pkg/provisioner/source/provision_hook_test.go
  • tests/cli_source_provisioner_workdir_test.go
🧰 Additional context used
📓 Path-based instructions (3)
**/*.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 using fmt.Errorf("context: %w", err), and consider using custom error types for domain-specific errors
Follow standard Go coding style: use gofmt and goimports to 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 by godot linter) in Go code
Organize imports into three groups separated by blank lines, sorted alphabetically: Go stdlib, 3rd-party (NOT cloudposse/atmos), then Atmos packages with maintained aliases (cfg, log, u, errUtils)
All errors MUST be wrapped using static errors defined in errors/errors.go - use errors.Join for combining errors, fmt.Errorf with %w for context, and errors.Is() for error checking
Never manually create mocks - use go.uber.org/mock/mockgen with //go:generate directives in Go code
Keep files small and focused - under 600 lines with one cmd/impl per file, co-locate tests, never use //revive:disable:file-length-limit
Use colors from pkg/ui/theme/colors.go for all UI theming in Go code
Code must be compatible with Linux, macOS, and Windows - use SDKs over binaries, use filepath.Join() instead of h...

Files:

  • pkg/provisioner/source/cmd/prompt_test.go
  • tests/cli_source_provisioner_workdir_test.go
  • pkg/provisioner/source/cmd/prompt.go
  • pkg/provisioner/source/provision_hook_test.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

Prefer unit tests with mocks over integration tests - use interfaces and dependency injection for testability, generate mocks with go.uber.org/mock/mockgen, use table-driven tests, target >80% coverage

Files:

  • pkg/provisioner/source/cmd/prompt_test.go
  • tests/cli_source_provisioner_workdir_test.go
  • pkg/provisioner/source/provision_hook_test.go
**/{pkg,internal,cmd}/**/*.go

📄 CodeRabbit inference engine (CLAUDE.md)

Add defer perf.Track(atmosConfig, "pkg.FuncName")() plus blank line to all public functions, using nil if no atmosConfig param - exceptions: trivial getters/setters, command constructors, simple factories, functions delegating to tracked functions

Files:

  • pkg/provisioner/source/cmd/prompt_test.go
  • pkg/provisioner/source/cmd/prompt.go
  • pkg/provisioner/source/provision_hook_test.go
🧠 Learnings (33)
📓 Common learnings
Learnt from: osterman
Repo: cloudposse/atmos PR: 727
File: internal/exec/terraform.go:114-118
Timestamp: 2024-10-21T17:51:53.976Z
Learning: When `atmos terraform clean --everything` is used without specifying a component and without the `--force` flag, prompt the user for confirmation before deleting all components. Use the `--force` flag to skip the confirmation prompt.
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
Learnt from: osterman
Repo: cloudposse/atmos PR: 727
File: internal/exec/terraform.go:114-118
Timestamp: 2024-10-21T17:51:07.087Z
Learning: Use `bubbletea` for confirmation prompts instead of `fmt.Scanln` in the `atmos terraform clean` command.
📚 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:

  • pkg/provisioner/source/cmd/prompt_test.go
  • tests/cli_source_provisioner_workdir_test.go
  • pkg/provisioner/source/provision_hook_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 : Every new feature must include comprehensive unit tests targeting >80% code coverage for all packages

Applied to files:

  • pkg/provisioner/source/cmd/prompt_test.go
  • tests/cli_source_provisioner_workdir_test.go
  • pkg/provisioner/source/provision_hook_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:

  • pkg/provisioner/source/cmd/prompt_test.go
  • pkg/provisioner/source/cmd/prompt.go
📚 Learning: 2025-12-10T18:32:51.237Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 1808
File: cmd/terraform/backend/backend_delete_test.go:9-23
Timestamp: 2025-12-10T18:32:51.237Z
Learning: In cmd subpackages (e.g., cmd/terraform/backend/), tests cannot use cmd.NewTestKit(t) due to Go's test visibility rules (NewTestKit is in a parent package test file). These tests only need TestKit if they execute commands through RootCmd or modify RootCmd state. Structural tests that only verify command structure/flags without touching RootCmd don't require TestKit cleanup.

Applied to files:

  • pkg/provisioner/source/cmd/prompt_test.go
  • tests/cli_source_provisioner_workdir_test.go
  • pkg/provisioner/source/provision_hook_test.go
📚 Learning: 2024-11-16T17:30:52.893Z
Learnt from: pkbhowmick
Repo: cloudposse/atmos PR: 786
File: internal/exec/shell_utils.go:159-162
Timestamp: 2024-11-16T17:30:52.893Z
Learning: For the `atmos terraform shell` command in `internal/exec/shell_utils.go`, input validation for the custom shell prompt is not required, as users will use this as a CLI tool and any issues will impact themselves.

Applied to files:

  • pkg/provisioner/source/cmd/prompt_test.go
  • pkg/provisioner/source/cmd/prompt.go
📚 Learning: 2026-01-04T00:55:21.720Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-04T00:55:21.720Z
Learning: Applies to cmd/**/*_test.go : Always use `cmd.NewTestKit(t)` for cmd tests to auto-clean RootCmd state

Applied to files:

  • pkg/provisioner/source/cmd/prompt_test.go
  • tests/cli_source_provisioner_workdir_test.go
  • pkg/provisioner/source/provision_hook_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 meaningful feedback to users and include progress indicators for long-running operations in CLI commands

Applied to files:

  • pkg/provisioner/source/cmd/prompt_test.go
📚 Learning: 2026-01-04T00:55:21.720Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-04T00:55:21.720Z
Learning: Applies to **/*_test.go : Prefer unit tests with mocks over integration tests - use interfaces and dependency injection for testability, generate mocks with `go.uber.org/mock/mockgen`, use table-driven tests, target >80% coverage

Applied to files:

  • pkg/provisioner/source/cmd/prompt_test.go
  • tests/cli_source_provisioner_workdir_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:

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

Applied to files:

  • pkg/provisioner/source/cmd/prompt_test.go
  • pkg/provisioner/source/cmd/prompt.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/provisioner/source/cmd/prompt_test.go
📚 Learning: 2025-12-13T04:37:40.435Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 1686
File: cmd/toolchain/get.go:23-40
Timestamp: 2025-12-13T04:37:40.435Z
Learning: In Go CLI command files using Cobra, constrain the subcommand to accept at most one positional argument (MaximumNArgs(1)) so it supports both listing all items (zero args) and fetching a specific item (one arg). Define and parse flags with a standard parser (e.g., flags.NewStandardParser()) and avoid binding flags to Viper (no viper.BindEnv/BindPFlag). This promotes explicit argument handling and predictable flag behavior across command files.

Applied to files:

  • pkg/provisioner/source/cmd/prompt_test.go
  • pkg/provisioner/source/cmd/prompt.go
📚 Learning: 2025-12-21T04:10:29.030Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 1891
File: internal/exec/describe_affected.go:468-468
Timestamp: 2025-12-21T04:10:29.030Z
Learning: In Go, package-level declarations (constants, variables, types, and functions) are visible to all files in the same package without imports. During reviews in cloudposse/atmos (and similar Go codebases), before suggesting to declare a new identifier, first check if it already exists in another file of the same package. If it exists, you can avoid adding a new declaration; if not, proceed with a proper package-level declaration. 

Applied to files:

  • pkg/provisioner/source/cmd/prompt_test.go
  • tests/cli_source_provisioner_workdir_test.go
  • pkg/provisioner/source/cmd/prompt.go
  • pkg/provisioner/source/provision_hook_test.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:

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

Applied to files:

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

Applied to files:

  • tests/cli_source_provisioner_workdir_test.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:

  • tests/cli_source_provisioner_workdir_test.go
📚 Learning: 2025-12-13T06:10:25.156Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 1686
File: internal/exec/workflow_utils.go:0-0
Timestamp: 2025-12-13T06:10:25.156Z
Learning: Atmos workflows: In internal/exec/workflow_utils.go ExecuteWorkflow, non-identity steps intentionally use baseWorkflowEnv, which is constructed from the parent environment with PATH modifications for the toolchain. Avoid appending os.Environ() again; prefer documenting this behavior and testing that standard environment variables are preserved.

Applied to files:

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

Applied to files:

  • tests/cli_source_provisioner_workdir_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:

  • tests/cli_source_provisioner_workdir_test.go
  • pkg/provisioner/source/provision_hook_test.go
📚 Learning: 2026-01-04T00:55:21.720Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-04T00:55:21.720Z
Learning: Define interfaces for all major functionality and use dependency injection for testability in Go code

Applied to files:

  • tests/cli_source_provisioner_workdir_test.go
  • pkg/provisioner/source/provision_hook_test.go
📚 Learning: 2026-01-04T00:55:21.720Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-04T00:55:21.720Z
Learning: Applies to **/*.go : Code must be compatible with Linux, macOS, and Windows - use SDKs over binaries, use `filepath.Join()` instead of hardcoded path separators

Applied to files:

  • tests/cli_source_provisioner_workdir_test.go
  • pkg/provisioner/source/provision_hook_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 **/*.go : Use interfaces for external dependencies to facilitate mocking and consider using testify/mock for creating mock implementations

Applied to files:

  • tests/cli_source_provisioner_workdir_test.go
  • pkg/provisioner/source/provision_hook_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:

  • tests/cli_source_provisioner_workdir_test.go
  • pkg/provisioner/source/provision_hook_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:

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

Applied to files:

  • tests/cli_source_provisioner_workdir_test.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:

  • tests/cli_source_provisioner_workdir_test.go
📚 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:

  • pkg/provisioner/source/cmd/prompt.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:

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

Applied to files:

  • pkg/provisioner/source/cmd/prompt.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:

  • pkg/provisioner/source/cmd/prompt.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/provisioner/source/provision_hook_test.go
🧬 Code graph analysis (1)
pkg/provisioner/source/cmd/prompt_test.go (2)
pkg/provisioner/source/cmd/prompt.go (3)
  • HandlePromptError (59-73)
  • ComponentArgCompletion (77-86)
  • StackFlagCompletion (91-107)
errors/errors.go (1)
  • ErrInteractiveModeNotAvailable (733-733)
⏰ 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 (linux)
  • GitHub Check: Acceptance Tests (macos)
  • GitHub Check: Acceptance Tests (windows)
  • GitHub Check: Summary
🔇 Additional comments (23)
pkg/provisioner/source/provision_hook_test.go (2)

4-4: LGTM on the import.

The os import is required for the new TestNeedsProvisioning setup functions using os.WriteFile and os.MkdirAll.


190-260: Solid table-driven test suite.

Good coverage of the needsProvisioning function. The setup functions are clean, t.TempDir() handles cleanup automatically, and filepath.Join ensures cross-platform compatibility. All key scenarios are covered: non-existent path, file instead of directory, empty directory, and populated directories.

One optional consideration: a test case for a permission-denied scenario could strengthen coverage, but that's platform-dependent and tricky to test reliably. Current coverage is sufficient.

tests/cli_source_provisioner_workdir_test.go (3)

4-4: Import looks good.

The os import is needed for directory creation and cleanup.


14-16: Helpful documentation.

Good practice documenting the shared utility location for future maintainers.


97-99: Flexible assertion handles both flows.

The extended assertion correctly accommodates the new interactive mode behavior alongside the existing --force requirement. Clean approach.

pkg/provisioner/source/cmd/prompt.go (9)

1-17: Clean imports and package setup.

Import grouping follows the guidelines: stdlib first, then third-party, then atmos packages with maintained aliases.


19-23: Dependency injection enables testability.

Function variables allow tests to mock external dependencies cleanly. Solid pattern.


25-37: PromptForComponent delegates appropriately.

Clean delegation to the shared prompt utility with proper perf tracking.


39-55: PromptForStack handles component filtering.

Good approach passing the component as args to enable filtered stack completion.


57-73: HandlePromptError covers key scenarios.

Graceful handling: nil returns nil, user abort exits cleanly, interactive mode unavailable falls through to validation, and other errors propagate. Clean control flow.


75-107: Shell completion functions fail gracefully.

Errors return empty lists with ShellCompDirectiveNoFileComp which prevents shell from falling back to file completion. Appropriate behavior.


136-159: Defensive type assertions.

Each type assertion checks the ok return value before proceeding. Robust handling of potentially malformed stack data.


161-209: Stack filtering logic is consistent.

listStacksWithSource and stackHasAnySource follow the same defensive patterns as the component-specific variants. Good consistency.


211-261: Component collection handles deduplication.

Using map[string]struct{} for the set is idiomatic Go. Results are sorted for deterministic output.

pkg/provisioner/source/cmd/prompt_test.go (9)

1-13: Imports properly grouped.

Follows the expected order: stdlib, third-party, atmos packages.


15-33: HandlePromptError tests cover key paths.

Nil error, ErrInteractiveModeNotAvailable graceful fallback, and generic error propagation are all verified. The ErrUserAborted case calls Exit() so skipping it is appropriate.


35-119: Thorough edge case coverage for stackContainsComponentWithSource.

Tests cover: invalid stack data, missing components, missing terraform, component not found, component without source, component with source, and invalid component data type. Solid.


121-196: stackHasAnySource tests mirror the pattern.

Consistent coverage approach for the any-source detection variant.


198-274: collectComponentsWithSource tests verify accumulation.

Tests confirm components are collected correctly across stacks and invalid entries are skipped.


276-333: Shell completion tests acknowledge environment limitations.

Tests correctly note that without proper stack config, results are empty. The tests still verify the directive behavior is correct.


335-436: Mock pattern for list functions is consistent.

Save-and-restore pattern with defer ensures original functions are restored. Tests cover success, config error, and describe error paths.


438-527: listStacksWithSource tests follow same pattern.

Consistent approach across all list function tests. Good.


529-629: listComponentsWithSource tests complete the coverage.

Verifies deduplication across stacks (vpc appears in both dev and prod but only once in output) and excludes components without source. Comprehensive.

✏️ Tip: You can disable this entire section by setting review_details to false in your review settings.


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

❤️ Share

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

@github-actions github-actions bot added the size/m Medium size PR label Jan 14, 2026
@github-actions
Copy link

github-actions bot commented Jan 14, 2026

Dependency Review

✅ No vulnerabilities or license issues found.

Scanned Files

None

When --stack flag is omitted, source commands (pull, delete, describe, list)
now prompt interactively for stack selection instead of immediately erroring.

The prompt shows only stacks that contain the specified component with source
configured, providing a filtered and relevant selection.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
When component argument is omitted, source commands (pull, delete, describe)
now prompt interactively for component selection in addition to stack selection.

The prompt shows only terraform components that have source configured,
providing a filtered and relevant selection.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
…force

The delete command returns nil when the directory doesn't exist (nothing
to delete), so the tests expecting an error about --force were failing.
Updated tests to create the target directory first so the --force
requirement can be properly tested.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
@codecov
Copy link

codecov bot commented Jan 14, 2026

Codecov Report

❌ Patch coverage is 69.69697% with 90 lines in your changes missing coverage. Please review.
✅ Project coverage is 74.37%. Comparing base (9580b43) to head (ed9bfea).
⚠️ Report is 1 commits behind head on main.

Files with missing lines Patch % Lines
pkg/provisioner/source/cmd/delete.go 64.15% 14 Missing and 5 partials ⚠️
pkg/provisioner/source/provision_hook.go 0.00% 19 Missing ⚠️
pkg/provisioner/source/cmd/prompt.go 89.43% 14 Missing and 1 partial ⚠️
pkg/flags/interactive.go 33.33% 12 Missing ⚠️
pkg/provisioner/source/cmd/pull.go 66.66% 8 Missing and 4 partials ⚠️
pkg/provisioner/source/cmd/describe.go 54.16% 8 Missing and 3 partials ⚠️
pkg/provisioner/source/cmd/list.go 60.00% 1 Missing and 1 partial ⚠️
Additional details and impacted files

Impacted file tree graph

@@            Coverage Diff             @@
##             main    #1965      +/-   ##
==========================================
- Coverage   74.37%   74.37%   -0.01%     
==========================================
  Files         774      775       +1     
  Lines       70119    70359     +240     
==========================================
+ Hits        52151    52328     +177     
- Misses      14548    14597      +49     
- Partials     3420     3434      +14     
Flag Coverage Δ
unittests 74.37% <69.69%> (-0.01%) ⬇️

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

Files with missing lines Coverage Δ
pkg/provisioner/source/cmd/list.go 84.61% <60.00%> (-3.62%) ⬇️
pkg/provisioner/source/cmd/describe.go 71.95% <54.16%> (-9.01%) ⬇️
pkg/flags/interactive.go 39.24% <33.33%> (-1.75%) ⬇️
pkg/provisioner/source/cmd/pull.go 79.31% <66.66%> (-12.07%) ⬇️
pkg/provisioner/source/cmd/prompt.go 89.43% <89.43%> (ø)
pkg/provisioner/source/cmd/delete.go 78.99% <64.15%> (-9.19%) ⬇️
pkg/provisioner/source/provision_hook.go 64.91% <0.00%> (+6.50%) ⬆️

... and 5 files with indirect coverage changes

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

The TestSourceProvisionerDelete_MissingForce tests were failing because
the `force` flag value from previous tests leaked via the global Viper
instance. Added viper.Reset() calls at the start of both delete tests
to ensure clean state.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
@osterman osterman added the minor New features that do not break anything label Jan 14, 2026
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 6

🤖 Fix all issues with AI agents
In `@pkg/provisioner/source/cmd/delete.go`:
- Around line 114-118: The code shadows the outer err when checking
PromptForStack's result: after calling PromptForStack (assigned to stack, err)
change the inner short-declaration so it reuses the existing err variable
instead of creating a new one; specifically replace the "if err :=
HandlePromptError(err, \"stack\"); err != nil" pattern with an assignment that
sets the outer err (e.g., "if err = HandlePromptError(err, \"stack\"); err !=
nil") so PromptForStack, HandlePromptError, stack and err are all correctly
handled without shadowing.
- Around line 72-76: The prompt error check currently uses a short-declared
variable that shadows the previously set err from PromptForComponent, causing
the original error to be ignored; change the shadowing short declaration to an
assignment so HandlePromptError reuses the existing err variable (i.e., assign
the result of HandlePromptError(err, "component") to the already-declared err
and return it if non-nil) for the PromptForComponent/HandlePromptError sequence.

In `@pkg/provisioner/source/cmd/describe.go`:
- Around line 86-90: The code shadows the earlier err from PromptForStack
because HandlePromptError is called with :=; change the shadowing assignment to
reuse the existing err variable—call PromptForStack as now, then replace `if err
:= HandlePromptError(err, "stack"); err != nil { return err }` with `if err =
HandlePromptError(err, "stack"); err != nil { return err }` so PromptForStack's
error is preserved and properly checked; references: PromptForStack,
HandlePromptError, stack, err.
- Around line 68-72: The code shadows the earlier err from PromptForComponent by
using := in the if statement, so the error returned by PromptForComponent is
ignored; change the if to assign to the existing err (e.g., use err =
HandlePromptError(err, "component") and then check if err != nil) or separate
into two statements: err = HandlePromptError(err, "component"); if err != nil {
return err } so PromptForComponent and HandlePromptError errors are correctly
handled (refer to PromptForComponent, HandlePromptError, and the err/component
variables).

In `@pkg/provisioner/source/cmd/pull.go`:
- Around line 91-95: The code shadows the previously declared err when calling
HandlePromptError after PromptForStack; replace the short-declaration that
creates a new err with an assignment to the existing err (i.e., use if err =
HandlePromptError(err, "stack"); err != nil { return err }) or use a distinct
name like perr to avoid shadowing; update the call site around
PromptForStack/HandlePromptError so PromptForStack's err is checked correctly
without shadowing (references: stack, err, PromptForStack, HandlePromptError,
cmd, component).
- Around line 73-77: The prompt error is being shadowed: in pull.go you call
component, err = PromptForComponent(cmd) but then redeclare a new err in the if
statement (if err := HandlePromptError(err, "component"); ...), which hides the
original err and can cause the prompt error to be ignored; change the if to
reuse the existing err variable (e.g., if err = HandlePromptError(err,
"component"); err != nil { return err }) so HandlePromptError actually receives
and returns the original error from PromptForComponent and is properly checked;
update the same pattern wherever PromptForComponent, HandlePromptError or
similar prompt/error handling occurs in this file.
♻️ Duplicate comments (1)
tests/cli_source_provisioner_test.go (1)

15-21: Same consolidation opportunity noted.

Duplicate of resetWorkdirViperState() in the other test file. Same package, could share.

🧹 Nitpick comments (2)
pkg/provisioner/source/cmd/prompt.go (1)

103-125: Consider caching ExecuteDescribeStacks results.

Each list function (listStacksWithSourceForComponent, listStacksWithSource, listComponentsWithSource) initializes config and calls ExecuteDescribeStacks independently. For shell completion, this is called on each tab press. Not a blocker, but could be optimized later with a shared cache.

Also applies to: 152-174, 202-227

tests/cli_source_provisioner_workdir_test.go (1)

15-21: Consider consolidating duplicate helper.

Both resetWorkdirViperState() here and resetViperState() in cli_source_provisioner_test.go do the same thing. Since they're in the same package, you could define it once in a shared test helper file (e.g., helpers_test.go) and use it across both test files.

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 1a20e5b and 810256b.

📒 Files selected for processing (14)
  • pkg/flags/interactive.go
  • pkg/provisioner/source/cmd/delete.go
  • pkg/provisioner/source/cmd/delete_test.go
  • pkg/provisioner/source/cmd/describe.go
  • pkg/provisioner/source/cmd/describe_test.go
  • pkg/provisioner/source/cmd/list.go
  • pkg/provisioner/source/cmd/prompt.go
  • pkg/provisioner/source/cmd/pull.go
  • pkg/provisioner/source/cmd/pull_test.go
  • pkg/provisioner/source/provision_hook.go
  • tests/cli_source_provisioner_test.go
  • tests/cli_source_provisioner_workdir_test.go
  • website/blog/2026-01-14-source-provisioner-ux.mdx
  • website/src/data/roadmap.js
🧰 Additional context used
📓 Path-based instructions (5)
**/*.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 using fmt.Errorf("context: %w", err), and consider using custom error types for domain-specific errors
Follow standard Go coding style: use gofmt and goimports to 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 by godot linter) in Go code
Organize imports into three groups separated by blank lines, sorted alphabetically: Go stdlib, 3rd-party (NOT cloudposse/atmos), then Atmos packages with maintained aliases (cfg, log, u, errUtils)
All errors MUST be wrapped using static errors defined in errors/errors.go - use errors.Join for combining errors, fmt.Errorf with %w for context, and errors.Is() for error checking
Never manually create mocks - use go.uber.org/mock/mockgen with //go:generate directives in Go code
Keep files small and focused - under 600 lines with one cmd/impl per file, co-locate tests, never use //revive:disable:file-length-limit
Use colors from pkg/ui/theme/colors.go for all UI theming in Go code
Code must be compatible with Linux, macOS, and Windows - use SDKs over binaries, use filepath.Join() instead of h...

Files:

  • pkg/provisioner/source/cmd/pull_test.go
  • pkg/provisioner/source/provision_hook.go
  • pkg/flags/interactive.go
  • pkg/provisioner/source/cmd/describe.go
  • pkg/provisioner/source/cmd/pull.go
  • pkg/provisioner/source/cmd/describe_test.go
  • pkg/provisioner/source/cmd/list.go
  • pkg/provisioner/source/cmd/delete.go
  • tests/cli_source_provisioner_test.go
  • pkg/provisioner/source/cmd/delete_test.go
  • pkg/provisioner/source/cmd/prompt.go
  • tests/cli_source_provisioner_workdir_test.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

Prefer unit tests with mocks over integration tests - use interfaces and dependency injection for testability, generate mocks with go.uber.org/mock/mockgen, use table-driven tests, target >80% coverage

Files:

  • pkg/provisioner/source/cmd/pull_test.go
  • pkg/provisioner/source/cmd/describe_test.go
  • tests/cli_source_provisioner_test.go
  • pkg/provisioner/source/cmd/delete_test.go
  • tests/cli_source_provisioner_workdir_test.go
**/{pkg,internal,cmd}/**/*.go

📄 CodeRabbit inference engine (CLAUDE.md)

Add defer perf.Track(atmosConfig, "pkg.FuncName")() plus blank line to all public functions, using nil if no atmosConfig param - exceptions: trivial getters/setters, command constructors, simple factories, functions delegating to tracked functions

Files:

  • pkg/provisioner/source/cmd/pull_test.go
  • pkg/provisioner/source/provision_hook.go
  • pkg/flags/interactive.go
  • pkg/provisioner/source/cmd/describe.go
  • pkg/provisioner/source/cmd/pull.go
  • pkg/provisioner/source/cmd/describe_test.go
  • pkg/provisioner/source/cmd/list.go
  • pkg/provisioner/source/cmd/delete.go
  • pkg/provisioner/source/cmd/delete_test.go
  • pkg/provisioner/source/cmd/prompt.go
website/**

📄 CodeRabbit inference engine (.cursor/rules/atmos-rules.mdc)

website/**: Update website documentation in the website/ directory when adding new features, ensure consistency between CLI help text and website documentation, and follow the website's documentation structure and style
Keep website code in the website/ directory, follow the existing website architecture and style, and test website changes locally before committing
Keep CLI documentation and website documentation in sync and document new features on the website with examples and use cases

Files:

  • website/src/data/roadmap.js
  • website/blog/2026-01-14-source-provisioner-ux.mdx
website/blog/*.mdx

📄 CodeRabbit inference engine (CLAUDE.md)

PRs labeled minor or major MUST include a blog post at website/blog/YYYY-MM-DD-feature-name.mdx with YAML frontmatter, using only tags defined in website/blog/tags.yml

Files:

  • website/blog/2026-01-14-source-provisioner-ux.mdx
🧠 Learnings (56)
📓 Common learnings
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.
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
Learnt from: osterman
Repo: cloudposse/atmos PR: 727
File: internal/exec/terraform.go:114-118
Timestamp: 2024-10-21T17:51:07.087Z
Learning: Use `bubbletea` for confirmation prompts instead of `fmt.Scanln` in the `atmos terraform clean` command.
Learnt from: osterman
Repo: cloudposse/atmos PR: 727
File: internal/exec/terraform.go:114-118
Timestamp: 2024-10-21T17:51:53.976Z
Learning: When `atmos terraform clean --everything` is used without specifying a component and without the `--force` flag, prompt the user for confirmation before deleting all components. Use the `--force` flag to skip the confirmation prompt.
📚 Learning: 2024-12-07T16:16:13.038Z
Learnt from: Listener430
Repo: cloudposse/atmos PR: 825
File: internal/exec/helmfile_generate_varfile.go:28-31
Timestamp: 2024-12-07T16:16:13.038Z
Learning: In `internal/exec/helmfile_generate_varfile.go`, the `--help` command (`./atmos helmfile generate varfile --help`) works correctly without requiring stack configurations, and the only change needed was to make `ProcessCommandLineArgs` exportable by capitalizing its name.

Applied to files:

  • pkg/provisioner/source/cmd/pull_test.go
  • pkg/provisioner/source/cmd/describe.go
  • pkg/provisioner/source/cmd/pull.go
  • pkg/provisioner/source/cmd/describe_test.go
  • pkg/provisioner/source/cmd/list.go
  • pkg/provisioner/source/cmd/prompt.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:

  • pkg/provisioner/source/cmd/pull_test.go
  • pkg/provisioner/source/cmd/describe.go
  • pkg/provisioner/source/cmd/pull.go
  • pkg/provisioner/source/cmd/describe_test.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:

  • pkg/provisioner/source/cmd/pull_test.go
  • pkg/provisioner/source/cmd/describe.go
  • pkg/provisioner/source/cmd/pull.go
  • pkg/provisioner/source/cmd/describe_test.go
  • pkg/provisioner/source/cmd/delete.go
  • pkg/provisioner/source/cmd/delete_test.go
  • pkg/provisioner/source/cmd/prompt.go
📚 Learning: 2025-12-10T18:32:51.237Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 1808
File: cmd/terraform/backend/backend_delete_test.go:9-23
Timestamp: 2025-12-10T18:32:51.237Z
Learning: In cmd subpackages (e.g., cmd/terraform/backend/), tests cannot use cmd.NewTestKit(t) due to Go's test visibility rules (NewTestKit is in a parent package test file). These tests only need TestKit if they execute commands through RootCmd or modify RootCmd state. Structural tests that only verify command structure/flags without touching RootCmd don't require TestKit cleanup.

Applied to files:

  • pkg/provisioner/source/cmd/pull_test.go
  • pkg/provisioner/source/cmd/describe_test.go
  • tests/cli_source_provisioner_test.go
  • pkg/provisioner/source/cmd/delete_test.go
  • tests/cli_source_provisioner_workdir_test.go
📚 Learning: 2025-12-13T04:37:40.435Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 1686
File: cmd/toolchain/get.go:23-40
Timestamp: 2025-12-13T04:37:40.435Z
Learning: In Go CLI command files using Cobra, constrain the subcommand to accept at most one positional argument (MaximumNArgs(1)) so it supports both listing all items (zero args) and fetching a specific item (one arg). Define and parse flags with a standard parser (e.g., flags.NewStandardParser()) and avoid binding flags to Viper (no viper.BindEnv/BindPFlag). This promotes explicit argument handling and predictable flag behavior across command files.

Applied to files:

  • pkg/provisioner/source/cmd/pull_test.go
  • pkg/provisioner/source/cmd/describe.go
  • pkg/provisioner/source/cmd/pull.go
  • pkg/provisioner/source/cmd/describe_test.go
  • pkg/provisioner/source/cmd/list.go
  • pkg/provisioner/source/cmd/delete.go
  • pkg/provisioner/source/cmd/delete_test.go
  • pkg/provisioner/source/cmd/prompt.go
📚 Learning: 2025-12-21T04:10:29.030Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 1891
File: internal/exec/describe_affected.go:468-468
Timestamp: 2025-12-21T04:10:29.030Z
Learning: In Go, package-level declarations (constants, variables, types, and functions) are visible to all files in the same package without imports. During reviews in cloudposse/atmos (and similar Go codebases), before suggesting to declare a new identifier, first check if it already exists in another file of the same package. If it exists, you can avoid adding a new declaration; if not, proceed with a proper package-level declaration. 

Applied to files:

  • pkg/provisioner/source/cmd/pull_test.go
  • pkg/provisioner/source/provision_hook.go
  • pkg/flags/interactive.go
  • pkg/provisioner/source/cmd/describe.go
  • pkg/provisioner/source/cmd/pull.go
  • pkg/provisioner/source/cmd/describe_test.go
  • pkg/provisioner/source/cmd/list.go
  • pkg/provisioner/source/cmd/delete.go
  • tests/cli_source_provisioner_test.go
  • pkg/provisioner/source/cmd/delete_test.go
  • pkg/provisioner/source/cmd/prompt.go
  • tests/cli_source_provisioner_workdir_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 meaningful feedback to users and include progress indicators for long-running operations in CLI commands

Applied to files:

  • pkg/provisioner/source/provision_hook.go
  • pkg/provisioner/source/cmd/delete.go
  • pkg/provisioner/source/cmd/prompt.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:

  • pkg/provisioner/source/provision_hook.go
📚 Learning: 2024-10-21T17:51:07.087Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 727
File: internal/exec/terraform.go:114-118
Timestamp: 2024-10-21T17:51:07.087Z
Learning: Use `bubbletea` for confirmation prompts instead of `fmt.Scanln` in the `atmos terraform clean` command.

Applied to files:

  • pkg/flags/interactive.go
  • pkg/provisioner/source/cmd/delete_test.go
  • pkg/provisioner/source/cmd/prompt.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:

  • pkg/provisioner/source/cmd/describe.go
  • pkg/provisioner/source/cmd/pull.go
  • pkg/provisioner/source/cmd/list.go
  • pkg/provisioner/source/cmd/prompt.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:

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

Applied to files:

  • pkg/provisioner/source/cmd/describe.go
  • pkg/provisioner/source/cmd/prompt.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 : Use Cobra's recommended command structure with a root command and subcommands, implementing each command in a separate file under `cmd/` directory

Applied to files:

  • pkg/provisioner/source/cmd/describe.go
  • pkg/provisioner/source/cmd/pull.go
  • pkg/provisioner/source/cmd/delete.go
📚 Learning: 2025-02-03T06:00:11.419Z
Learnt from: samtholiya
Repo: cloudposse/atmos PR: 959
File: cmd/describe_config.go:20-20
Timestamp: 2025-02-03T06:00:11.419Z
Learning: The `describe config` command should use `PrintErrorMarkdownAndExit` with empty title and suggestion for consistency with other commands.

Applied to files:

  • pkg/provisioner/source/cmd/describe.go
  • pkg/provisioner/source/cmd/describe_test.go
📚 Learning: 2025-08-16T23:33:07.477Z
Learnt from: aknysh
Repo: cloudposse/atmos PR: 1405
File: internal/exec/describe_dependents_test.go:651-652
Timestamp: 2025-08-16T23:33:07.477Z
Learning: In the cloudposse/atmos Go codebase, ExecuteDescribeDependents expects a pointer to AtmosConfiguration (*schema.AtmosConfiguration), so when calling it with a value returned by cfg.InitCliConfig (which returns schema.AtmosConfiguration), the address-of operator (&) is necessary: ExecuteDescribeDependents(&atmosConfig, ...).

Applied to files:

  • pkg/provisioner/source/cmd/describe.go
📚 Learning: 2025-12-13T03:21:35.786Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 1813
File: cmd/terraform/shell.go:28-73
Timestamp: 2025-12-13T03:21:35.786Z
Learning: In Atmos, when calling cfg.InitCliConfig, you must first populate the schema.ConfigAndStacksInfo struct with global flag values using flags.ParseGlobalFlags(cmd, v) rather than passing an empty struct. The LoadConfig function (pkg/config/load.go) reads config selection fields (AtmosConfigFilesFromArg, AtmosConfigDirsFromArg, BasePath, ProfilesFromArg) directly from the ConfigAndStacksInfo struct, NOT from Viper. Passing an empty struct causes config selection flags (--base-path, --config, --config-path, --profile) to be silently ignored. Correct pattern: parse flags → populate struct → call InitCliConfig. See cmd/terraform/plan_diff.go for reference implementation.

Applied to files:

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

Applied to files:

  • pkg/provisioner/source/cmd/pull.go
  • pkg/provisioner/source/cmd/describe_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 : Include integration tests for command flows and test CLI end-to-end when possible with test fixtures

Applied to files:

  • pkg/provisioner/source/cmd/describe_test.go
  • tests/cli_source_provisioner_test.go
  • pkg/provisioner/source/cmd/delete_test.go
  • tests/cli_source_provisioner_workdir_test.go
📚 Learning: 2024-11-16T17:30:52.893Z
Learnt from: pkbhowmick
Repo: cloudposse/atmos PR: 786
File: internal/exec/shell_utils.go:159-162
Timestamp: 2024-11-16T17:30:52.893Z
Learning: For the `atmos terraform shell` command in `internal/exec/shell_utils.go`, input validation for the custom shell prompt is not required, as users will use this as a CLI tool and any issues will impact themselves.

Applied to files:

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

Applied to files:

  • pkg/provisioner/source/cmd/list.go
  • tests/cli_source_provisioner_test.go
  • tests/cli_source_provisioner_workdir_test.go
📚 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:

  • pkg/provisioner/source/cmd/list.go
  • pkg/provisioner/source/cmd/prompt.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:

  • pkg/provisioner/source/cmd/delete.go
  • pkg/provisioner/source/cmd/delete_test.go
📚 Learning: 2024-11-07T20:16:15.381Z
Learnt from: pkbhowmick
Repo: cloudposse/atmos PR: 766
File: cmd/cmd_utils.go:177-178
Timestamp: 2024-11-07T20:16:15.381Z
Learning: In 'cmd/cmd_utils.go', using `os.Exit(1)` directly is acceptable in this context, and wrapping it with deferred cleanup is considered unnecessary.

Applied to files:

  • pkg/provisioner/source/cmd/delete.go
📚 Learning: 2026-01-04T00:55:21.720Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-04T00:55:21.720Z
Learning: Applies to **/*.go : All errors MUST be wrapped using static errors defined in `errors/errors.go` - use `errors.Join` for combining errors, `fmt.Errorf` with `%w` for context, and `errors.Is()` for error checking

Applied to files:

  • pkg/provisioner/source/cmd/delete.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/provisioner/source/cmd/delete.go
  • pkg/provisioner/source/cmd/delete_test.go
📚 Learning: 2025-01-07T20:38:09.618Z
Learnt from: samtholiya
Repo: cloudposse/atmos PR: 896
File: cmd/editor_config.go:37-40
Timestamp: 2025-01-07T20:38:09.618Z
Learning: Error handling suggestion for `cmd.Help()` in `cmd/editor_config.go` was deferred as the code is planned for future modifications.

Applied to files:

  • pkg/provisioner/source/cmd/delete.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 : Provide clear error messages to users, include troubleshooting hints when appropriate, and log detailed errors for debugging

Applied to files:

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

Applied to files:

  • pkg/provisioner/source/cmd/delete.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 : Follow Go's error handling idioms: use meaningful error messages, wrap errors with context using `fmt.Errorf("context: %w", err)`, and consider using custom error types for domain-specific errors

Applied to files:

  • pkg/provisioner/source/cmd/delete.go
📚 Learning: 2024-10-21T17:51:53.976Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 727
File: internal/exec/terraform.go:114-118
Timestamp: 2024-10-21T17:51:53.976Z
Learning: When `atmos terraform clean --everything` is used without specifying a component and without the `--force` flag, prompt the user for confirmation before deleting all components. Use the `--force` flag to skip the confirmation prompt.

Applied to files:

  • pkg/provisioner/source/cmd/delete.go
  • website/blog/2026-01-14-source-provisioner-ux.mdx
  • pkg/provisioner/source/cmd/delete_test.go
  • pkg/provisioner/source/cmd/prompt.go
📚 Learning: 2025-01-30T19:30:59.120Z
Learnt from: samtholiya
Repo: cloudposse/atmos PR: 959
File: cmd/workflow.go:74-74
Timestamp: 2025-01-30T19:30:59.120Z
Learning: Error handling for `cmd.Usage()` is not required in the Atmos CLI codebase, as confirmed by the maintainer.

Applied to files:

  • pkg/provisioner/source/cmd/delete.go
📚 Learning: 2024-10-27T04:54:32.397Z
Learnt from: haitham911
Repo: cloudposse/atmos PR: 727
File: internal/exec/terraform_clean.go:314-319
Timestamp: 2024-10-27T04:54:32.397Z
Learning: When deleting empty folders in the `deleteFolders` function, handling errors from `os.Remove` are not required, as failures do not affect the process.

Applied to files:

  • pkg/provisioner/source/cmd/delete.go
  • pkg/provisioner/source/cmd/delete_test.go
📚 Learning: 2026-01-04T00:55:21.720Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-04T00:55:21.720Z
Learning: PRs labeled `minor` or `major` MUST update `website/src/data/roadmap.js` with shipped milestones, status, changelog link, PR number, and initiative progress percentage

Applied to files:

  • website/src/data/roadmap.js
📚 Learning: 2026-01-04T00:55:21.720Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-04T00:55:21.720Z
Learning: Applies to cmd/**/*_test.go : Always use `cmd.NewTestKit(t)` for cmd tests to auto-clean RootCmd state

Applied to files:

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

Applied to files:

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

Applied to files:

  • tests/cli_source_provisioner_test.go
  • pkg/provisioner/source/cmd/delete_test.go
  • tests/cli_source_provisioner_workdir_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 **/*.go : Use Viper for managing configuration, environment variables, and flags in CLI commands

Applied to files:

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

Applied to files:

  • tests/cli_source_provisioner_test.go
  • pkg/provisioner/source/cmd/delete_test.go
📚 Learning: 2025-12-24T04:29:23.938Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 1891
File: pkg/ci/terraform/templates/apply.md:17-17
Timestamp: 2025-12-24T04:29:23.938Z
Learning: In the cloudposse/atmos repository, Terraform CI templates (pkg/ci/terraform/templates/*.md) are rendered using TerraformTemplateContext (defined in pkg/ci/terraform/context.go), not the base ci.TemplateContext. TerraformTemplateContext provides top-level fields: .Resources (ci.ResourceCounts), .HasChanges() method, and .HasDestroy field, which are correctly accessed directly in templates without a .Result prefix.

Applied to files:

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

Applied to files:

  • tests/cli_source_provisioner_test.go
  • pkg/provisioner/source/cmd/delete_test.go
  • tests/cli_source_provisioner_workdir_test.go
📚 Learning: 2026-01-04T00:55:21.720Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-04T00:55:21.720Z
Learning: Commands MUST use `flags.NewStandardParser()` for command-specific flags and NEVER call `viper.BindEnv()` or `viper.BindPFlag()` directly

Applied to files:

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

Applied to files:

  • pkg/provisioner/source/cmd/delete_test.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:

  • pkg/provisioner/source/cmd/delete_test.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/provisioner/source/cmd/delete_test.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/provisioner/source/cmd/delete_test.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/provisioner/source/cmd/delete_test.go
📚 Learning: 2024-11-24T19:13:10.287Z
Learnt from: haitham911
Repo: cloudposse/atmos PR: 727
File: internal/exec/terraform_clean.go:407-416
Timestamp: 2024-11-24T19:13:10.287Z
Learning: In `internal/exec/terraform_clean.go`, when `getStackTerraformStateFolder` returns an error in the `handleCleanSubCommand` function, the error is logged, and the process continues without returning the error.

Applied to files:

  • pkg/provisioner/source/cmd/delete_test.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/provisioner/source/cmd/delete_test.go
  • tests/cli_source_provisioner_workdir_test.go
📚 Learning: 2024-10-27T04:28:40.966Z
Learnt from: haitham911
Repo: cloudposse/atmos PR: 727
File: internal/exec/terraform_clean.go:155-175
Timestamp: 2024-10-27T04:28:40.966Z
Learning: In the `CollectDirectoryObjects` function in `internal/exec/terraform_clean.go`, recursive search through all subdirectories is not needed.

Applied to files:

  • pkg/provisioner/source/cmd/delete_test.go
📚 Learning: 2025-12-13T04:37:25.223Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 1686
File: cmd/root.go:0-0
Timestamp: 2025-12-13T04:37:25.223Z
Learning: In Atmos cmd/root.go Execute(), after cfg.InitCliConfig, we must call both toolchainCmd.SetAtmosConfig(&atmosConfig) and toolchain.SetAtmosConfig(&atmosConfig) so the CLI wrapper and the toolchain package receive configuration; missing either can cause nil-pointer panics in toolchain path resolution.

Applied to files:

  • pkg/provisioner/source/cmd/delete_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:

  • pkg/provisioner/source/cmd/delete_test.go
  • tests/cli_source_provisioner_workdir_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:

  • pkg/provisioner/source/cmd/delete_test.go
  • tests/cli_source_provisioner_workdir_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:

  • pkg/provisioner/source/cmd/delete_test.go
  • tests/cli_source_provisioner_workdir_test.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:

  • pkg/provisioner/source/cmd/prompt.go
📚 Learning: 2025-12-13T06:10:25.156Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 1686
File: internal/exec/workflow_utils.go:0-0
Timestamp: 2025-12-13T06:10:25.156Z
Learning: Atmos workflows: In internal/exec/workflow_utils.go ExecuteWorkflow, non-identity steps intentionally use baseWorkflowEnv, which is constructed from the parent environment with PATH modifications for the toolchain. Avoid appending os.Environ() again; prefer documenting this behavior and testing that standard environment variables are preserved.

Applied to files:

  • tests/cli_source_provisioner_workdir_test.go
🧬 Code graph analysis (8)
pkg/provisioner/source/provision_hook.go (4)
pkg/ui/spinner/spinner.go (1)
  • ExecWithSpinner (22-64)
errors/builder.go (1)
  • Build (24-37)
errors/errors.go (1)
  • ErrSourceProvision (743-743)
pkg/provisioner/source/vendor.go (1)
  • VendorSource (33-97)
pkg/flags/interactive.go (4)
pkg/perf/perf.go (1)
  • Track (121-138)
internal/tui/templates/term/term_writer.go (1)
  • IsTTYSupportForStdin (133-135)
errors/errors.go (2)
  • ErrInteractiveNotAvailable (297-297)
  • ErrUserAborted (614-614)
internal/tui/utils/utils.go (1)
  • NewAtmosHuhTheme (166-188)
pkg/provisioner/source/cmd/describe.go (3)
pkg/provisioner/source/cmd/prompt.go (3)
  • PromptForComponent (21-31)
  • HandlePromptError (53-67)
  • PromptForStack (35-49)
errors/errors.go (1)
  • ErrInvalidPositionalArgs (92-92)
pkg/flags/parser.go (1)
  • GetString (117-126)
pkg/provisioner/source/cmd/pull.go (4)
pkg/provisioner/source/cmd/prompt.go (3)
  • PromptForComponent (21-31)
  • HandlePromptError (53-67)
  • PromptForStack (35-49)
errors/errors.go (2)
  • ErrInvalidPositionalArgs (92-92)
  • ErrRequiredFlagNotProvided (270-270)
pkg/flags/parser.go (2)
  • GetString (117-126)
  • GetBool (141-150)
pkg/flags/global_registry.go (1)
  • ParseGlobalFlags (33-77)
pkg/provisioner/source/cmd/list.go (1)
pkg/provisioner/source/cmd/prompt.go (2)
  • PromptForStack (35-49)
  • HandlePromptError (53-67)
pkg/provisioner/source/cmd/delete_test.go (1)
errors/errors.go (2)
  • ErrRequiredFlagNotProvided (270-270)
  • ErrInteractiveNotAvailable (297-297)
pkg/provisioner/source/cmd/prompt.go (2)
errors/exit_code.go (1)
  • ExitCodeSIGINT (12-12)
pkg/provisioner/source/extract.go (1)
  • HasSource (147-170)
tests/cli_source_provisioner_workdir_test.go (1)
cmd/root.go (1)
  • RootCmd (333-515)
⏰ 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 (windows)
  • GitHub Check: Acceptance Tests (linux)
  • GitHub Check: Summary
🔇 Additional comments (20)
website/src/data/roadmap.js (1)

290-298: Roadmap updates look good.

Progress bump from 60 to 83 aligns with the new shipped milestone. The "Source provisioner UX improvements" entry follows the established structure and documents the spinner feedback and interactive confirmation features appropriately.

pkg/provisioner/source/provision_hook.go (1)

125-151: Spinner integration is solid.

The refactor wraps vendoring in spinner.ExecWithSpinner with meaningful progress/completion messages. Error handling stays within the callback, and the package handles non-TTY fallback gracefully. Based on learnings, this aligns with providing progress indicators for long-running operations.

website/blog/2026-01-14-source-provisioner-ux.mdx (2)

12-69: Documentation is clear and actionable.

The before/after examples effectively demonstrate the UX improvements. The "How to Use It" section covers TTY vs non-TTY behavior and the --force escape hatch for scripts.


1-6: Blog post tags are valid. Both enhancement and dx are properly defined in website/blog/tags.yml. Frontmatter is correct.

pkg/provisioner/source/cmd/prompt.go (3)

1-17: Imports are well-organized.

Follows the three-group pattern: stdlib, third-party, then atmos packages with proper aliases (errUtils, cfg, log).


51-67: HandlePromptError exit behavior is correct.

Calling errUtils.Exit(errUtils.ExitCodeSIGINT) on user abort matches expected CLI behavior for Ctrl+C-style interrupts.


128-150: Helper functions are clean and focused.

Good use of source.HasSource from the extract package to centralize the source-detection logic. Type assertions are handled defensively.

Also applies to: 176-200, 229-252

pkg/provisioner/source/cmd/pull_test.go (1)

29-29: Usage string update is correct.

The change from <component> (required) to [component] (optional) accurately reflects the new interactive prompt behavior when component is omitted.

pkg/provisioner/source/cmd/list.go (1)

54-69: LGTM — Interactive stack prompting looks solid.

The pattern correctly handles the prompt flow: attempt interactive selection, process any prompt errors, then fall back to validation if still empty. The error shadowing in line 59 is intentional Go idiom — HandlePromptError receives the outer err from line 58.

pkg/provisioner/source/cmd/describe_test.go (1)

25-25: LGTM.

Usage string correctly updated to reflect optional component argument.

pkg/flags/interactive.go (1)

196-241: Solid implementation for destructive action confirmation.

Good use of huh for the prompt per project conventions. The behavioral difference from other prompts (returning ErrInteractiveNotAvailable vs empty string) is appropriate here — destructive actions should fail-safe rather than silently skip confirmation.

One consideration: this checks only IsTTYSupportForStdin(), while isInteractive() also checks viper.GetBool("interactive") and !telemetry.IsCI(). If the --interactive=false flag should also disable this confirmation, you'd want to incorporate that check. However, for destructive actions, requiring explicit --force in CI/non-interactive environments is likely the safer design.

tests/cli_source_provisioner_workdir_test.go (1)

87-105: Test setup and assertions look good.

Creating the target directory before delete and cleaning up after is the right approach. The expanded assertion correctly handles both --force requirement and interactive mode unavailability.

tests/cli_source_provisioner_test.go (1)

86-103: Test improvements are well-structured.

The Viper reset prevents flaky tests from flag leakage. Creating the target directory ensures the delete command has a real path to evaluate. Cleanup via t.Cleanup is the right pattern.

pkg/provisioner/source/cmd/describe.go (1)

22-50: LGTM on command structure updates.

The shift to RangeArgs(0, 1) with updated help text and examples clearly documents the interactive behavior. Well done.

pkg/provisioner/source/cmd/pull.go (1)

105-110: LGTM on CommonOptions construction.

Global flags parsed properly, and the Force/Identity flags are correctly extracted from Viper.

pkg/provisioner/source/cmd/delete_test.go (3)

48-67: Good addition: Force default test.

Validates the expected behavior when --force is omitted.


243-300: Solid non-TTY test coverage.

Tests the interactive path gracefully degrades with ErrInteractiveNotAvailable in non-TTY environments. This aligns with the PR objectives.


108-113: LGTM on force parameter additions.

Using force=true in tests to skip interactive prompts is the right approach for unit test isolation.

Also applies to: 140-141, 353-354

pkg/provisioner/source/cmd/delete.go (2)

191-202: Nice: Interactive confirmation with graceful degradation.

Good UX—warns the user about --force when non-interactive mode isn't available. This aligns with learned preferences for confirmation prompts. Based on learnings, using a confirmation prompt before destructive operations is the expected pattern.


204-217: Good: Spinner feedback during deletion.

Provides visual feedback for long-running operations as per coding guidelines and PR objectives.

✏️ Tip: You can disable this entire section by setting review_details to false in your review settings.

Add comprehensive tests to improve coverage from 33% to 80%+ target:

- prompt.go: Add DI function variables for testability, test pure functions
  (stackHasAnySource, stackContainsComponentWithSource, collectComponentsWithSource)
  and config-loading functions with mocks
- provision_hook_test.go: Add tests for needsProvisioning and AutoProvisionSource
- interactive_test.go: Add tests for PromptForConfirmation force and non-TTY paths

Coverage improvements:
- pkg/provisioner/source: 84.1%
- pkg/provisioner/source/cmd: 84.1%
- pkg/flags: 79.2%

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
@github-actions github-actions bot added size/xl Extra large size PR and removed size/l Large size PR labels Jan 14, 2026
@mergify
Copy link

mergify bot commented Jan 14, 2026

Warning

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

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

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

Fix 6 critical variable shadowing bugs identified by CodeRabbit where
`err` was being shadowed in prompt error handling blocks. The pattern:

```go
var err error
value, err = PromptFunc(cmd)
if err := HandlePromptError(err, "name"); err != nil {
```

Was causing the original `err` to be shadowed by the `if` statement's
short variable declaration. This could lead to prompt errors being
silently ignored.

Fixed by renaming the prompt result variable to `promptErr` to avoid
shadowing in all affected locations:
- delete.go: component prompt and stack prompt in parseDeleteFlags
- describe.go: component prompt and stack prompt
- pull.go: component prompt and stack prompt

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
coderabbitai[bot]
coderabbitai bot previously approved these changes Jan 14, 2026
@aknysh aknysh merged commit b18051e into main Jan 14, 2026
57 checks passed
@aknysh aknysh deleted the osterman/source-ux-spinner branch January 14, 2026 18:25
@github-actions
Copy link

These changes were released in v1.204.0-rc.5.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

minor New features that do not break anything size/xl Extra large size PR

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants