docs: Phase 1 구현 계획 추가
This commit is contained in:
@@ -0,0 +1,703 @@
|
||||
# Project Infra Phase 1 validation and repository structure 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 validator changes and `superpowers:verification-before-completion` before reporting success.
|
||||
|
||||
**Goal:** Make repository-local validation deterministic, put scripts and presentation assets in their declared directory classes, normalize source modes, and remove misleading empty implementation leaves.
|
||||
|
||||
**Architecture:** `make validate` is the developer-friendly local contract and `make check` is the complete repository contract. Project tests and validators remain in this repository; workflow orchestration and authoritative tool provisioning remain owned by `cicd-platform`. Entrypoints live under `scripts/bin` or `scripts/ci`, shared code lives under `scripts/lib`, generated presentation artifacts are ignored, and empty IaC leaves are not represented as implemented environments.
|
||||
|
||||
**Tech Stack:** Make, Bash, Kustomize/Helm, kubeconform, kube-linter, ShellCheck, shfmt, gitleaks, yq 4.47.2, Python 3, python-pptx, Pillow, Git file modes.
|
||||
|
||||
## Global constraints
|
||||
|
||||
- Complete the dev GitOps and automation-safety plans first.
|
||||
- Read `docs/standards/infra/STYLE.md`, `scripts.md`, `kustomize.md`, and their approved examples before changing validation or examples.
|
||||
- Do not edit `.github/**`, `.gitea/**`, or `/home/donghyeon/workspace/desktop-server-git/cicd-platform`.
|
||||
- Treat `.mise.toml` only as a local developer convenience. Do not describe it as the authoritative CI lock.
|
||||
- Do not create a Terraform/OpenTofu root; deleting placeholder leaves does not choose an IaC engine.
|
||||
- Keep `docs/examples/infra/**` as the only approved manifest-example catalog.
|
||||
- Keep `.github/CODEOWNERS.example` unchanged until real organization/team identifiers are supplied.
|
||||
- Commit only task-scoped files and inspect the worktree before every commit.
|
||||
|
||||
## Dependency and public interfaces
|
||||
|
||||
- `scripts/bin/doctor.sh` is the user-facing tool diagnostic entrypoint.
|
||||
- `scripts/ci/validate-structure.sh` validates filesystem shape, sensitive file rules, source modes, shell syntax, and activated IaC syntax.
|
||||
- `scripts/ci/validate.sh` owns the project contract and sources `scripts/lib/kustomize.sh` for every render.
|
||||
- `VALIDATION_PROFILE=local` may skip optional heavyweight validators with an explicit warning; core render, test, structure, docs-YAML syntax, and path contracts never skip.
|
||||
- `VALIDATION_PROFILE=full` treats every declared validator as required.
|
||||
- `make validate` runs the local profile once. `make check` runs the full profile once and fails if a required tool is absent.
|
||||
- `validate_yaml_fences DOCS_ROOT` is sourceable from `scripts/ci/validate-docs.sh` for fixture tests.
|
||||
|
||||
---
|
||||
|
||||
## Task 1: Move repository entrypoints into their declared script classes
|
||||
|
||||
**Files:**
|
||||
|
||||
- Move: `scripts/doctor.sh` → `scripts/bin/doctor.sh`
|
||||
- Move: `scripts/validate.sh` → `scripts/ci/validate-structure.sh`
|
||||
- Modify: `scripts/bin/doctor.sh`
|
||||
- Modify: `scripts/ci/validate-structure.sh`
|
||||
- Modify: `Makefile`
|
||||
- Modify: `scripts/README.md`
|
||||
- Modify: `README.md`
|
||||
- Create: `tests/contracts/script-layout-test.sh`
|
||||
|
||||
**Step 1: Write the failing layout and entrypoint contract**
|
||||
|
||||
Assert:
|
||||
|
||||
```text
|
||||
scripts/doctor.sh is absent
|
||||
scripts/validate.sh is absent
|
||||
scripts/bin/doctor.sh exists and is executable
|
||||
scripts/ci/validate-structure.sh exists and is executable
|
||||
both moved files contain set -Eeuo pipefail and IFS=$'\n\t'
|
||||
both moved files define main and end through a main "$@" guard
|
||||
doctor defines usage and accepts -h/--help
|
||||
Makefile references only the moved paths
|
||||
make -n validate includes local project validation exactly once
|
||||
make -n check includes VALIDATION_PROFILE=full exactly once
|
||||
```
|
||||
|
||||
Run:
|
||||
|
||||
```bash
|
||||
bash tests/run.sh script-layout
|
||||
```
|
||||
|
||||
Expected: non-zero because both scripts still live at the `scripts/` root.
|
||||
|
||||
**Step 2: Move and refactor the scripts**
|
||||
|
||||
Use `git mv`. Both scripts must calculate the repository root from their new location:
|
||||
|
||||
```bash
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
REPO_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
|
||||
```
|
||||
|
||||
Wrap the current top-level validation flow in named functions and:
|
||||
|
||||
```bash
|
||||
main() {
|
||||
validate_required_structure
|
||||
validate_directory_names
|
||||
collect_sources
|
||||
validate_sensitive_sources
|
||||
validate_secret_manifests
|
||||
validate_replacement_tokens
|
||||
validate_source_modes
|
||||
validate_shell_syntax
|
||||
validate_kustomization_layout
|
||||
validate_local_helm_charts
|
||||
validate_activated_iac
|
||||
report_result
|
||||
}
|
||||
|
||||
if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then
|
||||
main "$@"
|
||||
fi
|
||||
```
|
||||
|
||||
Use these exact function names so the entrypoint contract can call them independently. Preserve existing checks; do not silently drop the Secret/SOPS, replacement-token, Helm, or IaC checks while refactoring.
|
||||
|
||||
Remove the Kustomize render loop from `validate-structure.sh`; deployable render ownership already lives in `scripts/ci/validate.sh` and rendering every catalog Kustomization is a duplicate network-heavy contract. Keep Kustomization path/type checks in structure validation, keep local `Chart.yaml` linting, and make `script-layout-test.sh` assert that `validate-structure.sh` contains neither `kustomize build` nor `kubectl kustomize`.
|
||||
|
||||
**Step 3: Separate Make local and full profiles**
|
||||
|
||||
The Make targets must have these exact dependencies and recipe commands:
|
||||
|
||||
- `doctor` runs `@./scripts/bin/doctor.sh`.
|
||||
- `validate-structure` runs `@./scripts/ci/validate-structure.sh`.
|
||||
- `validate-project` runs `@VALIDATION_PROFILE=local bash ./scripts/ci/validate.sh`.
|
||||
- `validate` depends on `validate-structure validate-project` and has no second recipe.
|
||||
- `check` depends on `validate-structure` and runs `@VALIDATION_PROFILE=full bash ./scripts/ci/validate.sh`.
|
||||
|
||||
Keep the existing help comments so `make help` remains useful.
|
||||
|
||||
**Step 4: Verify and commit**
|
||||
|
||||
Run:
|
||||
|
||||
```bash
|
||||
bash tests/run.sh script-layout
|
||||
bash -n scripts/bin/doctor.sh scripts/ci/validate-structure.sh
|
||||
make -n validate
|
||||
make -n check
|
||||
git diff --check
|
||||
```
|
||||
|
||||
Expected: all commands exit 0.
|
||||
|
||||
```bash
|
||||
git add scripts Makefile README.md tests/contracts/script-layout-test.sh
|
||||
git commit -m "refactor: 스크립트 entrypoint 위치 정규화"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Task 2: Remove false implementation leaves, fix copy examples, and normalize modes
|
||||
|
||||
**Files:**
|
||||
|
||||
- Delete: `infrastructure/components/compute/README.md`
|
||||
- Delete: `infrastructure/components/database/README.md`
|
||||
- Delete: `infrastructure/components/networking/README.md`
|
||||
- Delete: `infrastructure/components/storage/README.md`
|
||||
- Delete: `infrastructure/live/dev/cluster/README.md`
|
||||
- Delete: `infrastructure/live/staging/cluster/README.md`
|
||||
- Delete: `infrastructure/live/prod/cluster/README.md`
|
||||
- Modify: `infrastructure/components/README.md`
|
||||
- Modify: `infrastructure/live/README.md`
|
||||
- Modify: `README.md`
|
||||
- Modify: `docs/guides/getting-started.md`
|
||||
- Modify: `scripts/ci/validate-structure.sh`
|
||||
- Create: `tests/contracts/repository-shape-test.sh`
|
||||
- Change mode: every tracked `*.yaml` and `*.yml` source to `100644`
|
||||
|
||||
**Step 1: Write the failing shape and mode contract**
|
||||
|
||||
Assert:
|
||||
|
||||
```text
|
||||
the seven placeholder leaf directories listed above do not exist
|
||||
the three parent roots and all `_template` roots still exist
|
||||
tracked YAML/YML files have Git mode 100644
|
||||
tracked shell files under scripts have Git mode 100755
|
||||
no copy instruction uses `cp -R SOURCE/_template DEST`
|
||||
copy instructions create a destination then copy `SOURCE/_template/.` into it
|
||||
CODEOWNERS.example still exists
|
||||
```
|
||||
|
||||
Run:
|
||||
|
||||
```bash
|
||||
bash tests/run.sh repository-shape
|
||||
```
|
||||
|
||||
Expected: non-zero because placeholder leaves and thirteen executable YAML/value files exist.
|
||||
|
||||
**Step 2: Remove only the misleading leaves**
|
||||
|
||||
Delete the seven tracked README files and their now-empty directories. Update the parent READMEs to state:
|
||||
|
||||
- `components/<unit>` exists only when a real reusable primitive is selected;
|
||||
- `live/<env>/<root>` exists only when an executable plan/apply root and backend decision exist;
|
||||
- the IaC engine/provider/backend/state choice remains a Phase 2 decision.
|
||||
|
||||
Do not remove `infrastructure/components/_template`, `infrastructure/live/_template`, parent README files, or `infrastructure/.iac-engine.example`.
|
||||
|
||||
**Step 3: Correct template copy commands**
|
||||
|
||||
For each README/getting-started example, use this pattern with its actual destination:
|
||||
|
||||
```bash
|
||||
mkdir -p infrastructure/live/dev/cluster
|
||||
cp -R infrastructure/live/_template/. infrastructure/live/dev/cluster/
|
||||
```
|
||||
|
||||
Apply the same `mkdir -p` plus `SOURCE/. DEST/` form to component, stack, app, platform, and cluster examples. Use `gitops/clusters/staging/main` for the new-cluster example so instructions never copy a template over the active `gitops/clusters/dev/main`. This behaves the same whether a new destination was just created or already exists and never creates a nested `_template` directory.
|
||||
|
||||
**Step 4: Normalize tracked source modes**
|
||||
|
||||
Use `chmod 0644` on every tracked Kubernetes YAML, Kustomization YAML, and Helm values YAML. In particular verify the moved VSO values file, registry base, secret-delivery base, and Vault base files identified by the review.
|
||||
|
||||
Add a structural check based on the Git index:
|
||||
|
||||
```bash
|
||||
while IFS= read -r -d '' record; do
|
||||
mode="${record%% *}"
|
||||
path="${record#*$'\t'}"
|
||||
case "$path" in
|
||||
*.yaml | *.yml)
|
||||
[[ "$mode" == "100644" ]] || fail "YAML source must be mode 0644: $path"
|
||||
;;
|
||||
scripts/*.sh)
|
||||
[[ "$mode" == "100755" ]] || fail "script must be executable: $path"
|
||||
;;
|
||||
esac
|
||||
done < <(git ls-files -s -z)
|
||||
```
|
||||
|
||||
Handle untracked files in the existing source collection separately with filesystem modes so the check also fails before a new file is added to Git.
|
||||
|
||||
**Step 5: Verify and commit**
|
||||
|
||||
Run:
|
||||
|
||||
```bash
|
||||
bash tests/run.sh repository-shape
|
||||
./scripts/ci/validate-structure.sh
|
||||
git ls-files -s '*.yaml' '*.yml' | awk '$1 != "100644" {print; bad=1} END {exit bad}'
|
||||
git diff --check
|
||||
```
|
||||
|
||||
Expected: all commands exit 0 and the mode query prints nothing.
|
||||
|
||||
```bash
|
||||
git add infrastructure README.md docs/guides/getting-started.md scripts/ci/validate-structure.sh tests/contracts/repository-shape-test.sh gitops
|
||||
git commit -m "refactor: 저장소 shape과 YAML mode 정규화"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Task 3: Enforce inventory, render, and source-of-truth contracts
|
||||
|
||||
**Files:**
|
||||
|
||||
- Modify: `scripts/ci/validate.sh`
|
||||
- Modify: `tests/kustomize-entrypoints.txt`
|
||||
- Create: `tests/contracts/entrypoint-inventory-test.sh`
|
||||
- Modify: `tests/README.md`
|
||||
|
||||
**Step 1: Write the failing inventory contract**
|
||||
|
||||
Derive actual dev entrypoints from these paths:
|
||||
|
||||
```text
|
||||
gitops/clusters/dev/main/namespaces/kustomization.yaml
|
||||
gitops/clusters/dev/main/all/kustomization.yaml
|
||||
gitops/clusters/dev/main/stages/*/kustomization.yaml
|
||||
```
|
||||
|
||||
Convert them to parent-directory paths, sort them, and compare byte-for-byte with the sorted non-comment inventory. Assert additionally:
|
||||
|
||||
```text
|
||||
no cluster Kustomization outside gitops/clusters/_template imports a `_template` path
|
||||
no scripts/bin or scripts/tasks file references the cluster `all` entrypoint
|
||||
no deployable rendered output contains example.com/environment: lab
|
||||
every inventory entry renders only through kustomize_render
|
||||
every render has no replace-in-overlay or __REPLACE_ME_* token
|
||||
the existing ForwardAuth, Keycloak admin, and operator render contracts run from the full test runner
|
||||
```
|
||||
|
||||
Run:
|
||||
|
||||
```bash
|
||||
bash tests/run.sh entrypoint-inventory
|
||||
```
|
||||
|
||||
Expected: non-zero if the inventory is stale or if the current validator still has a second render implementation.
|
||||
|
||||
**Step 2: Add deterministic inventory validation**
|
||||
|
||||
Add `validate_entrypoint_inventory` before manifest rendering in `scripts/ci/validate.sh`. It must use temporary sorted files and `diff -u`; on mismatch, print the unified diff and fail the validation group.
|
||||
|
||||
Reject template imports with `rg` over cluster Kustomization source and reject apply-code references to `/all` with `rg` over `scripts/bin` and `scripts/tasks`. Exclude comments only when the parser proves the line is a comment; do not broadly suppress files.
|
||||
|
||||
**Step 3: Run contract tests from project validation**
|
||||
|
||||
Add:
|
||||
|
||||
```bash
|
||||
validate_contract_tests() {
|
||||
bash "$REPO_ROOT/tests/run.sh"
|
||||
}
|
||||
```
|
||||
|
||||
Call it once from `main`. Do not run tests a second time through Make dependencies.
|
||||
|
||||
**Step 4: Make full-profile tool requirements explicit**
|
||||
|
||||
In full mode require:
|
||||
|
||||
```text
|
||||
kustomize
|
||||
helm
|
||||
kubeconform
|
||||
kube-linter
|
||||
shellcheck
|
||||
shfmt
|
||||
gitleaks
|
||||
yq
|
||||
rg
|
||||
```
|
||||
|
||||
In local mode, Kustomize/Helm rendering, Bash contract tests, `rg`, and `yq` remain core and cannot skip. kubeconform, kube-linter, ShellCheck, shfmt, and gitleaks may skip only with a warning that names the missing tool.
|
||||
|
||||
**Step 5: Verify and commit**
|
||||
|
||||
Run:
|
||||
|
||||
```bash
|
||||
bash tests/run.sh entrypoint-inventory
|
||||
VALIDATION_PROFILE=local bash scripts/ci/validate.sh
|
||||
git diff --check
|
||||
```
|
||||
|
||||
Expected: all commands exit 0 and each contract test runs exactly once.
|
||||
|
||||
```bash
|
||||
git add scripts/ci/validate.sh tests/kustomize-entrypoints.txt tests/contracts/entrypoint-inventory-test.sh tests/README.md
|
||||
git commit -m "test: GitOps entrypoint 계약 강화"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Task 4: Validate every documentation YAML fence
|
||||
|
||||
**Files:**
|
||||
|
||||
- Modify: `.mise.toml`
|
||||
- Modify: `scripts/bin/doctor.sh`
|
||||
- Modify: `scripts/ci/validate-docs.sh`
|
||||
- Create: `tests/contracts/docs-yaml-test.sh`
|
||||
- Modify: Markdown files under `docs/**` only where a block is genuinely abbreviated, intentionally bad, or fails the approved example standards
|
||||
- Modify: `docs/standards/infra/STYLE.md` to document the example marker contract
|
||||
|
||||
**Step 1: Write fixture-driven failing tests**
|
||||
|
||||
Refactor `validate-docs.sh` so sourcing it does not execute `main`. The test sources it and calls `validate_yaml_fences` on temporary Markdown fixtures. Cover:
|
||||
|
||||
```text
|
||||
valid YAML fence succeeds
|
||||
syntactically invalid YAML fence fails even below a bad-example heading
|
||||
unclosed YAML fence fails
|
||||
normal complete Kubernetes resource invokes fake yq, kubeconform, and kube-linter
|
||||
`나쁜 예시`, `❌`, and case-insensitive `bad example` headings invoke yq but skip schema/policy
|
||||
an immediately preceding `<!-- infra-example: abbreviated -->` marker invokes yq but skips schema/policy
|
||||
a normal complete resource that fails kubeconform fails the docs gate
|
||||
a normal complete resource that fails kube-linter fails the docs gate
|
||||
an abbreviated marker cannot suppress YAML syntax failure
|
||||
```
|
||||
|
||||
Run:
|
||||
|
||||
```bash
|
||||
bash tests/run.sh docs-yaml
|
||||
```
|
||||
|
||||
Expected: non-zero because current docs validation does not parse fenced YAML.
|
||||
|
||||
**Step 2: Pin and diagnose the syntax parser**
|
||||
|
||||
Add this local convenience pin:
|
||||
|
||||
```toml
|
||||
yq = "4.47.2"
|
||||
```
|
||||
|
||||
Add `yq` to required doctor tools. In both local and full validation profiles, a missing yq is a hard error because syntax checking is a core docs contract. Document that `cicd-platform`, not `.mise.toml`, owns authoritative CI tool delivery.
|
||||
|
||||
**Step 3: Implement fence extraction and classification**
|
||||
|
||||
`validate_yaml_fences DOCS_ROOT` must read every tracked or present `*.md` file under the supplied root in sorted order and maintain:
|
||||
|
||||
```text
|
||||
current Markdown heading
|
||||
whether a YAML/YML fence is open
|
||||
source file and opening line
|
||||
whether the immediately preceding non-blank line is the abbreviated marker
|
||||
whether the current heading contains 나쁜 예시, ❌, or bad example
|
||||
```
|
||||
|
||||
For every closed fence:
|
||||
|
||||
1. write the exact block to a mode-`0600` temporary file;
|
||||
2. run `yq eval-all '.' BLOCK` unconditionally;
|
||||
3. classify it as a complete Kubernetes example only when it is not bad/abbreviated and every YAML document contains non-empty `apiVersion`, `kind`, and `metadata.name`;
|
||||
4. run kubeconform with the repository CRD catalog configuration for complete examples;
|
||||
5. run kube-linter with `.kube-linter.yaml` for complete examples;
|
||||
6. report `file:opening-line` on every failure.
|
||||
|
||||
Bad and abbreviated classifications skip only steps 4 and 5. They never skip syntax.
|
||||
|
||||
Add this exact marker contract to `STYLE.md`:
|
||||
|
||||
````markdown
|
||||
<!-- infra-example: abbreviated -->
|
||||
```yaml
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
```
|
||||
````
|
||||
|
||||
When documenting the marker inside a Markdown fence, use a four-backtick outer fence so the standard itself remains well formed.
|
||||
|
||||
**Step 4: Audit existing docs instead of blanket-suppressing them**
|
||||
|
||||
Run the new gate. For each failure:
|
||||
|
||||
- fix syntax in normal examples;
|
||||
- fix security/resource/probe defects in examples presented as approved;
|
||||
- add the abbreviated marker only when omitted fields are intentional prose;
|
||||
- rely on a bad-example heading only for genuinely rejected examples.
|
||||
|
||||
Do not mark all files or all standards as abbreviated. `docs/examples/infra/**` normal good examples must pass schema/policy when complete.
|
||||
|
||||
**Step 5: Verify and commit**
|
||||
|
||||
Run:
|
||||
|
||||
```bash
|
||||
bash tests/run.sh docs-yaml
|
||||
VALIDATION_PROFILE=full bash scripts/ci/validate-docs.sh
|
||||
git diff --check
|
||||
```
|
||||
|
||||
Expected: all commands exit 0; validation output reports YAML fence count and complete Kubernetes example count.
|
||||
|
||||
```bash
|
||||
git add .mise.toml scripts/bin/doctor.sh scripts/ci/validate-docs.sh tests/contracts/docs-yaml-test.sh docs
|
||||
git commit -m "test: 문서 YAML 예시 검증 추가"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Task 5: Move and make the presentation source reproducible
|
||||
|
||||
**Files:**
|
||||
|
||||
- Move: `presentation/diagrams/**` → `docs/presentation/diagrams/**`
|
||||
- Move: `presentation/exports/**` → `docs/presentation/exports/**`
|
||||
- Move: `presentation/scripts/build_pptx.py` → `docs/presentation/scripts/build_pptx.py`
|
||||
- Delete after move: `docs/presentation/build/deck.pptx`
|
||||
- Create: `docs/presentation/README.md`
|
||||
- Create: `docs/presentation/requirements.txt`
|
||||
- Modify: `docs/presentation/scripts/build_pptx.py`
|
||||
- Modify: `.gitignore`
|
||||
- Create: `tests/contracts/presentation-layout-test.sh`
|
||||
|
||||
**Step 1: Write the failing layout/reproducibility contract**
|
||||
|
||||
Assert:
|
||||
|
||||
```text
|
||||
root presentation directory is absent
|
||||
docs/presentation exists
|
||||
docs/presentation/build is ignored
|
||||
no PPTX file is tracked under docs/presentation
|
||||
build_pptx.py contains no /home/ path
|
||||
ROOT is derived from Path(__file__).resolve().parents[1]
|
||||
requirements pin python-pptx and Pillow with ==
|
||||
every PNG path referenced by build_pptx.py exists under exports
|
||||
the script compiles with python3 -m py_compile
|
||||
```
|
||||
|
||||
Run:
|
||||
|
||||
```bash
|
||||
bash tests/run.sh presentation-layout
|
||||
```
|
||||
|
||||
Expected: non-zero because the material is at repository root and the Python script hardcodes an absolute path.
|
||||
|
||||
**Step 2: Move source assets and remove the generated deck**
|
||||
|
||||
Use `git mv presentation docs/presentation`, then remove the tracked `docs/presentation/build/deck.pptx`. Add:
|
||||
|
||||
```gitignore
|
||||
docs/presentation/build/
|
||||
```
|
||||
|
||||
Keep every Draw.io source and every PNG referenced by the Python script. Do not delete source inputs merely to reduce repository size.
|
||||
|
||||
**Step 3: Make paths dynamic and dependencies explicit**
|
||||
|
||||
Replace the hardcoded root with:
|
||||
|
||||
```python
|
||||
ROOT = Path(__file__).resolve().parents[1]
|
||||
EXPORTS = ROOT / "exports"
|
||||
OUT = ROOT / "build" / "deck.pptx"
|
||||
```
|
||||
|
||||
Use this `requirements.txt`:
|
||||
|
||||
```text
|
||||
python-pptx==1.0.2
|
||||
Pillow==11.3.0
|
||||
```
|
||||
|
||||
The README must contain commands that work from any checkout:
|
||||
|
||||
```bash
|
||||
python3 -m venv docs/presentation/.venv
|
||||
docs/presentation/.venv/bin/pip install --requirement docs/presentation/requirements.txt
|
||||
docs/presentation/.venv/bin/python docs/presentation/scripts/build_pptx.py
|
||||
```
|
||||
|
||||
Explain that `build/deck.pptx` is generated and untracked.
|
||||
|
||||
**Step 4: Rebuild once in an isolated environment**
|
||||
|
||||
Create a temporary virtual environment outside the repository, install the pinned requirements, run the script, and validate the generated ZIP container:
|
||||
|
||||
```bash
|
||||
PRESENTATION_VENV="$(mktemp -d -t project-infra-presentation.XXXXXX)"
|
||||
python3 -m venv "$PRESENTATION_VENV"
|
||||
"$PRESENTATION_VENV/bin/pip" install --requirement docs/presentation/requirements.txt
|
||||
"$PRESENTATION_VENV/bin/python" docs/presentation/scripts/build_pptx.py
|
||||
"$PRESENTATION_VENV/bin/python" -m zipfile -t docs/presentation/build/deck.pptx
|
||||
```
|
||||
|
||||
If dependency download is unavailable, request network approval or use an already-populated package cache; do not claim reproducibility without a successful build. The generated deck remains ignored and is not committed.
|
||||
|
||||
**Step 5: Verify and commit**
|
||||
|
||||
Run:
|
||||
|
||||
```bash
|
||||
bash tests/run.sh presentation-layout
|
||||
git check-ignore docs/presentation/build/deck.pptx
|
||||
git ls-files 'docs/presentation/*.pptx' 'docs/presentation/**/*.pptx'
|
||||
git diff --check
|
||||
```
|
||||
|
||||
Expected: tests and ignore check exit 0; `git ls-files` prints nothing.
|
||||
|
||||
```bash
|
||||
git add .gitignore docs/presentation tests/contracts/presentation-layout-test.sh
|
||||
git commit -m "docs: presentation source를 문서 트리로 이동"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Task 6: Finalize Make validation semantics and repository documentation
|
||||
|
||||
**Files:**
|
||||
|
||||
- Modify: `Makefile`
|
||||
- Modify: `README.md`
|
||||
- Modify: `docs/validation-report.md`
|
||||
- Modify: `docs/architecture/repository-structure.md`
|
||||
- Modify: `scripts/README.md`
|
||||
- Modify: `tests/README.md`
|
||||
- Modify: `.mise.toml` only if tool names changed during implementation
|
||||
- Create: `tests/contracts/make-contract-test.sh`
|
||||
|
||||
**Step 1: Write the failing Make contract**
|
||||
|
||||
Use temporary fake validators to prove:
|
||||
|
||||
```text
|
||||
make validate uses VALIDATION_PROFILE=local
|
||||
make validate emits a warning and succeeds when an optional validator is absent
|
||||
make check uses VALIDATION_PROFILE=full
|
||||
make check fails when any declared full validator is absent
|
||||
make check runs structure, contracts, manifests, docs, shell, and secret groups once each
|
||||
neither target invokes or references a workflow file
|
||||
documentation states that cicd-platform owns authoritative CI execution and tool delivery
|
||||
documentation does not claim delivery-platform.yaml is already active for project-infra
|
||||
```
|
||||
|
||||
Run:
|
||||
|
||||
```bash
|
||||
bash tests/run.sh make-contract
|
||||
```
|
||||
|
||||
Expected: non-zero until final Make and validation reporting are aligned.
|
||||
|
||||
**Step 2: Update validation documentation with exact ownership**
|
||||
|
||||
Document these commands:
|
||||
|
||||
```bash
|
||||
make doctor
|
||||
make validate
|
||||
make check
|
||||
```
|
||||
|
||||
State explicitly:
|
||||
|
||||
- `make validate` is the friendly local profile;
|
||||
- `make check` is the complete repository contract and fails on missing tools;
|
||||
- `.mise.toml` helps developers reproduce the expected tool set locally;
|
||||
- the sibling `cicd-platform` repository owns triggers, runners, authoritative versions, evidence publication, and future consumer onboarding;
|
||||
- current project workflow definitions are transitional and were not modified by Phase 1.
|
||||
|
||||
Update `docs/validation-report.md` with the final gate list and the date of the latest local run. Do not record a passing result until Task 7 produces it.
|
||||
|
||||
**Step 3: Verify and commit**
|
||||
|
||||
Run:
|
||||
|
||||
```bash
|
||||
bash tests/run.sh make-contract
|
||||
make validate
|
||||
git diff --check
|
||||
```
|
||||
|
||||
Expected: tests and local validation exit 0.
|
||||
|
||||
```bash
|
||||
git add Makefile README.md docs/validation-report.md docs/architecture/repository-structure.md scripts/README.md tests/README.md .mise.toml tests/contracts/make-contract-test.sh
|
||||
git commit -m "docs: 로컬 검증과 중앙 CI 경계 명확화"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Task 7: Full Phase 1 verification and review handoff
|
||||
|
||||
**Files:**
|
||||
|
||||
- Modify: `docs/validation-report.md` only with observed results
|
||||
|
||||
**Step 1: Confirm no forbidden workflow or sibling-repository change**
|
||||
|
||||
Run:
|
||||
|
||||
```bash
|
||||
git diff --name-only d0d90ea..HEAD -- .github .gitea
|
||||
git -C /home/donghyeon/workspace/desktop-server-git/cicd-platform status --short
|
||||
```
|
||||
|
||||
Expected: the first command prints nothing. The second is read-only evidence; do not modify or clean any pre-existing sibling worktree changes.
|
||||
|
||||
**Step 2: Run the complete repository contract**
|
||||
|
||||
Run:
|
||||
|
||||
```bash
|
||||
make check
|
||||
```
|
||||
|
||||
Expected: exit 0 with no skipped validator. Capture the group summary, not secrets or rendered Secret data, in `docs/validation-report.md`.
|
||||
|
||||
**Step 3: Run acceptance searches**
|
||||
|
||||
```bash
|
||||
find gitops/clusters gitops/apps gitops/platform gitops/policies -type d -name lab -print
|
||||
rg -n 'example.com/environment:[[:space:]]*lab' gitops
|
||||
rg -n 'vault login|\.vault-token|vault_exec_sh|vault_login_root_from_keyfile' scripts bootstrap
|
||||
rg -n 'helm[[:space:]]+(install|upgrade|uninstall)' scripts
|
||||
git ls-files -s '*.yaml' '*.yml' | awk '$1 != "100644" {print; bad=1} END {exit bad}'
|
||||
git ls-files 'docs/presentation/*.pptx' 'docs/presentation/**/*.pptx'
|
||||
git diff --check
|
||||
```
|
||||
|
||||
Expected: every search prints nothing and every command exits 0.
|
||||
|
||||
**Step 4: Review the final diff by ownership area**
|
||||
|
||||
Run:
|
||||
|
||||
```bash
|
||||
git diff --stat d0d90ea..HEAD
|
||||
git diff --name-status d0d90ea..HEAD
|
||||
git status --short --branch
|
||||
```
|
||||
|
||||
Review separately:
|
||||
|
||||
1. dev path/labels and operator GitOps;
|
||||
2. ForwardAuth/Keycloak rendered security;
|
||||
3. context/Vault/bootstrap/teardown safety;
|
||||
4. validation and docs;
|
||||
5. repository moves, deletes, and file modes.
|
||||
|
||||
Confirm that no live-cluster mutation was performed during implementation.
|
||||
|
||||
**Step 5: Record evidence and commit**
|
||||
|
||||
Update `docs/validation-report.md` only with the commands actually run, their observed status, and any environment prerequisites. Then:
|
||||
|
||||
```bash
|
||||
git add docs/validation-report.md
|
||||
git commit -m "docs: Phase 1 검증 결과 기록"
|
||||
```
|
||||
|
||||
Do not merge, push, or start Phase 2 without a separate user decision.
|
||||
Reference in New Issue
Block a user