feat: Add multiple terraform output formats for CI integration @osterman (#1885)
## Summary - Moved all terraform output execution logic from `internal/exec/` to new `pkg/terraform/output/` package - Implemented dependency injection pattern using `ComponentDescriber` interface to eliminate circular dependency - Created backward-compatible wrappers to maintain API compatibility - Added 39 comprehensive unit tests with 89 total passing testsWhat Changed
- Architecture: Package-based dependency injection removes circular dependency
- Logic: No behavioral changes, same functionality with improved organization
- Testing: Comprehensive unit test coverage with mocks for testability
- Performance: Identical behavior, slight code organization improvements
Verification
- ✅
make buildpasses - ✅
make lintpasses (0 issues) - ✅ All 89 tests pass
- ✅ No circular dependencies
🤖 Generated with Claude Code
Summary by CodeRabbit
-
New Features
- terraform output: new --format (json,yaml,hcl,env,dotenv,bash,csv,tsv), --output-file, --uppercase and --flatten; supports single-output or all-outputs and write-to-file.
- Automatic generation of Terraform backend and provider override files; improved workspace handling and a TTY-aware spinner for CLI feedback.
-
Tests
- Extensive unit and integration tests covering formatting, executor, backend, environment and workspace behaviors.
-
Documentation
- CLI docs and blog post for output formatting and examples.
- Added “Concurrent Sessions (MANDATORY)” guidance.
✏️ Tip: You can customize this high-level summary in your review settings.
feat: Add native Terraform provider caching with XDG support @osterman (#1882)
## whatAtmos now automatically caches Terraform providers across all components using the TF_PLUGIN_CACHE_DIR environment variable with XDG-compliant default paths (~/.cache/atmos/terraform/plugins). This feature is enabled by default with zero configuration required, dramatically reducing terraform init times and network bandwidth.
why
In large Atmos projects with many components, each terraform init downloads the same providers repeatedly. For the AWS provider alone, this can mean downloading 300+ MB per component. With provider caching, Atmos downloads each provider version once and reuses it across all components - achieving 10-50x faster init times in testing.
references
This implements automatic provider caching with validation for invalid TF_PLUGIN_CACHE_DIR values (empty string or root path) and respects user overrides via environment variables or atmos.yaml configuration.
Summary by CodeRabbit
-
New Features
- Zero‑config Terraform provider caching enabled by default with optional custom cache directory and new terraform clean --cache flag (supports --force, dry‑run, interactive and non‑TTY flows). Exposes ATMOS_COMPONENTS_TERRAFORM_PLUGIN_CACHE and ATMOS_COMPONENTS_TERRAFORM_PLUGIN_CACHE_DIR plus TF_PLUGIN_CACHE_DIR behavior.
-
Documentation
- Added blog and CLI docs with examples, flags, and env var references.
-
Tests
- Extensive unit and end‑to‑end tests for configuration, cache path resolution, init/reuse, and cleaning.
✏️ Tip: You can customize this high-level summary in your review settings.
feat: Create pkg/runner with unified task execution @osterman (#1901)
## what- Introduced
pkg/runnerpackage with unified Task type and CommandRunner interface - Tasks support flexible YAML parsing for both simple strings and structured syntax with timeout, retry, and identity config
- Timeout enforcement via context.WithTimeout
- Proper shell argument parsing using mvdan.cc/sh for quote handling
- Updated custom commands to use the new Tasks type, enabling backward compatibility while supporting new syntax
why
Provides a shared execution layer for both custom commands and workflows, enabling code reuse and consistent task execution patterns across Atmos. Fixes DEV-3005.
references
Closes #DEV-3005
Summary by CodeRabbit
-
New Features
- Unified task runner with structured per-step entries (timeout, retry, working_directory, stack) and support for shell and atmos task types.
-
Breaking Change
- Command step format changed from simple string lists to structured Tasks — update custom command definitions accordingly.
-
Tests
- Expanded tests and new mocks/helpers covering runner behavior, YAML decoding, task parsing, timeouts, overrides, and sequential execution.
-
Chores
- Config decoding updated to handle the new task formats.
-
Documentation
- Blog post documenting the unified task runner and Task formats.
✏️ Tip: You can customize this high-level summary in your review settings.
🚀 Enhancements
fix: Terraform state path for disabled workspaces @aknysh (#1929)
## what- Fixed
!terraform.stateYAML function to use correct state file paths when Terraform workspaces are disabled (workspaces_enabled: false) - For S3 backend: state is now correctly read from
<key>instead of<workspace_key_prefix>/default/<key> - For Local backend: state is now correctly read from
terraform.tfstateinstead ofterraform.tfstate.d/default/terraform.tfstate - Added comprehensive unit tests for both S3 and local backend default workspace handling
- Added integration tests with a new test fixture for workspaces-disabled scenario
why
- When
workspaces_enabled: falseis set in atmos.yaml, Atmos sets the workspace to "default" but Terraform stores state at different paths for the default workspace vs named workspaces:- S3 backend: Default workspace stores state at
<key>, not<workspace_key_prefix>/default/<key> - Local backend: Default workspace stores state at
terraform.tfstate, notterraform.tfstate.d/default/terraform.tfstate
- S3 backend: Default workspace stores state at
- The
!terraform.stateYAML function was looking in the wrong locations, causing it to fail to find state files when workspaces are disabled - This aligns with Terraform's documented behavior for backend state storage
references
- closes #1920
Summary by CodeRabbit
-
Bug Fixes
- Fixed Terraform state lookup so default/disabled workspaces read state from the root terraform.tfstate location across backends (local, S3, Azure).
-
Tests
- Added unit and end-to-end tests covering state reads and path resolution for default, empty, and named workspaces.
-
Documentation
- Added fixtures and a blog post explaining behavior and upgrade notes when workspaces are disabled.
✏️ Tip: You can customize this high-level summary in your review settings.