Skip to content

[EPAC-2060]: migrate Terraform state to S3 remote backend with bootstrap-from-zero#594

Merged
riddim-developer-bot[bot] merged 1 commit into
mainfrom
symphony/epac-2060-migrate-terraform-state-to-s3-remote-backend-wit
May 25, 2026
Merged

[EPAC-2060]: migrate Terraform state to S3 remote backend with bootstrap-from-zero#594
riddim-developer-bot[bot] merged 1 commit into
mainfrom
symphony/epac-2060-migrate-terraform-state-to-s3-remote-backend-wit

Conversation

@riddim-developer-bot

Copy link
Copy Markdown
Contributor

Summary

  • Adds infra/terraform/bootstrap.sh — idempotent script that creates per-workspace S3 state buckets (versioned, encrypted, public-access-blocked) and DynamoDB lock tables (PAY_PER_REQUEST)
  • Migrates backend blocks in core/staging/production/versions.tf from the old shared epac-terraform-state bucket to per-workspace naming: epac-tfstate-{workspace}-227530433709
  • Removes state-storage Terraform resources from core/main.tf — bootstrap.sh owns those outside Terraform management to avoid the bootstrap cycle
  • Updates .gitignore with *.tfvars, *.tfplan, and infra/terraform/**/.terraform/ patterns
  • Rewrites infra/terraform/README.md with remote state table, bootstrap instructions, local usage, and smoke test

Design decisions

  • Account ID hard-coded in backend blocks because Terraform loads backend config before variables are available. Documented in README.
  • Per-workspace buckets (epac-tfstate-core-*, epac-tfstate-staging-*, epac-tfstate-production-*) instead of one shared bucket with key prefixes — isolates blast radius and makes IAM scoping straightforward.
  • Bootstrap also creates core workspace resources when bootstrapping staging or production — ensures terraform init in core always works from a fresh account.

Verification

  • terraform validate passes for all three modules (core, staging, production) with -backend=false
  • bootstrap.sh shellcheck-clean with set -euo pipefail
  • No committed .tfstate or .tfstate.backup files remain in the repo
  • Outputs audit: no sensitive material in any outputs.tf — all outputs are bucket names, ARNs, domain names, or function name lists
  • .github/workflows/infra-validate.yml unchanged and continues to use -backend=false

State migration (human step)

After this PR merges and bootstrap.sh is run against the target account:

cd infra/terraform/staging
terraform init -migrate-state -force-copy
terraform state list  # verify resource list matches pre-migration
terraform plan        # expect clean or only stranded Aurora resources

Stranded Aurora resources (aws_db_cluster.epac_db, aws_db_instance.epac_db_writer) should be removed via terraform state rm since the cluster was retired. Production migration requires human execution per the external validation gate.

Skipped checks

  • Actual state migration (terraform init -migrate-state): requires AWS credentials and the bootstrap resources to exist. This is a human-gated step documented above and in the README.
  • iOS build: no iOS code changed.

Resolves EPAC-2060

Reviewer-Boundary: review-only

…rap-from-zero

- Add infra/terraform/bootstrap.sh: idempotent script that creates per-workspace
  S3 buckets (versioned, encrypted, public-access-blocked) and DynamoDB lock
  tables using PAY_PER_REQUEST billing
- Update backend blocks in core/staging/production versions.tf to use new
  per-workspace bucket naming: epac-tfstate-{workspace}-{account_id}
- Remove state-storage resources (S3 bucket + DynamoDB table) from core/main.tf
  since bootstrap.sh now owns those resources outside Terraform management
- Update .gitignore with *.tfvars, *.tfplan, and infra/terraform/**/.terraform/
- Rewrite infra/terraform/README.md with remote state table, bootstrap
  instructions, local usage guide, and smoke test documentation
- Update core/staging/production README files to reference new backend layout

Account ID (227530433709) is hard-coded in backend blocks because Terraform
loads backend config before variables are available.

Resolves EPAC-2060
@riddim-developer-bot riddim-developer-bot Bot added the autonomous Enrolled in prconverged daemon for automated review and merge label May 25, 2026
@riddim-developer-bot
riddim-developer-bot Bot enabled auto-merge (squash) May 25, 2026 17:57
@riddim-developer-bot
riddim-developer-bot Bot merged commit 7680e6e into main May 25, 2026
6 checks passed
@riddim-developer-bot
riddim-developer-bot Bot deleted the symphony/epac-2060-migrate-terraform-state-to-s3-remote-backend-wit branch May 25, 2026 18:02
riddim-developer-bot Bot added a commit that referenced this pull request May 25, 2026
## Why
Terraform local state files were already removed as part of remote-state
migration, but the repository still needed explicit hygiene: enforce
ignore rules for generated state/plan artifacts and document the
operator path after the migration.

## What changed
- Updated `infra/terraform/README.md` with the post-migration operator
workflow:
- state storage and backend reference (A1 bootstrap script + A2 backend
declarations)
- local run path: `aws sso login` -> `bash infra/terraform/bootstrap.sh
<env>` -> `cd infra/terraform/<env> && terraform init && terraform plan`
- fresh-account path and note that bootstrap/migration is one-time
operational setup
- link to migration PR evidence:
[EPAC-2060](#594)
- Updated root `.gitignore` to ensure Terraform state and plan artifacts
are ignored.
- Confirmed `.terraform.lock.hcl` is not ignored so provider lockfiles
can stay committed.

## Acceptance criteria
- �[32mOK�[0m `infra/terraform/staging/terraform.tfstate` deleted if
present in git (already absent in this branch at issue time).
- �[32mOK�[0m `infra/terraform/staging/terraform.tfstate.backup` deleted
if present in git (already absent).
- �[32mOK�[0m production/core local state globs similarly absent in git.
- �[32mOK�[0m `.gitignore` excludes `*.tfstate`, `*.tfstate.backup`,
`*.tfvars`, `*.tfplan`, `.terraform/`.
- �[32mOK�[0m `.terraform.lock.hcl` remains tracked when present
(pattern removed).
- �[32mOK�[0m `infra/terraform/README.md` now documents remote state
path, local run commands, fresh-account operator flow, and migration
evidence link.

## Verification
- `git diff --stat origin/main...HEAD` shows only `.gitignore` and
`infra/terraform/README.md` changed.
- `gh pr create` performed after rebase + push (branch is clean and
rebased).

## Skipped checks
- No Terraform runtime commands were executed in this PR (no functional
verification requested by ticket).

Resolves EPAC-2070

Reviewer-Boundary: review-only

Co-authored-by: riddim-developer-bot <developer-bot@riddimsoftware.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

autonomous Enrolled in prconverged daemon for automated review and merge

Projects

None yet

Development

Successfully merging this pull request may close these issues.

0 participants