Some checks failed
ci/woodpecker/push/woodpecker Pipeline failed
stop-slop, taste-skill, terrashark had embedded .git dirs causing Woodpecker clone to fail on submodule update.
3.1 KiB
3.1 KiB
Do and Don't Patterns
Use this guide as a fast checklist for safe Terraform/OpenTofu output.
Identity and iteration
Do:
- use
for_eachwith stable, business-meaningful keys - keep identity keys separate from mutable attributes
- add
movedblocks when renaming resources or module addresses
Don't:
- use list index as long-lived identity
- derive identity from a computed attribute
- delete/rename addresses without an explicit migration plan
Secrets and sensitive data
Do:
- mark secret outputs as
sensitive = true - use secret managers and data sources for runtime injection
- avoid logging sensitive values in
localsoroutput
Don't:
- put secrets in
defaultvalues or.tfvarscommitted to VCS - echo secrets in provisioner commands
- rely on
sensitivealone to protect state contents
State boundaries and blast radius
Do:
- keep production in isolated state backends or workspaces
- split large stacks by lifecycle and ownership
- use environment protection and approvals for apply
Don't:
- mix unrelated systems in a single root state
- apply directly to production from unreviewed branches
- use one monolithic stack for all environments
Module contracts
Do:
- expose typed inputs and explicit outputs
- use
optional()for evolution-friendly contracts - validate invariants with
validationandprecondition
Don't:
- accept untyped
map(any)for core interfaces - expose entire provider objects as outputs
- push environment-specific policy into primitive modules
Providers and versions
Do:
- pin runtime and providers with bounded constraints
- commit
.terraform.lock.hclintentionally - pass provider aliases explicitly to child modules
Don't:
- float provider versions
- rely on implicit provider inheritance in multi-region setups
- mix upgrades with functional changes in the same PR
Data sources and dependencies
Do:
- use data sources for read-only integration
- model dependencies via input/output wiring
- keep
depends_onfor real ordering requirements only
Don't:
- use
depends_onto paper over missing interfaces - use data sources for identity fields that can change
- create hidden ordering between unrelated resources
CI/CD and policy
Do:
- separate plan and apply
- keep an auditable reviewed plan artifact
- run policy and cost checks on every plan
Don't:
- allow direct apply from arbitrary branches
- skip policy checks for production changes
- delete plan artifacts before approval
Testing
Do:
- run
terraform test/tofu testfor module-level checks - use Terratest for workflow or integration validation
- tier tests by risk and cost
Don't:
- rely on plan-only validation for runtime-only attributes
- run destructive tests without isolation and cleanup
- treat mocked provider tests as full integration coverage
Migration and refactors
Do:
- include
movedorimportstrategy in the same change - run a reviewed plan before any apply
- document rollback steps for destructive changes
Don't:
- rename resources without preserving state identity
- apply refactors without plan review
- remove resources without lifecycle transition