feat: Add automatic backend provisioning#1808
Conversation
Implement automatic Terraform backend provisioning system to eliminate manual bootstrapping steps. Includes extensible provisioner architecture, S3 backend implementation with hardcoded security defaults (versioning, AES-256 encryption, public access blocking), cross-account support via role assumption, and CLI commands for dev/test workflows. Features: - Self-registering provisioner system via hooks - S3 backend provisioner with opinionated security defaults - Automatic provisioning before terraform init - Manual provisioning via `atmos provision backend` command - Cross-account support with AuthManager integration - Idempotent operations (safe to run multiple times) - Production migration path with Terraform import blocks Documentation: - 3 PRDs: provisioner-system, backend-provisioner, s3-backend-provisioner - CLI reference: website/docs/cli/commands/provision/backend.mdx - Configuration guide: backends.mdx with automatic provisioning section - Blog post: Announcing automatic backend provisioning 🤖 Generated with Claude Code Co-Authored-By: Claude <noreply@anthropic.com>
📝 WalkthroughWalkthroughAdds an in-process backend provisioning system and CLI for Terraform state backends, registers and executes provisioner hooks before Terraform init, implements S3 create/delete provisioners (AWS interactions, assume-role support), provides CLI DI/helpers and tests, and wires a new Changes
Sequence Diagram(s)sequenceDiagram
autonumber
participant User
participant CLI as "atmos CLI"
participant BackendCmd as "backend subcommand"
participant Config as "InitConfigAndAuth"
participant Prov as "Provisioner (ProvisionWithParams)"
participant BackendPkg as "pkg/provisioner/backend"
participant Registry as "Provisioner Registry"
participant S3 as "S3 Provisioner"
participant AWS
User->>CLI: atmos terraform backend create <component>
CLI->>BackendCmd: dispatch create command
BackendCmd->>Config: Parse flags → InitConfigAndAuth(component, stack, identity)
Config-->>BackendCmd: return atmosConfig + authContext + componentConfig
BackendCmd->>Prov: call ProvisionWithParams(...)
Prov->>BackendPkg: ProvisionBackend(ctx, atmosConfig, componentConfig, authContext)
BackendPkg->>Registry: GetBackendCreate(backend_type)
Registry->>S3: invoke CreateS3Backend(ctx,...)
S3->>AWS: load creds / assume role (if configured)
AWS-->>S3: creds
S3->>AWS: HeadBucket
alt bucket missing
S3->>AWS: CreateBucket
end
S3->>AWS: PutBucketVersioning / PutBucketEncryption / PutPublicAccessBlock / PutBucketTagging
AWS-->>S3: ops success
S3-->>BackendPkg: success
BackendPkg-->>Prov: success
Prov-->>BackendCmd: success
BackendCmd-->>User: success message
Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes Points to focus review on:
Possibly related PRs
Suggested reviewers
Pre-merge checks and finishing touches❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✨ Finishing touches🧪 Generate unit tests (beta)
Warning Review ran into problems🔥 ProblemsErrors were encountered while retrieving linked issues. Errors (1)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
|
Warning This PR exceeds the recommended limit of 1,000 lines.Large PRs are difficult to review and may be rejected due to their size. Please verify that this PR does not address multiple issues. |
Dependency Review✅ No vulnerabilities or license issues found.Scanned FilesNone |
Update all PRDs and documentation to clarify that provision blocks can be specified at multiple levels in the stack hierarchy (top-level terraform, environment-level, component-level) and leverage Atmos's deep-merge system. Changes: - Add "Configuration Hierarchy" sections to all 3 PRDs showing inheritance patterns - Update CLI docs with hierarchy examples (global defaults, environment overrides, catalog inheritance) - Enhance core concepts backends.mdx with hierarchy section showing typical dev/prod patterns - Add "Configuration Flexibility" section to blog post demonstrating multi-level configuration - Fix broken documentation links (/core-concepts/backends/migration-to-production doesn't exist) Benefits: - Users can now set defaults at org/env level instead of repeating per component - Clear guidance on dev (auto-provision) vs prod (pre-provisioned) patterns - Inheritance via metadata.inherits now documented - Component-level overrides explained 🤖 Generated with Claude Code Co-Authored-By: Claude <noreply@anthropic.com>
There was a problem hiding this comment.
Actionable comments posted: 3
🧹 Nitpick comments (9)
docs/prd/s3-backend-provisioner.md (1)
413-426: Be explicit aboutHeadBucketerror handling semantics
checkS3BucketExistscurrently treats any error fromHeadBucketas “bucket does not exist” and returns(false, nil):if err != nil { // Bucket doesn't exist or access denied (treat as doesn't exist) return false, nil }That’s fine for the happy path (we’ll immediately try
CreateBucketand get a clearer error), but it also masks transient/network issues as “non-existent”. If you later add retry/backoff or richer error reporting, this is a spot worth revisiting to distinguish “definitely not found” from “couldn’t check”. For now the behavior is acceptable but should stay intentional.docs/prd/backend-provisioner.md (1)
340-352: Optional: clean up markdownlint issues in PRDThe PRD looks solid conceptually. Static analysis is flagging a bunch of markdown nits (hard tabs in code fences, some fences without a language like around the configuration filtering and error examples). If you run markdownlint as part of docs CI, these will likely show up:
MD010(no-hard-tabs) on many Go/YAML blocksMD040(fenced-code-language) on a few unlabeled fencesNot urgent, but worth a quick pass (or a markdownlint ignore) before merging if your pipeline enforces these.
Also applies to: 616-655
docs/prd/provisioner-system.md (1)
525-545: Optional: address markdownlint warningsThis PRD is thorough and lines up with the implementation. The only issues flagged by tooling are markdown hygiene:
- Hard tabs in many Go/YAML blocks (
MD010)- A few code fences without a language (
MD040)- One “emphasis as heading” case (
MD036) near the exit-code tableIf markdownlint is wired into CI, consider normalizing indentation to spaces and adding explicit languages (e.g.,
go,yaml) where missing, or updating the lint config for PRDs.Also applies to: 1013-1045
internal/exec/terraform.go (1)
24-30: Wire provisioners to pre-init hook using shared event constantThe new calls to:
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Minute) err = provisioner.ExecuteProvisioners(ctx, provisioner.HookEvent(beforeTerraformInitEvent), &atmosConfig, info.ComponentSection, info.AuthContext)nicely ensure all registered provisioners run before any
terraform init, both in the general path and the explicitinitsubcommand. The 5‑minute timeout is a reasonable bound for backend provisioning.One tweak to reduce drift risk: you already defined
BeforeTerraformInitinpkg/hooks/event.go. Instead of a local string:const ( beforeTerraformInitEvent = "before.terraform.init" )you could reuse the shared constant and avoid duplicate literals, e.g.:
-import ( - // ... - "github.com/cloudposse/atmos/pkg/provisioner" - // ... -) +import ( + // ... + "github.com/cloudposse/atmos/pkg/hooks" + "github.com/cloudposse/atmos/pkg/provisioner" + // ... +) - -const ( - beforeTerraformInitEvent = "before.terraform.init" -) +// Use shared hook event name for pre-init provisioners. + ... -err = provisioner.ExecuteProvisioners(ctx, provisioner.HookEvent(beforeTerraformInitEvent), &atmosConfig, info.ComponentSection, info.AuthContext) +err = provisioner.ExecuteProvisioners(ctx, provisioner.HookEvent(hooks.BeforeTerraformInit), &atmosConfig, info.ComponentSection, info.AuthContext)Same change can be applied in the
case "init"branch. This keeps the hook event name single-sourced and less error-prone if you ever rename it.Also applies to: 420-429, 522-531
pkg/provisioner/backend/s3.go (1)
186-272: Be careful when applying defaults to pre-existing bucketsRight now
applyS3BucketDefaultsalways:
- Forces encryption to SSE-S3 AES-256.
- Replaces the entire tag set with just
NameandManagedBy=Atmos.On a bucket that already exists (e.g., pre-provisioned or shared), this will silently:
- Downgrade or change a KMS-based encryption policy.
- Wipe any existing tags unrelated to Atmos.
For a dev/test-only provisioner this may be acceptable, but it’s a sharp edge if someone points it at a shared or production-style bucket.
Consider one of:
- Detecting whether the bucket was just created vs. pre-existing and only enforcing hard defaults on new buckets.
- Merging tags instead of replacing them wholesale, and skipping encryption changes if a non-AES256 policy is already configured.
- At minimum, making this overwrite behavior very explicit in docs and error messages.
website/docs/core-concepts/components/terraform/backends.mdx (1)
643-657: Clarify YAML context forbackend/provisionsnippetsThe examples under “Configuration” and “Supported Backend Types → S3” show
backend:andprovision:as top-level keys, but earlier in this doc the S3 backend examples are always nested under the component path (components.terraform.<component>.backend).To avoid confusion, it would help to mirror that full context here, e.g.:
components: terraform: vpc: backend: bucket: acme-terraform-state-dev key: vpc/terraform.tfstate region: us-east-1 backend_type: s3 provision: backend: enabled: trueSame idea for the cross-account example. That keeps the docs aligned with how
ProvisionBackendand the stack manifests actually structure component config.Also applies to: 753-781
pkg/provision/provision.go (1)
25-61: Consider plumbing AuthContext intoProvisionfor manual CLI usageThe implementation is straightforward and correct for backend provisioning, but
Provisionalways calls:err = backend.ProvisionBackend(ctx, atmosConfig, componentConfig, nil)so manual
atmos provision backend ...runs can’t benefit from Atmos-managed auth (e.g.,--identity/ AuthManager) and instead rely solely on the default AWS credential chain.If you want the manual provision command to behave like the Terraform path (which passes an
AuthContext), consider:
- Extending
ExecuteDescribeComponentFuncto also surface an*schema.AuthContext, or- Adding an explicit
authContext *schema.AuthContextparameter toProvisionand wiring it from the caller.That would make cross-account and SSO-based provisioning consistent across both automatic and manual flows.
cmd/provision/provision.go (1)
50-98: Verify config/init and consider passing AuthContext into provisioningA couple of small points in
RunE:
- You correctly use
StandardParser+ Viper for--stack(withATMOS_STACKenv support) and validate the flag; that’s consistent with the existing flag patterns.- You call
cfg.InitCliConfigwithprocessStacks=false, then separately callExecuteDescribeComponent, which will do its own stack processing. That’s probably fine, but it does mean config init work is split between two places—worth a quick sanity check against existing commands that useExecuteDescribeComponentto ensure behavior is consistent.- As in
pkg/provision.Provision, you don’t currently plumb anyAuthContextfrom the identity/CLI layer into backend provisioning, soatmos provision backendalways falls back to the default AWS SDK credential chain.If you want manual provisioning to honor
--identityand the AuthManager flow, you’ll likely need to:
- Grab the active
AuthContext(from the same placeinternal/exec/terraformdoes), and- Pass it down into
provision.Provision/backend.ProvisionBackend.Not urgent for a first cut, but it will make the manual command match the automatic Terraform-init provisioning behavior.
pkg/provisioner/backend/backend.go (1)
13-21: Consider defining hook event constants.The hook event
"before.terraform.init"is hardcoded as a string literal. If hook events are used across multiple provisioners, defining them as constants (e.g.,const HookBeforeTerraformInit HookEvent = "before.terraform.init") would prevent typos and improve discoverability.For example, in a separate constants file or in
pkg/provisioner/provisioner.go:const ( HookBeforeTerraformInit HookEvent = "before.terraform.init" HookAfterTerraformInit HookEvent = "after.terraform.init" // ... other hooks )Then use it here:
- HookEvent: "before.terraform.init", + HookEvent: HookBeforeTerraformInit,
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Disabled knowledge base sources:
- Linear integration is disabled by default for public repositories
You can enable these sources in your CodeRabbit configuration.
📒 Files selected for processing (15)
cmd/provision/provision.go(1 hunks)cmd/root.go(1 hunks)docs/prd/backend-provisioner.md(1 hunks)docs/prd/provisioner-system.md(1 hunks)docs/prd/s3-backend-provisioner.md(1 hunks)internal/exec/terraform.go(4 hunks)pkg/hooks/event.go(1 hunks)pkg/provision/provision.go(1 hunks)pkg/provisioner/backend/backend.go(1 hunks)pkg/provisioner/backend/s3.go(1 hunks)pkg/provisioner/errors.go(1 hunks)pkg/provisioner/provisioner.go(1 hunks)website/blog/2025-11-20-automatic-backend-provisioning.mdx(1 hunks)website/docs/cli/commands/provision/backend.mdx(1 hunks)website/docs/core-concepts/components/terraform/backends.mdx(1 hunks)
🧰 Additional context used
🧠 Learnings (30)
📓 Common learnings
Learnt from: Listener430
Repo: cloudposse/atmos PR: 934
File: tests/fixtures/scenarios/docs-generate/README.md.gotmpl:99-118
Timestamp: 2025-01-25T03:51:57.689Z
Learning: For the cloudposse/atmos repository, changes to template contents should be handled in dedicated PRs and are typically considered out of scope for PRs focused on other objectives.
Learnt from: aknysh
Repo: cloudposse/atmos PR: 944
File: go.mod:206-206
Timestamp: 2025-01-17T00:18:57.769Z
Learning: For indirect dependencies with license compliance issues in the cloudposse/atmos repository, the team prefers to handle them in follow-up PRs rather than blocking the current changes, as these issues often require deeper investigation of the dependency tree.
📚 Learning: 2025-09-13T16:39:20.007Z
Learnt from: samtholiya
Repo: cloudposse/atmos PR: 1466
File: cmd/markdown/atmos_toolchain_aliases.md:2-4
Timestamp: 2025-09-13T16:39:20.007Z
Learning: In the cloudposse/atmos repository, CLI documentation files in cmd/markdown/ follow a specific format that uses " $ atmos command" (with leading space and dollar sign prompt) in code blocks. This is the established project convention and should not be changed to comply with standard markdownlint rules MD040 and MD014.
Applied to files:
website/docs/cli/commands/provision/backend.mdx
📚 Learning: 2025-01-19T15:49:15.593Z
Learnt from: samtholiya
Repo: cloudposse/atmos PR: 955
File: tests/snapshots/TestCLICommands_atmos_validate_editorconfig_--help.stdout.golden:0-0
Timestamp: 2025-01-19T15:49:15.593Z
Learning: In future commits, the help text for Atmos CLI commands should be limited to only show component and stack parameters for commands that actually use them. This applies to the example usage section in command help text.
Applied to files:
website/docs/cli/commands/provision/backend.mdx
📚 Learning: 2024-12-03T05:29:07.718Z
Learnt from: aknysh
Repo: cloudposse/atmos PR: 810
File: internal/exec/terraform_utils.go:145-146
Timestamp: 2024-12-03T05:29:07.718Z
Learning: In the Atmos project, a 5-minute timeout in the `execTerraformOutput` function is acceptable for retrieving `terraform output` for a component in a stack.
Applied to files:
website/docs/cli/commands/provision/backend.mdx
📚 Learning: 2025-09-10T21:17:55.273Z
Learnt from: samtholiya
Repo: cloudposse/atmos PR: 1466
File: toolchain/http_client_test.go:3-10
Timestamp: 2025-09-10T21:17:55.273Z
Learning: In the cloudposse/atmos repository, imports should never be changed as per samtholiya's coding guidelines.
Applied to files:
cmd/root.go
📚 Learning: 2025-07-05T20:59:02.914Z
Learnt from: aknysh
Repo: cloudposse/atmos PR: 1363
File: internal/exec/template_utils.go:18-18
Timestamp: 2025-07-05T20:59:02.914Z
Learning: In the Atmos project, gomplate v4 is imported with a blank import (`_ "github.com/hairyhenderson/gomplate/v4"`) alongside v3 imports to resolve AWS SDK version conflicts. V3 uses older AWS SDK versions that conflict with newer AWS modules used by Atmos. A full migration to v4 requires extensive refactoring due to API changes and should be handled in a separate PR.
Applied to files:
cmd/root.gointernal/exec/terraform.go
📚 Learning: 2024-12-07T16:16:13.038Z
Learnt from: Listener430
Repo: cloudposse/atmos PR: 825
File: internal/exec/helmfile_generate_varfile.go:28-31
Timestamp: 2024-12-07T16:16:13.038Z
Learning: In `internal/exec/helmfile_generate_varfile.go`, the `--help` command (`./atmos helmfile generate varfile --help`) works correctly without requiring stack configurations, and the only change needed was to make `ProcessCommandLineArgs` exportable by capitalizing its name.
Applied to files:
cmd/root.gocmd/provision/provision.go
📚 Learning: 2024-12-11T18:40:12.808Z
Learnt from: Listener430
Repo: cloudposse/atmos PR: 844
File: cmd/helmfile.go:37-37
Timestamp: 2024-12-11T18:40:12.808Z
Learning: In the atmos project, `cliConfig` is initialized within the `cmd` package in `root.go` and can be used in other command files.
Applied to files:
cmd/root.gocmd/provision/provision.gointernal/exec/terraform.go
📚 Learning: 2025-10-07T00:25:16.333Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 1498
File: website/src/components/Screengrabs/atmos-terraform-metadata--help.html:25-55
Timestamp: 2025-10-07T00:25:16.333Z
Learning: In Atmos CLI, subcommands inherit flags from their parent commands via Cobra's command inheritance. For example, `atmos terraform metadata --help` shows `--affected` and related flags inherited from the parent `terraform` command (defined in cmd/terraform.go), even though the metadata subcommand doesn't explicitly define these flags. This is expected Cobra behavior and auto-generated help screengrabs accurately reflect this inheritance.
Applied to files:
cmd/root.gocmd/provision/provision.go
📚 Learning: 2025-10-10T23:51:36.597Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 1599
File: internal/exec/terraform.go:394-402
Timestamp: 2025-10-10T23:51:36.597Z
Learning: In Atmos (internal/exec/terraform.go), when adding OpenTofu-specific flags like `--var-file` for `init`, do not gate them based on command name (e.g., checking if `info.Command == "tofu"` or `info.Command == "opentofu"`) because command names don't reliably indicate the actual binary being executed (symlinks, aliases). Instead, document the OpenTofu requirement in code comments and documentation, trusting users who enable the feature (e.g., `PassVars`) to ensure their terraform command points to an OpenTofu binary.
Applied to files:
cmd/root.gocmd/provision/provision.go
📚 Learning: 2025-09-27T20:50:20.564Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 1533
File: pkg/config/load.go:585-637
Timestamp: 2025-09-27T20:50:20.564Z
Learning: In the cloudposse/atmos repository, command merging prioritizes precedence over display ordering. Help commands are displayed lexicographically regardless of internal array order, so the mergeCommandArrays function focuses on ensuring the correct precedence chain (top-level file wins) rather than maintaining specific display order.
Applied to files:
cmd/root.go
📚 Learning: 2025-01-30T19:30:59.120Z
Learnt from: samtholiya
Repo: cloudposse/atmos PR: 959
File: cmd/workflow.go:74-74
Timestamp: 2025-01-30T19:30:59.120Z
Learning: Error handling for `cmd.Usage()` is not required in the Atmos CLI codebase, as confirmed by the maintainer.
Applied to files:
cmd/root.go
📚 Learning: 2024-10-20T13:12:46.499Z
Learnt from: haitham911
Repo: cloudposse/atmos PR: 736
File: pkg/config/const.go:6-6
Timestamp: 2024-10-20T13:12:46.499Z
Learning: In `cmd/cmd_utils.go`, it's acceptable to have hardcoded references to `atmos.yaml` in logs, and it's not necessary to update them to use the `CliConfigFileName` constant.
Applied to files:
cmd/root.go
📚 Learning: 2024-10-23T21:36:40.262Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 740
File: cmd/cmd_utils.go:340-359
Timestamp: 2024-10-23T21:36:40.262Z
Learning: In the Go codebase for Atmos, when reviewing functions like `checkAtmosConfig` in `cmd/cmd_utils.go`, avoid suggesting refactoring to return errors instead of calling `os.Exit` if such changes would significantly increase the scope due to the need to update multiple call sites.
Applied to files:
cmd/root.gointernal/exec/terraform.go
📚 Learning: 2025-11-09T19:06:58.470Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 1752
File: pkg/profile/list/formatter_table.go:27-29
Timestamp: 2025-11-09T19:06:58.470Z
Learning: In the cloudposse/atmos repository, performance tracking with `defer perf.Track()` is enforced on all functions via linting, including high-frequency utility functions, formatters, and renderers. This is a repository-wide policy to maintain consistency and avoid making case-by-case judgment calls about which functions should have profiling.
Applied to files:
cmd/root.gointernal/exec/terraform.go
📚 Learning: 2025-11-08T19:56:18.660Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 1697
File: internal/exec/oci_utils.go:0-0
Timestamp: 2025-11-08T19:56:18.660Z
Learning: In the Atmos codebase, when a function receives an `*schema.AtmosConfiguration` parameter, it should read configuration values from `atmosConfig.Settings` fields rather than using direct `os.Getenv()` or `viper.GetString()` calls. The Atmos pattern is: viper.BindEnv in cmd/root.go binds environment variables → Viper unmarshals into atmosConfig.Settings via mapstructure → business logic reads from the Settings struct. This provides centralized config management, respects precedence, and enables testability. Example: `atmosConfig.Settings.AtmosGithubToken` instead of `os.Getenv("ATMOS_GITHUB_TOKEN")` in functions like `getGHCRAuth` in internal/exec/oci_utils.go.
Applied to files:
cmd/provision/provision.gointernal/exec/terraform.go
📚 Learning: 2025-11-10T03:03:31.505Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 0
File: :0-0
Timestamp: 2025-11-10T03:03:31.505Z
Learning: In the Atmos codebase, commands using the `StandardParser` flag pattern (from pkg/flags) do NOT need explicit `viper.BindPFlag()` calls in their code. The StandardParser encapsulates flag binding internally: flags are registered via `parser.RegisterFlags(cmd)` in init(), and bound via `parser.BindFlagsToViper(cmd, v)` in RunE, which internally calls viper.BindPFlag for each flag. This pattern is used throughout Atmos (e.g., cmd/toolchain/get.go, cmd/toolchain/info.go, cmd/toolchain/install.go, cmd/toolchain/path.go). Do not flag missing viper.BindPFlag calls when StandardParser is used.
Applied to files:
cmd/provision/provision.go
📚 Learning: 2025-01-09T22:27:25.538Z
Learnt from: samtholiya
Repo: cloudposse/atmos PR: 914
File: cmd/validate_stacks.go:20-23
Timestamp: 2025-01-09T22:27:25.538Z
Learning: The validate commands in Atmos can have different help handling implementations. Specifically, validate_component.go and validate_stacks.go are designed to handle help requests differently, with validate_stacks.go including positional argument checks while validate_component.go does not.
Applied to files:
cmd/provision/provision.go
📚 Learning: 2025-01-25T03:51:57.689Z
Learnt from: Listener430
Repo: cloudposse/atmos PR: 934
File: tests/fixtures/scenarios/docs-generate/README.md.gotmpl:99-118
Timestamp: 2025-01-25T03:51:57.689Z
Learning: For the cloudposse/atmos repository, changes to template contents should be handled in dedicated PRs and are typically considered out of scope for PRs focused on other objectives.
Applied to files:
website/blog/2025-11-20-automatic-backend-provisioning.mdx
📚 Learning: 2025-10-03T18:02:08.535Z
Learnt from: Benbentwo
Repo: cloudposse/atmos PR: 1475
File: internal/exec/terraform.go:269-272
Timestamp: 2025-10-03T18:02:08.535Z
Learning: In internal/exec/terraform.go, when auth.TerraformPreHook fails, the error is logged but execution continues. This is a deliberate design choice to allow Terraform commands to proceed even if authentication setup fails, rather than failing fast.
Applied to files:
internal/exec/terraform.godocs/prd/provisioner-system.mddocs/prd/backend-provisioner.md
📚 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:
internal/exec/terraform.go
📚 Learning: 2024-12-03T03:52:02.524Z
Learnt from: aknysh
Repo: cloudposse/atmos PR: 810
File: internal/exec/terraform_utils.go:144-145
Timestamp: 2024-12-03T03:52:02.524Z
Learning: Avoid adding context timeouts to Terraform commands in `execTerraformOutput` because their execution time can vary from seconds to hours, and making it configurable would require redesigning the command interface.
Applied to files:
internal/exec/terraform.go
📚 Learning: 2024-12-05T22:33:40.955Z
Learnt from: aknysh
Repo: cloudposse/atmos PR: 820
File: cmd/list_components.go:53-54
Timestamp: 2024-12-05T22:33:40.955Z
Learning: In the Atmos CLI Go codebase, using `u.LogErrorAndExit` within completion functions is acceptable because it logs the error and exits the command execution.
Applied to files:
internal/exec/terraform.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:
internal/exec/terraform.go
📚 Learning: 2025-09-13T18:06:07.674Z
Learnt from: samtholiya
Repo: cloudposse/atmos PR: 1466
File: toolchain/list.go:39-42
Timestamp: 2025-09-13T18:06:07.674Z
Learning: In the cloudposse/atmos repository, for UI messages in the toolchain package, use utils.PrintfMessageToTUI instead of log.Error or fmt.Fprintln(os.Stderr, ...). Import pkg/utils with alias "u" to follow the established pattern.
Applied to files:
internal/exec/terraform.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:
internal/exec/terraform.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:
internal/exec/terraform.go
📚 Learning: 2025-08-16T23:32:40.412Z
Learnt from: aknysh
Repo: cloudposse/atmos PR: 1405
File: internal/exec/describe_dependents_test.go:455-456
Timestamp: 2025-08-16T23:32:40.412Z
Learning: In the cloudposse/atmos Go codebase, `InitCliConfig` returns a `schema.AtmosConfiguration` value (not a pointer), while `ExecuteDescribeDependents` expects a `*schema.AtmosConfiguration` pointer parameter. Therefore, when passing the result of `InitCliConfig` to `ExecuteDescribeDependents`, use `&atmosConfig` to pass the address of the value.
Applied to files:
internal/exec/terraform.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:
internal/exec/terraform.go
📚 Learning: 2025-04-26T15:54:10.506Z
Learnt from: haitham911
Repo: cloudposse/atmos PR: 1195
File: internal/exec/terraform_clean.go:99-99
Timestamp: 2025-04-26T15:54:10.506Z
Learning: The error variable `ErrRelPath` is defined in `internal/exec/terraform_clean_util.go` and is used across files in the `exec` package, including in `terraform_clean.go`. This is part of an approach to standardize error handling in the codebase.
Applied to files:
pkg/provisioner/errors.go
🧬 Code graph analysis (7)
pkg/hooks/event.go (1)
pkg/provisioner/provisioner.go (1)
HookEvent(14-14)
pkg/provisioner/backend/s3.go (6)
pkg/provisioner/backend/backend.go (1)
RegisterBackendProvisioner(38-45)pkg/schema/schema.go (3)
AtmosConfiguration(53-94)AuthContext(568-578)AWSAuthContext(582-597)pkg/perf/perf.go (1)
Track(121-138)pkg/provisioner/errors.go (10)
ErrLoadAWSConfig(13-13)ErrApplyBucketDefaults(16-16)ErrBucketRequired(7-7)ErrRegionRequired(8-8)ErrCheckBucketExist(14-14)ErrCreateBucket(15-15)ErrEnableVersioning(17-17)ErrEnableEncryption(18-18)ErrBlockPublicAccess(19-19)ErrApplyTags(20-20)pkg/ui/formatter.go (1)
Success(169-175)internal/aws_utils/aws_utils.go (1)
LoadAWSConfigWithAuth(53-119)
cmd/provision/provision.go (9)
pkg/schema/schema.go (2)
AtmosConfiguration(53-94)ConfigAndStacksInfo(620-714)pkg/flags/standard_parser.go (2)
StandardParser(18-22)NewStandardParser(34-40)pkg/perf/perf.go (1)
Track(121-138)pkg/flags/global_registry.go (1)
ParseGlobalFlags(33-74)errors/errors.go (2)
ErrRequiredFlagNotProvided(188-188)ErrFailedToInitConfig(386-386)pkg/config/config.go (1)
InitCliConfig(25-64)internal/exec/describe_component.go (1)
ExecuteDescribeComponentParams(202-209)pkg/provision/provision.go (1)
Provision(27-62)pkg/flags/options.go (2)
WithStringFlag(37-48)WithEnvVars(221-244)
pkg/provisioner/provisioner.go (3)
pkg/schema/schema.go (2)
AtmosConfiguration(53-94)AuthContext(568-578)pkg/hooks/event.go (1)
HookEvent(3-3)pkg/perf/perf.go (1)
Track(121-138)
pkg/provisioner/backend/backend.go (4)
pkg/provisioner/provisioner.go (3)
RegisterProvisioner(46-53)Provisioner(27-36)HookEvent(14-14)pkg/schema/schema.go (2)
AtmosConfiguration(53-94)AuthContext(568-578)pkg/perf/perf.go (1)
Track(121-138)pkg/provisioner/errors.go (3)
ErrBackendNotFound(9-9)ErrBackendTypeRequired(10-10)ErrNoProvisionerFound(11-11)
internal/exec/terraform.go (2)
pkg/provisioner/provisioner.go (2)
ExecuteProvisioners(75-96)HookEvent(14-14)pkg/schema/schema.go (1)
AuthContext(568-578)
pkg/provision/provision.go (4)
pkg/schema/schema.go (1)
AtmosConfiguration(53-94)pkg/perf/perf.go (1)
Track(121-138)pkg/provisioner/backend/backend.go (1)
ProvisionBackend(60-103)pkg/ui/formatter.go (1)
Success(169-175)
🪛 LanguageTool
website/blog/2025-11-20-automatic-backend-provisioning.mdx
[style] ~25-~25: This word has been used in one of the immediately preceding sentences. Using a synonym could make your text more interesting to read, unless the repetition is intentional.
Context: ... provisions backends automatically when needed. Just enable it in your stack configura...
(EN_REPEATEDWORDS_NEED)
[style] ~106-~106: This word has been used in one of the immediately preceding sentences. Using a synonym could make your text more interesting to read, unless the repetition is intentional.
Context: ...ment and testing workflows**, where you need backends quickly without manual setup. ...
(EN_REPEATEDWORDS_NEED)
website/docs/core-concepts/components/terraform/backends.mdx
[typographical] ~846-~846: In American English, use a period after an abbreviation.
Context: ...min" } ``` ### Development vs Production Development Workflow - ...
(MISSING_PERIOD_AFTER_ABBREVIATION)
[typographical] ~876-~876: Consider using a typographic opening quote here.
Context: ..."acme-terraform-state-prod" } resource "aws_s3_bucket" "terraform_state" { buc...
(EN_QUOTES)
[typographical] ~876-~876: Consider using a typographic close quote here.
Context: ...m-state-prod" } resource "aws_s3_bucket" "terraform_state" { bucket = "acme-te...
(EN_QUOTES)
[typographical] ~876-~876: Consider using a typographic opening quote here.
Context: ...state-prod" } resource "aws_s3_bucket" "terraform_state" { bucket = "acme-terr...
(EN_QUOTES)
[typographical] ~876-~876: Consider using a typographic close quote here.
Context: ...esource "aws_s3_bucket" "terraform_state" { bucket = "acme-terraform-state-prod...
(EN_QUOTES)
[typographical] ~881-~881: Consider using a typographic opening quote here.
Context: ...d production-specific features resource "aws_s3_bucket_lifecycle_configuration" "...
(EN_QUOTES)
[typographical] ~881-~881: Consider using a typographic close quote here.
Context: ...e "aws_s3_bucket_lifecycle_configuration" "terraform_state" { bucket = aws_s3_b...
(EN_QUOTES)
[typographical] ~881-~881: Consider using a typographic opening quote here.
Context: ..."aws_s3_bucket_lifecycle_configuration" "terraform_state" { bucket = aws_s3_buc...
(EN_QUOTES)
[typographical] ~881-~881: Consider using a typographic close quote here.
Context: ...ifecycle_configuration" "terraform_state" { bucket = aws_s3_bucket.terraform_st...
(EN_QUOTES)
[typographical] ~894-~894: Consider using a typographic opening quote here.
Context: ...current_days = 90 } } } resource "aws_s3_bucket_replication_configuration"...
(EN_QUOTES)
[typographical] ~894-~894: Consider using a typographic close quote here.
Context: ..."aws_s3_bucket_replication_configuration" "terraform_state" { bucket = aws_s3_b...
(EN_QUOTES)
[typographical] ~894-~894: Consider using a typographic opening quote here.
Context: ...ws_s3_bucket_replication_configuration" "terraform_state" { bucket = aws_s3_buc...
(EN_QUOTES)
[typographical] ~894-~894: Consider using a typographic close quote here.
Context: ...lication_configuration" "terraform_state" { bucket = aws_s3_bucket.terraform_st...
(EN_QUOTES)
docs/prd/provisioner-system.md
[style] ~14-~14: Since ownership is already implied, this phrasing may be redundant.
Context: ...Key Principle:** Each provisioner knows its own requirements and timing - the system pr...
(PRP_OWN)
[typographical] ~33-~33: Consider using a typographic opening quote here.
Context: ...Discoverability*: Hook system queries "what runs at this event?" ### First Imp...
(EN_QUOTES)
[typographical] ~33-~33: Consider using a typographic close quote here.
Context: ...system queries "what runs at this event?" ### First Implementation **Backend Pr...
(EN_QUOTES)
[style] ~411-~411: Since ownership is already implied, this phrasing may be redundant.
Context: ...ypothetical) - Each provisioner defines its own role assumption pattern --- ## Packag...
(PRP_OWN)
[grammar] ~752-~752: Please add a punctuation mark at the end of paragraph.
Context: ...igration** - How to migrate from manual provisioning --- ## Success Metrics ### Adoption ...
(PUNCTUATION_PARAGRAPH_END)
[typographical] ~954-~954: In American English, use a period after an abbreviation.
Context: ...omp --stack dev done ``` ### Automatic vs Manual Provisioning **Automatic (via h...
(MISSING_PERIOD_AFTER_ABBREVIATION)
🪛 markdownlint-cli2 (0.18.1)
docs/prd/provisioner-system.md
51-51: Hard tabs
Column: 1
(MD010, no-hard-tabs)
52-52: Hard tabs
Column: 1
(MD010, no-hard-tabs)
57-57: Hard tabs
Column: 1
(MD010, no-hard-tabs)
58-58: Hard tabs
Column: 1
(MD010, no-hard-tabs)
59-59: Hard tabs
Column: 1
(MD010, no-hard-tabs)
64-64: Hard tabs
Column: 1
(MD010, no-hard-tabs)
65-65: Hard tabs
Column: 1
(MD010, no-hard-tabs)
66-66: Hard tabs
Column: 1
(MD010, no-hard-tabs)
74-74: Hard tabs
Column: 1
(MD010, no-hard-tabs)
75-75: Hard tabs
Column: 1
(MD010, no-hard-tabs)
76-76: Hard tabs
Column: 1
(MD010, no-hard-tabs)
77-77: Hard tabs
Column: 1
(MD010, no-hard-tabs)
82-82: Hard tabs
Column: 1
(MD010, no-hard-tabs)
83-83: Hard tabs
Column: 1
(MD010, no-hard-tabs)
84-84: Hard tabs
Column: 1
(MD010, no-hard-tabs)
85-85: Hard tabs
Column: 1
(MD010, no-hard-tabs)
97-97: Hard tabs
Column: 1
(MD010, no-hard-tabs)
98-98: Hard tabs
Column: 1
(MD010, no-hard-tabs)
102-102: Hard tabs
Column: 1
(MD010, no-hard-tabs)
103-103: Hard tabs
Column: 1
(MD010, no-hard-tabs)
104-104: Hard tabs
Column: 1
(MD010, no-hard-tabs)
105-105: Hard tabs
Column: 1
(MD010, no-hard-tabs)
106-106: Hard tabs
Column: 1
(MD010, no-hard-tabs)
107-107: Hard tabs
Column: 1
(MD010, no-hard-tabs)
111-111: Hard tabs
Column: 1
(MD010, no-hard-tabs)
112-112: Hard tabs
Column: 1
(MD010, no-hard-tabs)
113-113: Hard tabs
Column: 1
(MD010, no-hard-tabs)
115-115: Hard tabs
Column: 1
(MD010, no-hard-tabs)
116-116: Hard tabs
Column: 1
(MD010, no-hard-tabs)
117-117: Hard tabs
Column: 1
(MD010, no-hard-tabs)
118-118: Hard tabs
Column: 1
(MD010, no-hard-tabs)
120-120: Hard tabs
Column: 1
(MD010, no-hard-tabs)
121-121: Hard tabs
Column: 1
(MD010, no-hard-tabs)
136-136: Hard tabs
Column: 1
(MD010, no-hard-tabs)
137-137: Hard tabs
Column: 1
(MD010, no-hard-tabs)
138-138: Hard tabs
Column: 1
(MD010, no-hard-tabs)
140-140: Hard tabs
Column: 1
(MD010, no-hard-tabs)
142-142: Hard tabs
Column: 1
(MD010, no-hard-tabs)
143-143: Hard tabs
Column: 1
(MD010, no-hard-tabs)
144-144: Hard tabs
Column: 1
(MD010, no-hard-tabs)
145-145: Hard tabs
Column: 1
(MD010, no-hard-tabs)
147-147: Hard tabs
Column: 1
(MD010, no-hard-tabs)
148-148: Hard tabs
Column: 1
(MD010, no-hard-tabs)
149-149: Hard tabs
Column: 1
(MD010, no-hard-tabs)
150-150: Hard tabs
Column: 1
(MD010, no-hard-tabs)
151-151: Hard tabs
Column: 1
(MD010, no-hard-tabs)
152-152: Hard tabs
Column: 1
(MD010, no-hard-tabs)
153-153: Hard tabs
Column: 1
(MD010, no-hard-tabs)
154-154: Hard tabs
Column: 1
(MD010, no-hard-tabs)
155-155: Hard tabs
Column: 1
(MD010, no-hard-tabs)
157-157: Hard tabs
Column: 1
(MD010, no-hard-tabs)
162-162: Hard tabs
Column: 1
(MD010, no-hard-tabs)
163-163: Hard tabs
Column: 1
(MD010, no-hard-tabs)
164-164: Hard tabs
Column: 1
(MD010, no-hard-tabs)
165-165: Hard tabs
Column: 1
(MD010, no-hard-tabs)
167-167: Hard tabs
Column: 1
(MD010, no-hard-tabs)
168-168: Hard tabs
Column: 1
(MD010, no-hard-tabs)
169-169: Hard tabs
Column: 1
(MD010, no-hard-tabs)
170-170: Hard tabs
Column: 1
(MD010, no-hard-tabs)
172-172: Hard tabs
Column: 1
(MD010, no-hard-tabs)
173-173: Hard tabs
Column: 1
(MD010, no-hard-tabs)
183-183: Hard tabs
Column: 1
(MD010, no-hard-tabs)
184-184: Hard tabs
Column: 1
(MD010, no-hard-tabs)
185-185: Hard tabs
Column: 1
(MD010, no-hard-tabs)
186-186: Hard tabs
Column: 1
(MD010, no-hard-tabs)
188-188: Hard tabs
Column: 1
(MD010, no-hard-tabs)
189-189: Hard tabs
Column: 1
(MD010, no-hard-tabs)
190-190: Hard tabs
Column: 1
(MD010, no-hard-tabs)
191-191: Hard tabs
Column: 1
(MD010, no-hard-tabs)
192-192: Hard tabs
Column: 1
(MD010, no-hard-tabs)
193-193: Hard tabs
Column: 1
(MD010, no-hard-tabs)
194-194: Hard tabs
Column: 1
(MD010, no-hard-tabs)
195-195: Hard tabs
Column: 1
(MD010, no-hard-tabs)
197-197: Hard tabs
Column: 1
(MD010, no-hard-tabs)
198-198: Hard tabs
Column: 1
(MD010, no-hard-tabs)
199-199: Hard tabs
Column: 1
(MD010, no-hard-tabs)
200-200: Hard tabs
Column: 1
(MD010, no-hard-tabs)
202-202: Hard tabs
Column: 1
(MD010, no-hard-tabs)
203-203: Hard tabs
Column: 1
(MD010, no-hard-tabs)
359-359: Fenced code blocks should have a language specified
(MD040, fenced-code-language)
377-377: Hard tabs
Column: 1
(MD010, no-hard-tabs)
378-378: Hard tabs
Column: 1
(MD010, no-hard-tabs)
379-379: Hard tabs
Column: 1
(MD010, no-hard-tabs)
381-381: Hard tabs
Column: 1
(MD010, no-hard-tabs)
382-382: Hard tabs
Column: 1
(MD010, no-hard-tabs)
383-383: Hard tabs
Column: 1
(MD010, no-hard-tabs)
385-385: Hard tabs
Column: 1
(MD010, no-hard-tabs)
386-386: Hard tabs
Column: 1
(MD010, no-hard-tabs)
387-387: Hard tabs
Column: 1
(MD010, no-hard-tabs)
388-388: Hard tabs
Column: 1
(MD010, no-hard-tabs)
389-389: Hard tabs
Column: 1
(MD010, no-hard-tabs)
390-390: Hard tabs
Column: 1
(MD010, no-hard-tabs)
391-391: Hard tabs
Column: 1
(MD010, no-hard-tabs)
392-392: Hard tabs
Column: 1
(MD010, no-hard-tabs)
394-394: Hard tabs
Column: 1
(MD010, no-hard-tabs)
395-395: Hard tabs
Column: 1
(MD010, no-hard-tabs)
396-396: Hard tabs
Column: 1
(MD010, no-hard-tabs)
417-417: Fenced code blocks should have a language specified
(MD040, fenced-code-language)
449-449: Hard tabs
Column: 1
(MD010, no-hard-tabs)
450-450: Hard tabs
Column: 1
(MD010, no-hard-tabs)
451-451: Hard tabs
Column: 1
(MD010, no-hard-tabs)
455-455: Hard tabs
Column: 1
(MD010, no-hard-tabs)
456-456: Hard tabs
Column: 1
(MD010, no-hard-tabs)
457-457: Hard tabs
Column: 1
(MD010, no-hard-tabs)
458-458: Hard tabs
Column: 1
(MD010, no-hard-tabs)
459-459: Hard tabs
Column: 1
(MD010, no-hard-tabs)
460-460: Hard tabs
Column: 1
(MD010, no-hard-tabs)
464-464: Hard tabs
Column: 1
(MD010, no-hard-tabs)
465-465: Hard tabs
Column: 1
(MD010, no-hard-tabs)
466-466: Hard tabs
Column: 1
(MD010, no-hard-tabs)
468-468: Hard tabs
Column: 1
(MD010, no-hard-tabs)
469-469: Hard tabs
Column: 1
(MD010, no-hard-tabs)
470-470: Hard tabs
Column: 1
(MD010, no-hard-tabs)
471-471: Hard tabs
Column: 1
(MD010, no-hard-tabs)
473-473: Hard tabs
Column: 1
(MD010, no-hard-tabs)
474-474: Hard tabs
Column: 1
(MD010, no-hard-tabs)
476-476: Hard tabs
Column: 1
(MD010, no-hard-tabs)
477-477: Hard tabs
Column: 1
(MD010, no-hard-tabs)
481-481: Hard tabs
Column: 1
(MD010, no-hard-tabs)
482-482: Hard tabs
Column: 1
(MD010, no-hard-tabs)
483-483: Hard tabs
Column: 1
(MD010, no-hard-tabs)
484-484: Hard tabs
Column: 1
(MD010, no-hard-tabs)
486-486: Hard tabs
Column: 1
(MD010, no-hard-tabs)
487-487: Hard tabs
Column: 1
(MD010, no-hard-tabs)
488-488: Hard tabs
Column: 1
(MD010, no-hard-tabs)
489-489: Hard tabs
Column: 1
(MD010, no-hard-tabs)
491-491: Hard tabs
Column: 1
(MD010, no-hard-tabs)
492-492: Hard tabs
Column: 1
(MD010, no-hard-tabs)
502-502: Hard tabs
Column: 1
(MD010, no-hard-tabs)
503-503: Hard tabs
Column: 1
(MD010, no-hard-tabs)
528-528: Hard tabs
Column: 1
(MD010, no-hard-tabs)
529-529: Hard tabs
Column: 1
(MD010, no-hard-tabs)
530-530: Hard tabs
Column: 1
(MD010, no-hard-tabs)
531-531: Hard tabs
Column: 1
(MD010, no-hard-tabs)
539-539: Hard tabs
Column: 1
(MD010, no-hard-tabs)
540-540: Hard tabs
Column: 1
(MD010, no-hard-tabs)
541-541: Hard tabs
Column: 1
(MD010, no-hard-tabs)
542-542: Hard tabs
Column: 1
(MD010, no-hard-tabs)
543-543: Hard tabs
Column: 1
(MD010, no-hard-tabs)
575-575: Hard tabs
Column: 1
(MD010, no-hard-tabs)
576-576: Hard tabs
Column: 1
(MD010, no-hard-tabs)
577-577: Hard tabs
Column: 1
(MD010, no-hard-tabs)
578-578: Hard tabs
Column: 1
(MD010, no-hard-tabs)
579-579: Hard tabs
Column: 1
(MD010, no-hard-tabs)
580-580: Hard tabs
Column: 1
(MD010, no-hard-tabs)
581-581: Hard tabs
Column: 1
(MD010, no-hard-tabs)
582-582: Hard tabs
Column: 1
(MD010, no-hard-tabs)
583-583: Hard tabs
Column: 1
(MD010, no-hard-tabs)
585-585: Hard tabs
Column: 1
(MD010, no-hard-tabs)
586-586: Hard tabs
Column: 1
(MD010, no-hard-tabs)
587-587: Hard tabs
Column: 1
(MD010, no-hard-tabs)
588-588: Hard tabs
Column: 1
(MD010, no-hard-tabs)
589-589: Hard tabs
Column: 1
(MD010, no-hard-tabs)
590-590: Hard tabs
Column: 1
(MD010, no-hard-tabs)
592-592: Hard tabs
Column: 1
(MD010, no-hard-tabs)
617-617: Hard tabs
Column: 1
(MD010, no-hard-tabs)
618-618: Hard tabs
Column: 1
(MD010, no-hard-tabs)
619-619: Hard tabs
Column: 1
(MD010, no-hard-tabs)
620-620: Hard tabs
Column: 1
(MD010, no-hard-tabs)
621-621: Hard tabs
Column: 1
(MD010, no-hard-tabs)
663-663: Hard tabs
Column: 1
(MD010, no-hard-tabs)
664-664: Hard tabs
Column: 1
(MD010, no-hard-tabs)
665-665: Hard tabs
Column: 1
(MD010, no-hard-tabs)
667-667: Hard tabs
Column: 1
(MD010, no-hard-tabs)
668-668: Hard tabs
Column: 1
(MD010, no-hard-tabs)
669-669: Hard tabs
Column: 1
(MD010, no-hard-tabs)
683-683: Hard tabs
Column: 1
(MD010, no-hard-tabs)
684-684: Hard tabs
Column: 1
(MD010, no-hard-tabs)
685-685: Hard tabs
Column: 1
(MD010, no-hard-tabs)
686-686: Hard tabs
Column: 1
(MD010, no-hard-tabs)
688-688: Hard tabs
Column: 1
(MD010, no-hard-tabs)
689-689: Hard tabs
Column: 1
(MD010, no-hard-tabs)
690-690: Hard tabs
Column: 1
(MD010, no-hard-tabs)
691-691: Hard tabs
Column: 1
(MD010, no-hard-tabs)
693-693: Hard tabs
Column: 1
(MD010, no-hard-tabs)
706-706: Hard tabs
Column: 1
(MD010, no-hard-tabs)
707-707: Hard tabs
Column: 1
(MD010, no-hard-tabs)
708-708: Hard tabs
Column: 1
(MD010, no-hard-tabs)
713-713: Hard tabs
Column: 1
(MD010, no-hard-tabs)
714-714: Hard tabs
Column: 1
(MD010, no-hard-tabs)
715-715: Hard tabs
Column: 1
(MD010, no-hard-tabs)
716-716: Hard tabs
Column: 1
(MD010, no-hard-tabs)
717-717: Hard tabs
Column: 1
(MD010, no-hard-tabs)
718-718: Hard tabs
Column: 1
(MD010, no-hard-tabs)
804-804: Hard tabs
Column: 1
(MD010, no-hard-tabs)
805-805: Hard tabs
Column: 1
(MD010, no-hard-tabs)
811-811: Hard tabs
Column: 1
(MD010, no-hard-tabs)
815-815: Hard tabs
Column: 1
(MD010, no-hard-tabs)
819-819: Hard tabs
Column: 1
(MD010, no-hard-tabs)
820-820: Hard tabs
Column: 1
(MD010, no-hard-tabs)
821-821: Hard tabs
Column: 1
(MD010, no-hard-tabs)
838-838: Hard tabs
Column: 1
(MD010, no-hard-tabs)
839-839: Hard tabs
Column: 1
(MD010, no-hard-tabs)
840-840: Hard tabs
Column: 1
(MD010, no-hard-tabs)
841-841: Hard tabs
Column: 1
(MD010, no-hard-tabs)
842-842: Hard tabs
Column: 1
(MD010, no-hard-tabs)
844-844: Hard tabs
Column: 1
(MD010, no-hard-tabs)
845-845: Hard tabs
Column: 1
(MD010, no-hard-tabs)
849-849: Hard tabs
Column: 1
(MD010, no-hard-tabs)
850-850: Hard tabs
Column: 1
(MD010, no-hard-tabs)
852-852: Hard tabs
Column: 1
(MD010, no-hard-tabs)
853-853: Hard tabs
Column: 1
(MD010, no-hard-tabs)
867-867: Hard tabs
Column: 1
(MD010, no-hard-tabs)
869-869: Hard tabs
Column: 1
(MD010, no-hard-tabs)
870-870: Hard tabs
Column: 1
(MD010, no-hard-tabs)
871-871: Hard tabs
Column: 1
(MD010, no-hard-tabs)
876-876: Hard tabs
Column: 1
(MD010, no-hard-tabs)
877-877: Hard tabs
Column: 1
(MD010, no-hard-tabs)
878-878: Hard tabs
Column: 1
(MD010, no-hard-tabs)
879-879: Hard tabs
Column: 1
(MD010, no-hard-tabs)
880-880: Hard tabs
Column: 1
(MD010, no-hard-tabs)
882-882: Hard tabs
Column: 1
(MD010, no-hard-tabs)
883-883: Hard tabs
Column: 1
(MD010, no-hard-tabs)
884-884: Hard tabs
Column: 1
(MD010, no-hard-tabs)
885-885: Hard tabs
Column: 1
(MD010, no-hard-tabs)
887-887: Hard tabs
Column: 1
(MD010, no-hard-tabs)
888-888: Hard tabs
Column: 1
(MD010, no-hard-tabs)
889-889: Hard tabs
Column: 1
(MD010, no-hard-tabs)
891-891: Hard tabs
Column: 1
(MD010, no-hard-tabs)
892-892: Hard tabs
Column: 1
(MD010, no-hard-tabs)
893-893: Hard tabs
Column: 1
(MD010, no-hard-tabs)
894-894: Hard tabs
Column: 1
(MD010, no-hard-tabs)
895-895: Hard tabs
Column: 1
(MD010, no-hard-tabs)
896-896: Hard tabs
Column: 1
(MD010, no-hard-tabs)
898-898: Hard tabs
Column: 1
(MD010, no-hard-tabs)
899-899: Hard tabs
Column: 1
(MD010, no-hard-tabs)
900-900: Hard tabs
Column: 1
(MD010, no-hard-tabs)
902-902: Hard tabs
Column: 1
(MD010, no-hard-tabs)
903-903: Hard tabs
Column: 1
(MD010, no-hard-tabs)
904-904: Hard tabs
Column: 1
(MD010, no-hard-tabs)
906-906: Hard tabs
Column: 1
(MD010, no-hard-tabs)
907-907: Hard tabs
Column: 1
(MD010, no-hard-tabs)
908-908: Hard tabs
Column: 1
(MD010, no-hard-tabs)
909-909: Hard tabs
Column: 1
(MD010, no-hard-tabs)
910-910: Hard tabs
Column: 1
(MD010, no-hard-tabs)
911-911: Hard tabs
Column: 1
(MD010, no-hard-tabs)
912-912: Hard tabs
Column: 1
(MD010, no-hard-tabs)
913-913: Hard tabs
Column: 1
(MD010, no-hard-tabs)
915-915: Hard tabs
Column: 1
(MD010, no-hard-tabs)
916-916: Hard tabs
Column: 1
(MD010, no-hard-tabs)
996-996: Fenced code blocks should have a language specified
(MD040, fenced-code-language)
1017-1017: Hard tabs
Column: 1
(MD010, no-hard-tabs)
1018-1018: Hard tabs
Column: 1
(MD010, no-hard-tabs)
1019-1019: Hard tabs
Column: 1
(MD010, no-hard-tabs)
1021-1021: Hard tabs
Column: 1
(MD010, no-hard-tabs)
1023-1023: Hard tabs
Column: 1
(MD010, no-hard-tabs)
1024-1024: Hard tabs
Column: 1
(MD010, no-hard-tabs)
1025-1025: Hard tabs
Column: 1
(MD010, no-hard-tabs)
1027-1027: Hard tabs
Column: 1
(MD010, no-hard-tabs)
1028-1028: Hard tabs
Column: 1
(MD010, no-hard-tabs)
1029-1029: Hard tabs
Column: 1
(MD010, no-hard-tabs)
1030-1030: Hard tabs
Column: 1
(MD010, no-hard-tabs)
1031-1031: Hard tabs
Column: 1
(MD010, no-hard-tabs)
1032-1032: Hard tabs
Column: 1
(MD010, no-hard-tabs)
1033-1033: Hard tabs
Column: 1
(MD010, no-hard-tabs)
1034-1034: Hard tabs
Column: 1
(MD010, no-hard-tabs)
1035-1035: Hard tabs
Column: 1
(MD010, no-hard-tabs)
1036-1036: Hard tabs
Column: 1
(MD010, no-hard-tabs)
1037-1037: Hard tabs
Column: 1
(MD010, no-hard-tabs)
1039-1039: Hard tabs
Column: 1
(MD010, no-hard-tabs)
1040-1040: Hard tabs
Column: 1
(MD010, no-hard-tabs)
1041-1041: Hard tabs
Column: 1
(MD010, no-hard-tabs)
1043-1043: Hard tabs
Column: 1
(MD010, no-hard-tabs)
1052-1052: Hard tabs
Column: 1
(MD010, no-hard-tabs)
1053-1053: Hard tabs
Column: 1
(MD010, no-hard-tabs)
1060-1060: Hard tabs
Column: 1
(MD010, no-hard-tabs)
1061-1061: Hard tabs
Column: 1
(MD010, no-hard-tabs)
1062-1062: Hard tabs
Column: 1
(MD010, no-hard-tabs)
1063-1063: Hard tabs
Column: 1
(MD010, no-hard-tabs)
1064-1064: Hard tabs
Column: 1
(MD010, no-hard-tabs)
1065-1065: Hard tabs
Column: 1
(MD010, no-hard-tabs)
1072-1072: Hard tabs
Column: 1
(MD010, no-hard-tabs)
1073-1073: Hard tabs
Column: 1
(MD010, no-hard-tabs)
1074-1074: Hard tabs
Column: 1
(MD010, no-hard-tabs)
1075-1075: Hard tabs
Column: 1
(MD010, no-hard-tabs)
1076-1076: Hard tabs
Column: 1
(MD010, no-hard-tabs)
1077-1077: Hard tabs
Column: 1
(MD010, no-hard-tabs)
1078-1078: Hard tabs
Column: 1
(MD010, no-hard-tabs)
1098-1098: Hard tabs
Column: 1
(MD010, no-hard-tabs)
1099-1099: Hard tabs
Column: 1
(MD010, no-hard-tabs)
1100-1100: Hard tabs
Column: 1
(MD010, no-hard-tabs)
1101-1101: Hard tabs
Column: 1
(MD010, no-hard-tabs)
1103-1103: Hard tabs
Column: 1
(MD010, no-hard-tabs)
1104-1104: Hard tabs
Column: 1
(MD010, no-hard-tabs)
1105-1105: Hard tabs
Column: 1
(MD010, no-hard-tabs)
1106-1106: Hard tabs
Column: 1
(MD010, no-hard-tabs)
1107-1107: Hard tabs
Column: 1
(MD010, no-hard-tabs)
1108-1108: Hard tabs
Column: 1
(MD010, no-hard-tabs)
1109-1109: Hard tabs
Column: 1
(MD010, no-hard-tabs)
1110-1110: Hard tabs
Column: 1
(MD010, no-hard-tabs)
1111-1111: Hard tabs
Column: 1
(MD010, no-hard-tabs)
1112-1112: Hard tabs
Column: 1
(MD010, no-hard-tabs)
1114-1114: Hard tabs
Column: 1
(MD010, no-hard-tabs)
1115-1115: Hard tabs
Column: 1
(MD010, no-hard-tabs)
1116-1116: Hard tabs
Column: 1
(MD010, no-hard-tabs)
1117-1117: Hard tabs
Column: 1
(MD010, no-hard-tabs)
1119-1119: Hard tabs
Column: 1
(MD010, no-hard-tabs)
1120-1120: Hard tabs
Column: 1
(MD010, no-hard-tabs)
1138-1138: Fenced code blocks should have a language specified
(MD040, fenced-code-language)
1168-1168: Hard tabs
Column: 1
(MD010, no-hard-tabs)
1169-1169: Hard tabs
Column: 1
(MD010, no-hard-tabs)
1170-1170: Hard tabs
Column: 1
(MD010, no-hard-tabs)
1174-1174: Hard tabs
Column: 1
(MD010, no-hard-tabs)
1175-1175: Hard tabs
Column: 1
(MD010, no-hard-tabs)
1176-1176: Hard tabs
Column: 1
(MD010, no-hard-tabs)
1177-1177: Hard tabs
Column: 1
(MD010, no-hard-tabs)
1178-1178: Hard tabs
Column: 1
(MD010, no-hard-tabs)
1182-1182: Hard tabs
Column: 1
(MD010, no-hard-tabs)
1183-1183: Hard tabs
Column: 1
(MD010, no-hard-tabs)
1184-1184: Hard tabs
Column: 1
(MD010, no-hard-tabs)
1186-1186: Hard tabs
Column: 1
(MD010, no-hard-tabs)
1187-1187: Hard tabs
Column: 1
(MD010, no-hard-tabs)
1188-1188: Hard tabs
Column: 1
(MD010, no-hard-tabs)
1189-1189: Hard tabs
Column: 1
(MD010, no-hard-tabs)
1190-1190: Hard tabs
Column: 1
(MD010, no-hard-tabs)
1192-1192: Hard tabs
Column: 1
(MD010, no-hard-tabs)
1193-1193: Hard tabs
Column: 1
(MD010, no-hard-tabs)
1194-1194: Hard tabs
Column: 1
(MD010, no-hard-tabs)
1195-1195: Hard tabs
Column: 1
(MD010, no-hard-tabs)
1197-1197: Hard tabs
Column: 1
(MD010, no-hard-tabs)
1198-1198: Hard tabs
Column: 1
(MD010, no-hard-tabs)
1199-1199: Hard tabs
Column: 1
(MD010, no-hard-tabs)
1200-1200: Hard tabs
Column: 1
(MD010, no-hard-tabs)
1202-1202: Hard tabs
Column: 1
(MD010, no-hard-tabs)
1203-1203: Hard tabs
Column: 1
(MD010, no-hard-tabs)
1205-1205: Hard tabs
Column: 1
(MD010, no-hard-tabs)
1206-1206: Hard tabs
Column: 1
(MD010, no-hard-tabs)
1207-1207: Hard tabs
Column: 1
(MD010, no-hard-tabs)
1208-1208: Hard tabs
Column: 1
(MD010, no-hard-tabs)
1209-1209: Hard tabs
Column: 1
(MD010, no-hard-tabs)
1211-1211: Hard tabs
Column: 1
(MD010, no-hard-tabs)
1212-1212: Hard tabs
Column: 1
(MD010, no-hard-tabs)
1213-1213: Hard tabs
Column: 1
(MD010, no-hard-tabs)
1214-1214: Hard tabs
Column: 1
(MD010, no-hard-tabs)
1216-1216: Hard tabs
Column: 1
(MD010, no-hard-tabs)
1217-1217: Hard tabs
Column: 1
(MD010, no-hard-tabs)
1218-1218: Hard tabs
Column: 1
(MD010, no-hard-tabs)
1219-1219: Hard tabs
Column: 1
(MD010, no-hard-tabs)
1220-1220: Hard tabs
Column: 1
(MD010, no-hard-tabs)
1222-1222: Hard tabs
Column: 1
(MD010, no-hard-tabs)
1223-1223: Hard tabs
Column: 1
(MD010, no-hard-tabs)
1247-1247: Emphasis used instead of a heading
(MD036, no-emphasis-as-heading)
⏰ Context from checks skipped due to timeout of 900000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
- GitHub Check: Acceptance Tests (linux)
- GitHub Check: Acceptance Tests (windows)
- GitHub Check: Summary
🔇 Additional comments (11)
pkg/hooks/event.go (1)
5-11: NewBeforeTerraformInithook constant looks goodDefining
BeforeTerraformInithere keeps the event name centralized and consistent with other hook events. It lines up with the provisioner design that runs before terraform init.cmd/root.go (1)
44-53: Provision command registration via blank import is consistentImporting
cmd/provisionfor side effects matches the existing pattern for built-in commands (about, list, profile, theme, version). This is the right minimal change to surfaceatmos provisionwithout further plumbing.website/docs/cli/commands/provision/backend.mdx (1)
210-216: Review comment is incorrect—documentation already matches implementationThe doc lists tags as
NameandManagedBy=Atmos, which directly matches the implementation inpkg/provisioner/backend/s3.go(lines 261–266). The code applies exactly those two tags:
Key: "Name"→ bucket nameKey: "ManagedBy"→"Atmos"The review claims the implementation has
CreatedAtandPurposetags, but these don't exist in the S3 provisioner code. Additionally, the reference to lines 499-507 is invalid (the file has 419 lines).No changes needed.
Likely an incorrect or invalid review comment.
pkg/provisioner/backend/s3.go (1)
48-85: Provision flow and error wrapping look solidConfig extraction, AWS config loading (with optional assume role), and the overall provision flow are clean and consistent with the existing error-sentinel pattern (
ErrLoadAWSConfig,ErrApplyBucketDefaults, etc.). Idempotent re-runs on the same bucket look correctly supported.pkg/provisioner/provisioner.go (1)
38-96: Provisioner registry and execution model look goodThe registry is concurrency-safe,
GetProvisionersForEventreturns a defensive copy, andExecuteProvisioners’s fail-fast behavior with a typed error ("provisioner %s failed: %w") is a nice, predictable contract for callers. This is a solid foundation for hook-based provisioning.pkg/provisioner/backend/backend.go (5)
23-29: Clean function signature.The
BackendProvisionerFunctype is well-defined with clear parameters and a straightforward error return. Good choice passingbackendConfigasmap[string]anyfor flexibility across different backend types.
31-35: Thread-safe registry implementation looks good.Using
sync.RWMutexis appropriate here since the registry will be read-heavy (many lookups, few registrations). The initialization and documentation are clear.
37-45: Proper locking and registration.The function correctly uses write lock for map mutation and properly defers the unlock. The perf tracking is consistent with the codebase pattern.
47-56: Correct read lock usage.The function appropriately uses
RLockfor read-only access and returnsnilfor missing provisioners, which the caller handles gracefully.
58-103: Well-structured orchestration with proper error handling.The function correctly:
- Returns early when provisioning is disabled (avoiding unnecessary work)
- Uses safe type assertions with ok checks
- Wraps errors with
%wfor proper error chain support- Delegates to the appropriate backend provisioner
The nested map traversal pattern is safe and handles all edge cases appropriately.
pkg/provisioner/errors.go (1)
5-21: Well-defined sentinel errors.The error variables follow Go best practices:
- Standard
errors.New()pattern for sentinel errors (compatible witherrors.Is())- Consistent
Errprefix naming convention- Clear, specific error messages
These errors align well with the backend provisioning operations described in the PR.
This commit addresses all major CodeRabbit review comments: ## Critical Fixes - **Add AuthContext support**: Provision commands now support `--identity` flag for Atmos-managed authentication (SSO). Credentials are written to files and picked up by AWS SDK credential chain. - **Improve S3 error handling**: Enhanced error messages with actionable hints using Atmos error builder pattern. Distinguish between 403 (permissions), 404 (not found), and network errors with specific guidance. - **Add S3 defaults warnings**: Warn users when modifying pre-existing buckets that settings (encryption, tags) will be overwritten with opinionated defaults. - **Fix CLI help text**: Changed from `provision <type>` to `provision backend` to only advertise supported provisioner types. Updated descriptions. - **Fix YAML examples**: Corrected `backend_type` placement in blog post and CLI docs - must be at component level, not nested in backend block. ## Code Quality Improvements - **Use consistent hook constants**: Added local constants with documentation linking to canonical definitions in pkg/hooks/event.go (avoiding import cycles). - **Add new error type**: `ErrS3BucketAccessDenied` for permission-denied scenarios. - **Refactor Provision function**: Added ProvisionParams struct and ProvisionWithParams to comply with argument-limit linting rule while maintaining backward compatibility. ## Files Changed - cmd/provision/provision.go: Add identity flag and auth integration - pkg/provision/provision.go: Thread authManager, add params struct - pkg/provisioner/backend/s3.go: Enhanced error handling and warnings - pkg/provisioner/backend/backend.go: Document hook event constant - internal/exec/terraform.go: Add hook constant documentation - errors/errors.go: Add ErrS3BucketAccessDenied - website/blog/2025-11-20-automatic-backend-provisioning.mdx: Fix YAML examples - website/docs/cli/commands/provision/backend.mdx: Fix YAML examples 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (2)
pkg/provisioner/backend/s3.go (1)
127-147: Consider preservingErrS3BucketAccessDeniedwhen wrapping errors inensureBucketThe concern is valid.
bucketExistsintentionally classifies errors—returningErrS3BucketAccessDeniedwith rich hints at lines 184–189 and 200–207—butensureBucketre-wraps all errors withErrCheckBucketExistat line 132, losing that semantic distinction.Although no current callers check for the sentinel, the error classification at the lower layer represents intentional design. Preserving it via a conditional check:
func ensureBucket(ctx context.Context, client *s3.Client, bucket, region string) (bool, error) { exists, err := bucketExists(ctx, client, bucket) if err != nil { + // Preserve access-denied classification for callers. + if errors.Is(err, errUtils.ErrS3BucketAccessDenied) { + return false, err + } return false, fmt.Errorf(errFormat, provisioner.ErrCheckBucketExist, err) }…keeps error type info available for future handling. Note:
createBucket(line 142) doesn't return specialized errors, so that wrapping remains appropriate.cmd/provision/provision.go (1)
58-60: Redundant argument validation.The manual
len(args) != 2check is redundant sinceArgs: cobra.ExactArgs(2)on line 52 already enforces this. Cobra will preventRunEfrom executing if the argument count is incorrect.Apply this diff to remove the redundant check:
RunE: func(cmd *cobra.Command, args []string) error { defer perf.Track(atmosConfigPtr, "provision.RunE")() - if len(args) != 2 { - return errUtils.ErrInvalidArguments - } - provisionerType := args[0] component := args[1]
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Disabled knowledge base sources:
- Linear integration is disabled by default for public repositories
You can enable these sources in your CodeRabbit configuration.
📒 Files selected for processing (8)
cmd/provision/provision.go(1 hunks)errors/errors.go(1 hunks)internal/exec/terraform.go(4 hunks)pkg/provision/provision.go(1 hunks)pkg/provisioner/backend/backend.go(1 hunks)pkg/provisioner/backend/s3.go(1 hunks)website/blog/2025-11-20-automatic-backend-provisioning.mdx(1 hunks)website/docs/cli/commands/provision/backend.mdx(1 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
- internal/exec/terraform.go
- pkg/provisioner/backend/backend.go
🧰 Additional context used
🧠 Learnings (16)
📓 Common learnings
Learnt from: Listener430
Repo: cloudposse/atmos PR: 934
File: tests/fixtures/scenarios/docs-generate/README.md.gotmpl:99-118
Timestamp: 2025-01-25T03:51:57.689Z
Learning: For the cloudposse/atmos repository, changes to template contents should be handled in dedicated PRs and are typically considered out of scope for PRs focused on other objectives.
📚 Learning: 2025-09-13T16:39:20.007Z
Learnt from: samtholiya
Repo: cloudposse/atmos PR: 1466
File: cmd/markdown/atmos_toolchain_aliases.md:2-4
Timestamp: 2025-09-13T16:39:20.007Z
Learning: In the cloudposse/atmos repository, CLI documentation files in cmd/markdown/ follow a specific format that uses " $ atmos command" (with leading space and dollar sign prompt) in code blocks. This is the established project convention and should not be changed to comply with standard markdownlint rules MD040 and MD014.
Applied to files:
website/docs/cli/commands/provision/backend.mdx
📚 Learning: 2025-01-19T15:49:15.593Z
Learnt from: samtholiya
Repo: cloudposse/atmos PR: 955
File: tests/snapshots/TestCLICommands_atmos_validate_editorconfig_--help.stdout.golden:0-0
Timestamp: 2025-01-19T15:49:15.593Z
Learning: In future commits, the help text for Atmos CLI commands should be limited to only show component and stack parameters for commands that actually use them. This applies to the example usage section in command help text.
Applied to files:
website/docs/cli/commands/provision/backend.mdxcmd/provision/provision.go
📚 Learning: 2024-12-03T05:29:07.718Z
Learnt from: aknysh
Repo: cloudposse/atmos PR: 810
File: internal/exec/terraform_utils.go:145-146
Timestamp: 2024-12-03T05:29:07.718Z
Learning: In the Atmos project, a 5-minute timeout in the `execTerraformOutput` function is acceptable for retrieving `terraform output` for a component in a stack.
Applied to files:
website/docs/cli/commands/provision/backend.mdx
📚 Learning: 2025-01-25T03:51:57.689Z
Learnt from: Listener430
Repo: cloudposse/atmos PR: 934
File: tests/fixtures/scenarios/docs-generate/README.md.gotmpl:99-118
Timestamp: 2025-01-25T03:51:57.689Z
Learning: For the cloudposse/atmos repository, changes to template contents should be handled in dedicated PRs and are typically considered out of scope for PRs focused on other objectives.
Applied to files:
website/blog/2025-11-20-automatic-backend-provisioning.mdx
📚 Learning: 2025-10-27T01:54:35.665Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 1714
File: website/blog/2025-10-26-zero-config-terminal-output.md:6-6
Timestamp: 2025-10-27T01:54:35.665Z
Learning: In the Atmos blog (website/blog/), blog post authors in frontmatter should always be set to the actual committer or PR opener (e.g., "osterman"), not generic organization names like "cloudposse" or "atmos". Authors must exist in website/blog/authors.yml.
Applied to files:
website/blog/2025-11-20-automatic-backend-provisioning.mdx
📚 Learning: 2025-03-18T12:26:25.329Z
Learnt from: Listener430
Repo: cloudposse/atmos PR: 1149
File: tests/snapshots/TestCLICommands_atmos_vendor_pull_ssh.stderr.golden:7-7
Timestamp: 2025-03-18T12:26:25.329Z
Learning: In the Atmos project, typos or inconsistencies in test snapshot files (such as "terrafrom" instead of "terraform") may be intentional as they capture the exact output of commands and should not be flagged as issues requiring correction.
Applied to files:
website/blog/2025-11-20-automatic-backend-provisioning.mdx
📚 Learning: 2024-12-07T16:16:13.038Z
Learnt from: Listener430
Repo: cloudposse/atmos PR: 825
File: internal/exec/helmfile_generate_varfile.go:28-31
Timestamp: 2024-12-07T16:16:13.038Z
Learning: In `internal/exec/helmfile_generate_varfile.go`, the `--help` command (`./atmos helmfile generate varfile --help`) works correctly without requiring stack configurations, and the only change needed was to make `ProcessCommandLineArgs` exportable by capitalizing its name.
Applied to files:
cmd/provision/provision.go
📚 Learning: 2025-10-10T23:51:36.597Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 1599
File: internal/exec/terraform.go:394-402
Timestamp: 2025-10-10T23:51:36.597Z
Learning: In Atmos (internal/exec/terraform.go), when adding OpenTofu-specific flags like `--var-file` for `init`, do not gate them based on command name (e.g., checking if `info.Command == "tofu"` or `info.Command == "opentofu"`) because command names don't reliably indicate the actual binary being executed (symlinks, aliases). Instead, document the OpenTofu requirement in code comments and documentation, trusting users who enable the feature (e.g., `PassVars`) to ensure their terraform command points to an OpenTofu binary.
Applied to files:
cmd/provision/provision.go
📚 Learning: 2025-11-08T19:56:18.660Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 1697
File: internal/exec/oci_utils.go:0-0
Timestamp: 2025-11-08T19:56:18.660Z
Learning: In the Atmos codebase, when a function receives an `*schema.AtmosConfiguration` parameter, it should read configuration values from `atmosConfig.Settings` fields rather than using direct `os.Getenv()` or `viper.GetString()` calls. The Atmos pattern is: viper.BindEnv in cmd/root.go binds environment variables → Viper unmarshals into atmosConfig.Settings via mapstructure → business logic reads from the Settings struct. This provides centralized config management, respects precedence, and enables testability. Example: `atmosConfig.Settings.AtmosGithubToken` instead of `os.Getenv("ATMOS_GITHUB_TOKEN")` in functions like `getGHCRAuth` in internal/exec/oci_utils.go.
Applied to files:
cmd/provision/provision.go
📚 Learning: 2025-10-07T00:25:16.333Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 1498
File: website/src/components/Screengrabs/atmos-terraform-metadata--help.html:25-55
Timestamp: 2025-10-07T00:25:16.333Z
Learning: In Atmos CLI, subcommands inherit flags from their parent commands via Cobra's command inheritance. For example, `atmos terraform metadata --help` shows `--affected` and related flags inherited from the parent `terraform` command (defined in cmd/terraform.go), even though the metadata subcommand doesn't explicitly define these flags. This is expected Cobra behavior and auto-generated help screengrabs accurately reflect this inheritance.
Applied to files:
cmd/provision/provision.go
📚 Learning: 2025-01-09T22:27:25.538Z
Learnt from: samtholiya
Repo: cloudposse/atmos PR: 914
File: cmd/validate_stacks.go:20-23
Timestamp: 2025-01-09T22:27:25.538Z
Learning: The validate commands in Atmos can have different help handling implementations. Specifically, validate_component.go and validate_stacks.go are designed to handle help requests differently, with validate_stacks.go including positional argument checks while validate_component.go does not.
Applied to files:
cmd/provision/provision.go
📚 Learning: 2025-11-10T03:03:31.505Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 0
File: :0-0
Timestamp: 2025-11-10T03:03:31.505Z
Learning: In the Atmos codebase, commands using the `StandardParser` flag pattern (from pkg/flags) do NOT need explicit `viper.BindPFlag()` calls in their code. The StandardParser encapsulates flag binding internally: flags are registered via `parser.RegisterFlags(cmd)` in init(), and bound via `parser.BindFlagsToViper(cmd, v)` in RunE, which internally calls viper.BindPFlag for each flag. This pattern is used throughout Atmos (e.g., cmd/toolchain/get.go, cmd/toolchain/info.go, cmd/toolchain/install.go, cmd/toolchain/path.go). Do not flag missing viper.BindPFlag calls when StandardParser is used.
Applied to files:
cmd/provision/provision.go
📚 Learning: 2025-09-05T14:57:37.360Z
Learnt from: RoseSecurity
Repo: cloudposse/atmos PR: 1448
File: cmd/ansible.go:26-28
Timestamp: 2025-09-05T14:57:37.360Z
Learning: The Atmos codebase uses a consistent pattern for commands that delegate to external tools: `PersistentFlags().Bool("", false, doubleDashHint)` where doubleDashHint provides help text about using double dashes to separate Atmos options from native command arguments. This pattern is used across terraform, packer, helmfile, atlantis, aws, and ansible commands.
Applied to files:
cmd/provision/provision.go
📚 Learning: 2024-12-11T18:40:12.808Z
Learnt from: Listener430
Repo: cloudposse/atmos PR: 844
File: cmd/helmfile.go:37-37
Timestamp: 2024-12-11T18:40:12.808Z
Learning: In the atmos project, `cliConfig` is initialized within the `cmd` package in `root.go` and can be used in other command files.
Applied to files:
cmd/provision/provision.go
📚 Learning: 2025-01-07T20:38:09.618Z
Learnt from: samtholiya
Repo: cloudposse/atmos PR: 896
File: cmd/editor_config.go:37-40
Timestamp: 2025-01-07T20:38:09.618Z
Learning: Error handling suggestion for `cmd.Help()` in `cmd/editor_config.go` was deferred as the code is planned for future modifications.
Applied to files:
cmd/provision/provision.go
🧬 Code graph analysis (3)
pkg/provisioner/backend/s3.go (7)
pkg/provisioner/backend/backend.go (1)
RegisterBackendProvisioner(45-52)pkg/schema/schema.go (2)
AuthContext(568-578)AWSAuthContext(582-597)errors/builder.go (1)
Build(21-23)pkg/provisioner/errors.go (10)
ErrLoadAWSConfig(13-13)ErrApplyBucketDefaults(16-16)ErrBucketRequired(7-7)ErrRegionRequired(8-8)ErrCheckBucketExist(14-14)ErrCreateBucket(15-15)ErrEnableVersioning(17-17)ErrEnableEncryption(18-18)ErrBlockPublicAccess(19-19)ErrApplyTags(20-20)pkg/ui/formatter.go (2)
Success(169-175)Warning(213-219)internal/aws_utils/aws_utils.go (1)
LoadAWSConfigWithAuth(53-119)errors/errors.go (1)
ErrS3BucketAccessDenied(91-91)
cmd/provision/provision.go (8)
pkg/schema/schema.go (2)
AtmosConfiguration(53-94)ConfigAndStacksInfo(620-714)pkg/flags/standard_parser.go (2)
StandardParser(18-22)NewStandardParser(34-40)errors/errors.go (3)
ErrInvalidArguments(191-191)ErrRequiredFlagNotProvided(189-189)ErrFailedToInitConfig(387-387)pkg/config/config.go (1)
InitCliConfig(25-64)pkg/auth/manager_helpers.go (1)
CreateAndAuthenticateManager(180-222)internal/exec/describe_component.go (1)
ExecuteDescribeComponentParams(202-209)pkg/provision/provision.go (1)
Provision(41-58)pkg/flags/options.go (2)
WithStringFlag(37-48)WithEnvVars(221-244)
pkg/provision/provision.go (4)
pkg/schema/schema.go (2)
AtmosConfiguration(53-94)AuthContext(568-578)pkg/perf/perf.go (1)
Track(121-138)pkg/provisioner/backend/backend.go (1)
ProvisionBackend(67-110)pkg/ui/formatter.go (1)
Success(169-175)
🪛 LanguageTool
website/blog/2025-11-20-automatic-backend-provisioning.mdx
[style] ~25-~25: This word has been used in one of the immediately preceding sentences. Using a synonym could make your text more interesting to read, unless the repetition is intentional.
Context: ... provisions backends automatically when needed. Just enable it in your stack configura...
(EN_REPEATEDWORDS_NEED)
[style] ~107-~107: This word has been used in one of the immediately preceding sentences. Using a synonym could make your text more interesting to read, unless the repetition is intentional.
Context: ...ment and testing workflows**, where you need backends quickly without manual setup. ...
(EN_REPEATEDWORDS_NEED)
⏰ Context from checks skipped due to timeout of 900000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
- GitHub Check: Acceptance Tests (windows)
- GitHub Check: Acceptance Tests (linux)
- GitHub Check: Summary
🔇 Additional comments (11)
errors/errors.go (1)
91-91: New S3 access-denied sentinel looks consistent
ErrS3BucketAccessDeniedmatches existing naming and usage patterns and is ready to wire into S3-related flows.website/blog/2025-11-20-automatic-backend-provisioning.mdx (1)
25-41: Blog examples now match the actual backend schemaThe YAML snippets correctly keep
backend_type: s3at the component level (sibling ofbackendandprovision), and the cross-account/“Getting Started” examples align with the S3 provisioner’s config shape. Frontmatter author also matches the PR opener.Looks good as a user-facing overview of the new flow.
Also applies to: 139-152, 191-206
pkg/provisioner/backend/s3.go (1)
26-27: Review comment is incorrect—multiple%wverbs are valid and explicitly supportedGo 1.20+ supports multiple
%wverbs infmt.Errorf, which return errors implementingUnwrap() []error. The codebase's.golangci.ymlconfirms this: "supports multiple %w verbs per fmt.Errorf call (requires Go 1.20+)". The current format"%w: %w"is correct and will not panic. Changing it to"%w: %v"would actually lose error chain semantics needed forerrors.Is/As.The code is correct as written and requires no changes.
Likely an incorrect or invalid review comment.
website/docs/cli/commands/provision/backend.mdx (1)
80-86: Verify Issue #1 accuracy; Issue #2 appears potentially incorrectIssue #1 is solid: the docs list backend types
(s3, gcs, azurerm)but only the S3 provisioner is registered in code—no GCS or Azure implementations exist.Issue #2 needs clarification: the backend provisioner code directly accesses
componentConfig["provision"],componentConfig["backend"], andcomponentConfig["backend_type"]as top-level keys. This suggests root-levelprovision:in stack config is actually what the code expects, contradicting the review's claim that it should be nested underterraform:.Before updating the docs, confirm with the team:
- Whether stack config uses root-level
provision:orterraform: provision:(or if both merge down to top-level during processing)- Which pattern the existing docs should show as canonical
Fix confirmed: Update line 83 to reflect S3-only support (mark GCS/Azure as planned or remove them).
cmd/provision/provision.go (7)
1-19: Clean package structure.Imports are well-organized and all appear necessary for the command implementation.
21-26: LGTM.Package-level variables follow the Atmos command pattern for config and flag parser management.
28-39: Well-structured options and config setup.The ProvisionOptions struct cleanly embeds global flags, and SetAtmosConfig provides the integration point for config injection from root.go.
41-51: Help text correctly scoped to supported provisioners.The command documentation now only advertises the
backendprovisioner type, which matches the implementation. This addresses previous feedback about advertising unsupported types.
82-114: Solid integration with Atmos internals.The config loading, auth manager setup, and provision orchestration follow established Atmos patterns. The describeComponent callback appropriately disables template and function processing for the provisioning workflow.
149-171: Clean CommandProvider implementation.The provider correctly implements the interface with appropriate return values. Grouping under "Core Stack Commands" makes sense for this infrastructure provisioning command.
117-147: The dual binding pattern is correct and standard across Atmos.The concern about
BindToViperin init() being redundant is incorrect. Verification shows that all StandardParser commands consistently use this dual-binding approach:
BindToViper()in init() for early environment variable supportBindFlagsToViper()in RunE() for flag and precedence handling at execution timeThis pattern is used identically in
cmd/list/components.go,cmd/list/stacks.go, and other commands.One minor observation: Line 118's explicit
DisableFlagParsing = falsesets the default value and isn't necessary (other commands omit it). This is harmless but optional to remove.
Add unit tests for the automatic backend provisioning feature: - pkg/provision/provision_test.go: Tests for nil parameter validation (CodeRabbit critical fix), provisioner type validation, and backend provisioning success/failure scenarios - pkg/provisioner/provisioner_test.go: Tests for provisioner registry, concurrent registration, fail-fast behavior, and context cancellation - pkg/provisioner/backend/backend_test.go: Tests for backend provisioner registry, enable/disable scenarios, missing configuration handling, and multi-backend support - pkg/provisioner/backend/s3_test.go: Tests for S3 config extraction, bucket name validation, and region handling - cmd/provision/provision_test.go: Tests for CommandProvider interface, flag parsing, environment variable support, and help text Test coverage: - pkg/provision: 95.5% - pkg/provisioner: 100% - pkg/provisioner/backend: 34.7% (AWS SDK operations require integration tests) - cmd/provision: 36.1% (RunE requires full config initialization) Also adds nil parameter validation to ProvisionWithParams using static errors (ErrNilParam) to prevent panics when called with nil params. This addresses the CodeRabbit review feedback. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
There was a problem hiding this comment.
Actionable comments posted: 0
🧹 Nitpick comments (1)
pkg/provisioner/backend/backend_test.go (1)
340-341: Inconsistent variable naming.The variable
gcsCALLEDuses uppercase, while similar variables elsewhere use camelCase (e.g.,s3Calledon line 340,provisioner1Called,provisioner2Calledin other tests).Apply this diff for consistency:
- gcsCALLED := false + gcsCalled := falseAnd update the references on lines 349, 373, 377, 395:
- gcsCALLED = true + gcsCalled = true- assert.False(t, gcsCALLED, "GCS provisioner should not have been called") + assert.False(t, gcsCalled, "GCS provisioner should not have been called")- gcsCALLED = false + gcsCalled = false- assert.True(t, gcsCALLED, "GCS provisioner should have been called") + assert.True(t, gcsCalled, "GCS provisioner should have been called")
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Disabled knowledge base sources:
- Linear integration is disabled by default for public repositories
You can enable these sources in your CodeRabbit configuration.
📒 Files selected for processing (6)
cmd/provision/provision_test.go(1 hunks)pkg/provision/provision.go(1 hunks)pkg/provision/provision_test.go(1 hunks)pkg/provisioner/backend/backend_test.go(1 hunks)pkg/provisioner/backend/s3_test.go(1 hunks)pkg/provisioner/provisioner_test.go(1 hunks)
🧰 Additional context used
🧠 Learnings (12)
📓 Common learnings
Learnt from: Listener430
Repo: cloudposse/atmos PR: 934
File: tests/fixtures/scenarios/docs-generate/README.md.gotmpl:99-118
Timestamp: 2025-01-25T03:51:57.689Z
Learning: For the cloudposse/atmos repository, changes to template contents should be handled in dedicated PRs and are typically considered out of scope for PRs focused on other objectives.
📚 Learning: 2025-11-10T23:23:39.771Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 1686
File: toolchain/registry/aqua/aqua_test.go:417-442
Timestamp: 2025-11-10T23:23:39.771Z
Learning: In Atmos toolchain AquaRegistry, tests should not hit real GitHub. Use the options pattern via WithGitHubBaseURL to inject an httptest server URL and make GetLatestVersion/GetAvailableVersions deterministic.
Applied to files:
pkg/provisioner/backend/s3_test.gopkg/provisioner/provisioner_test.gopkg/provisioner/backend/backend_test.go
📚 Learning: 2025-11-11T03:47:59.576Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 1686
File: toolchain/which_test.go:166-223
Timestamp: 2025-11-11T03:47:59.576Z
Learning: In the cloudposse/atmos repo, tests that manipulate environment variables should use testing.T.Setenv for automatic setup/teardown instead of os.Setenv/Unsetenv.
Applied to files:
pkg/provisioner/backend/s3_test.gopkg/provisioner/backend/backend_test.gocmd/provision/provision_test.go
📚 Learning: 2025-11-11T03:47:45.878Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 1686
File: toolchain/add_test.go:67-77
Timestamp: 2025-11-11T03:47:45.878Z
Learning: In the cloudposse/atmos codebase, tests should prefer t.Setenv for environment variable setup/teardown instead of os.Setenv/Unsetenv to ensure test-scoped isolation.
Applied to files:
pkg/provisioner/backend/backend_test.gocmd/provision/provision_test.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/provision/provision.go
📚 Learning: 2024-12-02T21:26:32.337Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 808
File: pkg/config/config.go:478-483
Timestamp: 2024-12-02T21:26:32.337Z
Learning: In the 'atmos' project, when reviewing Go code like `pkg/config/config.go`, avoid suggesting file size checks after downloading remote configs if such checks aren't implemented elsewhere in the codebase.
Applied to files:
pkg/provision/provision.go
📚 Learning: 2024-12-07T16:16:13.038Z
Learnt from: Listener430
Repo: cloudposse/atmos PR: 825
File: internal/exec/helmfile_generate_varfile.go:28-31
Timestamp: 2024-12-07T16:16:13.038Z
Learning: In `internal/exec/helmfile_generate_varfile.go`, the `--help` command (`./atmos helmfile generate varfile --help`) works correctly without requiring stack configurations, and the only change needed was to make `ProcessCommandLineArgs` exportable by capitalizing its name.
Applied to files:
cmd/provision/provision_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:
cmd/provision/provision_test.go
📚 Learning: 2025-01-09T22:27:25.538Z
Learnt from: samtholiya
Repo: cloudposse/atmos PR: 914
File: cmd/validate_stacks.go:20-23
Timestamp: 2025-01-09T22:27:25.538Z
Learning: The validate commands in Atmos can have different help handling implementations. Specifically, validate_component.go and validate_stacks.go are designed to handle help requests differently, with validate_stacks.go including positional argument checks while validate_component.go does not.
Applied to files:
cmd/provision/provision_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:
cmd/provision/provision_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:
cmd/provision/provision_test.go
📚 Learning: 2025-01-30T19:30:59.120Z
Learnt from: samtholiya
Repo: cloudposse/atmos PR: 959
File: cmd/workflow.go:74-74
Timestamp: 2025-01-30T19:30:59.120Z
Learning: Error handling for `cmd.Usage()` is not required in the Atmos CLI codebase, as confirmed by the maintainer.
Applied to files:
cmd/provision/provision_test.go
🧬 Code graph analysis (6)
pkg/provisioner/backend/s3_test.go (2)
pkg/provisioner/errors.go (1)
ErrBucketRequired(7-7)pkg/provisioner/backend/backend.go (1)
GetBackendProvisioner(56-63)
pkg/provisioner/provisioner_test.go (2)
pkg/provisioner/provisioner.go (4)
Provisioner(27-36)RegisterProvisioner(46-53)GetProvisionersForEvent(56-71)ExecuteProvisioners(75-96)pkg/schema/schema.go (3)
AtmosConfiguration(53-94)AuthContext(568-578)AWSAuthContext(582-597)
pkg/provisioner/backend/backend_test.go (3)
pkg/provisioner/backend/backend.go (4)
BackendProvisionerFunc(31-36)RegisterBackendProvisioner(45-52)GetBackendProvisioner(56-63)ProvisionBackend(67-110)pkg/schema/schema.go (3)
AtmosConfiguration(53-94)AuthContext(568-578)AWSAuthContext(582-597)pkg/provisioner/errors.go (3)
ErrBackendNotFound(9-9)ErrBackendTypeRequired(10-10)ErrNoProvisionerFound(11-11)
pkg/provision/provision.go (5)
pkg/schema/schema.go (2)
AtmosConfiguration(53-94)AuthContext(568-578)errors/errors.go (1)
ErrNilParam(499-499)pkg/perf/perf.go (1)
Track(121-138)pkg/provisioner/backend/backend.go (1)
ProvisionBackend(67-110)pkg/ui/formatter.go (1)
Success(169-175)
pkg/provision/provision_test.go (4)
pkg/provision/provision.go (4)
ProvisionWithParams(65-119)ProvisionParams(28-35)ErrUnsupportedProvisionerType(18-18)Provision(42-59)errors/errors.go (1)
ErrNilParam(499-499)pkg/schema/schema.go (2)
AtmosConfiguration(53-94)AuthContext(568-578)pkg/provisioner/backend/backend.go (1)
RegisterBackendProvisioner(45-52)
cmd/provision/provision_test.go (3)
cmd/provision/provision.go (2)
ProvisionCommandProvider(150-150)ProvisionOptions(29-33)pkg/schema/schema.go (1)
AtmosConfiguration(53-94)errors/errors.go (1)
ErrRequiredFlagNotProvided(189-189)
⏰ Context from checks skipped due to timeout of 900000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
- GitHub Check: Acceptance Tests (windows)
- GitHub Check: Summary
🔇 Additional comments (7)
pkg/provisioner/provisioner_test.go (1)
1-417: Comprehensive test coverage for provisioner registry.This test suite provides excellent coverage of the provisioner registry system, including registration, retrieval, execution, concurrency, and error handling. The use of
resetRegistry()ensures proper test isolation, and edge cases like context cancellation and event-scoped isolation are well-tested.pkg/provisioner/backend/s3_test.go (1)
1-291: Well-focused S3 backend config tests.The test suite appropriately focuses on config parsing and validation logic without hitting real AWS services. The table-driven approach for
TestExtractS3Configprovides comprehensive coverage of edge cases, and the note at the end clearly explains the testing strategy.pkg/provisioner/backend/backend_test.go (1)
1-515: Comprehensive backend provisioning tests.The test suite provides thorough coverage of the backend provisioning flow, including edge cases for missing configuration, disabled provisioning, auth context propagation, and concurrent operations. The use of
resetBackendRegistry()ensures proper test isolation.pkg/provision/provision_test.go (1)
1-331: Thorough provision orchestration tests.This test suite effectively validates the provision orchestration logic, including parameter validation, error propagation, and successful provisioning flows. The use of mock provisioners and callbacks allows testing without external dependencies.
cmd/provision/provision_test.go (1)
1-369: Comprehensive CLI command tests.This test suite provides excellent coverage of the provision command structure, including metadata, flags, argument validation, environment variable handling, and precedence rules. The tests properly use
t.Setenvfor environment variable setup as per project conventions.Based on learnings
pkg/provision/provision.go (2)
65-76: Proper nil parameter validation.The nil checks for
paramsandparams.DescribeComponentbefore callingperf.Trackand using the callbacks prevent potential panics and provide clear error messages. This addresses the defensive programming concerns from previous reviews.
95-110: Clear TODO for future authContext integration.The TODO comment clearly explains the current approach (relying on AWS SDK credential chain) and the future direction (populating schema.AuthContext for in-process SDK calls). This is good documentation for future maintainers.
- Add S3ClientAPI interface for all S3 operations - Refactor internal functions to accept interface for testability - Add comprehensive mock-based tests for S3 operations - Increase backend coverage from 34.7% to 77.1% 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
Add provision command to help output snapshots. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
Codecov Report❌ Patch coverage is Additional details and impacted files@@ Coverage Diff @@
## main #1808 +/- ##
==========================================
+ Coverage 73.27% 73.31% +0.04%
==========================================
Files 551 563 +12
Lines 53458 54195 +737
==========================================
+ Hits 39170 39735 +565
- Misses 11442 11607 +165
- Partials 2846 2853 +7
Flags with carried forward coverage won't be shown. Click here to find out more.
🚀 New features to boost your workflow:
|
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (2)
pkg/provisioner/backend/s3.go (2)
53-64: Align ProvisionS3Backend doc comment with actual configuration requirements.The comment says “No configuration options beyond enabled: true”, but
extractS3Configrequiresbucketandregionand supports optionalassume_role.role_arn. That’s a bit misleading for callers.Might be clearer to say something like “No knobs for the security defaults; only bucket/region/assume_role are configurable” so expectations match the code.
Also applies to: 111-137
80-90: Propagate the underlying AWS config error for better diagnostics.On
loadAWSConfigWithAuthfailure you return a nicely annotatedErrLoadAWSConfig, but the originalerrfrom the AWS SDK is dropped. That can make debugging auth/region issues harder.Consider including the cause as context, e.g.:
- if err != nil { - return errUtils.Build(provisioner.ErrLoadAWSConfig). + if err != nil { + return errUtils.Build(provisioner.ErrLoadAWSConfig). WithHint("Check AWS credentials are configured correctly"). WithHintf("Verify AWS region '%s' is valid", config.region). WithHint("If using --identity flag, ensure the identity is authenticated"). WithContext("region", config.region). WithContext("bucket", config.bucket). + WithContext("cause", err.Error()). Err() }Keeps the same UX while preserving the root cause for logs and troubleshooting.
Also applies to: 161-174
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Disabled knowledge base sources:
- Linear integration is disabled by default for public repositories
You can enable these sources in your CodeRabbit configuration.
📒 Files selected for processing (5)
cmd/root.go(1 hunks)pkg/provisioner/backend/s3.go(1 hunks)pkg/provisioner/backend/s3_test.go(1 hunks)tests/snapshots/TestCLICommands_atmos_--help.stdout.golden(1 hunks)tests/snapshots/TestCLICommands_atmos_non-existent.stderr.golden(1 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
- cmd/root.go
- pkg/provisioner/backend/s3_test.go
🧰 Additional context used
🧠 Learnings (12)
📓 Common learnings
Learnt from: Listener430
Repo: cloudposse/atmos PR: 934
File: tests/fixtures/scenarios/docs-generate/README.md.gotmpl:99-118
Timestamp: 2025-01-25T03:51:57.689Z
Learning: For the cloudposse/atmos repository, changes to template contents should be handled in dedicated PRs and are typically considered out of scope for PRs focused on other objectives.
📚 Learning: 2025-09-13T16:39:20.007Z
Learnt from: samtholiya
Repo: cloudposse/atmos PR: 1466
File: cmd/markdown/atmos_toolchain_aliases.md:2-4
Timestamp: 2025-09-13T16:39:20.007Z
Learning: In the cloudposse/atmos repository, CLI documentation files in cmd/markdown/ follow a specific format that uses " $ atmos command" (with leading space and dollar sign prompt) in code blocks. This is the established project convention and should not be changed to comply with standard markdownlint rules MD040 and MD014.
Applied to files:
tests/snapshots/TestCLICommands_atmos_non-existent.stderr.goldentests/snapshots/TestCLICommands_atmos_--help.stdout.golden
📚 Learning: 2025-03-18T12:26:25.329Z
Learnt from: Listener430
Repo: cloudposse/atmos PR: 1149
File: tests/snapshots/TestCLICommands_atmos_vendor_pull_ssh.stderr.golden:7-7
Timestamp: 2025-03-18T12:26:25.329Z
Learning: In the Atmos project, typos or inconsistencies in test snapshot files (such as "terrafrom" instead of "terraform") may be intentional as they capture the exact output of commands and should not be flagged as issues requiring correction.
Applied to files:
tests/snapshots/TestCLICommands_atmos_non-existent.stderr.goldentests/snapshots/TestCLICommands_atmos_--help.stdout.golden
📚 Learning: 2025-02-14T23:12:38.030Z
Learnt from: Listener430
Repo: cloudposse/atmos PR: 1061
File: tests/snapshots/TestCLICommands_atmos_vendor_pull_ssh.stderr.golden:8-8
Timestamp: 2025-02-14T23:12:38.030Z
Learning: Test snapshots in the Atmos project, particularly for dry run scenarios, may be updated during the development process, and temporary inconsistencies in their content should not be flagged as issues.
Applied to files:
tests/snapshots/TestCLICommands_atmos_non-existent.stderr.golden
📚 Learning: 2025-09-27T20:50:20.564Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 1533
File: pkg/config/load.go:585-637
Timestamp: 2025-09-27T20:50:20.564Z
Learning: In the cloudposse/atmos repository, command merging prioritizes precedence over display ordering. Help commands are displayed lexicographically regardless of internal array order, so the mergeCommandArrays function focuses on ensuring the correct precedence chain (top-level file wins) rather than maintaining specific display order.
Applied to files:
tests/snapshots/TestCLICommands_atmos_non-existent.stderr.goldentests/snapshots/TestCLICommands_atmos_--help.stdout.golden
📚 Learning: 2025-09-10T21:17:55.273Z
Learnt from: samtholiya
Repo: cloudposse/atmos PR: 1466
File: toolchain/http_client_test.go:3-10
Timestamp: 2025-09-10T21:17:55.273Z
Learning: In the cloudposse/atmos repository, imports should never be changed as per samtholiya's coding guidelines.
Applied to files:
tests/snapshots/TestCLICommands_atmos_non-existent.stderr.golden
📚 Learning: 2025-01-19T15:49:15.593Z
Learnt from: samtholiya
Repo: cloudposse/atmos PR: 955
File: tests/snapshots/TestCLICommands_atmos_validate_editorconfig_--help.stdout.golden:0-0
Timestamp: 2025-01-19T15:49:15.593Z
Learning: In future commits, the help text for Atmos CLI commands should be limited to only show component and stack parameters for commands that actually use them. This applies to the example usage section in command help text.
Applied to files:
tests/snapshots/TestCLICommands_atmos_non-existent.stderr.goldentests/snapshots/TestCLICommands_atmos_--help.stdout.golden
📚 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:
tests/snapshots/TestCLICommands_atmos_non-existent.stderr.goldentests/snapshots/TestCLICommands_atmos_--help.stdout.golden
📚 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:
tests/snapshots/TestCLICommands_atmos_non-existent.stderr.golden
📚 Learning: 2024-11-25T17:17:15.703Z
Learnt from: RoseSecurity
Repo: cloudposse/atmos PR: 797
File: pkg/list/atmos.yaml:213-214
Timestamp: 2024-11-25T17:17:15.703Z
Learning: The file `pkg/list/atmos.yaml` is primarily intended for testing purposes.
Applied to files:
tests/snapshots/TestCLICommands_atmos_non-existent.stderr.golden
📚 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:
tests/snapshots/TestCLICommands_atmos_non-existent.stderr.goldentests/snapshots/TestCLICommands_atmos_--help.stdout.golden
📚 Learning: 2025-09-05T14:57:37.360Z
Learnt from: RoseSecurity
Repo: cloudposse/atmos PR: 1448
File: cmd/ansible.go:26-28
Timestamp: 2025-09-05T14:57:37.360Z
Learning: The Atmos codebase uses a consistent pattern for commands that delegate to external tools: `PersistentFlags().Bool("", false, doubleDashHint)` where doubleDashHint provides help text about using double dashes to separate Atmos options from native command arguments. This pattern is used across terraform, packer, helmfile, atlantis, aws, and ansible commands.
Applied to files:
tests/snapshots/TestCLICommands_atmos_--help.stdout.golden
🧬 Code graph analysis (1)
pkg/provisioner/backend/s3.go (8)
pkg/provisioner/backend/backend.go (1)
RegisterBackendProvisioner(45-52)pkg/schema/schema.go (3)
AtmosConfiguration(53-94)AuthContext(568-578)AWSAuthContext(582-597)pkg/perf/perf.go (1)
Track(121-138)errors/builder.go (1)
Build(21-23)pkg/provisioner/errors.go (10)
ErrLoadAWSConfig(13-13)ErrApplyBucketDefaults(16-16)ErrBucketRequired(7-7)ErrRegionRequired(8-8)ErrCheckBucketExist(14-14)ErrCreateBucket(15-15)ErrEnableVersioning(17-17)ErrEnableEncryption(18-18)ErrBlockPublicAccess(19-19)ErrApplyTags(20-20)pkg/ui/formatter.go (2)
Success(169-175)Warning(213-219)internal/aws_utils/aws_utils.go (1)
LoadAWSConfigWithAuth(53-119)errors/errors.go (1)
ErrS3BucketAccessDenied(91-91)
⏰ Context from checks skipped due to timeout of 900000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
- GitHub Check: Acceptance Tests (windows)
- GitHub Check: Summary
🔇 Additional comments (4)
tests/snapshots/TestCLICommands_atmos_non-existent.stderr.golden (1)
21-21: Snapshot correctly updated for new subcommand.The addition of "provision" to the error output is properly positioned alphabetically and follows the established formatting pattern.
tests/snapshots/TestCLICommands_atmos_--help.stdout.golden (1)
26-26: Help output accurately reflects new command.The provision subcommand is properly documented in the help text with a clear, concise description that matches the PR objectives.
pkg/provisioner/backend/s3.go (2)
238-253: CreateBucket flow looks solid for region handling.Good call on omitting
CreateBucketConfigurationforus-east-1and using a region-specificLocationConstraintelsewhere. That matches S3’s quirky create semantics and keeps the helper narrow and testable.
26-27: The original review comment is incorrect.Go 1.20+ supports multiple %w verbs in fmt.Errorf, which returns an error implementing Unwrap() []error — there is no runtime panic. Your retrieved learnings further confirm this: Atmos uses Go 1.24.8 and explicitly configures errorlint with
errorf-multi: trueto validate this exact pattern. The learnings also show this format ("%w: %w") is already established throughout the codebase in the errors package and used correctly.The code at line 26–27 is valid and follows Atmos' own conventions. No changes needed.
Likely an incorrect or invalid review comment.
BucketKeyEnabled only applies to SSE-KMS encryption, not AES-256. Remove the field from the ServerSideEncryptionConfiguration when using AES-256 to avoid invalid configuration. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
There was a problem hiding this comment.
Actionable comments posted: 8
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
website/docs/components/terraform/backends.mdx (1)
1-200: Test website build with documentation changes.Per coding guidelines, all documentation changes in
website/**/*.mdxmust be tested locally. Runcd website && npm run buildto verify no broken links, missing images, or component rendering issues.
♻️ Duplicate comments (5)
cmd/terraform/backend/backend_helpers_test.go (1)
15-91: Global Viper mutation in tests remains brittle; DI would isolate better.docs/prd/s3-backend-provisioner.md (1)
369-612: Fix markdownlint blockers (tabs + “emphasis as heading”) to prevent docs CI failures.Also applies to: 867-969, 1429-1433
docs/prd/backend-provisioner.md (1)
51-190: Fix markdownlint issues (tabs/missing fence languages/MD036 headings) to keep docs lint green.Also applies to: 339-352, 918-932, 1058-1065
docs/prd/provisioner-system.md (2)
45-87: Fix markdownlint blockers (tabs + fence languages + MD036 headings).Also applies to: 359-372, 417-437, 996-1058, 1247-1261
182-206: PRD auth failure semantics conflict with repo behavior (TerraformPreHook is non-fatal).Based on learnings, the PRD examples should reflect that
auth.TerraformPreHook(...)errors are logged but do not abort Terraform execution.Also applies to: 1113-1138
🧹 Nitpick comments (3)
docs/prd/s3-backend-provisioner.md (1)
492-506: Doc snippet: don’t treat allHeadBucketerrors as “bucket doesn’t exist”.
checkS3BucketExistsreturning(false, nil)on any error conflates 404 with 403 (AccessDenied), which can lead readers to think provisioning should proceed when it should fail fast. Recommend documenting/illustrating “404 → false; AccessDenied/other → error”.pkg/provisioner/provisioner.go (2)
36-79: ProvisionWithParams has proper validation but perf.Track could use params.AtmosConfig.The nil checks (lines 41-47) address past review concerns. However, line 39 passes
niltoperf.Trackwhenparams.AtmosConfigis available after validation.func ProvisionWithParams(params *ProvisionParams) error { - defer perf.Track(nil, "provision.ProvisionWithParams")() - if params == nil { return fmt.Errorf("%w: provision params", errUtils.ErrNilParam) } + defer perf.Track(params.AtmosConfig, "provision.ProvisionWithParams")()Move the
deferafter the nil check to useparams.AtmosConfig.
142-177: DeleteBackendWithParams has proper structure but perf.Track could be improved.Similar to
ProvisionWithParams, line 144 passesniltoperf.Trackwhenparams.AtmosConfigcould be available after validation.func DeleteBackendWithParams(params *DeleteBackendParams) error { - defer perf.Track(nil, "provision.DeleteBackend")() - if err := validateDeleteParams(params); err != nil { return err } + defer perf.Track(params.AtmosConfig, "provision.DeleteBackend")()Move
deferafter validation to useparams.AtmosConfig.
There was a problem hiding this comment.
Actionable comments posted: 4
♻️ Duplicate comments (5)
pkg/provisioner/backend/backend_test.go (1)
438-503: Minor:gcsCALLEDnaming typo makes the test harder to scan.The variable
gcsCALLED(mixed case) at line 446 is a typo—rename it togcsCalledfor consistency withs3Calledat line 445.Apply this diff:
- gcsCALLED := false + gcsCalled := false mockGCSProvisioner := func(ctx context.Context, atmosConfig *schema.AtmosConfiguration, backendConfig map[string]any, authContext *schema.AuthContext) error { - gcsCALLED = true + gcsCalled = true return nil } @@ -477,11 +477,11 @@ err := ProvisionBackend(ctx, atmosConfig, componentConfigS3, nil) require.NoError(t, err) assert.True(t, s3Called, "S3 provisioner should have been called") - assert.False(t, gcsCALLED, "GCS provisioner should not have been called") + assert.False(t, gcsCalled, "GCS provisioner should not have been called") // Reset flags. s3Called = false - gcsCALLED = false + gcsCalled = false @@ -498,7 +498,7 @@ err = ProvisionBackend(ctx, atmosConfig, componentConfigGCS, nil) require.NoError(t, err) assert.False(t, s3Called, "S3 provisioner should not have been called") - assert.True(t, gcsCALLED, "GCS provisioner should have been called") + assert.True(t, gcsCalled, "GCS provisioner should have been called")pkg/provisioner/provisioner.go (1)
36-79: Fix perf.Track to use params.AtmosConfig instead of nil.Line 39 passes
niltoperf.Track(), butparams.AtmosConfigis available. All other provisioner functions correctly track withatmosConfigwhen available—use the same pattern here.Apply this diff:
func ProvisionWithParams(params *ProvisionParams) error { - defer perf.Track(nil, "provisioner.ProvisionWithParams")() + defer perf.Track(params.AtmosConfig, "provisioner.ProvisionWithParams")()Optional: Consider context propagation.
Line 63 creates a fresh
context.Background()timeout instead of propagating the caller's context. For proper cancellation support (e.g., Ctrl-C), the context should flow from the CLI handler through to backend provisioning. This would require addingCtx context.ContexttoProvisionParamsand threading it through the call chain.docs/prd/s3-backend-provisioner.md (1)
369-606: Fix markdownlint violations to avoid doc build failures.Static hints show MD010/MD036 still present (hard tabs + emphasis used as headings). Please convert tabs → spaces and promote bold “Step X” lines to real headings.
Also applies to: 879-904, 922-982, 1441-1445
docs/prd/backend-provisioner.md (1)
51-190: Fix markdownlint issues (tabs, fenced block languages, emphasis-as-heading).Static hints still report MD010 across multiple fenced blocks; please normalize tabs → spaces in code fences (if MD010 is enforced there) and avoid bold-only “headings”.
Also applies to: 339-355, 909-935, 1038-1066
website/docs/components/terraform/backends.mdx (1)
194-200: Fix “Backend Configuration” related link inconsistency.The “Related” list links “Backend Configuration” to
/stacks/backend, but earlier you direct readers to/stacks/components/terraform/backendas the configuration reference. Align the label/link so users don’t bounce to the wrong page.
🧹 Nitpick comments (6)
pkg/provisioner/backend/backend_test.go (1)
23-43: Inconsistent registry reset helper usage.Line 25 uses
resetBackendRegistry()while other tests (lines 67, 82, 91, etc.) useResetRegistryForTesting(). Both appear to do the same thing—clearing the backend provisioner registry. For consistency and maintainability, use the same helper throughout.Suggestion:
Replace
resetBackendRegistry()withResetRegistryForTesting()in all tests, or clarify if there's a semantic difference between the two.pkg/provisioner/backend/s3_delete.go (5)
115-124: Consider removing unicode glyphs from CLI output for portability.Strings like
⚠/✓can render poorly in some terminals and CI logs; optional to keep, but worth considering a plain-text fallback.
126-162:listAllObjects: consider explicitly settingMaxKeysand tightening state-file detection.Minor: you set
MaxKeyselsewhere but not here; also you only count.tfstateinVersions(not delete markers), which is probably fine but worth confirming as intended.
164-178: HardencollectObjectIdentifiersagainst nil keys.If AWS ever returns entries with
Key == nil,DeleteObjectswill fail. Skipping nil keys defensively avoids turning one bad entry into a full stop.
202-222: Potential TOCTOU: bucket can refill between listing and deletion.If new objects are written while deleting,
DeleteBucketcan fail. Optional: retry list+delete once when delete-bucket fails with “not empty”, or surface a specific “bucket changed during delete” hint.
224-233: Consider classifying “bucket not empty” separately.If
DeleteBucketfails due toBucketNotEmpty, mapping to a dedicated sentinel (e.g.,ErrBucketNotEmpty) can improve UX and remediation guidance.
- Fix encryption/Bucket Key claim in s3-backend-provisioner.md: SSE-S3 (AES-256) doesn't use Bucket Key (only applies to SSE-KMS) - Fix godot violations in DeleteS3Backend doc comment: Convert bullet points to flowing prose ending with periods 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
Convert all user-facing errors to use ErrorBuilder pattern per repo guidelines for consistent hints, context, and error handling: - errForceRequired: --force flag requirement error - createS3ClientForDeletion: AWS config loading error - validateBucketExistsForDeletion: bucket not found error - listAllObjects: list objects permission error - deleteBatch: delete objects error with partial failure handling - deleteAllObjects: list versions for deletion error - deleteBucket: bucket deletion error Extracted helper functions to keep DeleteS3Backend under 60 lines: - errForceRequired() - createS3ClientForDeletion() - validateBucketExistsForDeletion() - deleteS3BucketAndContents() 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
Add helper functions to safely extract AtmosConfig from params structs, allowing perf.Track to use the actual AtmosConfig instead of nil while still satisfying the lintroller requirement that perf.Track must be at the start of the function (before nil checks). - getAtmosConfigFromProvisionParams: safely extracts from ProvisionParams - getAtmosConfigFromDeleteParams: safely extracts from DeleteBackendParams 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
There was a problem hiding this comment.
Actionable comments posted: 2
♻️ Duplicate comments (2)
docs/prd/s3-backend-provisioner.md (2)
880-880: Convert emphasis-used-as-headings to proper markdown headings (MD036).Lines marked with "Step X:" or similar emphasis should be converted to
##or###headings to pass markdownlint and improve document structure.Example fix (line 880):
-**Step 1: Enable global feature flag (optional)** +### Step 1: Enable global feature flag (optional)Apply similar fixes to lines: 890, 907, 923, 946, 952, 967, 977, and 1442.
Also applies to: 890-890, 907-907, 923-923, 946-946, 952-952, 967-967, 977-977, 1442-1442
113-135: Clarify deletion semantics—the wording contradicts itself.Line 115 states "--force flag is always required", but line 122 introduces a "Non-Empty Bucket Handling" section implying the flag's behavior differs. Reword to unambiguously convey the CLI contract:
-### Non-Empty Bucket Handling - -The `--force` flag is always required. When provided, the command: +### Safety Mechanisms -**Without `--force` flag:** -- Command exits with error: "the --force flag is required for deletion" -- No bucket inspection or deletion occurs +If `--force` is not provided, deletion is rejected. When `--force` is provided, the command:
🧹 Nitpick comments (3)
pkg/provisioner/provisioner.go (3)
16-33: Good error handling and safe config extraction.The sentinel error and helper functions are well-structured. The helpers ensure
perf.Trackreceives a validAtmosConfigeven when params are nil, addressing previous feedback.Optional: The two helper functions are nearly identical. If this pattern repeats elsewhere, consider a generic helper or interface-based approach to reduce duplication.
52-95: Well-structured provisioning orchestration.The function properly validates inputs, uses
ErrorBuilderfor user-facing errors, tracks performance, and propagatesAuthContextfor cross-account provisioning. All major concerns from past reviews have been addressed.Optional: For CLI cancellation support (e.g., Ctrl-C), consider adding a
Ctx context.Contextfield toProvisionParamsand propagating it instead of creatingcontext.Background(). This would flow cancellation signals from the CLI through to backend operations. Not critical for this PR but noted for future enhancement.
118-193: Solid deletion flow with proper validation.The deletion functions mirror the provisioning pattern: parameter struct, thorough validation via
validateDeleteParams,ErrorBuilderwith helpful hints, and proper nil-checking. All prior concerns about missing validations have been resolved.Same optional note as
ProvisionWithParams: adding aCtxfield toDeleteBackendParamswould enable cancellation propagation from the CLI, but this is not critical.
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Disabled knowledge base sources:
- Linear integration is disabled by default for public repositories
You can enable these sources in your CodeRabbit configuration.
📒 Files selected for processing (3)
docs/prd/s3-backend-provisioner.md(1 hunks)pkg/provisioner/backend/s3_delete.go(1 hunks)pkg/provisioner/provisioner.go(1 hunks)
🧰 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 usingfmt.Errorf("context: %w", err), and consider using custom error types for domain-specific errors
Follow standard Go coding style: usegofmtandgoimportsto format code, prefer short descriptive variable names, use kebab-case for command-line flags, and snake_case for environment variables
Document all exported functions, types, and methods following Go's documentation conventions
Document complex logic with inline comments in Go code
Support configuration via files, environment variables, and flags following the precedence order: flags > environment variables > config file > defaults
Provide clear error messages to users, include troubleshooting hints when appropriate, and log detailed errors for debugging
**/*.go: All comments must end with periods (enforced bygodotlinter)
NEVER delete existing comments without a very strong reason. Comments document why/how/what/where. Preserve helpful comments, update to match code, refactor for clarity, add context when modifying.
Organize imports in three groups separated by blank lines, sorted alphabetically: 1) Go stdlib, 2) 3rd-party (NOT cloudposse/atmos), 3) Atmos packages. Maintain aliases:cfg,log,u,errUtils
Adddefer perf.Track(atmosConfig, "pkg.FuncName")()with a blank line to all public functions. Usenilif no atmosConfig parameter is available.
Define interfaces for all major functionality. Use dependency injection for testability. Generate mocks withgo.uber.org/mock/mockgen. Avoid integration tests by mocking external dependencies.
Use//go:generatedirectives withgo.uber.org/mock/mockgenfor mock generation. Never creat...
Files:
pkg/provisioner/backend/s3_delete.gopkg/provisioner/provisioner.go
pkg/**/*.go
📄 CodeRabbit inference engine (CLAUDE.md)
pkg/**/*.go: For complex domains with multiple operations, use Service-Oriented Architecture with one Service struct per domain, provider interfaces for classes of problems, default implementations, mock implementations, and dependency injection for testability.
Follow multi-provider registry pattern: 1) Define interface in dedicated package, 2) Implement per provider, 3) Register implementations, 4) Generate mocks.
Files:
pkg/provisioner/backend/s3_delete.gopkg/provisioner/provisioner.go
docs/prd/**/*.md
📄 CodeRabbit inference engine (CLAUDE.md)
PRDs (Product Requirements Documents) must be in
docs/prd/using kebab-case filenames:command-registry-pattern.md,error-handling-strategy.md,testing-strategy.md
Files:
docs/prd/s3-backend-provisioner.md
🧠 Learnings (43)
📓 Common learnings
Learnt from: Listener430
Repo: cloudposse/atmos PR: 934
File: tests/fixtures/scenarios/docs-generate/README.md.gotmpl:99-118
Timestamp: 2025-01-25T03:51:57.689Z
Learning: For the cloudposse/atmos repository, changes to template contents should be handled in dedicated PRs and are typically considered out of scope for PRs focused on other objectives.
Learnt from: aknysh
Repo: cloudposse/atmos PR: 944
File: go.mod:206-206
Timestamp: 2025-01-17T00:18:57.769Z
Learning: For indirect dependencies with license compliance issues in the cloudposse/atmos repository, the team prefers to handle them in follow-up PRs rather than blocking the current changes, as these issues often require deeper investigation of the dependency tree.
📚 Learning: 2024-12-02T21:26:32.337Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 808
File: pkg/config/config.go:478-483
Timestamp: 2024-12-02T21:26:32.337Z
Learning: In the 'atmos' project, when reviewing Go code like `pkg/config/config.go`, avoid suggesting file size checks after downloading remote configs if such checks aren't implemented elsewhere in the codebase.
Applied to files:
pkg/provisioner/backend/s3_delete.gopkg/provisioner/provisioner.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/backend/s3_delete.gopkg/provisioner/provisioner.go
📚 Learning: 2025-11-08T19:56:18.660Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 1697
File: internal/exec/oci_utils.go:0-0
Timestamp: 2025-11-08T19:56:18.660Z
Learning: In the Atmos codebase, when a function receives an `*schema.AtmosConfiguration` parameter, it should read configuration values from `atmosConfig.Settings` fields rather than using direct `os.Getenv()` or `viper.GetString()` calls. The Atmos pattern is: viper.BindEnv in cmd/root.go binds environment variables → Viper unmarshals into atmosConfig.Settings via mapstructure → business logic reads from the Settings struct. This provides centralized config management, respects precedence, and enables testability. Example: `atmosConfig.Settings.AtmosGithubToken` instead of `os.Getenv("ATMOS_GITHUB_TOKEN")` in functions like `getGHCRAuth` in internal/exec/oci_utils.go.
Applied to files:
pkg/provisioner/backend/s3_delete.gopkg/provisioner/provisioner.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/backend/s3_delete.gopkg/provisioner/provisioner.go
📚 Learning: 2025-04-11T22:06:46.999Z
Learnt from: samtholiya
Repo: cloudposse/atmos PR: 1147
File: internal/exec/validate_schema.go:42-57
Timestamp: 2025-04-11T22:06:46.999Z
Learning: The "ExecuteAtmosValidateSchemaCmd" function in internal/exec/validate_schema.go has been reviewed and confirmed to have acceptable cognitive complexity despite static analysis warnings. The function uses a clean structure with only three if statements for error handling and delegates complex operations to helper methods.
Applied to files:
pkg/provisioner/backend/s3_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/backend/s3_delete.go
📚 Learning: 2025-12-10T23:12:15.805Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-10T23:12:15.805Z
Learning: Applies to **/*.go : All comments must end with periods (enforced by `godot` linter)
Applied to files:
pkg/provisioner/backend/s3_delete.go
📚 Learning: 2025-12-10T23:12:15.805Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-10T23:12:15.805Z
Learning: Applies to **/*.go : NEVER delete existing comments without a very strong reason. Comments document why/how/what/where. Preserve helpful comments, update to match code, refactor for clarity, add context when modifying.
Applied to files:
pkg/provisioner/backend/s3_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 : Document complex logic with inline comments in Go code
Applied to files:
pkg/provisioner/backend/s3_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/backend/s3_delete.gopkg/provisioner/provisioner.go
📚 Learning: 2025-12-10T23:12:15.805Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-10T23:12:15.805Z
Learning: Applies to **/*.go : ALL user-facing errors MUST use ErrorBuilder with sentinel errors from `errors/errors.go`. ALWAYS use `errors.Is()` for checking, NEVER string comparison. ALWAYS use `assert.ErrorIs()` in tests, NEVER `assert.Contains(err.Error(), ...)`
Applied to files:
pkg/provisioner/backend/s3_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/backend/s3_delete.go
📚 Learning: 2025-09-10T22:38:42.212Z
Learnt from: Benbentwo
Repo: cloudposse/atmos PR: 1475
File: pkg/auth/identities/aws/user.go:141-145
Timestamp: 2025-09-10T22:38:42.212Z
Learning: The user confirmed that the errors package has an error string wrapping format, contradicting the previous learning about ErrWrappingFormat being invalid. The current usage of fmt.Errorf(errUtils.ErrWrappingFormat, errUtils.ErrAuthAwsFileManagerFailed, err) appears to be the correct pattern.
Applied to files:
pkg/provisioner/backend/s3_delete.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/backend/s3_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/backend/s3_delete.go
📚 Learning: 2024-10-12T18:38:28.458Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 715
File: pkg/logger/logger.go:21-32
Timestamp: 2024-10-12T18:38:28.458Z
Learning: In Go code, avoid prefixing struct names with 'I' (e.g., `IError`) as it can be confusing, suggesting an interface. Use descriptive names for structs to improve code clarity.
Applied to files:
pkg/provisioner/backend/s3_delete.go
📚 Learning: 2025-04-04T02:03:23.676Z
Learnt from: aknysh
Repo: cloudposse/atmos PR: 1185
File: internal/exec/yaml_func_store.go:26-26
Timestamp: 2025-04-04T02:03:23.676Z
Learning: The Atmos codebase currently uses `log.Fatal` for error handling in multiple places. The maintainers are aware this isn't an ideal pattern (should only be used in main() or init() functions) and plan to address it comprehensively in a separate PR. CodeRabbit should not flag these issues or push for immediate changes until that refactoring is complete.
Applied to files:
pkg/provisioner/backend/s3_delete.gopkg/provisioner/provisioner.go
📚 Learning: 2025-12-10T23:12:15.805Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-10T23:12:15.805Z
Learning: Applies to **/*.go : Small focused files (<600 lines). One cmd/impl per file. Co-locate tests. Never use `//revive:disable:file-length-limit`.
Applied to files:
pkg/provisioner/provisioner.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/provisioner.go
📚 Learning: 2025-12-10T23:12:15.805Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-10T23:12:15.805Z
Learning: Applies to **/*.go : ALWAYS ask for user approval before adding nolint comments. Prefer refactoring over nolint. Exception for bubbletea models: `//nolint:gocritic // bubbletea models must be passed by value`. Exception for intentional subprocess calls: `//nolint:gosec // intentional subprocess call`. NEVER add nolint for gocognit, cyclomatic complexity, magic numbers, or nestif.
Applied to files:
pkg/provisioner/provisioner.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/provisioner.go
📚 Learning: 2025-06-07T19:28:21.289Z
Learnt from: samtholiya
Repo: cloudposse/atmos PR: 1266
File: cmd/describe_affected.go:0-0
Timestamp: 2025-06-07T19:28:21.289Z
Learning: In the Atmos codebase, using panic for unsupported flag types in flag processing functions like setDescribeAffectedFlagValueInCliArgs is the expected behavior rather than returning errors. This pattern is preferred for developer errors when unsupported types are added to the flagsKeyValue map.
Applied to files:
pkg/provisioner/provisioner.go
📚 Learning: 2025-04-04T02:03:21.906Z
Learnt from: aknysh
Repo: cloudposse/atmos PR: 1185
File: internal/exec/yaml_func_store.go:71-72
Timestamp: 2025-04-04T02:03:21.906Z
Learning: The codebase currently uses `log.Fatal` for error handling in library functions, which terminates the program. There is a plan to refactor this approach in a separate PR to improve API design by returning error messages instead of terminating execution.
Applied to files:
pkg/provisioner/provisioner.go
📚 Learning: 2025-12-10T23:12:15.805Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-10T23:12:15.805Z
Learning: Applies to **/*_test.go : Test behavior, not implementation. Never test stub functions. Avoid tautological tests. Make code testable using DI. No coverage theater. Remove always-skipped tests. Table-driven tests need real scenarios. Use `assert.ErrorIs(err, ErrSentinel)` for our/stdlib errors.
Applied to files:
pkg/provisioner/provisioner.go
📚 Learning: 2024-12-05T22:33:40.955Z
Learnt from: aknysh
Repo: cloudposse/atmos PR: 820
File: cmd/list_components.go:53-54
Timestamp: 2024-12-05T22:33:40.955Z
Learning: In the Atmos CLI Go codebase, using `u.LogErrorAndExit` within completion functions is acceptable because it logs the error and exits the command execution.
Applied to files:
pkg/provisioner/provisioner.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/provisioner.go
📚 Learning: 2025-08-16T23:32:40.412Z
Learnt from: aknysh
Repo: cloudposse/atmos PR: 1405
File: internal/exec/describe_dependents_test.go:455-456
Timestamp: 2025-08-16T23:32:40.412Z
Learning: In the cloudposse/atmos Go codebase, `InitCliConfig` returns a `schema.AtmosConfiguration` value (not a pointer), while `ExecuteDescribeDependents` expects a `*schema.AtmosConfiguration` pointer parameter. Therefore, when passing the result of `InitCliConfig` to `ExecuteDescribeDependents`, use `&atmosConfig` to pass the address of the value.
Applied to files:
pkg/provisioner/provisioner.go
📚 Learning: 2024-11-13T21:37:07.852Z
Learnt from: Cerebrovinny
Repo: cloudposse/atmos PR: 764
File: internal/exec/describe_stacks.go:289-295
Timestamp: 2024-11-13T21:37:07.852Z
Learning: In the `internal/exec/describe_stacks.go` file of the `atmos` project written in Go, avoid extracting the stack name handling logic into a helper function within the `ExecuteDescribeStacks` method, even if the logic appears duplicated.
Applied to files:
pkg/provisioner/provisioner.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/provisioner.go
📚 Learning: 2024-10-30T13:25:45.965Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 727
File: internal/exec/terraform_clean.go:405-412
Timestamp: 2024-10-30T13:25:45.965Z
Learning: In `internal/exec/terraform_clean.go`, when appending `stackFolders` to `folders` in the `handleCleanSubCommand` function, it's unnecessary to check if `stackFolders` is nil before appending, because in Go, appending a nil slice is safe and does not cause a panic.
Applied to files:
pkg/provisioner/provisioner.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/provisioner.go
📚 Learning: 2025-11-30T04:16:24.155Z
Learnt from: aknysh
Repo: cloudposse/atmos PR: 1821
File: pkg/merge/deferred.go:34-48
Timestamp: 2025-11-30T04:16:24.155Z
Learning: In the cloudposse/atmos repository, the `defer perf.Track()` guideline applies to functions that perform meaningful work (I/O, computation, external calls), but explicitly excludes trivial accessors/mutators (e.g., simple getters, setters with single integer increments, string joins, or map appends) where the tracking overhead would exceed the actual method cost and provide no actionable performance data. Hot-path methods called in tight loops should especially avoid perf.Track() if they perform only trivial operations.
Applied to files:
pkg/provisioner/provisioner.go
📚 Learning: 2025-12-10T23:12:15.805Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-10T23:12:15.805Z
Learning: Applies to **/*.go : Add `defer perf.Track(atmosConfig, "pkg.FuncName")()` with a blank line to all public functions. Use `nil` if no atmosConfig parameter is available.
Applied to files:
pkg/provisioner/provisioner.go
📚 Learning: 2025-11-09T19:06:58.470Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 1752
File: pkg/profile/list/formatter_table.go:27-29
Timestamp: 2025-11-09T19:06:58.470Z
Learning: In the cloudposse/atmos repository, performance tracking with `defer perf.Track()` is enforced on all functions via linting, including high-frequency utility functions, formatters, and renderers. This is a repository-wide policy to maintain consistency and avoid making case-by-case judgment calls about which functions should have profiling.
Applied to files:
pkg/provisioner/provisioner.go
📚 Learning: 2025-10-13T18:13:54.020Z
Learnt from: aknysh
Repo: cloudposse/atmos PR: 1622
File: pkg/perf/perf.go:140-184
Timestamp: 2025-10-13T18:13:54.020Z
Learning: In pkg/perf/perf.go, the `trackWithSimpleStack` function intentionally skips ownership checks at call stack depth > 1 to avoid expensive `getGoroutineID()` calls on every nested function. This is a performance optimization for the common single-goroutine execution case (most Atmos commands), accepting the rare edge case of potential metric corruption if multi-goroutine execution occurs at depth > 1. The ~19× performance improvement justifies this trade-off.
Applied to files:
pkg/provisioner/provisioner.go
📚 Learning: 2025-11-30T04:16:01.899Z
Learnt from: aknysh
Repo: cloudposse/atmos PR: 1821
File: pkg/merge/deferred.go:50-59
Timestamp: 2025-11-30T04:16:01.899Z
Learning: In the cloudposse/atmos repository, performance tracking with `defer perf.Track()` should NOT be added to trivial O(1) getter methods that only return field references or check map lengths (e.g., `GetDeferredValues()`, `HasDeferredValues()`). The guideline to add perf tracking to "all public functions" applies to functions that do meaningful work (I/O, computation, external calls), not to trivial accessors where the tracking overhead would exceed the operation time and pollute performance reports.
Applied to files:
pkg/provisioner/provisioner.go
📚 Learning: 2025-12-10T23:12:15.805Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-10T23:12:15.805Z
Learning: Applies to **/*.go : Use `context.Context` for cancellation signals, deadlines/timeouts, and request-scoped values. Context should be the first parameter in functions that accept it. DO NOT use context for configuration, dependencies, or avoiding proper function parameters.
Applied to files:
pkg/provisioner/provisioner.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/provisioner.go
📚 Learning: 2025-12-10T23:12:15.805Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-10T23:12:15.805Z
Learning: Applies to website/docs/cli/commands/**/*.mdx : All CLI commands/flags need Docusaurus docs in `website/docs/cli/commands/`. Use `<dl>` for args/flags. Build: `cd website && npm run build`
Applied to files:
docs/prd/s3-backend-provisioner.md
📚 Learning: 2025-09-13T16:39:20.007Z
Learnt from: samtholiya
Repo: cloudposse/atmos PR: 1466
File: cmd/markdown/atmos_toolchain_aliases.md:2-4
Timestamp: 2025-09-13T16:39:20.007Z
Learning: In the cloudposse/atmos repository, CLI documentation files in cmd/markdown/ follow a specific format that uses " $ atmos command" (with leading space and dollar sign prompt) in code blocks. This is the established project convention and should not be changed to comply with standard markdownlint rules MD040 and MD014.
Applied to files:
docs/prd/s3-backend-provisioner.md
📚 Learning: 2025-12-10T23:12:15.805Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-10T23:12:15.805Z
Learning: Applies to website/docs/cli/commands/**/*.mdx : Use `<dl>` for arguments/flags in documentation. Follow Docusaurus conventions: frontmatter, purpose note, screengrab, usage/examples/arguments/flags sections.
Applied to files:
docs/prd/s3-backend-provisioner.md
📚 Learning: 2025-12-10T23:12:15.805Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-10T23:12:15.805Z
Learning: Applies to website/blog/**/*.mdx : Follow PR template (what/why/references). PRs labeled `minor`/`major` MUST include blog post: `website/blog/YYYY-MM-DD-feature-name.mdx`. Use `.mdx` with YAML front matter, `<!--truncate-->` after intro. MUST use tags from `website/blog/tags.yml` only. MUST use existing author from `website/blog/authors.yml` or add new entry.
Applied to files:
docs/prd/s3-backend-provisioner.md
🧬 Code graph analysis (1)
pkg/provisioner/backend/s3_delete.go (1)
pkg/provisioner/backend/s3.go (1)
S3ClientAPI(28-38)
🪛 LanguageTool
docs/prd/s3-backend-provisioner.md
[typographical] ~134-~134: Consider using a typographic opening quote here.
Context: ...ce` flag:** - Command exits with error: "the --force flag is required for deletio...
(EN_QUOTES)
[typographical] ~1384-~1384: To join two clauses or introduce examples, consider using an em dash.
Context: ...ioner System](./provisioner-system.md)** - Generic provisioner infrastructure - **[...
(DASH_RULE)
[typographical] ~1385-~1385: To join two clauses or introduce examples, consider using an em dash.
Context: ...Provisioner](./backend-provisioner.md)** - Backend provisioner interface --- ## A...
(DASH_RULE)
🪛 markdownlint-cli2 (0.18.1)
docs/prd/s3-backend-provisioner.md
376-376: Hard tabs
Column: 1
(MD010, no-hard-tabs)
377-377: Hard tabs
Column: 1
(MD010, no-hard-tabs)
378-378: Hard tabs
Column: 1
(MD010, no-hard-tabs)
379-379: Hard tabs
Column: 1
(MD010, no-hard-tabs)
381-381: Hard tabs
Column: 1
(MD010, no-hard-tabs)
382-382: Hard tabs
Column: 1
(MD010, no-hard-tabs)
383-383: Hard tabs
Column: 1
(MD010, no-hard-tabs)
385-385: Hard tabs
Column: 1
(MD010, no-hard-tabs)
386-386: Hard tabs
Column: 1
(MD010, no-hard-tabs)
387-387: Hard tabs
Column: 1
(MD010, no-hard-tabs)
388-388: Hard tabs
Column: 1
(MD010, no-hard-tabs)
396-396: Hard tabs
Column: 1
(MD010, no-hard-tabs)
397-397: Hard tabs
Column: 1
(MD010, no-hard-tabs)
398-398: Hard tabs
Column: 1
(MD010, no-hard-tabs)
400-400: Hard tabs
Column: 1
(MD010, no-hard-tabs)
402-402: Hard tabs
Column: 1
(MD010, no-hard-tabs)
403-403: Hard tabs
Column: 1
(MD010, no-hard-tabs)
404-404: Hard tabs
Column: 1
(MD010, no-hard-tabs)
405-405: Hard tabs
Column: 1
(MD010, no-hard-tabs)
406-406: Hard tabs
Column: 1
(MD010, no-hard-tabs)
408-408: Hard tabs
Column: 1
(MD010, no-hard-tabs)
409-409: Hard tabs
Column: 1
(MD010, no-hard-tabs)
410-410: Hard tabs
Column: 1
(MD010, no-hard-tabs)
411-411: Hard tabs
Column: 1
(MD010, no-hard-tabs)
413-413: Hard tabs
Column: 1
(MD010, no-hard-tabs)
414-414: Hard tabs
Column: 1
(MD010, no-hard-tabs)
415-415: Hard tabs
Column: 1
(MD010, no-hard-tabs)
416-416: Hard tabs
Column: 1
(MD010, no-hard-tabs)
418-418: Hard tabs
Column: 1
(MD010, no-hard-tabs)
419-419: Hard tabs
Column: 1
(MD010, no-hard-tabs)
420-420: Hard tabs
Column: 1
(MD010, no-hard-tabs)
421-421: Hard tabs
Column: 1
(MD010, no-hard-tabs)
422-422: Hard tabs
Column: 1
(MD010, no-hard-tabs)
424-424: Hard tabs
Column: 1
(MD010, no-hard-tabs)
425-425: Hard tabs
Column: 1
(MD010, no-hard-tabs)
426-426: Hard tabs
Column: 1
(MD010, no-hard-tabs)
427-427: Hard tabs
Column: 1
(MD010, no-hard-tabs)
428-428: Hard tabs
Column: 1
(MD010, no-hard-tabs)
429-429: Hard tabs
Column: 1
(MD010, no-hard-tabs)
431-431: Hard tabs
Column: 1
(MD010, no-hard-tabs)
432-432: Hard tabs
Column: 1
(MD010, no-hard-tabs)
433-433: Hard tabs
Column: 1
(MD010, no-hard-tabs)
434-434: Hard tabs
Column: 1
(MD010, no-hard-tabs)
436-436: Hard tabs
Column: 1
(MD010, no-hard-tabs)
437-437: Hard tabs
Column: 1
(MD010, no-hard-tabs)
438-438: Hard tabs
Column: 1
(MD010, no-hard-tabs)
439-439: Hard tabs
Column: 1
(MD010, no-hard-tabs)
440-440: Hard tabs
Column: 1
(MD010, no-hard-tabs)
442-442: Hard tabs
Column: 1
(MD010, no-hard-tabs)
443-443: Hard tabs
Column: 1
(MD010, no-hard-tabs)
448-448: Hard tabs
Column: 1
(MD010, no-hard-tabs)
449-449: Hard tabs
Column: 1
(MD010, no-hard-tabs)
450-450: Hard tabs
Column: 1
(MD010, no-hard-tabs)
452-452: Hard tabs
Column: 1
(MD010, no-hard-tabs)
454-454: Hard tabs
Column: 1
(MD010, no-hard-tabs)
455-455: Hard tabs
Column: 1
(MD010, no-hard-tabs)
457-457: Hard tabs
Column: 1
(MD010, no-hard-tabs)
458-458: Hard tabs
Column: 1
(MD010, no-hard-tabs)
459-459: Hard tabs
Column: 1
(MD010, no-hard-tabs)
460-460: Hard tabs
Column: 1
(MD010, no-hard-tabs)
461-461: Hard tabs
Column: 1
(MD010, no-hard-tabs)
462-462: Hard tabs
Column: 1
(MD010, no-hard-tabs)
463-463: Hard tabs
Column: 1
(MD010, no-hard-tabs)
464-464: Hard tabs
Column: 1
(MD010, no-hard-tabs)
466-466: Hard tabs
Column: 1
(MD010, no-hard-tabs)
467-467: Hard tabs
Column: 1
(MD010, no-hard-tabs)
468-468: Hard tabs
Column: 1
(MD010, no-hard-tabs)
469-469: Hard tabs
Column: 1
(MD010, no-hard-tabs)
471-471: Hard tabs
Column: 1
(MD010, no-hard-tabs)
472-472: Hard tabs
Column: 1
(MD010, no-hard-tabs)
473-473: Hard tabs
Column: 1
(MD010, no-hard-tabs)
475-475: Hard tabs
Column: 1
(MD010, no-hard-tabs)
476-476: Hard tabs
Column: 1
(MD010, no-hard-tabs)
477-477: Hard tabs
Column: 1
(MD010, no-hard-tabs)
478-478: Hard tabs
Column: 1
(MD010, no-hard-tabs)
479-479: Hard tabs
Column: 1
(MD010, no-hard-tabs)
480-480: Hard tabs
Column: 1
(MD010, no-hard-tabs)
481-481: Hard tabs
Column: 1
(MD010, no-hard-tabs)
482-482: Hard tabs
Column: 1
(MD010, no-hard-tabs)
483-483: Hard tabs
Column: 1
(MD010, no-hard-tabs)
484-484: Hard tabs
Column: 1
(MD010, no-hard-tabs)
485-485: Hard tabs
Column: 1
(MD010, no-hard-tabs)
487-487: Hard tabs
Column: 1
(MD010, no-hard-tabs)
488-488: Hard tabs
Column: 1
(MD010, no-hard-tabs)
489-489: Hard tabs
Column: 1
(MD010, no-hard-tabs)
490-490: Hard tabs
Column: 1
(MD010, no-hard-tabs)
499-499: Hard tabs
Column: 1
(MD010, no-hard-tabs)
501-501: Hard tabs
Column: 1
(MD010, no-hard-tabs)
502-502: Hard tabs
Column: 1
(MD010, no-hard-tabs)
503-503: Hard tabs
Column: 1
(MD010, no-hard-tabs)
505-505: Hard tabs
Column: 1
(MD010, no-hard-tabs)
506-506: Hard tabs
Column: 1
(MD010, no-hard-tabs)
507-507: Hard tabs
Column: 1
(MD010, no-hard-tabs)
508-508: Hard tabs
Column: 1
(MD010, no-hard-tabs)
509-509: Hard tabs
Column: 1
(MD010, no-hard-tabs)
510-510: Hard tabs
Column: 1
(MD010, no-hard-tabs)
511-511: Hard tabs
Column: 1
(MD010, no-hard-tabs)
512-512: Hard tabs
Column: 1
(MD010, no-hard-tabs)
513-513: Hard tabs
Column: 1
(MD010, no-hard-tabs)
514-514: Hard tabs
Column: 1
(MD010, no-hard-tabs)
515-515: Hard tabs
Column: 1
(MD010, no-hard-tabs)
516-516: Hard tabs
Column: 1
(MD010, no-hard-tabs)
518-518: Hard tabs
Column: 1
(MD010, no-hard-tabs)
523-523: Hard tabs
Column: 1
(MD010, no-hard-tabs)
524-524: Hard tabs
Column: 1
(MD010, no-hard-tabs)
525-525: Hard tabs
Column: 1
(MD010, no-hard-tabs)
527-527: Hard tabs
Column: 1
(MD010, no-hard-tabs)
529-529: Hard tabs
Column: 1
(MD010, no-hard-tabs)
530-530: Hard tabs
Column: 1
(MD010, no-hard-tabs)
531-531: Hard tabs
Column: 1
(MD010, no-hard-tabs)
532-532: Hard tabs
Column: 1
(MD010, no-hard-tabs)
534-534: Hard tabs
Column: 1
(MD010, no-hard-tabs)
535-535: Hard tabs
Column: 1
(MD010, no-hard-tabs)
536-536: Hard tabs
Column: 1
(MD010, no-hard-tabs)
537-537: Hard tabs
Column: 1
(MD010, no-hard-tabs)
538-538: Hard tabs
Column: 1
(MD010, no-hard-tabs)
539-539: Hard tabs
Column: 1
(MD010, no-hard-tabs)
541-541: Hard tabs
Column: 1
(MD010, no-hard-tabs)
542-542: Hard tabs
Column: 1
(MD010, no-hard-tabs)
543-543: Hard tabs
Column: 1
(MD010, no-hard-tabs)
545-545: Hard tabs
Column: 1
(MD010, no-hard-tabs)
546-546: Hard tabs
Column: 1
(MD010, no-hard-tabs)
548-548: Hard tabs
Column: 1
(MD010, no-hard-tabs)
549-549: Hard tabs
Column: 1
(MD010, no-hard-tabs)
550-550: Hard tabs
Column: 1
(MD010, no-hard-tabs)
551-551: Hard tabs
Column: 1
(MD010, no-hard-tabs)
552-552: Hard tabs
Column: 1
(MD010, no-hard-tabs)
553-553: Hard tabs
Column: 1
(MD010, no-hard-tabs)
554-554: Hard tabs
Column: 1
(MD010, no-hard-tabs)
555-555: Hard tabs
Column: 1
(MD010, no-hard-tabs)
556-556: Hard tabs
Column: 1
(MD010, no-hard-tabs)
557-557: Hard tabs
Column: 1
(MD010, no-hard-tabs)
559-559: Hard tabs
Column: 1
(MD010, no-hard-tabs)
560-560: Hard tabs
Column: 1
(MD010, no-hard-tabs)
561-561: Hard tabs
Column: 1
(MD010, no-hard-tabs)
562-562: Hard tabs
Column: 1
(MD010, no-hard-tabs)
563-563: Hard tabs
Column: 1
(MD010, no-hard-tabs)
564-564: Hard tabs
Column: 1
(MD010, no-hard-tabs)
565-565: Hard tabs
Column: 1
(MD010, no-hard-tabs)
566-566: Hard tabs
Column: 1
(MD010, no-hard-tabs)
567-567: Hard tabs
Column: 1
(MD010, no-hard-tabs)
568-568: Hard tabs
Column: 1
(MD010, no-hard-tabs)
569-569: Hard tabs
Column: 1
(MD010, no-hard-tabs)
570-570: Hard tabs
Column: 1
(MD010, no-hard-tabs)
571-571: Hard tabs
Column: 1
(MD010, no-hard-tabs)
572-572: Hard tabs
Column: 1
(MD010, no-hard-tabs)
573-573: Hard tabs
Column: 1
(MD010, no-hard-tabs)
574-574: Hard tabs
Column: 1
(MD010, no-hard-tabs)
575-575: Hard tabs
Column: 1
(MD010, no-hard-tabs)
577-577: Hard tabs
Column: 1
(MD010, no-hard-tabs)
578-578: Hard tabs
Column: 1
(MD010, no-hard-tabs)
579-579: Hard tabs
Column: 1
(MD010, no-hard-tabs)
580-580: Hard tabs
Column: 1
(MD010, no-hard-tabs)
581-581: Hard tabs
Column: 1
(MD010, no-hard-tabs)
582-582: Hard tabs
Column: 1
(MD010, no-hard-tabs)
583-583: Hard tabs
Column: 1
(MD010, no-hard-tabs)
584-584: Hard tabs
Column: 1
(MD010, no-hard-tabs)
585-585: Hard tabs
Column: 1
(MD010, no-hard-tabs)
586-586: Hard tabs
Column: 1
(MD010, no-hard-tabs)
587-587: Hard tabs
Column: 1
(MD010, no-hard-tabs)
588-588: Hard tabs
Column: 1
(MD010, no-hard-tabs)
589-589: Hard tabs
Column: 1
(MD010, no-hard-tabs)
591-591: Hard tabs
Column: 1
(MD010, no-hard-tabs)
592-592: Hard tabs
Column: 1
(MD010, no-hard-tabs)
593-593: Hard tabs
Column: 1
(MD010, no-hard-tabs)
594-594: Hard tabs
Column: 1
(MD010, no-hard-tabs)
595-595: Hard tabs
Column: 1
(MD010, no-hard-tabs)
596-596: Hard tabs
Column: 1
(MD010, no-hard-tabs)
597-597: Hard tabs
Column: 1
(MD010, no-hard-tabs)
598-598: Hard tabs
Column: 1
(MD010, no-hard-tabs)
599-599: Hard tabs
Column: 1
(MD010, no-hard-tabs)
600-600: Hard tabs
Column: 1
(MD010, no-hard-tabs)
601-601: Hard tabs
Column: 1
(MD010, no-hard-tabs)
602-602: Hard tabs
Column: 1
(MD010, no-hard-tabs)
603-603: Hard tabs
Column: 1
(MD010, no-hard-tabs)
604-604: Hard tabs
Column: 1
(MD010, no-hard-tabs)
606-606: Hard tabs
Column: 1
(MD010, no-hard-tabs)
611-611: Hard tabs
Column: 1
(MD010, no-hard-tabs)
612-612: Hard tabs
Column: 1
(MD010, no-hard-tabs)
613-613: Hard tabs
Column: 1
(MD010, no-hard-tabs)
614-614: Hard tabs
Column: 1
(MD010, no-hard-tabs)
615-615: Hard tabs
Column: 1
(MD010, no-hard-tabs)
616-616: Hard tabs
Column: 1
(MD010, no-hard-tabs)
618-618: Hard tabs
Column: 1
(MD010, no-hard-tabs)
619-619: Hard tabs
Column: 1
(MD010, no-hard-tabs)
620-620: Hard tabs
Column: 1
(MD010, no-hard-tabs)
621-621: Hard tabs
Column: 1
(MD010, no-hard-tabs)
623-623: Hard tabs
Column: 1
(MD010, no-hard-tabs)
637-637: Hard tabs
Column: 1
(MD010, no-hard-tabs)
641-641: Hard tabs
Column: 1
(MD010, no-hard-tabs)
645-645: Hard tabs
Column: 1
(MD010, no-hard-tabs)
649-649: Hard tabs
Column: 1
(MD010, no-hard-tabs)
653-653: Hard tabs
Column: 1
(MD010, no-hard-tabs)
654-654: Hard tabs
Column: 1
(MD010, no-hard-tabs)
658-658: Hard tabs
Column: 1
(MD010, no-hard-tabs)
659-659: Hard tabs
Column: 1
(MD010, no-hard-tabs)
660-660: Hard tabs
Column: 1
(MD010, no-hard-tabs)
661-661: Hard tabs
Column: 1
(MD010, no-hard-tabs)
662-662: Hard tabs
Column: 1
(MD010, no-hard-tabs)
666-666: Hard tabs
Column: 1
(MD010, no-hard-tabs)
667-667: Hard tabs
Column: 1
(MD010, no-hard-tabs)
671-671: Hard tabs
Column: 1
(MD010, no-hard-tabs)
672-672: Hard tabs
Column: 1
(MD010, no-hard-tabs)
673-673: Hard tabs
Column: 1
(MD010, no-hard-tabs)
688-688: Hard tabs
Column: 1
(MD010, no-hard-tabs)
689-689: Hard tabs
Column: 1
(MD010, no-hard-tabs)
691-691: Hard tabs
Column: 1
(MD010, no-hard-tabs)
692-692: Hard tabs
Column: 1
(MD010, no-hard-tabs)
693-693: Hard tabs
Column: 1
(MD010, no-hard-tabs)
694-694: Hard tabs
Column: 1
(MD010, no-hard-tabs)
695-695: Hard tabs
Column: 1
(MD010, no-hard-tabs)
696-696: Hard tabs
Column: 1
(MD010, no-hard-tabs)
700-700: Hard tabs
Column: 1
(MD010, no-hard-tabs)
701-701: Hard tabs
Column: 1
(MD010, no-hard-tabs)
703-703: Hard tabs
Column: 1
(MD010, no-hard-tabs)
704-704: Hard tabs
Column: 1
(MD010, no-hard-tabs)
706-706: Hard tabs
Column: 1
(MD010, no-hard-tabs)
707-707: Hard tabs
Column: 1
(MD010, no-hard-tabs)
708-708: Hard tabs
Column: 1
(MD010, no-hard-tabs)
712-712: Hard tabs
Column: 1
(MD010, no-hard-tabs)
713-713: Hard tabs
Column: 1
(MD010, no-hard-tabs)
714-714: Hard tabs
Column: 1
(MD010, no-hard-tabs)
880-880: Emphasis used instead of a heading
(MD036, no-emphasis-as-heading)
890-890: Emphasis used instead of a heading
(MD036, no-emphasis-as-heading)
907-907: Emphasis used instead of a heading
(MD036, no-emphasis-as-heading)
923-923: Emphasis used instead of a heading
(MD036, no-emphasis-as-heading)
946-946: Emphasis used instead of a heading
(MD036, no-emphasis-as-heading)
952-952: Emphasis used instead of a heading
(MD036, no-emphasis-as-heading)
967-967: Emphasis used instead of a heading
(MD036, no-emphasis-as-heading)
977-977: Emphasis used instead of a heading
(MD036, no-emphasis-as-heading)
1442-1442: Emphasis used instead of a heading
(MD036, no-emphasis-as-heading)
⏰ Context from checks skipped due to timeout of 900000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
- GitHub Check: Acceptance Tests (macos)
- GitHub Check: Acceptance Tests (windows)
- GitHub Check: Summary
🔇 Additional comments (9)
docs/prd/s3-backend-provisioner.md (1)
74-85: Encryption note correctly clarifies SSE-S3 vs Bucket Key—LGTM.The clarification at line 83 explicitly states Bucket Key applies only to SSE-KMS, resolving prior ambiguity. This is accurate and helpful.
pkg/provisioner/backend/s3_delete.go (5)
1-16: LGTM! Clean package structure and properly organized imports.Imports follow the three-group convention (stdlib, 3rd-party, atmos) with correct aliasing.
18-64: Excellent resolution of previous review feedback.The function now:
- Enforces the
forceflag at the start (lines 38-40), addressing the "unused parameter" concern- Uses a clean orchestration pattern with well-factored helpers
- Includes comprehensive documentation with proper godot compliance
The safety mechanisms (validation, warnings, batch deletion) are well-structured.
66-189: Excellent ErrorBuilder usage throughout.All helper functions properly use ErrorBuilder with sentinel errors from
errors/errors.go, providing clear explanations, context, and actionable hints. This addresses the previous feedback about consistent error handling patterns.The
listAllObjectsfunction correctly handles pagination and counts state files for informative warnings.
207-238: Critical partial failure handling implemented correctly.Lines 224-236 properly handle the case where
DeleteObjectsreturns HTTP 200 but includes per-key errors inresp.Errors. This prevents infinite loops on undeletable objects and provides clear diagnostic information.The error includes bucket, key, version, code, and message context—exactly what's needed for troubleshooting.
240-281: Clean batch deletion and bucket removal.The
deleteAllObjectsfunction correctly paginates through large buckets (up to 1000 keys per batch per AWS limits) and delegates todeleteBatchfor consistent error handling.The
deleteBucketfunction provides clear error context and hints when the final deletion fails.pkg/provisioner/provisioner.go (3)
3-14: Imports organized correctly.Package declaration and import structure follow the guidelines. All necessary packages are imported with proper aliases.
35-50: Excellent use of DI and parameter structs.
ExecuteDescribeComponentFuncprovides clean dependency injection to avoid circular dependencies. TheProvisionParamsstruct eliminates the need for long parameter lists and revive suppressions, directly addressing prior feedback.
97-116: Correct not-implemented handling.Both functions now return proper errors via
ErrorBuilderinstead of nil, ensuring the CLI exits with non-zero status. This directly addresses prior feedback about false-success exit codes.
Convert all hard tabs to 2 spaces in Go code examples to pass markdownlint MD010 rule and prevent docs build failures. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
The checkS3BucketExists function uses errors.As() but the import block was missing the errors package. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
There was a problem hiding this comment.
Actionable comments posted: 1
♻️ Duplicate comments (4)
docs/prd/s3-backend-provisioner.md (4)
370-390: Fix hard tabs in Go code block (MD010 blocker).This issue was previously flagged but remains unresolved. The Go code block contains hard tab characters that violate markdownlint MD010 and will cause docs build failures. Replace all hard tabs with spaces (2 spaces per tab to match project style).
Run this to fix:
#!/bin/bash sed -i 's/\t/ /g' docs/prd/s3-backend-provisioner.mdThen verify with:
markdownlint docs/prd/s3-backend-provisioner.md
499-520: Add missingerrorsimport to Go example.Line 510 calls
errors.As()but the import block (lines 375–389) does not include theerrorsstandard library package. This is a code example correctness issue.import ( "context" + "errors" "fmt" "sync" "time"
113-135: Resolve contradictory deletion semantics.The section states
--forceis "always required" but then describes a "default behavior (no --force)" mode. Reword to avoid ambiguity: if--forceis always required, there is no default non-forced path. Either update the heading from "Non-Empty Bucket Handling" to clarify behavior when--forceis supplied, or revise the opening statement if deletion without--forceis actually possible.Suggested fix: remove lines 133–135 and reword:
-**Without `--force` flag:** -- Command exits with error: "the --force flag is required for deletion" -- No bucket inspection or deletion occursThen add at the end of line 124 context: "When the
--forceflag is provided:" and remove the "Without--force" subsection.
881-881: Convert bold "Step X" lines to markdown headings (MD036).Lines using bold text (e.g.,
**Step 1: ...**) should be markdown headings (### Step 1: ...) to comply with markdownlint MD036 and improve semantic structure. This affects the Migration Guide and other sections.Examples:
- Line 881:
**Step 1: Enable global feature flag (optional)**→### Step 1: Enable global feature flag (optional)- Line 891:
**Step 2: Enable per-component**→### Step 2: Enable per-component- Line 908:
**Step 3: Generate backend**→### Step 3: Generate backend- Line 924:
**Step 1: Provision production backend via Terraform module**→### Step 1: Provision production backend via Terraform module- Line 947:
**Step 2: Apply backend infrastructure**→### Step 2: Apply backend infrastructure- Line 953:
**Step 3: Update component to use production backend**→### Step 3: Update component to use production backend- Line 968:
**Step 4: Migrate state**→### Step 4: Migrate state- Line 978:
**Step 5: (Optional) Delete old auto-provisioned bucket**→### Step 5: (Optional) Delete old auto-provisioned bucket- Line 1443:
**End of PRD**→### End of PRDAlso applies to: 891-891, 908-908, 924-924, 947-947, 953-953, 968-968, 978-978
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Disabled knowledge base sources:
- Linear integration is disabled by default for public repositories
You can enable these sources in your CodeRabbit configuration.
📒 Files selected for processing (1)
docs/prd/s3-backend-provisioner.md(1 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
docs/prd/**/*.md
📄 CodeRabbit inference engine (CLAUDE.md)
PRDs (Product Requirements Documents) must be in
docs/prd/using kebab-case filenames:command-registry-pattern.md,error-handling-strategy.md,testing-strategy.md
Files:
docs/prd/s3-backend-provisioner.md
🧠 Learnings (16)
📓 Common learnings
Learnt from: Listener430
Repo: cloudposse/atmos PR: 934
File: tests/fixtures/scenarios/docs-generate/README.md.gotmpl:99-118
Timestamp: 2025-01-25T03:51:57.689Z
Learning: For the cloudposse/atmos repository, changes to template contents should be handled in dedicated PRs and are typically considered out of scope for PRs focused on other objectives.
Learnt from: aknysh
Repo: cloudposse/atmos PR: 944
File: go.mod:206-206
Timestamp: 2025-01-17T00:18:57.769Z
Learning: For indirect dependencies with license compliance issues in the cloudposse/atmos repository, the team prefers to handle them in follow-up PRs rather than blocking the current changes, as these issues often require deeper investigation of the dependency tree.
📚 Learning: 2025-12-10T23:12:15.805Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-10T23:12:15.805Z
Learning: Applies to website/docs/cli/commands/**/*.mdx : All CLI commands/flags need Docusaurus docs in `website/docs/cli/commands/`. Use `<dl>` for args/flags. Build: `cd website && npm run build`
Applied to files:
docs/prd/s3-backend-provisioner.md
📚 Learning: 2025-09-13T16:39:20.007Z
Learnt from: samtholiya
Repo: cloudposse/atmos PR: 1466
File: cmd/markdown/atmos_toolchain_aliases.md:2-4
Timestamp: 2025-09-13T16:39:20.007Z
Learning: In the cloudposse/atmos repository, CLI documentation files in cmd/markdown/ follow a specific format that uses " $ atmos command" (with leading space and dollar sign prompt) in code blocks. This is the established project convention and should not be changed to comply with standard markdownlint rules MD040 and MD014.
Applied to files:
docs/prd/s3-backend-provisioner.md
📚 Learning: 2025-12-10T23:12:15.805Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-10T23:12:15.805Z
Learning: Applies to website/docs/cli/commands/**/*.mdx : Use `<dl>` for arguments/flags in documentation. Follow Docusaurus conventions: frontmatter, purpose note, screengrab, usage/examples/arguments/flags sections.
Applied to files:
docs/prd/s3-backend-provisioner.md
📚 Learning: 2025-12-10T23:12:15.805Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-10T23:12:15.805Z
Learning: Applies to website/blog/**/*.mdx : Follow PR template (what/why/references). PRs labeled `minor`/`major` MUST include blog post: `website/blog/YYYY-MM-DD-feature-name.mdx`. Use `.mdx` with YAML front matter, `<!--truncate-->` after intro. MUST use tags from `website/blog/tags.yml` only. MUST use existing author from `website/blog/authors.yml` or add new entry.
Applied to files:
docs/prd/s3-backend-provisioner.md
📚 Learning: 2024-12-02T21:26:32.337Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 808
File: pkg/config/config.go:478-483
Timestamp: 2024-12-02T21:26:32.337Z
Learning: In the 'atmos' project, when reviewing Go code like `pkg/config/config.go`, avoid suggesting file size checks after downloading remote configs if such checks aren't implemented elsewhere in the codebase.
Applied to files:
docs/prd/s3-backend-provisioner.md
📚 Learning: 2025-12-10T23:12:15.805Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-10T23:12:15.805Z
Learning: Applies to **/*.go : ALWAYS ask for user approval before adding nolint comments. Prefer refactoring over nolint. Exception for bubbletea models: `//nolint:gocritic // bubbletea models must be passed by value`. Exception for intentional subprocess calls: `//nolint:gosec // intentional subprocess call`. NEVER add nolint for gocognit, cyclomatic complexity, magic numbers, or nestif.
Applied to files:
docs/prd/s3-backend-provisioner.md
📚 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 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
Applied to files:
docs/prd/s3-backend-provisioner.md
📚 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:
docs/prd/s3-backend-provisioner.md
📚 Learning: 2025-07-05T20:59:02.914Z
Learnt from: aknysh
Repo: cloudposse/atmos PR: 1363
File: internal/exec/template_utils.go:18-18
Timestamp: 2025-07-05T20:59:02.914Z
Learning: In the Atmos project, gomplate v4 is imported with a blank import (`_ "github.com/hairyhenderson/gomplate/v4"`) alongside v3 imports to resolve AWS SDK version conflicts. V3 uses older AWS SDK versions that conflict with newer AWS modules used by Atmos. A full migration to v4 requires extensive refactoring due to API changes and should be handled in a separate PR.
Applied to files:
docs/prd/s3-backend-provisioner.md
📚 Learning: 2025-12-10T23:12:15.805Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-10T23:12:15.805Z
Learning: Applies to internal/**/*.go : For legacy patterns (internal/non-user-facing only): use `errors.Join` for multiple errors, `fmt.Errorf("%w", err)` for chains (sequential call stack), or `fmt.Errorf` with multiple `%w` like `errors.Join` (Go 1.20+).
Applied to files:
docs/prd/s3-backend-provisioner.md
📚 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:
docs/prd/s3-backend-provisioner.md
📚 Learning: 2025-12-10T23:12:15.805Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-10T23:12:15.805Z
Learning: Applies to **/*.go : ALL user-facing errors MUST use ErrorBuilder with sentinel errors from `errors/errors.go`. ALWAYS use `errors.Is()` for checking, NEVER string comparison. ALWAYS use `assert.ErrorIs()` in tests, NEVER `assert.Contains(err.Error(), ...)`
Applied to files:
docs/prd/s3-backend-provisioner.md
📚 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:
docs/prd/s3-backend-provisioner.md
📚 Learning: 2025-04-04T02:03:23.676Z
Learnt from: aknysh
Repo: cloudposse/atmos PR: 1185
File: internal/exec/yaml_func_store.go:26-26
Timestamp: 2025-04-04T02:03:23.676Z
Learning: The Atmos codebase currently uses `log.Fatal` for error handling in multiple places. The maintainers are aware this isn't an ideal pattern (should only be used in main() or init() functions) and plan to address it comprehensively in a separate PR. CodeRabbit should not flag these issues or push for immediate changes until that refactoring is complete.
Applied to files:
docs/prd/s3-backend-provisioner.md
📚 Learning: 2025-12-10T23:12:15.805Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-10T23:12:15.805Z
Learning: Applies to **/*.go : Organize imports in three groups separated by blank lines, sorted alphabetically: 1) Go stdlib, 2) 3rd-party (NOT cloudposse/atmos), 3) Atmos packages. Maintain aliases: `cfg`, `log`, `u`, `errUtils`
Applied to files:
docs/prd/s3-backend-provisioner.md
🪛 LanguageTool
docs/prd/s3-backend-provisioner.md
[typographical] ~134-~134: Consider using a typographic opening quote here.
Context: ...ce` flag:** - Command exits with error: "the --force flag is required for deletio...
(EN_QUOTES)
[typographical] ~1385-~1385: To join two clauses or introduce examples, consider using an em dash.
Context: ...ioner System](./provisioner-system.md)** - Generic provisioner infrastructure - **[...
(DASH_RULE)
[typographical] ~1386-~1386: To join two clauses or introduce examples, consider using an em dash.
Context: ...Provisioner](./backend-provisioner.md)** - Backend provisioner interface --- ## A...
(DASH_RULE)
🪛 markdownlint-cli2 (0.18.1)
docs/prd/s3-backend-provisioner.md
881-881: Emphasis used instead of a heading
(MD036, no-emphasis-as-heading)
891-891: Emphasis used instead of a heading
(MD036, no-emphasis-as-heading)
908-908: Emphasis used instead of a heading
(MD036, no-emphasis-as-heading)
924-924: Emphasis used instead of a heading
(MD036, no-emphasis-as-heading)
947-947: Emphasis used instead of a heading
(MD036, no-emphasis-as-heading)
953-953: Emphasis used instead of a heading
(MD036, no-emphasis-as-heading)
968-968: Emphasis used instead of a heading
(MD036, no-emphasis-as-heading)
978-978: Emphasis used instead of a heading
(MD036, no-emphasis-as-heading)
1443-1443: Emphasis used instead of a heading
(MD036, no-emphasis-as-heading)
⏰ 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
|
Warning Changelog Entry RequiredThis PR is labeled Action needed: Add a new blog post in Example filename: Alternatively: If this change doesn't require a changelog entry, remove the |
|
These changes were released in v1.202.0-rc.1. |
|
These changes were released in v1.203.0-test.1. |
Summary
atmos provision backendDetails
terraform initwhen enabledTest Plan
atmos provision backend <component> --stack <stack>🤖 Generated with Claude Code
Co-Authored-By: Claude noreply@anthropic.com
Summary by CodeRabbit
New Features
Documentation
Bug Fixes
Tests
✏️ Tip: You can customize this high-level summary in your review settings.