# AGENTS.md This file provides guidance to AI coding agents when working with code in this repository. ## Repository Overview This is the Go-based Terraform AWS Provider (`github.com/hashicorp/terraform-provider-aws`). It maps AWS API resources to Terraform resources, data sources, ephemeral resources and actions (collectively often referred to as just resources). The primary language is Go; HCL appears in acceptance test configurations and website documentation. ## Agent Registry This project uses specialized personas for different tasks. ### Available Personas - **`@contributor`**: [Contributor Persona](./.agents/contributor.md) - Contributes code in the form of bugfixes, enhancements to existing resources, and new resources. Makes clarifications and corrections to existing documentation. - **`@maintainer`**: [Maintainer Persona](./.agents/maintainer.md) - Steward of the project, responsible for both internal and external quality. Reviews contributions. Maintains provider-level features, including new Terraform language constructs. - **`@tcm`**: [TCM Persona](./.agents/tcm.md) - Triages incoming GitHub issues and PRs. Engages with community members to answer technical and process questions. Suggests workarounds and alternatives to reported bugs. ### Registry Rules - Always use the requested persona for tasks. - If no persona is specified, default to `@contributor`. - A persona defines a role with a perspective and responsibilities. - Personas may invoke skills. ## Skills Skills are loaded from `./.agents/skills`. Each skill supplies step-by-step instructions, code patterns, and guardrails for a specific task. | Skill | Task | |---|---| | [go-conventions](./.agents/skills/go-conventions/SKILL.md) | Fundamental Go conventions for the provider. Load before writing or editing any Go file in `internal/**`. | | [breaking-changes](./.agents/skills/breaking-changes/SKILL.md) | Review a PR for possible breaking changes. | | [changelog](./.agents/skills/changelog/SKILL.md) | Add a `.changelog/.txt` entry from a PR URL, commit, and push (with confirmation). | | [fixdocs](./.agents/skills/fixdocs/SKILL.md) | Fix end user documentation with `swissshepherd`. | | [new-list-resource](./.agents/skills/new-list-resource/SKILL.md) | Implement a new list resource. | | [resource-identity](./.agents/skills/resource-identity/SKILL.md) | Add resource identity to a resource. | | [review-pr](./.agents/skills/review-pr/SKILL.md) | Review a Terraform AWS Provider PR. Router: holds cross-cutting principles and routes to the scoped `review-*` leaf skills below based on the files a PR changes. | | [review-lifecycle](./.agents/skills/review-lifecycle/SKILL.md) | Review resource CRUD, errors, and AutoFlex (`internal/service/**/*.go`). | | [review-schema](./.agents/skills/review-schema/SKILL.md) | Review Plugin Framework schema shape (`internal/service/**/*.go`). | | [review-helpers](./.agents/skills/review-helpers/SKILL.md) | Review finders, waiters, sweepers, data sources, list resources (`internal/service/**/*.go`). | | [review-identity](./.agents/skills/review-identity/SKILL.md) | Review Resource Identity annotations and import-ID handlers (`internal/service/**/*.go`). | | [review-tags](./.agents/skills/review-tags/SKILL.md) | Review tag schema attributes, wiring, and the `@Tags` annotation (`internal/service/**/*.go`). | | [review-generated](./.agents/skills/review-generated/SKILL.md) | Review generated code (`internal/service/**/*_gen.go`). | | [review-tests](./.agents/skills/review-tests/SKILL.md) | Review acceptance/unit test basics (`internal/service/**/*_test.go`). | | [review-tests-helpers](./.agents/skills/review-tests-helpers/SKILL.md) | Review Exists/Destroy, data source, list, and unit tests (`internal/service/**/*_test.go`). | | [review-docs](./.agents/skills/review-docs/SKILL.md) | Review a PR's end user documentation updates (`website/docs/**/*.markdown`). | ## Stack - Go 1.26+, AWS SDK for Go v2. - Terraform Plugin Framework + Terraform Plugin SDKv2 ([muxed](https://developer.hashicorp.com/terraform/plugin/mux) provider). - Code generators in `internal/generate/`. - Build system: GNU Make (see `GNUmakefile`). - Testing: Go standard `testing` package + [`terraform-plugin-testing` acceptance test framework](https://developer.hashicorp.com/terraform/plugin/testing/acceptance-tests). ## Code Structure (The important parts) ``` terraform-provider-aws/ ├── .changelog/ # CHANGELOG entries ├── internal/ │ ├── acctest/ # Acceptance test helpers │ ├── backoff/ # Low-level backoff loop implementation │ ├── conns/ # Provider-level global state, including provider configuration │ ├── enum/ # AWS SDK for Go v2 enumeration utilities │ ├── errs/ # Go `error` utilities │ │ ├── fwdiag/ # Terraform Plugin Framework `Diagnostic` utilities │ │ └── sdkdiag/ # Terraform Plugin SDKv2 `Diagnostic` utilities │ ├── flex/ # General and Terraform Plugin SDKv2-specific flatteners and expanders │ ├── framework/ # Terraform Plugin Framework utilities │ │ ├── flex/ # Flatteners and expanders, including AutoFlex │ │ ├── types/ # Custom type implementations │ │ └── validators/ # Validator implementations │ ├── function/ # Provider functions │ ├── generate/ # Code generators │ ├── iter/ # Go iterator utilities │ ├── json/ # JSON utilities │ ├── maps/ # Go `map` utilities │ ├── provider/ # Provider initialization and configuration │ │ ├── framework/ # Terraform Plugin Framework-specific initialization and configuration plus interceptors │ │ ├── interceptors/ # Common interceptor utilities │ │ └── sdkv2/ # Terraform Plugin SDKv2-specific initialization and configuration plus interceptors │ ├── reflect/ # Go reflection utilities │ ├── retry/ # Generic operation retry functionality │ │ └── state.go # Resource wait-for-state functionality │ ├── sdkv2/ # Terraform Plugin SDKv2 utilities │ ├── service/*/ # Per-service resource implementations │ │ ├── exports.go # Functions and variables used by other Go packages │ │ ├── exports_test.go # Functions and variables used by acceptance tests for this Go package │ │ ├── generate.go # Code generation instructions │ │ └── sweep.go # This service's resource sweepers │ ├── slices/ # Go slice utilities │ ├── smerr/ # Smarterr utilities │ ├── sweep/ # Resource sweeper utilities │ ├── tags/ # Resource tagging utilities │ ├── types/ # Go types │ ├── vcr/ # VCR testing utilities │ └── verify/ # Terraform Plugin SDKv2-specific attribute validation ├── go.mod ├── go.sum ├── GNUmakefile # Build and test commands └── main.go # Entry point ``` ## Important: Dual Framework This provider uses TWO Terraform plugin frameworks simultaneously: - **Terraform Plugin SDKv2** (older resources) — uses `schema.Resource`, `d.Set()`, `d.Get()` - **Terraform Plugin Framework** (newer resources) — uses `resource.Resource`, plan modifiers, AutoFlex When modifying an existing resource, use the SAME framework it already uses. When creating a new resource, use the Terraform Plugin Framework. ## Conventions ### Non-negotiable Rules - Verification is a hard exit criterion for every PR (see [Development workflow](#development-workflow)). Without it, the task is not done. - Prefer the boring, obvious solution. Touch only what you're asked to touch. - Every PR must build, pass tests, and be lint-free. - Follow existing conventions for naming, style, and idioms. - Follow current best practices and conventions for naming, style, idioms. Legacy patterns should be avoided. - Reuse the repository's utility packages (in `internal/`, excluding `internal/generate/` and `internal/service/`) before writing new utility code. Add new dependencies only after exhausting these. ### Coding Conventions (Follow These) #### Go language usage - **Before writing or editing any Go file in `internal/**`, load the [go-conventions](./.agents/skills/go-conventions/SKILL.md) skill and follow it.** - **GO USES TAB (`\t`) CHARACTERS TO INDENT** - **Use elegant Go, modern (Go 1.26+) idioms** (e.g., `slices.Contains()`) - **Go nuance**: Don't build single files, **build a package** #### Error handling - Use smarterr/smerr - Use `retry.NotFound()` to check for missing resources during Read. - Return early on error; don't accumulate diagnostics past the first fatal error. ### Common Patterns #### Resource file naming - `internal/service/{service}/{thing}.go` — thing resource implementation - `internal/service/{service}/{thing}_test.go` — thing resource acceptance tests - `internal/service/{service}/{thing}_data_source.go` — thing data source - `website/docs/r/{service}_{thing}.html.markdown` — thing resource documentation - `website/docs/d/{service}_{thing}.html.markdown` — thing data source documentation #### Resource implementation pattern (Framework) New resources use the Terraform Plugin Framework pattern: - Implement `resource.Resource` interface - Use AutoFlex for flattening/expanding where possible - Use `retry.RetryContext` for eventual consistency For example: ```go func (r *thingResource) Read(ctx context.Context, req resource.ReadRequest, resp *resource.ReadResponse) { // 1. Read model from state // 2. Call AWS API // 3. Handle NotFound → remove from state // 4. AutoFlex response into model // 5. Write model to state } ``` ## Development workflow ### Overview - Substantive changes and correctness first, lint after: run `make quick-fix PKG=` near the end, before raising PR. Avoid the tiny change → lint → tiny change → lint loop. `make fmt` is the cheap exception — run it freely. - Scope most commands to the package changed — the provider is very large. CI is the provider-wide gate for build, lint, and semgrep. ### AI usage When you help prepare a PR, disclose the AI's role in the description and add `🤖🤖🤖` to the title. See [`docs/ai-usage.md`](docs/ai-usage.md) for the full policy. **Humans are fully responsible for the code regardless of AI usage.** ### Running commands - `make t` and `make testacc`: Run acceptance tests and create real AWS resources. Get explicit approval before running. - `make …` (except acceptance tests), `go …`, and read-only commands (`awk`, `grep`, `ls`, `rg`) are safe to run without confirmation. ### Regenerate, test, and verify (scoped to your package) - **Regenerate** after changing annotations or a service's `generate.go`: `make gen PKG=`. Run the provider-wide `make gen` only after changing `names/data/names_data.hcl`, anything under `internal/generate/` — it affects every service and takes many minutes. - **Test** with `make test PKG=` (unit test) (`T=` filters by name); for non-service changes, e.g., `go test ./internal/conns/...`. - **Fix and verify** with `make quick-fix PKG=` — the default final pass. It applies formatting, imports, lint, semgrep fixes, and `copyright-fix`, and fails if the build is broken (no separate build step needed). - **Documentation**: run `make swissshepherd` to verify changes align with docs. Run `make swissshepherd-refresh` only once at the beginning of a session. ### Commits, CHANGELOG, and docs - Keep each commit small, atomic, and single-purpose; the message describes the change. - Add a `.changelog/` entry for new features, bug fixes, and enhancements. - New features require new documentation; `./docs/end-user-documentation.md` is authoritative. ## Boundaries - Never edit `CHANGELOG.md` directly — use `.changelog/` entries. - Never edit generated files by hand — modify the generator or annotations, then run `make gen PKG=` or `make gen` (provider level). - Do not modify `go.mod`/`go.sum` without running `go mod tidy`. - Do not add new external dependencies without explicit approval. - The `website/` directory follows different conventions; see `docs/end-user-documentation.md`.