582 lines
22 KiB
Markdown
582 lines
22 KiB
Markdown
# Project Infra Phase 1 dev GitOps Implementation Plan
|
|
|
|
> **For agentic workers:** REQUIRED SUB-SKILL: Use `superpowers:subagent-driven-development` (recommended) or `superpowers:executing-plans` to execute this plan task by task. Use `superpowers:test-driven-development` for behavior changes and `superpowers:verification-before-completion` before reporting success.
|
|
|
|
**Goal:** Rename the active rollout from `lab` to `dev`, make operator desired state render from Git, and correct the ForwardAuth/Keycloak ownership defects without changing a live cluster.
|
|
|
|
**Architecture:** The catalog remains ownership-first and environment-neutral in `base`, while `overlays/dev` contains dev-only values. `gitops/clusters/dev/main` is the only current deployable Kubernetes root. A shared render function always enables Kustomize Helm support. Operator charts live in independent platform units and are selected by a dedicated ordered stage. This plan only changes Git-owned source and local tests; it must not invoke `kubectl apply`, `kubectl delete`, or Helm mutation commands.
|
|
|
|
**Tech Stack:** Bash, Kustomize 5.8.1, Helm 3.19.4, Kubernetes/K3s manifests, repository shell test harness, `rg`.
|
|
|
|
## Global constraints
|
|
|
|
- Read `/AGENTS.md`, the nearest nested `AGENTS.md`, `docs/standards/infra/STYLE.md`, and the directly relevant standards before each manifest task.
|
|
- Preserve `mnt`, `minio-operator`, and `vault-secrets-operator-system` namespace names in Phase 1.
|
|
- Preserve `.local.test` hostnames as dev-only values.
|
|
- Never apply `gitops/clusters/dev/main/all`; it is render/audit-only.
|
|
- Do not run a live-cluster mutation command while executing this plan.
|
|
- Do not edit CI workflow definitions or the sibling `cicd-platform` repository.
|
|
- Commit only the files listed by the current task and inspect `git status --short` before each commit.
|
|
|
|
## Dependency and interface contract
|
|
|
|
This plan is executed before the automation-safety and validation-structure plans.
|
|
|
|
- `tests/run.sh [name-fragment]` discovers executable `tests/contracts/*-test.sh` files and optionally filters by basename.
|
|
- `tests/lib/assert.sh` provides `fail`, `assert_eq`, `assert_file_exists`, `assert_file_absent`, `assert_contains`, and `assert_not_contains`.
|
|
- `scripts/lib/kustomize.sh` exports `kustomize_render ENTRYPOINT`; rendered YAML is written only to stdout and diagnostics only to stderr.
|
|
- Every later render path must call `kustomize_render`; no later script may reimplement `kustomize build` or `kubectl kustomize`.
|
|
- The ordered dev stages are `00-platform`, `05-operators`, `10-vault`, `20-secrets`, `30-data`, `35-registry`, `40-operations`, and `50-apps`.
|
|
|
|
---
|
|
|
|
## Task 1: Add the contract-test harness and rename the active environment
|
|
|
|
**Files:**
|
|
|
|
- Create: `tests/lib/assert.sh`
|
|
- Create: `tests/run.sh`
|
|
- Create: `tests/contracts/dev-layout-test.sh`
|
|
- Move: `gitops/clusters/lab/main` → `gitops/clusters/dev/main`
|
|
- Move: `gitops/apps/auth-migration/overlays/lab` → `gitops/apps/auth-migration/overlays/dev`
|
|
- Move: `gitops/apps/auth-server/overlays/lab` → `gitops/apps/auth-server/overlays/dev`
|
|
- Move: `gitops/apps/identity-postgres/overlays/lab` → `gitops/apps/identity-postgres/overlays/dev`
|
|
- Move: `gitops/apps/keycloak-realm-import/overlays/lab` → `gitops/apps/keycloak-realm-import/overlays/dev`
|
|
- Move: `gitops/platform/cert-manager/overlays/lab` → `gitops/platform/cert-manager/overlays/dev`
|
|
- Move: `gitops/platform/forward-auth/overlays/lab` → `gitops/platform/forward-auth/overlays/dev`
|
|
- Move: `gitops/platform/keycloak-operator/overlays/lab` → `gitops/platform/keycloak-operator/overlays/dev`
|
|
- Move: `gitops/platform/keycloak/overlays/lab` → `gitops/platform/keycloak/overlays/dev`
|
|
- Move: `gitops/platform/minio/overlays/lab` → `gitops/platform/minio/overlays/dev`
|
|
- Move: `gitops/platform/registry/overlays/lab` → `gitops/platform/registry/overlays/dev`
|
|
- Move: `gitops/platform/secret-delivery/overlays/lab` → `gitops/platform/secret-delivery/overlays/dev`
|
|
- Move: `gitops/platform/traefik/overlays/lab` → `gitops/platform/traefik/overlays/dev`
|
|
- Move: `gitops/platform/vault/overlays/lab` → `gitops/platform/vault/overlays/dev`
|
|
- Move: `gitops/policies/baseline/overlays/lab` → `gitops/policies/baseline/overlays/dev`
|
|
- Modify: moved Kustomization files, `tests/kustomize-entrypoints.txt`
|
|
- Modify: `AGENTS.md`, `README.md`, `guide.md`, `gitops/AGENTS.md`, `gitops/PROJECT.md`, `gitops/clusters/AGENTS.md`, `gitops/clusters/README.md`, `gitops/clusters/dev/main/README.md`, `docs/architecture.md`, `docs/architecture/repository-structure.md`, `docs/guides/getting-started.md`, `docs/ingress-traefik.md`, `docs/operations.md`, `docs/security-hardening.md`, `docs/troubleshooting.md`, `docs/vault-vso.md`, `scripts/bin/bootstrap.sh`, `scripts/bin/teardown.sh`, `scripts/tasks/minio-provision-registry.sh`, `scripts/ci/validate-docs.sh`, `scripts/README.md`, `tests/README.md`
|
|
|
|
**Step 1: Write the failing layout contract**
|
|
|
|
Use strict mode in every new script. The runner must execute each selected test in a fresh Bash process and return non-zero if any test fails:
|
|
|
|
```bash
|
|
#!/usr/bin/env bash
|
|
set -Eeuo pipefail
|
|
IFS=$'\n\t'
|
|
|
|
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
|
filter="${1:-}"
|
|
failed=0
|
|
|
|
while IFS= read -r test_file; do
|
|
[[ -z "$filter" || "$(basename "$test_file")" == *"$filter"* ]] || continue
|
|
bash "$test_file" || failed=$((failed + 1))
|
|
done < <(find "$ROOT_DIR/tests/contracts" -type f -name '*-test.sh' -print | sort)
|
|
|
|
((failed == 0))
|
|
```
|
|
|
|
`dev-layout-test.sh` must assert all of these conditions:
|
|
|
|
```text
|
|
gitops/clusters/dev/main exists
|
|
gitops/clusters/lab does not exist
|
|
every selected unit has overlays/dev and no overlays/lab
|
|
tests/kustomize-entrypoints.txt contains gitops/clusters/dev/main
|
|
tests/kustomize-entrypoints.txt does not contain gitops/clusters/lab
|
|
no deployable kustomization contains example.com/environment: lab
|
|
the active docs listed above do not instruct users to deploy lab
|
|
```
|
|
|
|
**Step 2: Run the contract and verify that it fails for the current tree**
|
|
|
|
Run:
|
|
|
|
```bash
|
|
bash tests/run.sh dev-layout
|
|
```
|
|
|
|
Expected: non-zero, with the first failure reporting the missing `gitops/clusters/dev/main` path.
|
|
|
|
**Step 3: Move the directories with Git-aware renames**
|
|
|
|
Run one `git mv` per source directory. Do not use recursive copy/delete. After the moves, replace only active environment references:
|
|
|
|
```bash
|
|
rg -l 'clusters/lab|overlays/lab|environment: lab|\blab\b' \
|
|
AGENTS.md README.md guide.md gitops scripts docs tests \
|
|
--glob '!docs/standards/**' \
|
|
--glob '!docs/examples/**' \
|
|
--glob '!docs/superpowers/**'
|
|
```
|
|
|
|
Review every hit and change current deployment semantics from `lab` to `dev`, including bootstrap/teardown accepted environment names and MinIO's dev-only HTTP default. Preserve historical text in approved design/spec documents and normative examples that intentionally compare environments. Change `gitops/AGENTS.md` base reuse wording to name `dev`, `staging`, and `prod`; it may still describe `lab` only as an optional disposable environment.
|
|
|
|
**Step 4: Update the moved cluster root**
|
|
|
|
All resource paths under `gitops/clusters/dev/main/stages/*/kustomization.yaml` must select `overlays/dev`. Every stage label must be:
|
|
|
|
```yaml
|
|
labels:
|
|
- pairs:
|
|
example.com/environment: dev
|
|
example.com/owner-team: platform
|
|
includeSelectors: false
|
|
includeTemplates: true
|
|
```
|
|
|
|
Remove `../../../../../tenants/mnt/base` from `stages/00-platform`; namespace ownership belongs only to the separate `namespaces` entrypoint.
|
|
|
|
Update `tests/kustomize-entrypoints.txt` to contain only dev cluster entrypoints. Keep `all/` in the render inventory, but mark it audit-only in the cluster README and tests README.
|
|
|
|
**Step 5: Run the test and documentation gate**
|
|
|
|
Run:
|
|
|
|
```bash
|
|
bash tests/run.sh dev-layout
|
|
bash scripts/ci/validate-docs.sh
|
|
git diff --check
|
|
```
|
|
|
|
Expected: all commands exit 0.
|
|
|
|
**Step 6: Commit**
|
|
|
|
```bash
|
|
git add tests gitops AGENTS.md README.md guide.md docs scripts/bin/bootstrap.sh scripts/bin/teardown.sh scripts/tasks/minio-provision-registry.sh scripts/ci/validate-docs.sh scripts/README.md
|
|
git commit -m "refactor: dev 환경 경로로 전환"
|
|
```
|
|
|
|
---
|
|
|
|
## Task 2: Introduce one Helm-aware Kustomize render interface
|
|
|
|
**Files:**
|
|
|
|
- Create: `scripts/lib/kustomize.sh`
|
|
- Create: `tests/contracts/kustomize-render-test.sh`
|
|
- Modify: `scripts/ci/validate.sh`
|
|
- Modify: `scripts/lib/common.sh` only if it is needed to share `REPO_ROOT` without changing cluster behavior
|
|
|
|
**Step 1: Write the failing fake-command test**
|
|
|
|
The test creates a temporary `PATH` with fake `kustomize` and `kubectl` executables. It must prove:
|
|
|
|
1. when `kustomize` exists, the helper calls exactly `kustomize build --enable-helm ENTRYPOINT`;
|
|
2. when only `kubectl` exists, it calls exactly `kubectl kustomize ENTRYPOINT --enable-helm`;
|
|
3. when neither exists, it exits non-zero;
|
|
4. rendered YAML remains on stdout and the command trace remains outside stdout.
|
|
|
|
Run:
|
|
|
|
```bash
|
|
bash tests/run.sh kustomize-render
|
|
```
|
|
|
|
Expected: non-zero because `scripts/lib/kustomize.sh` does not yet exist.
|
|
|
|
**Step 2: Implement the shared helper**
|
|
|
|
Use this public interface:
|
|
|
|
```bash
|
|
#!/usr/bin/env bash
|
|
set -Eeuo pipefail
|
|
IFS=$'\n\t'
|
|
|
|
kustomize_render() {
|
|
local entrypoint="${1:?entrypoint is required}"
|
|
if command -v kustomize >/dev/null 2>&1; then
|
|
kustomize build --enable-helm "$entrypoint"
|
|
elif command -v kubectl >/dev/null 2>&1; then
|
|
kubectl kustomize "$entrypoint" --enable-helm
|
|
else
|
|
printf 'ERROR: kustomize 또는 kubectl이 필요합니다.\n' >&2
|
|
return 1
|
|
fi
|
|
}
|
|
```
|
|
|
|
Source this file from `scripts/ci/validate.sh` and delete its local `render_kustomization` implementation. Change the validation call to:
|
|
|
|
```bash
|
|
kustomize_render "$entrypoint" >"$rendered"
|
|
```
|
|
|
|
**Step 3: Verify the helper and current dev renders**
|
|
|
|
Run:
|
|
|
|
```bash
|
|
bash tests/run.sh kustomize-render
|
|
VALIDATION_PROFILE=local bash scripts/ci/validate.sh
|
|
git diff --check
|
|
```
|
|
|
|
Expected: all commands exit 0; render log lines identify dev entrypoints.
|
|
|
|
**Step 4: Commit**
|
|
|
|
```bash
|
|
git add scripts/lib/kustomize.sh scripts/ci/validate.sh tests/contracts/kustomize-render-test.sh
|
|
git commit -m "refactor: Helm 지원 렌더 경로 통합"
|
|
```
|
|
|
|
---
|
|
|
|
## Task 3: Add declarative operator namespaces and catalog units
|
|
|
|
**Files:**
|
|
|
|
- Create: `gitops/tenants/minio-operator/base/kustomization.yaml`
|
|
- Create: `gitops/tenants/minio-operator/base/namespace.yaml`
|
|
- Create: `gitops/tenants/vault-secrets-operator-system/base/kustomization.yaml`
|
|
- Create: `gitops/tenants/vault-secrets-operator-system/base/namespace.yaml`
|
|
- Create: `gitops/platform/minio-operator/base/kustomization.yaml`
|
|
- Create: `gitops/platform/minio-operator/overlays/dev/kustomization.yaml`
|
|
- Create: `gitops/platform/minio-operator/overlays/dev/values.yaml`
|
|
- Create: `gitops/platform/vault-secrets-operator/base/kustomization.yaml`
|
|
- Create: `gitops/platform/vault-secrets-operator/overlays/dev/kustomization.yaml`
|
|
- Move: `gitops/platform/secret-delivery/base/helm/values.yaml` → `gitops/platform/vault-secrets-operator/overlays/dev/values.yaml`
|
|
- Create: `gitops/clusters/dev/main/stages/05-operators/kustomization.yaml`
|
|
- Modify: `gitops/clusters/dev/main/namespaces/kustomization.yaml`
|
|
- Modify: `gitops/clusters/dev/main/all/kustomization.yaml`
|
|
- Modify: `tests/kustomize-entrypoints.txt`
|
|
- Create: `tests/contracts/operator-render-test.sh`
|
|
- Modify: `gitops/platform/README.md`, `gitops/tenants/README.md`, `gitops/clusters/dev/main/README.md`
|
|
|
|
**Step 1: Write the failing operator render contract**
|
|
|
|
Render `gitops/clusters/dev/main/stages/05-operators` through `kustomize_render`. Assert:
|
|
|
|
```text
|
|
the render exits 0
|
|
at least two Deployment documents exist
|
|
tenants.minio.min.io exists as a CustomResourceDefinition name
|
|
vaultstaticsecrets.secrets.hashicorp.com exists as a CustomResourceDefinition name
|
|
the namespaces entrypoint renders Namespace/minio-operator and Namespace/vault-secrets-operator-system
|
|
every namespaced resource in the operator stage targets minio-operator or vault-secrets-operator-system
|
|
no HelmRelease custom resource is present
|
|
chart versions 7.0.0 and 0.9.0 are pinned in source
|
|
includeCRDs: true is present in both dev overlay kustomizations
|
|
```
|
|
|
|
Run:
|
|
|
|
```bash
|
|
bash tests/run.sh operator-render
|
|
```
|
|
|
|
Expected: non-zero because the operator stage does not exist.
|
|
|
|
**Step 2: Add namespace ownership units**
|
|
|
|
Each Namespace must use the standard labels from `gitops/tenants/mnt/base/namespace.yaml`, with `app.kubernetes.io/name` and `app.kubernetes.io/instance` set to its namespace. Apply the `restricted` Pod Security labels. Each base Kustomization contains only its `namespace.yaml`.
|
|
|
|
Add both bases to `gitops/clusters/dev/main/namespaces/kustomization.yaml` after `mnt`.
|
|
|
|
**Step 3: Add the MinIO Operator unit**
|
|
|
|
The dev overlay Kustomization must be exactly shaped as follows:
|
|
|
|
```yaml
|
|
apiVersion: kustomize.config.k8s.io/v1beta1
|
|
kind: Kustomization
|
|
|
|
resources:
|
|
- ../../base
|
|
|
|
helmCharts:
|
|
- name: operator
|
|
repo: https://operator.min.io
|
|
version: 7.0.0
|
|
releaseName: minio-operator
|
|
namespace: minio-operator
|
|
includeCRDs: true
|
|
valuesFile: values.yaml
|
|
```
|
|
|
|
Use only chart-supported keys from the pinned MinIO Operator 7.0.0 values schema. `values.yaml` must be:
|
|
|
|
```yaml
|
|
operator:
|
|
replicaCount: 1
|
|
securityContext:
|
|
runAsUser: 1000
|
|
runAsGroup: 1000
|
|
runAsNonRoot: true
|
|
fsGroup: 1000
|
|
seccompProfile:
|
|
type: RuntimeDefault
|
|
containerSecurityContext:
|
|
runAsUser: 1000
|
|
runAsGroup: 1000
|
|
runAsNonRoot: true
|
|
allowPrivilegeEscalation: false
|
|
readOnlyRootFilesystem: true
|
|
capabilities:
|
|
drop:
|
|
- ALL
|
|
seccompProfile:
|
|
type: RuntimeDefault
|
|
resources:
|
|
requests:
|
|
cpu: 200m
|
|
memory: 256Mi
|
|
ephemeral-storage: 500Mi
|
|
limits:
|
|
memory: 384Mi
|
|
ephemeral-storage: 1Gi
|
|
```
|
|
|
|
The single replica is a dev overlay decision. A later staging/prod overlay must reassess replicas, PDB, and topology from measured capacity.
|
|
|
|
**Step 4: Add the Vault Secrets Operator unit**
|
|
|
|
The dev overlay Kustomization must pin:
|
|
|
|
```yaml
|
|
helmCharts:
|
|
- name: vault-secrets-operator
|
|
repo: https://helm.releases.hashicorp.com
|
|
version: 0.9.0
|
|
releaseName: vault-secrets-operator
|
|
namespace: vault-secrets-operator-system
|
|
includeCRDs: true
|
|
valuesFile: values.yaml
|
|
```
|
|
|
|
Move the existing hardened VSO values file unchanged first. Remove the now-empty `gitops/platform/secret-delivery/base/helm` directory from Git. Keep secret-delivery CRs in their existing unit; only the controller chart moves.
|
|
|
|
**Step 5: Add the ordered stage and inventory**
|
|
|
|
`gitops/clusters/dev/main/stages/05-operators/kustomization.yaml` contains exactly the two dev overlays and the normal dev/platform labels. Insert it between `00-platform` and `10-vault` in `all/kustomization.yaml` and in `tests/kustomize-entrypoints.txt`.
|
|
|
|
Do not add these operator overlays to `00-platform`.
|
|
|
|
**Step 6: Verify render, schema, and policy**
|
|
|
|
Run:
|
|
|
|
```bash
|
|
bash tests/run.sh operator-render
|
|
VALIDATION_PROFILE=full bash scripts/ci/validate.sh
|
|
git diff --check
|
|
```
|
|
|
|
Expected: operator test exits 0; full validation reports no invalid schema or policy result. If chart download is unavailable, stop and report the external availability failure rather than committing an unrendered chart definition.
|
|
|
|
**Step 7: Commit**
|
|
|
|
```bash
|
|
git add gitops/tenants gitops/platform/minio-operator gitops/platform/vault-secrets-operator gitops/platform/secret-delivery gitops/clusters/dev/main tests
|
|
git commit -m "feat: operator desired state를 GitOps로 선언"
|
|
```
|
|
|
|
---
|
|
|
|
## Task 4: Put ForwardAuth resources and patches under their real owners
|
|
|
|
**Files:**
|
|
|
|
- Move: `gitops/platform/forward-auth/component/oauth2-proxy-config.yaml` → `gitops/platform/forward-auth/overlays/dev/oauth2-proxy-config.yaml`
|
|
- Move: `gitops/platform/forward-auth/component/oauth2-proxy-ingress.yaml` → `gitops/platform/forward-auth/overlays/dev/oauth2-proxy-ingress.yaml`
|
|
- Move: `gitops/platform/forward-auth/component/oauth2-proxy-middleware.yaml` → `gitops/platform/forward-auth/overlays/dev/oauth2-proxy-middleware.yaml`
|
|
- Move: `gitops/platform/forward-auth/component/oauth2-proxy-networkpolicy.yaml` → `gitops/platform/forward-auth/overlays/dev/oauth2-proxy-networkpolicy.yaml`
|
|
- Delete: `gitops/platform/forward-auth/component/kustomization.yaml`
|
|
- Modify: `gitops/platform/forward-auth/overlays/dev/kustomization.yaml`
|
|
- Modify: `gitops/apps/auth-server/base/configmap.yaml`
|
|
- Modify: `gitops/apps/auth-server/overlays/dev/kustomization.yaml`
|
|
- Modify: `gitops/platform/keycloak/overlays/dev/kustomization.yaml`
|
|
- Delete: `gitops/platform/keycloak/overlays/dev/ingress-admin.yaml`
|
|
- Create: `tests/contracts/dev-ingress-render-test.sh`
|
|
|
|
**Step 1: Write the failing rendered-output assertions**
|
|
|
|
Render `gitops/clusters/dev/main/stages/50-apps` and `00-platform`. Extract resources by `kind` and `metadata.name` without assuming document order. Assert:
|
|
|
|
```text
|
|
Ingress/auth-server annotation is exactly:
|
|
mnt-oauth2-proxy-errors@kubernetescrd,mnt-oauth2-proxy-auth@kubernetescrd,kube-system-security-headers@kubernetescrd
|
|
Ingress/keycloak exists
|
|
Ingress/keycloak-admin does not exist
|
|
ConfigMap/auth-server-config in the app stage contains SPRING_PROFILES_ACTIVE=dev
|
|
ConfigMap/auth-server-config rendered from gitops/apps/auth-server/base does not contain SPRING_PROFILES_ACTIVE
|
|
the 00-platform render contains oauth2-proxy ConfigMap, Ingress, Middleware resources, and NetworkPolicy
|
|
```
|
|
|
|
Run:
|
|
|
|
```bash
|
|
bash tests/run.sh dev-ingress-render
|
|
```
|
|
|
|
Expected: non-zero because the current auth-server annotation has only the security middleware.
|
|
|
|
**Step 2: Refactor the ForwardAuth overlay**
|
|
|
|
Change the dev overlay from a Component reference to normal ownership:
|
|
|
|
```yaml
|
|
apiVersion: kustomize.config.k8s.io/v1beta1
|
|
kind: Kustomization
|
|
|
|
namespace: mnt
|
|
|
|
resources:
|
|
- ../../base
|
|
- oauth2-proxy-config.yaml
|
|
- oauth2-proxy-ingress.yaml
|
|
- oauth2-proxy-middleware.yaml
|
|
- oauth2-proxy-networkpolicy.yaml
|
|
```
|
|
|
|
Delete the component directory after all resources are moved. The platform stage continues to select only `forward-auth/overlays/dev`.
|
|
|
|
**Step 3: Move the auth-server patch to the auth-server owner**
|
|
|
|
Add this patch to `gitops/apps/auth-server/overlays/dev/kustomization.yaml`:
|
|
|
|
```yaml
|
|
- target:
|
|
kind: Ingress
|
|
name: auth-server
|
|
patch: |-
|
|
- op: replace
|
|
path: /metadata/annotations/traefik.ingress.kubernetes.io~1router.middlewares
|
|
value: mnt-oauth2-proxy-errors@kubernetescrd,mnt-oauth2-proxy-auth@kubernetescrd,kube-system-security-headers@kubernetescrd
|
|
```
|
|
|
|
Remove `SPRING_PROFILES_ACTIVE` from the base ConfigMap and add it through the existing dev ConfigMap patch.
|
|
|
|
**Step 4: Remove the dev admin Ingress from desired state**
|
|
|
|
Remove `ingress-admin.yaml` from the Keycloak dev Kustomization and delete the file. Do not run `kubectl delete`; live cleanup belongs to Phase 2.
|
|
|
|
**Step 5: Verify exact rendered behavior**
|
|
|
|
Run:
|
|
|
|
```bash
|
|
bash tests/run.sh dev-ingress-render
|
|
VALIDATION_PROFILE=full bash scripts/ci/validate.sh
|
|
git diff --check
|
|
```
|
|
|
|
Expected: all commands exit 0.
|
|
|
|
**Step 6: Commit**
|
|
|
|
```bash
|
|
git add gitops/platform/forward-auth gitops/apps/auth-server gitops/platform/keycloak tests/contracts/dev-ingress-render-test.sh
|
|
git commit -m "fix: dev ForwardAuth 소유 경계 수정"
|
|
```
|
|
|
|
---
|
|
|
|
## Task 5: Record the environment and CI ownership decisions
|
|
|
|
**Files:**
|
|
|
|
- Create: `docs/adr/0002-dev-environment-and-external-ci-ownership.md`
|
|
- Modify: `docs/architecture/repository-structure.md`
|
|
- Modify: `README.md`
|
|
- Modify: `docs/superpowers/specs/2026-08-02-project-infra-dev-structure-refactor-design.md`
|
|
- Modify: `scripts/ci/validate-docs.sh`
|
|
|
|
**Step 1: Extend the docs contract so it fails first**
|
|
|
|
Add assertions to `scripts/ci/validate-docs.sh` requiring the ADR to contain all of these literals:
|
|
|
|
```text
|
|
Status: Accepted
|
|
gitops/clusters/dev/main
|
|
cicd-platform
|
|
delivery-platform.yaml
|
|
all/ is render/audit-only
|
|
```
|
|
|
|
Run:
|
|
|
|
```bash
|
|
bash scripts/ci/validate-docs.sh
|
|
```
|
|
|
|
Expected: non-zero because ADR 0002 does not exist.
|
|
|
|
**Step 2: Write the ADR**
|
|
|
|
Use sections `Context`, `Decision`, `Consequences`, and `Phase 2 follow-up`. Record:
|
|
|
|
- current rollout environment is `dev`, not `lab`;
|
|
- dev is controller-less and uses ordered bootstrap stages;
|
|
- `all/ is render/audit-only` and is never an apply target;
|
|
- project-infra owns local validation contracts;
|
|
- `cicd-platform` owns workflow execution, authoritative tools, evidence, and the future `delivery-platform.yaml` consumer onboarding;
|
|
- existing workflows remain transitional and are not changed in Phase 1.
|
|
|
|
Verify that the approved design document remains marked `Status: approved`.
|
|
|
|
**Step 3: Verify documentation**
|
|
|
|
Run:
|
|
|
|
```bash
|
|
bash scripts/ci/validate-docs.sh
|
|
git diff --check
|
|
```
|
|
|
|
Expected: both commands exit 0.
|
|
|
|
**Step 4: Commit**
|
|
|
|
```bash
|
|
git add docs/adr docs/architecture/repository-structure.md README.md docs/superpowers/specs scripts/ci/validate-docs.sh
|
|
git commit -m "docs: dev 및 CI 소유권 결정 기록"
|
|
```
|
|
|
|
---
|
|
|
|
## Task 6: Plan-level verification checkpoint
|
|
|
|
**Files:** No source changes expected.
|
|
|
|
**Step 1: Prove no live mutation was introduced by this plan**
|
|
|
|
Run:
|
|
|
|
```bash
|
|
rg -n 'kubectl[[:space:]]+(apply|delete|replace|patch)|helm[[:space:]]+(install|upgrade|uninstall)' tests scripts/ci scripts/lib
|
|
```
|
|
|
|
Expected: no new invocation in files created or modified by this plan. Existing task/bootstrap matches are handled by the next plan.
|
|
|
|
**Step 2: Run the complete plan contract**
|
|
|
|
Run:
|
|
|
|
```bash
|
|
bash tests/run.sh
|
|
VALIDATION_PROFILE=full bash scripts/ci/validate.sh
|
|
bash scripts/ci/validate-docs.sh
|
|
git diff --check
|
|
git status --short
|
|
```
|
|
|
|
Expected:
|
|
|
|
- tests and validation exit 0;
|
|
- every inventory entrypoint renders with Helm enabled;
|
|
- no active `lab` cluster or overlay path remains;
|
|
- `git diff --check` emits nothing;
|
|
- status contains no unrelated files.
|
|
|
|
**Step 3: Inspect commits**
|
|
|
|
```bash
|
|
git log --oneline --decorate -7
|
|
```
|
|
|
|
Confirm that each task is independently reviewable. Do not squash before the user reviews the phase.
|