Skip to content

feat(terraform): make the ECS starter apply-ready under model B - #6

Merged
iflov merged 1 commit into
mainfrom
iflov/terraform-model-b-inputs
Sep 1, 2026
Merged

iflov merged 1 commit into
mainfrom
iflov/terraform-model-b-inputs

Conversation

@iflov

@iflov iflov commented Sep 1, 2026

Copy link
Copy Markdown
Owner

무엇을

결정 문서의 미결 질문 1번에 모델 B(파생 프로젝트가 버전 모듈을 참조한다) 로 답했다. 저장소 분리는 아직 실행하지 않는다 — 모듈 인터페이스는 한 번 apply해서 무엇이 입력이고 무엇이 프로젝트별인지 드러난 뒤에 정한다.

대신 B는 그 사이 작업의 내용을 바꾼다. 참조 모듈은 소비자가 편집할 수 없으므로, 사본에서 고쳤을 값이 전부 input이 되어야 한다.

변경

파일 내용
infra/terraform/backend.tf (신규) backend "s3" {}. 없으면 -backend-config=backend.hcl이 Warning: Missing backend configuration을 내고 local backend로 초기화된다. 별도 파일인 이유는 하위 모듈이 backend를 가질 수 없어서 — 모듈화 시 소비 root로 통째 이동한다
infra/terraform/.gitignore (신규) root의 infra/terraform/backend.hcl 규칙은 경로가 root 기준이라 디렉터리가 나가면 따라가지 못한다. .terraform.lock.hcl은 tracked 유지
variables.tf :: cors_origins 기본값 없는 필수 input
variables.tf :: trust_proxy_hops 기본 1(ALB 하나), 0–10 정수 — 앱 Joi와 동일 범위
variables.tf :: enable_sqs 기본 false. 큐/DLQ/IAM/MESSAGE_QUEUE_URL 전부 조건부
.github/workflows/terraform.yml (신규) fmt -check / init -backend=false / validate, infra/terraform/**에만 반응
.github/workflows/ci.yml paths-ignore로 terraform-only 변경이 앱 파이프라인을 안 태운다

리뷰할 때 봐야 할 것

CORS_ORIGINS는 단순 하드코딩이 아니라 조용한 결함이었다. "https://replace-me.example"은 앱의 production 검증을 통과한다 — 스킴이 있고 와일드카드가 아니다(src/config/env.validation.ts:136). 그래서 task는 정상 부팅하고 브라우저 요청만 막힌다. 배포해도 에러가 안 난다. 이제 앱의 규칙을 plan 시점 validation으로 당겼다.

SQS는 지우지 않고 input으로 남겼다. 앱 참조가 0건이고 CLAUDE.md가 BullMQ를 기본 messaging composition root로 못박고 있으므로 삭제가 가장 정직한 상태다. 그럼에도 남긴 이유는 모델 B에서 소비자가 모듈을 고칠 수 없기 때문 — 삭제 쪽이 되돌리기 어렵다. 대신 아무도 안 쓰는 코드 경로가 남는다. 이 트레이드오프에 이견이 있으면 여기서 말해달라.

CI 순서. paths-ignore를 먼저 넣으면 terraform이 무보호가 되므로 terraform.yml을 먼저 만든 뒤 끊었다. ⚠ main에 branch protection을 걸 때 ci.yml의 job을 required check로 지정하면 skip된 실행이 Pending으로 남아 terraform-only PR이 영구히 막힌다 — ci.yml에 주석으로 남겨뒀다.

검증

  • terraform fmt -check -recursive / init -backend=false / validate 통과
  • 변수 validation 실제 발화 확인: ["*"] → must not contain "*", ["app.example.com"] → must include a scheme, [] → must list at least one origin, trust_proxy_hops=11 → must be an integer between 0 and 10. 정상 케이스는 오류 없음
  • check:scaffold(typeorm + postgres 일관), check:observability, typecheck, lint 통과
  • pnpm test → Test Files 35 passed (35) / Tests 317 passed (317)

미검증 / 남은 것

  • 이 구성은 한 번도 apply된 적이 없다. 실제로 뜨는지, ECS task가 부팅하는지 전부 미검증
  • plan/apply는 CI에 없다 — backend 블록이 생긴 뒤로 backend 초기화가 필요하고, OIDC role과 승인 경로가 미정
  • 문서의 결함 4개 중 이미지 전달 경로(ECR build/push, 태그 전달, apply 승인 주체)만 남았다. AWS 계정 쪽 결정이 선행

🤖 Generated with Claude Code

https://claude.ai/code/session_01DrsDBRXt7sYCYxt5gmFMVy

Derived projects will reference a versioned module rather than copy the
starter (docs/terraform-repo-boundary.md). A referenced module cannot be
edited by its consumer, so every value a copy would have edited has to
become an input.

- backend.tf: add the empty `backend "s3" {}` block. Without it,
  `-backend-config=backend.hcl` warned and initialized a local backend.
  It lives in its own file because a child module cannot declare a
  backend, so it moves to the consumer root on extraction.
- cors_origins: required input replacing the hardcoded
  "https://replace-me.example", which *passed* the app's production
  validation (has a scheme, not a wildcard) so the task booted fine and
  only browsers were blocked. Validation mirrors the app's rules at plan
  time instead of at task startup.
- trust_proxy_hops: inject TRUST_PROXY_HOPS, default 1 for the single
  ALB this config builds. It was never injected, so the app defaulted to
  0 and ThrottlerGuard bucketed every user under the ALB IP.
- enable_sqs: gate the queues, DLQ, IAM policy and MESSAGE_QUEUE_URL,
  default false. The app's messaging root is BullMQ/Redis and nothing
  reads MESSAGE_QUEUE_URL. Kept as an input rather than deleted because
  a consumer of a referenced module has no other way to turn it on.
- infra/terraform/.gitignore: the root ignore rules are root-relative
  and would not follow the directory out of this repo.
- terraform.yml: fmt/init -backend=false/validate, scoped to
  infra/terraform/**. ci.yml gets paths-ignore so terraform-only changes
  stop running the app pipeline. CI first, then the split, so terraform
  is never left unchecked.

plan/apply stay out of CI: the backend block now requires backend
initialization, and no OIDC role or approval path exists yet. This
config has still never been applied.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DrsDBRXt7sYCYxt5gmFMVy
@iflov
iflov merged commit a314217 into main Sep 1, 2026
2 checks passed
@iflov
iflov deleted the iflov/terraform-model-b-inputs branch September 1, 2026 00:11
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant