Repository navigation
fix(scripts): make init-backend.sh write the state key CI uses - #1142
Conversation
init-backend.sh wrote terraform/environments/aws/<env>/backend.tf with key "<env>/terraform.tfstate" and told the operator to init and apply from that new, empty directory. Every deploy workflow instead inits the flat terraform/environments/aws root with -backend-config and key "github-<env>/terraform.tfstate" (Lambda) or "github-fargate-<env>/terraform.tfstate" (Fargate), so the script documented a state object and a root the pipeline never uses. The script now writes terraform/environments/aws/backends/<env>.tfbackend (gitignored by *.tfbackend) with the workflows' key, takes --compute-platform lambda|fargate (default lambda) to pick the namespace, prints init/plan/apply steps for the flat root, and refuses to run outside the repository root before making any AWS call. scripts/test-init-backend.sh runs the script against a stubbed aws CLI in a temp copy of the root and reads the expected keys from deploy-aws-lambda.yml and deploy-aws-fargate.yml; ci.yml runs it in the aws-tfstate-platform-key job. Closes LeanerCloud#306 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Warning Review limit reached
This review includes 3 billable files and costs up to $0.75. Or wait 59 minutes for your next included review. View limit details
Comment |
|
Independent review 2 (claude-fleet, cold): APPROVE 898f279 Findings (none blocking):
Against #306: this fixes the root cause.
Attacked:
Verified locally, on git-initialised minimal copies of the head, base and merged exports:
Reviewed by an independent agent with no author context (second reviewer). Review only: nothing was pushed, and the GitHub review state is unchanged. |
|
Independent review (IAmJSD's agent, fresh context, given only the diff, the issue and the PR text): VERDICT: APPROVE Blocking:
Non-blocking:
Attacked:
Body-stale:
Reviewer: rB1. Bar while the maintainers are away (set by IAmJSD as acting owner): one approving independent review on the head, two for money, auth and security paths. |
Brings the branch up to date with main so the PR is mergeable again. Conflicted files: - .github/workflows/ci.yml: the branch appended a "Run init-backend.sh self-test" step to the aws-tfstate-platform-key job, and main added the tfstate-concurrency-group (LeanerCloud#1149) and rollback-ecr-registry (LeanerCloud#1112) jobs right after that job. The step stays at the end of aws-tfstate-platform-key and both new main jobs follow it unchanged. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Merged current main into the branch. New head: b7ac3aa.
Checks:
|
|
Independent review (IAmJSD's agent, fresh context, given only the diff, the issue and the PR text): VERDICT: APPROVE Blocking:
Non-blocking:
Attacked:
Body-stale:
Reviewer: rB18. Bar while the maintainers are away (set by IAmJSD as acting owner): one approving independent review on the head, two for money, auth and security paths. |
|
Local verification at |
|
Merged by IAmJSD's agent at IAmJSD's request (IAmJSD is acting owner while the maintainers are away), under the bar IAmJSD set: 1 approving independent review(s) on |
Root cause
scripts/init-backend.shwroteterraform/environments/aws/<env>/backend.tfwithkey = "<env>/terraform.tfstate"and told the operator tocdinto that new, empty directory and runterraform init/plan/applythere. Every deploy workflow does something else: it inits the flatterraform/environments/awsroot with-backend-configand keygithub-<env>/terraform.tfstatefor Lambda (deploy-aws-lambda.yml) orgithub-fargate-<env>/terraform.tfstatefor Fargate (deploy-aws-fargate.yml). So the script described a state object and a Terraform root that the pipeline never uses (audit finding A14-035).Fix
scripts/init-backend.sh:terraform/environments/aws/backends/<env>.tfbackend(already gitignored by*.tfbackend, next to the existingdev.tfbackend.example) with bare-backend-configattributes and the workflows' key, instead of aterraform {}block in a per-env directory. It no longer createsterraform/environments/aws/<env>/.--compute-platform lambda|fargateflag, defaultlambda, which picksgithub-<env>/orgithub-fargate-<env>/. Any other value is rejected.terraform init -backend-config=backends/<env>.tfbackend, thenterraform plan -var-file=github-<env>.tfvars -var="compute_platform=<platform>", then apply. This is the same shape as CI.TF_BACKEND_AWSsecret, so local and CI runs share one state object only when that secret (for the env's GitHub Environment) names the same bucket.terraform/environments/aws/backend.tfexists relative to the working directory. The check runs before any AWS call, so starting the script from the wrong directory no longer creates a strayterraform/tree there.The bucket creation and hardening steps are unchanged.
Regression test
scripts/test-init-backend.shruns the real script against a stubbedawsCLI (onPATH; every call is logged) inside a temp copy of the AWS root. It makes no AWS calls and writes nothing into the working tree. The expected keys are read fromdeploy-aws-lambda.ymlanddeploy-aws-fargate.yml, not hard-coded, so the test also fails if the workflows' key changes without the script. It asserts:backends/<env>.tfbackend, and no per-env root is createduse_lockfileare written, and the file is bare attributes rather than aterraform {}blockcompute_platform, and nevercdintoterraform/environments/aws/<env>--compute-platform, or a run outside the repo root, exits non-zero with zero AWS callsci.ymlruns it as a new step in the existingaws-tfstate-platform-keyjob, soci-successneeds no change.The test builds the
compute_platform=<x>strings from a variable on purpose.test-aws-tfstate-platform-key.shsweeps every script underscripts/, and literalcompute_platform=lambdapluscompute_platform=fargatein one file show up there as a "MIXED platform" job. I hit that during development and fixed it; the sweep now passes with the new files included (26/26).Verification
All local, macOS, bash 3.2. This is stub/fixture evidence only: nothing ran against a real AWS account, and no
terraform initwas run against a real S3 backend.bash scripts/test-init-backend.shagainst the original script (git show origin/main:scripts/init-backend.sh): 6 passed, 11 failed. The failures are nobackends/dev.tfbackend, aterraform/environments/aws/devdirectory created, the operator sent into the per-env dir, nocompute_platformin the plan step, Fargate flags rejected, and a run outside the repo root still callingawsand creatingterraform/.bash scripts/test-init-backend.sh: 24 passed, 0 failed.github-prefix: 1 failbackends/: 3 fail plus skipped content checks-varhard-coded to lambda: 1 failscripts/:bash scripts/test-aws-tfstate-platform-key.sh: 26/26bash scripts/test-ecr-delete-selection.sh: 59/59bash scripts/test-rds-deletion-protection-scope.sh: 58/58bash scripts/test-cloud-sql-delete-scope.sh: 62/62shellcheck scripts/init-backend.sh scripts/test-init-backend.shis clean.actionlint .github/workflows/ci.ymlis clean.zizmor==1.29.0 --offline --persona=pedantic --min-severity=medium .github/workflows/ci.ymlreports no findings.ci.yml:AWS_CONFIG_FILE=/dev/null AWS_SHARED_CREDENTIALS_FILE=/dev/null go test ./internal/database/postgres/migrations/ -run TestShellMigrationURLs -count=1passes. The AWS config override is only because this machine's~/.aws/configdefault profile is invalid.--register-awsplusscripts/setup-git-secrets.shpatterns, in a freshgit initrepo with an isolated HOME, finds nothing in the three changed files. A positive control (an assigned 12-digit account ID) is caught.bash scripts/test-git-secrets-allowlist.sh: 42 PASS, 0 FAIL.Out of scope (noted, not changed)
docs/DEPLOYMENT.md"State Management". It still shows abackends/prod.tfbackendexample withbucket = "cudly-terraform-state-prod"andkey = "prod/terraform.tfstate", which is the same stale key in prose. Happy to fix it here or in a follow-up if you want it.cudly-terraform-state-<env>bucket. CI's bucket comes fromTF_BACKEND_AWS, which this repo can't see;ci-cd-permissionsuses a singlecudly-terraform-state-<account>bucket. I didn't add a--bucketoption to target CI's existing bucket on purpose: the script runsput-bucket-taggingandput-bucket-lifecycle-configuration, and both replace existing config, so pointing it at a shared, live bucket would be destructive. The new warning tells the operator when local and CI state will actually coincide.scripts/tf-deploy.shlayout mismatch is tracked in chore(ci): medium/low findings from the 2026-07-28 full review cloud-commitments-cli#1594 (A14-034).--profile,--regionand the other flags still crash underset -uwith a confusing message when given without a value.Maintainer: please mirror the issue's triage labels onto this PR:
priority/p2,severity/medium,urgency/this-quarter,impact/internal,effort/s,type/chore,triaged.Closes #306
🤖 Generated with Claude Code