diff --git a/.github/prompts/renovate-major-review.md b/.github/prompts/renovate-major-review.md index db638fc3..bac6aed0 100644 --- a/.github/prompts/renovate-major-review.md +++ b/.github/prompts/renovate-major-review.md @@ -7,7 +7,7 @@ You only read. Never modify files, push, approve, label, or comment yourself. ## How this repository deploys - Helm charts are never installed with `helm install` / `helm upgrade`. - `scripts/kubernetes-hydrate/hydrate-component.sh` renders `kubernetes/components///` with `helmfile template --include-crds` (plus `kustomize build kustomization/`) into `kubernetes/manifests///manifest.yaml`, and Flux applies them after merge (production only: the `flux-system` Kustomization syncs `kubernetes/clusters/production`, which includes `kubernetes/manifests/production`, with `prune: true`). + `.github/scripts/kubernetes-hydrate/hydrate-component.sh` renders `kubernetes/components///` with `helmfile template --include-crds` (plus `kustomize build kustomization/`) into `kubernetes/manifests///manifest.yaml`, and Flux applies them after merge (production only: the `flux-system` Kustomization syncs `kubernetes/clusters/production`, which includes `kubernetes/manifests/production`, with `prune: true`). - Consequences for upgrade guides written for `helm upgrade`: - CRDs rendered from the chart with this repository's values are applied by Flux with everything else, so "apply the CRDs manually before `helm upgrade`" steps are already satisfied for them; do not report them as manual work. CRDs the guide expects from another source (e.g. Gateway API CRDs managed by `kubernetes/components/gateway-api`) are not covered; report the needed change to that component as ⚠️. @@ -27,7 +27,7 @@ You only read. Never modify files, push, approve, label, or comment yourself. - the files Renovate changed 3. Ignore changes under `kubernetes/manifests/`; the hydrator generates them in parallel with this review, so they may be stale. 4. Read `.render-diff/summary.md` (the rendered diff). - For every component directory the pull request changes, it compares the base and the head rendered with this repository's values (`scripts/kubernetes-hydrate/render-diff.sh`): image references, CRD versions, and added / removed resources. + For every component directory the pull request changes, it compares the base and the head rendered with this repository's values (`.github/scripts/kubernetes-hydrate/render-diff.sh`): image references, CRD versions, and added / removed resources. Its `Full diff` paths are relative to `.render-diff/`; the files can be large, so Grep them instead of reading them whole. A component marked `Rendering failed` or `Summarizing failed` is uncovered (for `Summarizing failed`, still Grep its full diff). A component marked `Not rendered` is not deployed by the hydrator; review it from its files only. diff --git a/scripts/kubernetes-hydrate/hydrate-component.sh b/.github/scripts/kubernetes-hydrate/hydrate-component.sh similarity index 100% rename from scripts/kubernetes-hydrate/hydrate-component.sh rename to .github/scripts/kubernetes-hydrate/hydrate-component.sh diff --git a/scripts/kubernetes-hydrate/hydrate-index.sh b/.github/scripts/kubernetes-hydrate/hydrate-index.sh similarity index 100% rename from scripts/kubernetes-hydrate/hydrate-index.sh rename to .github/scripts/kubernetes-hydrate/hydrate-index.sh diff --git a/scripts/kubernetes-hydrate/render-diff.sh b/.github/scripts/kubernetes-hydrate/render-diff.sh similarity index 98% rename from scripts/kubernetes-hydrate/render-diff.sh rename to .github/scripts/kubernetes-hydrate/render-diff.sh index 133b99a4..1446774f 100755 --- a/scripts/kubernetes-hydrate/render-diff.sh +++ b/.github/scripts/kubernetes-hydrate/render-diff.sh @@ -5,7 +5,7 @@ base_ref="${1:?base revision required}" out_dir="${2:?output directory required}" cd "$(git rev-parse --show-toplevel)" -script_dir="$(pwd)/scripts/kubernetes-hydrate" +script_dir="$(pwd)/.github/scripts/kubernetes-hydrate" mkdir -p "${out_dir}" out_dir="$(cd "${out_dir}" && pwd)" summary="${out_dir}/summary.md" diff --git a/scripts/kubernetes-hydrate/summarize-manifest-diff.sh b/.github/scripts/kubernetes-hydrate/summarize-manifest-diff.sh similarity index 100% rename from scripts/kubernetes-hydrate/summarize-manifest-diff.sh rename to .github/scripts/kubernetes-hydrate/summarize-manifest-diff.sh diff --git a/scripts/kubernetes-hydrate/tests/fixtures/identical/expected.md b/.github/scripts/kubernetes-hydrate/tests/fixtures/identical/expected.md similarity index 100% rename from scripts/kubernetes-hydrate/tests/fixtures/identical/expected.md rename to .github/scripts/kubernetes-hydrate/tests/fixtures/identical/expected.md diff --git a/scripts/kubernetes-hydrate/tests/fixtures/identical/manifest.yaml b/.github/scripts/kubernetes-hydrate/tests/fixtures/identical/manifest.yaml similarity index 100% rename from scripts/kubernetes-hydrate/tests/fixtures/identical/manifest.yaml rename to .github/scripts/kubernetes-hydrate/tests/fixtures/identical/manifest.yaml diff --git a/scripts/kubernetes-hydrate/tests/fixtures/invalid/manifest.yaml b/.github/scripts/kubernetes-hydrate/tests/fixtures/invalid/manifest.yaml similarity index 100% rename from scripts/kubernetes-hydrate/tests/fixtures/invalid/manifest.yaml rename to .github/scripts/kubernetes-hydrate/tests/fixtures/invalid/manifest.yaml diff --git a/scripts/kubernetes-hydrate/tests/fixtures/summarize/base.yaml b/.github/scripts/kubernetes-hydrate/tests/fixtures/summarize/base.yaml similarity index 100% rename from scripts/kubernetes-hydrate/tests/fixtures/summarize/base.yaml rename to .github/scripts/kubernetes-hydrate/tests/fixtures/summarize/base.yaml diff --git a/scripts/kubernetes-hydrate/tests/fixtures/summarize/expected.md b/.github/scripts/kubernetes-hydrate/tests/fixtures/summarize/expected.md similarity index 100% rename from scripts/kubernetes-hydrate/tests/fixtures/summarize/expected.md rename to .github/scripts/kubernetes-hydrate/tests/fixtures/summarize/expected.md diff --git a/scripts/kubernetes-hydrate/tests/fixtures/summarize/head.yaml b/.github/scripts/kubernetes-hydrate/tests/fixtures/summarize/head.yaml similarity index 100% rename from scripts/kubernetes-hydrate/tests/fixtures/summarize/head.yaml rename to .github/scripts/kubernetes-hydrate/tests/fixtures/summarize/head.yaml diff --git a/scripts/kubernetes-hydrate/tests/render-diff.test.sh b/.github/scripts/kubernetes-hydrate/tests/render-diff.test.sh similarity index 85% rename from scripts/kubernetes-hydrate/tests/render-diff.test.sh rename to .github/scripts/kubernetes-hydrate/tests/render-diff.test.sh index f56e3270..04a9650e 100755 --- a/scripts/kubernetes-hydrate/tests/render-diff.test.sh +++ b/.github/scripts/kubernetes-hydrate/tests/render-diff.test.sh @@ -31,8 +31,8 @@ YAML } repo="${work}/repo" -mkdir -p "${repo}/scripts/kubernetes-hydrate" "${repo}/aws/eks/production" -cp "${scripts}"/hydrate-component.sh "${scripts}"/render-diff.sh "${scripts}"/summarize-manifest-diff.sh "${repo}/scripts/kubernetes-hydrate/" +mkdir -p "${repo}/.github/scripts/kubernetes-hydrate" "${repo}/aws/eks/production" +cp "${scripts}"/hydrate-component.sh "${scripts}"/render-diff.sh "${scripts}"/summarize-manifest-diff.sh "${repo}/.github/scripts/kubernetes-hydrate/" printf 'locals {\n cluster_version = "1.33"\n}\n' > "${repo}/aws/eks/production/env.hcl" write_deployment "${repo}/kubernetes/components/demo/production" demo nginx:1.0 write_deployment "${repo}/kubernetes/components/gone/production" gone busybox:1.36 @@ -52,7 +52,7 @@ git -C "${repo}" -c user.name=test -c user.email=test@example.com add -A git -C "${repo}" -c user.name=test -c user.email=test@example.com commit -q -m head out="${work}/out" -(cd "${repo}" && bash scripts/kubernetes-hydrate/render-diff.sh HEAD^ "${out}") > "${work}/stdout" 2>&1 || { fail "render-diff exits 0"; sed 's/^/# /' "${work}/stdout"; } +(cd "${repo}" && bash .github/scripts/kubernetes-hydrate/render-diff.sh HEAD^ "${out}") > "${work}/stdout" 2>&1 || { fail "render-diff exits 0"; sed 's/^/# /' "${work}/stdout"; } summary="${out}/summary.md" expect_contains "lists a changed component" "## demo (production)" "${summary}" @@ -76,13 +76,13 @@ failing_bin="${work}/failing-bin" mkdir -p "${failing_bin}" printf '#!/bin/sh\nexit 1\n' > "${failing_bin}/yq" chmod +x "${failing_bin}/yq" -(cd "${repo}" && PATH="${failing_bin}:${PATH}" bash scripts/kubernetes-hydrate/render-diff.sh HEAD^ "${work}/out-failing") > /dev/null 2>&1 || fail "render-diff exits 0 when summarizing fails" +(cd "${repo}" && PATH="${failing_bin}:${PATH}" bash .github/scripts/kubernetes-hydrate/render-diff.sh HEAD^ "${work}/out-failing") > /dev/null 2>&1 || fail "render-diff exits 0 when summarizing fails" expect_contains "reports a summarizing failure instead of aborting" "Summarizing failed" "${work}/out-failing/summary.md" echo "# changed" >> "${repo}/README.md" git -C "${repo}" -c user.name=test -c user.email=test@example.com add -A git -C "${repo}" -c user.name=test -c user.email=test@example.com commit -q -m docs -(cd "${repo}" && bash scripts/kubernetes-hydrate/render-diff.sh HEAD^ "${work}/out-none") > /dev/null 2>&1 || fail "render-diff exits 0 without components" +(cd "${repo}" && bash .github/scripts/kubernetes-hydrate/render-diff.sh HEAD^ "${work}/out-none") > /dev/null 2>&1 || fail "render-diff exits 0 without components" expect_contains "reports when no component changed" "No Kubernetes components changed." "${work}/out-none/summary.md" exit "${failures}" diff --git a/scripts/kubernetes-hydrate/tests/summarize-manifest-diff.test.sh b/.github/scripts/kubernetes-hydrate/tests/summarize-manifest-diff.test.sh similarity index 100% rename from scripts/kubernetes-hydrate/tests/summarize-manifest-diff.test.sh rename to .github/scripts/kubernetes-hydrate/tests/summarize-manifest-diff.test.sh diff --git a/scripts/terragrunt-release/check-release-configs.sh b/.github/scripts/terragrunt-release/check-release-configs.sh similarity index 100% rename from scripts/terragrunt-release/check-release-configs.sh rename to .github/scripts/terragrunt-release/check-release-configs.sh diff --git a/scripts/terragrunt-release/release-service.sh b/.github/scripts/terragrunt-release/release-service.sh similarity index 100% rename from scripts/terragrunt-release/release-service.sh rename to .github/scripts/terragrunt-release/release-service.sh diff --git a/scripts/terragrunt-release/release-targets.sh b/.github/scripts/terragrunt-release/release-targets.sh similarity index 100% rename from scripts/terragrunt-release/release-targets.sh rename to .github/scripts/terragrunt-release/release-targets.sh diff --git a/scripts/terragrunt-release/test.sh b/.github/scripts/terragrunt-release/test.sh similarity index 100% rename from scripts/terragrunt-release/test.sh rename to .github/scripts/terragrunt-release/test.sh diff --git a/scripts/terragrunt-release/validate-apply-trigger.sh b/.github/scripts/terragrunt-release/validate-apply-trigger.sh similarity index 100% rename from scripts/terragrunt-release/validate-apply-trigger.sh rename to .github/scripts/terragrunt-release/validate-apply-trigger.sh diff --git a/.github/workflows/auto-label--deploy-trigger.yaml b/.github/workflows/auto-label--deploy-trigger.yaml index 781dff92..a0c2753b 100644 --- a/.github/workflows/auto-label--deploy-trigger.yaml +++ b/.github/workflows/auto-label--deploy-trigger.yaml @@ -30,7 +30,7 @@ jobs: uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 - name: Validate apply_trigger - run: bash scripts/terragrunt-release/validate-apply-trigger.sh + run: bash .github/scripts/terragrunt-release/validate-apply-trigger.sh - name: Generate GitHub App token id: app-token diff --git a/.github/workflows/auto-release--plan.yaml b/.github/workflows/auto-release--plan.yaml index 40051095..6da45010 100644 --- a/.github/workflows/auto-release--plan.yaml +++ b/.github/workflows/auto-release--plan.yaml @@ -32,8 +32,8 @@ jobs: HEAD_REF: ${{ github.head_ref }} run: | set -euo pipefail - service=$(bash scripts/terragrunt-release/release-service.sh --branch "$HEAD_REF") - targets=$(bash scripts/terragrunt-release/release-targets.sh "$service") + service=$(bash .github/scripts/terragrunt-release/release-service.sh --branch "$HEAD_REF") + targets=$(bash .github/scripts/terragrunt-release/release-targets.sh "$service") echo "targets=$targets" >> "$GITHUB_OUTPUT" plan: diff --git a/.github/workflows/auto-release--trigger.yaml b/.github/workflows/auto-release--trigger.yaml index 62222d7d..a649273a 100644 --- a/.github/workflows/auto-release--trigger.yaml +++ b/.github/workflows/auto-release--trigger.yaml @@ -40,8 +40,8 @@ jobs: id: resolve run: | set -euo pipefail - service=$(bash scripts/terragrunt-release/release-service.sh --tag "$TAG") - targets=$(bash scripts/terragrunt-release/release-targets.sh "$service") + service=$(bash .github/scripts/terragrunt-release/release-service.sh --tag "$TAG") + targets=$(bash .github/scripts/terragrunt-release/release-targets.sh "$service") echo "targets=$targets" >> "$GITHUB_OUTPUT" echo "tag=$TAG" >> "$GITHUB_OUTPUT" diff --git a/.github/workflows/renovate-major-review.yaml b/.github/workflows/renovate-major-review.yaml index 98c66f36..c58f1d33 100644 --- a/.github/workflows/renovate-major-review.yaml +++ b/.github/workflows/renovate-major-review.yaml @@ -34,7 +34,7 @@ jobs: - name: Render manifest diff # HEAD is the PR merge commit, so its first parent is the base it merges into. - run: bash scripts/kubernetes-hydrate/render-diff.sh HEAD^1 "${RUNNER_TEMP}/render-diff" + run: bash .github/scripts/kubernetes-hydrate/render-diff.sh HEAD^1 "${RUNNER_TEMP}/render-diff" - name: Upload manifest diff uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2 diff --git a/.github/workflows/reusable--kubernetes-hydrator.yaml b/.github/workflows/reusable--kubernetes-hydrator.yaml index 39c5e09b..8e3f83ac 100644 --- a/.github/workflows/reusable--kubernetes-hydrator.yaml +++ b/.github/workflows/reusable--kubernetes-hydrator.yaml @@ -67,11 +67,11 @@ jobs: run: | set -euo pipefail for svc in $(echo "$SERVICES_JSON" | jq -r '.[]'); do - bash scripts/kubernetes-hydrate/hydrate-component.sh "$svc" "${{ inputs.environment }}" + bash .github/scripts/kubernetes-hydrate/hydrate-component.sh "$svc" "${{ inputs.environment }}" done - name: Hydrate index - run: bash scripts/kubernetes-hydrate/hydrate-index.sh "${{ inputs.environment }}" + run: bash .github/scripts/kubernetes-hydrate/hydrate-index.sh "${{ inputs.environment }}" - name: Commit and push hydrated manifests id: auto-commit diff --git a/.github/workflows/test-terragrunt-release.yaml b/.github/workflows/test-terragrunt-release.yaml index 6b15a6fc..50beaac2 100644 --- a/.github/workflows/test-terragrunt-release.yaml +++ b/.github/workflows/test-terragrunt-release.yaml @@ -14,6 +14,6 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 - - run: bash scripts/terragrunt-release/test.sh - - run: bash scripts/terragrunt-release/validate-apply-trigger.sh - - run: bash scripts/terragrunt-release/check-release-configs.sh + - run: bash .github/scripts/terragrunt-release/test.sh + - run: bash .github/scripts/terragrunt-release/validate-apply-trigger.sh + - run: bash .github/scripts/terragrunt-release/check-release-configs.sh diff --git a/README-ja.md b/README-ja.md index ecc2478b..1adea03e 100644 --- a/README-ja.md +++ b/README-ja.md @@ -6,17 +6,19 @@ ラベル駆動の単一 CI パイプラインから 3 つのデプロイ面を管理する monorepo: -- **AWS infrastructure** — Terragrunt + OpenTofu (`aws/`) -- **GitHub configuration** — Repo / branch / ruleset 設定を Terragrunt で管理 (`github/`) -- **Kubernetes platform** — Helmfile でレンダリングしたマニフェストを Flux CD で適用 (`kubernetes/`) +- **AWS infrastructure** — Terragrunt + OpenTofu ([aws/](aws/)) +- **GitHub configuration** — Repo / branch / ruleset 設定を Terragrunt で管理 ([github/](github/)) +- **Kubernetes platform** — Helmfile でレンダリングしたマニフェストを Flux CD で適用 ([kubernetes/](kubernetes/)) -`panicboat/deploy-actions` が PR に付与したラベルを `workflow-config.yaml` に基づき具体的なデプロイ対象に展開し、対応する reusable workflow が実行される。 +`panicboat/deploy-actions` が PR に付与したラベルを [workflow-config.yaml](workflow-config.yaml) に基づき具体的なデプロイ対象に展開し、対応する reusable workflow が実行される。 ## 📂 Structure ``` . -├── .github/workflows/ # reusable executor, deploy trigger, hydrator/builder など +├── .github/ +│ ├── scripts/ # workflow が実行するスクリプト(hydration, terragrunt release) +│ └── workflows/ # reusable executor, deploy trigger, hydrator/builder など ├── aws/ # service ごとの Terragrunt stack ({environment}) ├── github/ # GitHub repo / branch 設定の Terragrunt stack ├── kubernetes/ @@ -24,7 +26,7 @@ │ ├── components/ # environment ごとの Helmfile source │ └── manifests/ # Flux が適用するレンダリング済みマニフェスト ├── docs/ # runbook と設計ノート -├── scripts/ # EKS lifecycle / hydration 用 helper +├── scripts/ # EKS lifecycle 用 helper ├── Makefile # EKS teardown entry point └── workflow-config.yaml # environment と stack convention の source of truth ``` @@ -33,35 +35,45 @@ ### Trigger -- `auto-label--deploy-trigger.yaml` が PR ラベル / `main` への push で起動する。 -- `panicboat/deploy-actions/label-resolver` が `workflow-config.yaml` を参照して各ラベルを 1 つ以上の `{service}/{environment}` ターゲットに展開する。 -- `apply_trigger: merge` の Terragrunt environment は `main` への push で apply される。 -- `apply_trigger: release` の Terragrunt environment は `aws/{service}` の release 公開時に `auto-release--trigger.yaml` が apply する。 - - release PR では `auto-release--plan.yaml` が `terragrunt plan` を実行する。plan を出し直すときは該当する `auto-release--plan` の run で「Re-run all jobs」を使う。 - - release の apply を再実行するときは、`auto-release--trigger` を release tag の ref で `workflow_dispatch` 起動し、同じ tag を渡す:`gh workflow run auto-release--trigger.yaml --ref {service}-vX.Y.Z -f tag={service}-vX.Y.Z`。 -- `workflow-config.yaml` の `terragrunt` stack の `exclude` の rule に一致する `{service}/{environment}` の組は、`label-resolver` の target(PR の plan・`main` への push の apply)にならず、release の plan / apply も行われない。 - - rule のキー(`service`、`environment`)がすべて組の値と一致したとき、その組に一致する。`environment` だけの rule はすべての service に効く。 - - release PR は作られるが、merge しても apply されない:`release-targets.sh` が target を返さないとき、`auto-release--plan.yaml` と `auto-release--trigger.yaml` は `plan` / `apply` を skip する。 -- `aws/{service}/` 配下の environment ディレクトリ以外のファイル(module、`root.hcl` など)の変更は `terragrunt-shared` stack で検出され、その service の全 environment が対象になる。 -- `apply_trigger: release` の environment ディレクトリを持つ service には `aws/{service}/release-please-config.json` と `release-please-manifest.json` が必要。無い場合は `check-release-configs.sh` が CI を失敗させる。 - - `apply_trigger: merge` の environment ディレクトリだけを変える commit は、`release-please-config.json` の `exclude-paths` で release から外れる。 - - `check-release-configs.sh` は `exclude-paths` を `workflow-config.yaml` の `apply_trigger: merge` の environment と照合する。 +| Event | Workflow | Terragrunt | +|-------|----------|------------| +| PR に `deploy:{service}` ラベルが付く | [auto-label--deploy-trigger.yaml](.github/workflows/auto-label--deploy-trigger.yaml) | すべての target を plan | +| `main` への push | [auto-label--deploy-trigger.yaml](.github/workflows/auto-label--deploy-trigger.yaml) | `apply_trigger: merge` の target を apply | +| release PR の作成・更新 | [auto-release--plan.yaml](.github/workflows/auto-release--plan.yaml) | その service の `apply_trigger: release` の environment を plan | +| release の公開 | [auto-release--trigger.yaml](.github/workflows/auto-release--trigger.yaml) | その service の `apply_trigger: release` の environment を apply | + +#### Targets + +- PR の作成・更新時に、[auto-label--label-dispatcher.yaml](.github/workflows/auto-label--label-dispatcher.yaml) が `deploy:{service}` ラベルを付ける。release-please の branch にはラベルを付けない。 + - module や `root.hcl` を含め、`aws/{service}/` 配下のどの変更でもラベルが付く。 +- `label-resolver` が [workflow-config.yaml](workflow-config.yaml) を使って、ラベルをその service の全 environment に展開する。 +- `terragrunt` stack の `exclude` に一致する `{service}/{environment}` の組は、release も含めて plan も apply もされない。 + - `environment` だけの rule はすべての service に効く。 + +#### Releases + +- `apply_trigger: release` の environment を持つ `aws/{service}` は、それぞれ release-please の設定(`release-please-config.json` / `release-please-manifest.json`)を持つ。 + - 設定がないと [check-release-configs.sh](.github/scripts/terragrunt-release/check-release-configs.sh) が CI を失敗させる。 +- `apply_trigger: merge` の environment ディレクトリだけを変える commit は、release を作らない(`exclude-paths`)。 +- `apply_trigger: release` の environment がすべて除外されている間も release PR は作られるが、plan も apply もされない。 +- plan を出し直すときは、`auto-release--plan` の run で「Re-run all jobs」を使う。 +- apply を再実行するときは、`gh workflow run auto-release--trigger.yaml --ref {service}-vX.Y.Z -f tag={service}-vX.Y.Z` を実行する。 ### Stacks | Stack | Path convention | Tooling | |-------|-----------------|---------| -| AWS infrastructure | `aws/{service}/{environment}` | Terragrunt + OpenTofu (`reusable--terragrunt-executor.yaml`) | -| GitHub configuration | `github/{service}/{environment}` | Terragrunt + OpenTofu (`reusable--terragrunt-executor.yaml`) | -| Kubernetes platform | `kubernetes/components/{service}/{environment}` | Helmfile → Kustomize hydration (`reusable--kubernetes-hydrator.yaml` / `reusable--kubernetes-builder.yaml`) → Flux CD | +| AWS infrastructure | `aws/{service}/{environment}` | Terragrunt + OpenTofu ([reusable--terragrunt-executor.yaml](.github/workflows/reusable--terragrunt-executor.yaml)) | +| GitHub configuration | `github/{service}/{environment}` | Terragrunt + OpenTofu ([reusable--terragrunt-executor.yaml](.github/workflows/reusable--terragrunt-executor.yaml)) | +| Kubernetes platform | `kubernetes/components/{service}/{environment}` | Helmfile → Kustomize hydration ([reusable--kubernetes-hydrator.yaml](.github/workflows/reusable--kubernetes-hydrator.yaml) / [reusable--kubernetes-builder.yaml](.github/workflows/reusable--kubernetes-builder.yaml)) → Flux CD | ### Environments and Authentication -- Environment、AWS region、IAM role は `workflow-config.yaml` で定義する。環境の追加・削除は同ファイルの編集で行う。 -- `workflow-config.yaml` の `apply_trigger` が environment を apply するタイミングを決める。`merge` は `main` への push、`release` は service の release 公開時に apply する。 -- 認証は GitHub OIDC。`aws/github-oidc-auth/` が environment ごとの plan / apply role を発行し、executor がそれを引き受ける。 -- `platform` の GitHub environment `production` は tag pattern `*-v*` に一致する ref からの deployment だけを受け付け、`monorepo` の `production` はどの ref からの deployment も受け付けない。これらの設定は `github/repository/` で管理する。 -- Terragrunt の remote state は S3 + DynamoDB に保存される。bucket / lock table 名は各 `aws/{service}/root.hcl`(および `github/` 配下の同等ファイル)で定義される。 +- Environment、AWS region、IAM role は [workflow-config.yaml](workflow-config.yaml) で定義する。環境の追加・削除は同ファイルの編集で行う。 +- [workflow-config.yaml](workflow-config.yaml) の `apply_trigger` が environment を apply するタイミングを決める。`merge` は `main` への push、`release` は service の release 公開時に apply する。 +- 認証は GitHub OIDC。[aws/github-oidc-auth/](aws/github-oidc-auth/) が environment ごとの plan / apply role を発行し、executor がそれを引き受ける。 +- `platform` の GitHub environment `production` は tag pattern `*-v*` に一致する ref からの deployment だけを受け付け、`monorepo` の `production` はどの ref からの deployment も受け付けない。これらの設定は [github/repository/](github/repository/) で管理する。 +- Terragrunt の remote state は S3 + DynamoDB に保存される。bucket / lock table 名は各 `aws/{service}/root.hcl`(および [github/](github/) 配下の同等ファイル)で定義される。 ### Pipeline Flow @@ -127,15 +139,4 @@ flowchart LR - Flux bootstrap は `kubernetes/clusters/{cluster}/flux-system/` に置く。cluster の root Kustomization が `kubernetes/manifests/{cluster}/` 配下のレンダリング済みマニフェストと外部 `GitRepository`(現状はアプリケーション monorepo)を集約する。 - Platform と application の repository は別々に pull され、疎結合に保たれる。同期間隔や source URL は `kubernetes/clusters/{cluster}/` 配下のマニフェストが source of truth。 -- `kubernetes/components/` を変更する PR では CI が `scripts/kubernetes-hydrate/` を実行し、レンダリング結果を `kubernetes/manifests/` にコミット、差分を PR コメントに投稿する。マージ後に Flux が適用する。 - -### EKS Lifecycle - -EKS の teardown / recreate は deploy pipeline の外側、operator が手動で実行する。 - -- `make eks-teardown ENV=` で Kubernetes cleanup → Terragrunt destroy → orphan verify (`scripts/eks-lifecycle/`) が走る。`DRY_RUN=1` を付けるとコマンドを実行せずエコーのみ。 -- Recreate 手順は `docs/runbooks/eks-production-recreate.md` を参照。 - -### Claude Code Integration - -`@claude` コメントで `.github/workflows/claude-code-action.yaml` が起動し、`ai-assistant` IAM role を引き受けて AWS Bedrock の Claude を呼び出す。role 定義は `aws/ai-assistant/` 配下。 +- [kubernetes/components/](kubernetes/components/) を変更する PR では CI が [.github/scripts/kubernetes-hydrate/](.github/scripts/kubernetes-hydrate/) を実行し、レンダリング結果を [kubernetes/manifests/](kubernetes/manifests/) にコミット、差分を PR コメントに投稿する。マージ後に Flux が適用する。 diff --git a/README.md b/README.md index 29df20a8..e3c6da66 100644 --- a/README.md +++ b/README.md @@ -6,17 +6,19 @@ A monorepo that manages three deployment surfaces from a single label-driven CI pipeline: -- **AWS infrastructure** — Terragrunt + OpenTofu (`aws/`) -- **GitHub configuration** — Terragrunt for repo / branch / ruleset settings (`github/`) -- **Kubernetes platform** — Helmfile-rendered manifests applied by Flux CD (`kubernetes/`) +- **AWS infrastructure** — Terragrunt + OpenTofu ([aws/](aws/)) +- **GitHub configuration** — Terragrunt for repo / branch / ruleset settings ([github/](github/)) +- **Kubernetes platform** — Helmfile-rendered manifests applied by Flux CD ([kubernetes/](kubernetes/)) -A PR labeled by `panicboat/deploy-actions` is resolved against `workflow-config.yaml` to expand into concrete deploy targets, and the matching reusable workflow runs. +A PR labeled by `panicboat/deploy-actions` is resolved against [workflow-config.yaml](workflow-config.yaml) to expand into concrete deploy targets, and the matching reusable workflow runs. ## 📂 Structure ``` . -├── .github/workflows/ # Reusable executors, deploy trigger, hydrator/builder, etc. +├── .github/ +│ ├── scripts/ # Scripts run by workflows (hydration, terragrunt release) +│ └── workflows/ # Reusable executors, deploy trigger, hydrator/builder, etc. ├── aws/ # Terragrunt stacks per service ({environment}) ├── github/ # Terragrunt stacks for GitHub repo / branch settings ├── kubernetes/ @@ -24,7 +26,7 @@ A PR labeled by `panicboat/deploy-actions` is resolved against `workflow-config. │ ├── components/ # Helmfile sources (per environment) │ └── manifests/ # Rendered output that Flux applies ├── docs/ # Runbooks and design notes -├── scripts/ # EKS lifecycle / hydration helpers +├── scripts/ # EKS lifecycle helpers ├── Makefile # EKS teardown entry points └── workflow-config.yaml # Environments and stack conventions (source of truth) ``` @@ -33,35 +35,45 @@ A PR labeled by `panicboat/deploy-actions` is resolved against `workflow-config. ### Trigger -- `auto-label--deploy-trigger.yaml` runs on PR labels and on push to `main`. -- `panicboat/deploy-actions/label-resolver` reads `workflow-config.yaml` to expand each label into one or more `{service}/{environment}` targets. -- Terragrunt environments with `apply_trigger: merge` are applied on push to `main`. -- Terragrunt environments with `apply_trigger: release` are applied by `auto-release--trigger.yaml` when the `aws/{service}` release is published. - - The release PR runs `terragrunt plan` through `auto-release--plan.yaml`; to re-plan, use "Re-run all jobs" on that `auto-release--plan` run. - - To re-apply a release, run `auto-release--trigger` with `workflow_dispatch` on the release tag ref and pass the same tag: `gh workflow run auto-release--trigger.yaml --ref {service}-vX.Y.Z -f tag={service}-vX.Y.Z`. -- A `{service}/{environment}` pair matched by a rule in `exclude` of the `terragrunt` stack in `workflow-config.yaml` gets no target from `label-resolver` (PR plan, apply on push to `main`) and no release plan / apply. - - A rule matches a pair when every key (`service`, `environment`) equals the pair's value; a rule with only `environment` covers every service. - - The release PR is still created, but merging it applies nothing: `auto-release--plan.yaml` and `auto-release--trigger.yaml` skip `plan` / `apply` when `release-targets.sh` returns no target. -- Changes to files outside environment directories under `aws/{service}/` (modules, `root.hcl`, ...) are detected through the `terragrunt-shared` stack and target every environment of that service. -- A service with an `apply_trigger: release` environment directory needs `aws/{service}/release-please-config.json` and `release-please-manifest.json`; `check-release-configs.sh` fails CI otherwise. - - Commits that change only `apply_trigger: merge` environment directories are kept out of the release through `exclude-paths` in `release-please-config.json`. - - `check-release-configs.sh` compares `exclude-paths` with the `apply_trigger: merge` environments in `workflow-config.yaml`. +| Event | Workflow | Terragrunt | +|-------|----------|------------| +| `deploy:{service}` label added to a PR | [auto-label--deploy-trigger.yaml](.github/workflows/auto-label--deploy-trigger.yaml) | plan every target | +| Push to `main` | [auto-label--deploy-trigger.yaml](.github/workflows/auto-label--deploy-trigger.yaml) | apply targets with `apply_trigger: merge` | +| Release PR opened / updated | [auto-release--plan.yaml](.github/workflows/auto-release--plan.yaml) | plan the service's `apply_trigger: release` environments | +| Release published | [auto-release--trigger.yaml](.github/workflows/auto-release--trigger.yaml) | apply the service's `apply_trigger: release` environments | + +#### Targets + +- [auto-label--label-dispatcher.yaml](.github/workflows/auto-label--label-dispatcher.yaml) adds `deploy:{service}` to a PR when it is opened or updated; release-please branches get no label. + - Any change under `aws/{service}/`, including modules and `root.hcl`, adds the label. +- `label-resolver` expands the label into every environment of that service using [workflow-config.yaml](workflow-config.yaml). +- A `{service}/{environment}` pair matched by `exclude` of the `terragrunt` stack is never planned or applied, including by releases. + - A rule with only `environment` covers every service. + +#### Releases + +- Each `aws/{service}` with an `apply_trigger: release` environment has its own release-please config (`release-please-config.json` / `release-please-manifest.json`). + - [check-release-configs.sh](.github/scripts/terragrunt-release/check-release-configs.sh) fails CI when a config is missing. +- Commits that touch only `apply_trigger: merge` environment directories do not create a release (`exclude-paths`). +- While every `apply_trigger: release` environment is excluded, the release PR is still created, but nothing is planned or applied. +- To re-plan, use "Re-run all jobs" on the `auto-release--plan` run. +- To re-apply, run `gh workflow run auto-release--trigger.yaml --ref {service}-vX.Y.Z -f tag={service}-vX.Y.Z`. ### Stacks | Stack | Path convention | Tooling | |-------|-----------------|---------| -| AWS infrastructure | `aws/{service}/{environment}` | Terragrunt + OpenTofu (`reusable--terragrunt-executor.yaml`) | -| GitHub configuration | `github/{service}/{environment}` | Terragrunt + OpenTofu (`reusable--terragrunt-executor.yaml`) | -| Kubernetes platform | `kubernetes/components/{service}/{environment}` | Helmfile → Kustomize hydration (`reusable--kubernetes-hydrator.yaml` / `reusable--kubernetes-builder.yaml`) → Flux CD | +| AWS infrastructure | `aws/{service}/{environment}` | Terragrunt + OpenTofu ([reusable--terragrunt-executor.yaml](.github/workflows/reusable--terragrunt-executor.yaml)) | +| GitHub configuration | `github/{service}/{environment}` | Terragrunt + OpenTofu ([reusable--terragrunt-executor.yaml](.github/workflows/reusable--terragrunt-executor.yaml)) | +| Kubernetes platform | `kubernetes/components/{service}/{environment}` | Helmfile → Kustomize hydration ([reusable--kubernetes-hydrator.yaml](.github/workflows/reusable--kubernetes-hydrator.yaml) / [reusable--kubernetes-builder.yaml](.github/workflows/reusable--kubernetes-builder.yaml)) → Flux CD | ### Environments and authentication -- Environments, AWS regions, and IAM roles are defined in `workflow-config.yaml`. Adding or removing an environment means editing that file. -- `apply_trigger` in `workflow-config.yaml` decides when an environment is applied: `merge` applies on push to `main`, `release` applies when the service release is published. -- Authentication uses GitHub OIDC. `aws/github-oidc-auth/` issues per-environment plan / apply roles that the executors assume. -- The GitHub environment `production` of `platform` accepts deployments only from refs that match the tag pattern `*-v*`, and that of `monorepo` accepts deployments from no ref. The settings are managed in `github/repository/`. -- Terragrunt remote state lives in S3 + DynamoDB; bucket and lock-table names are defined in each `aws/{service}/root.hcl` (and the equivalent under `github/`). +- Environments, AWS regions, and IAM roles are defined in [workflow-config.yaml](workflow-config.yaml). Adding or removing an environment means editing that file. +- `apply_trigger` in [workflow-config.yaml](workflow-config.yaml) decides when an environment is applied: `merge` applies on push to `main`, `release` applies when the service release is published. +- Authentication uses GitHub OIDC. [aws/github-oidc-auth/](aws/github-oidc-auth/) issues per-environment plan / apply roles that the executors assume. +- The GitHub environment `production` of `platform` accepts deployments only from refs that match the tag pattern `*-v*`, and that of `monorepo` accepts deployments from no ref. The settings are managed in [github/repository/](github/repository/). +- Terragrunt remote state lives in S3 + DynamoDB; bucket and lock-table names are defined in each `aws/{service}/root.hcl` (and the equivalent under [github/](github/)). ### Pipeline Flow @@ -127,15 +139,4 @@ flowchart LR - Flux bootstrap lives in `kubernetes/clusters/{cluster}/flux-system/`. The cluster's root Kustomization aggregates the rendered manifests under `kubernetes/manifests/{cluster}/` and any external `GitRepository` (currently the application monorepo). - Platform and application repositories are pulled independently and stay loosely coupled. Sync intervals and source URLs are configured in `kubernetes/clusters/{cluster}/` — treat those manifests as the source of truth. -- When `kubernetes/components/` changes, CI runs `scripts/kubernetes-hydrate/`, commits the rendered output to `kubernetes/manifests/`, and posts the diff as a PR comment. Flux applies the change once merged. - -### EKS Lifecycle - -EKS teardown / recreate is operator-driven and runs outside the deploy pipeline. - -- `make eks-teardown ENV=` runs Kubernetes cleanup → Terragrunt destroy → orphan verify (`scripts/eks-lifecycle/`). `DRY_RUN=1` echoes commands without executing them. -- Recreate is a manual procedure — see `docs/runbooks/eks-production-recreate.md`. - -### Claude Code Integration - -`@claude` comments trigger `.github/workflows/claude-code-action.yaml`, which assumes the `ai-assistant` IAM role to invoke Bedrock Claude. The role is defined under `aws/ai-assistant/`. +- When [kubernetes/components/](kubernetes/components/) changes, CI runs [.github/scripts/kubernetes-hydrate/](.github/scripts/kubernetes-hydrate/), commits the rendered output to [kubernetes/manifests/](kubernetes/manifests/), and posts the diff as a PR comment. Flux applies the change once merged. diff --git a/docs/runbooks/eks-production-recreate.md b/docs/runbooks/eks-production-recreate.md index ddd36283..19c2e7b3 100644 --- a/docs/runbooks/eks-production-recreate.md +++ b/docs/runbooks/eks-production-recreate.md @@ -251,10 +251,10 @@ Karpenter が NodePool 観測 → Pending pod (= ebs-csi-controller / hubble-rel for comp in $(find kubernetes/components -mindepth 1 -maxdepth 1 -type d -exec basename {} \;); do if [ -d "kubernetes/components/${comp}/production" ]; then echo "Hydrating ${comp}..." - bash scripts/kubernetes-hydrate/hydrate-component.sh "$comp" production + bash .github/scripts/kubernetes-hydrate/hydrate-component.sh "$comp" production fi done -bash scripts/kubernetes-hydrate/hydrate-index.sh production +bash .github/scripts/kubernetes-hydrate/hydrate-index.sh production # commit + push (= main 直接 push は branch protection で blocked のため PR 経由) git checkout -b chore/hydrate-after-recreate-$(date +%Y%m%d)