From 975883c80cca2cd1dc692817f87c12ef36be9407 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=98=A4=EC=A4=80=EC=84=9D=28Junseok=20Oh=29DevOps?= <52226147+Atom-oh@users.noreply.github.com> Date: Fri, 4 Sep 2026 04:05:19 +0000 Subject: [PATCH] CI: user branches manage their own stacks; DNS delegation prerequisite documented MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - terraform.yml: plan on user-branch pushes and apply/agentcore dispatches from user branches, against that user's TF_*_PREVIEW_ pair (fail-closed case selection; development environment + dev deployer role) - branch-strategy runbook: the awsops-dev.whchoi.net zone lives in the samples account but its NS delegation from the live whchoi.net zone (another account) is PENDING — exact record listed; every stack's ACM validation waits on it --- .github/workflows/deploy-agentcore.yml | 7 +++++-- .github/workflows/terraform.yml | 12 +++++++++--- docs/runbooks/branch-strategy.md | 22 ++++++++++++++++++---- 3 files changed, 32 insertions(+), 9 deletions(-) diff --git a/.github/workflows/deploy-agentcore.yml b/.github/workflows/deploy-agentcore.yml index 4b4567a2e..fb91c0611 100644 --- a/.github/workflows/deploy-agentcore.yml +++ b/.github/workflows/deploy-agentcore.yml @@ -31,6 +31,8 @@ jobs: MAIN_TFVARS_B64: ${{ secrets.TF_TFVARS }} DEV_BACKEND_B64: ${{ secrets.TF_BACKEND_HCL_DEV }} DEV_TFVARS_B64: ${{ secrets.TF_TFVARS_DEV }} + USER_BACKEND_B64: ${{ secrets[format('TF_BACKEND_HCL_PREVIEW_{0}', github.ref_name)] }} + USER_TFVARS_B64: ${{ secrets[format('TF_TFVARS_PREVIEW_{0}', github.ref_name)] }} steps: - uses: actions/checkout@v4 @@ -39,8 +41,8 @@ jobs: run: | case "$TARGET" in main) ROLE="$MAIN_ROLE";; - dev) ROLE="$DEV_ROLE";; - *) echo "::error::agentcore dispatches only from main or dev (got '$TARGET')"; exit 1;; + dev|atomoh|ssminji|whchoi) ROLE="$DEV_ROLE";; + *) echo "::error::unexpected dispatch target '$TARGET'"; exit 1;; esac [ -n "$ROLE" ] || { echo "::error::deployer role variable for '$TARGET' is not set"; exit 1; } echo "role=$ROLE" >> "$GITHUB_OUTPUT" @@ -59,6 +61,7 @@ jobs: case "$TARGET" in main) B="$MAIN_BACKEND_B64"; V="$MAIN_TFVARS_B64";; dev) B="$DEV_BACKEND_B64"; V="$DEV_TFVARS_B64";; + atomoh|ssminji|whchoi) B="$USER_BACKEND_B64"; V="$USER_TFVARS_B64";; *) echo "::error::unexpected target '$TARGET'"; exit 1;; esac if [ -z "$B" ] || [ -z "$V" ]; then diff --git a/.github/workflows/terraform.yml b/.github/workflows/terraform.yml index db37bae88..8a8c59650 100644 --- a/.github/workflows/terraform.yml +++ b/.github/workflows/terraform.yml @@ -25,7 +25,7 @@ on: branches: [main, dev] paths: ["terraform/foundation/**"] push: - branches: [main, dev] + branches: [main, dev, atomoh, ssminji, whchoi] paths: ["terraform/foundation/**"] workflow_dispatch: inputs: @@ -56,6 +56,8 @@ jobs: MAIN_TFVARS_B64: ${{ secrets.TF_TFVARS }} DEV_BACKEND_B64: ${{ secrets.TF_BACKEND_HCL_DEV }} DEV_TFVARS_B64: ${{ secrets.TF_TFVARS_DEV }} + USER_BACKEND_B64: ${{ secrets[format('TF_BACKEND_HCL_PREVIEW_{0}', github.base_ref || github.ref_name)] }} + USER_TFVARS_B64: ${{ secrets[format('TF_TFVARS_PREVIEW_{0}', github.base_ref || github.ref_name)] }} steps: - uses: actions/checkout@v4 @@ -73,6 +75,7 @@ jobs: case "$TARGET" in main) B="$MAIN_BACKEND_B64"; V="$MAIN_TFVARS_B64";; dev) B="$DEV_BACKEND_B64"; V="$DEV_TFVARS_B64";; + atomoh|ssminji|whchoi) B="$USER_BACKEND_B64"; V="$USER_TFVARS_B64";; *) echo "::error::unexpected target '$TARGET'"; exit 1;; esac if [ -z "$B" ] || [ -z "$V" ]; then @@ -112,6 +115,8 @@ jobs: MAIN_TFVARS_B64: ${{ secrets.TF_TFVARS }} DEV_BACKEND_B64: ${{ secrets.TF_BACKEND_HCL_DEV }} DEV_TFVARS_B64: ${{ secrets.TF_TFVARS_DEV }} + USER_BACKEND_B64: ${{ secrets[format('TF_BACKEND_HCL_PREVIEW_{0}', github.ref_name)] }} + USER_TFVARS_B64: ${{ secrets[format('TF_TFVARS_PREVIEW_{0}', github.ref_name)] }} steps: - uses: actions/checkout@v4 @@ -120,8 +125,8 @@ jobs: run: | case "$TARGET" in main) ROLE="$MAIN_ROLE";; - dev) ROLE="$DEV_ROLE";; - *) echo "::error::apply dispatches only from main or dev (got '$TARGET')"; exit 1;; + dev|atomoh|ssminji|whchoi) ROLE="$DEV_ROLE";; + *) echo "::error::unexpected dispatch target '$TARGET'"; exit 1;; esac [ -n "$ROLE" ] || { echo "::error::deployer role variable for '$TARGET' is not set"; exit 1; } echo "role=$ROLE" >> "$GITHUB_OUTPUT" @@ -137,6 +142,7 @@ jobs: case "$TARGET" in main) B="$MAIN_BACKEND_B64"; V="$MAIN_TFVARS_B64";; dev) B="$DEV_BACKEND_B64"; V="$DEV_TFVARS_B64";; + atomoh|ssminji|whchoi) B="$USER_BACKEND_B64"; V="$USER_TFVARS_B64";; *) echo "::error::unexpected target '$TARGET'"; exit 1;; esac if [ -z "$B" ] || [ -z "$V" ]; then diff --git a/docs/runbooks/branch-strategy.md b/docs/runbooks/branch-strategy.md index 1988ce5c2..53cdf7ce2 100644 --- a/docs/runbooks/branch-strategy.md +++ b/docs/runbooks/branch-strategy.md @@ -93,8 +93,20 @@ plan/apply.) ## Per-user preview stacks / 사용자별 프리뷰 스택 -The public hosted zone **`awsops-dev.whchoi.net` already exists** (operator-managed; -not in the workload account's Route53 — stacks reference it via tfvars). Previews are +The public hosted zone **`awsops-dev.whchoi.net` exists in the samples account** +(`Z05356393HGNKULJIZ69V`) — but ⚠️ **its NS delegation from the live `whchoi.net` +zone (owned by another account) is PENDING**. Until the domain owner adds this +record to the live parent zone, ACM validation for every stack under this zone +stalls and applies time out: + +``` +awsops-dev.whchoi.net NS ns-565.awsdns-06.net + ns-1465.awsdns-55.org + ns-12.awsdns-01.com + ns-1997.awsdns-57.co.uk +``` +(라이브 whchoi.net 존 소유자가 위 NS 위임 레코드를 추가해야 이 존 아래 모든 +스택의 ACM 검증이 통과합니다 — 1회성 공용 작업.) Previews are `.awsops-dev.whchoi.net`, so one **wildcard ACM cert `*.awsops-dev.whchoi.net`** (us-east-1) covers every preview AND the dev stack — issue once, reuse across stacks. (`awsops-dev.whchoi.net` 퍼블릭 호스티드 존은 이미 존재하며, 프리뷰가 그 아래 서브도메인 @@ -113,8 +125,10 @@ Provision once per user: --body "$(base64 -w0 terraform/foundation/terraform.tfvars)" ``` 4. Push to your branch — `deploy-web.yml` builds and rolls your stack - automatically. Missing secrets fail with a pointer here — no fallback to the - dev/production stacks, by design. + automatically, and `terraform.yml` plans your stack on terraform-path pushes + (apply = dispatch from your branch; `deploy-agentcore` likewise). Missing + secrets fail with a pointer here — no fallback to the dev/production stacks, + by design. User-branch deploys run under the dev-tier roles (`environment: development` gates which branches may deploy — its branch policy lists dev + the three user