shoc-frontend-new/terraform
Cursor Agent cc7ecb9b5a
fix(ci): classify G13 per queued PR on merge_group
Run live isolation on the merge-queue event so ci-complete actually
gates mixed change sets, without treating the group union as one PR.
2026-09-19 20:20:30 +00:00
..
live chore(terraform): complete staging SPA adoption 2026-09-18 16:14:10 -04:00
README.md fix(ci): classify G13 per queued PR on merge_group 2026-09-19 20:20:30 +00:00

Frontend Terraform (SPA CD)

terraform/live/dev and terraform/live/staging in AWS account 396287094661. HCP Terraform owns the bucket, CloudFront, DNS, and the GitHub deploy role. GitHub Actions owns content: .github/workflows/deploy-web.yaml syncs dist/ to the bucket root and invalidates /*.

Creating, formatting, initializing with -backend=false, and validating these files does not authorize an AWS, HCP Terraform, GitHub, or deployment mutation.

Do not collapse these roots into one terraform/ tree. Flattening retargets two live HCP working directories and is its own change.

Fixed targets

dev staging
Site dev.seahaven.com staging.seahaven.com
Bucket seahaven-shoc-frontend-dev seahaven-shoc-frontend-staging
Distribution E2CWLM1AFB964P E2JDVEZ6EGD49J
Deploy role githubdeploy-shoc-frontend-new-dev githubdeploy-shoc-frontend-new-staging
HCP workspace shoc-frontend-new-dev shoc-frontend-new-staging
Working dir terraform/live/dev terraform/live/staging

There is no prod CloudFront in this round. Do not create shoc-frontend-new-prod.

Ownership

module.environment_owned keeps the same addresses as the adopted HCP shoc-frontend-new-dev state. The SPA origin path is empty. The release pointer is forgotten (removed { destroy = false }), not destroyed.

Deploy parameters live under /shoc-frontend-new/<env>/deploy/{bucket,distribution-id}. githubdeploy may List/Get/Put/Delete the bucket root, CreateInvalidation, and GetParameter on those two names. OIDC trust is environment:<env> plus job_workflow_ref for .github/workflows/deploy-web.yaml at refs/heads/main and refs/tags/v*.

adoption_complete is pinned in each live root. It is not a workspace variable.

Local checks (no apply)

terraform fmt -check -recursive terraform
terraform -chdir=terraform/live/dev init -backend=false -lockfile=readonly
terraform -chdir=terraform/live/dev validate
terraform -chdir=terraform/live/staging init -backend=false -lockfile=readonly
terraform -chdir=terraform/live/staging validate
python3 scripts/test-terraform-import-plan-check.py
python3 scripts/test_check_app_terraform_isolation.py
bash scripts/test-verify-cloudfront-release.sh

PRs cannot mix terraform/ with deployable application files. Workflow, docs, and gate-script changes may travel with either side. G13 is python3 scripts/check_app_terraform_isolation.py against the merge base of the PR, and against each queued PR (first-parent commit) on merge_group.

npm run test:terraform and npm run verify wrap the same gates. They never create an HCP run or touch AWS.

Workspaces

Dev (shoc-frontend-new-dev) watches main with working directory terraform/live/dev and auto-apply on. Staging (shoc-frontend-new-staging) watches tag regex ^v[0-9]+\.[0-9]+\.[0-9]+-staging$ with working directory terraform/live/staging and auto-apply on. Merges to main do not apply staging.

GitHub Environments dev and staging set DEPLOY_ROLE_ARN and allow main plus tag v*. Promote staging with gh release create vX.Y.Z-staging --target main.