# Helm Diff Engine 설계 ## 1. 개요 두 버전의 Helm Chart를 비교하여 **Structured Diff JSON**을 생성하는 컴포넌트. 모든 출력은 deterministic하며 LLM을 사용하지 않는다. --- ## 2. Chart Version Detector ### 역할 새로운 Helm Chart 버전 출시를 감지한다. ### 감지 방법 | 방법 | 설명 | 적합 대상 | |------|------|---------| | **Repo 디렉토리 스캔** | `manifests/helm//` 하위 버전 디렉토리 변화를 감지 | dip-catalog 구조 | | Git diff 기반 감지 | 최신 커밋에서 추가된 `/` 디렉토리 파악 | dip-catalog 구조 | | Helm repo `index.yaml` 주기 스캔 | 등록된 repo의 index 파일 직접 파싱 | 외부/사내 Helm repo | | ArtifactHub API 조회 | `https://artifacthub.io/api/v1/packages/helm/{org}/{chart}` | 공개 chart | | GitHub Release Webhook | 차트 소스 저장소의 release 이벤트 구독 | GitHub 기반 차트 | | Cron 기반 스케줄링 | 위 방법들을 주기적으로 실행 | 공통 | ### 출력 ```json { "chart": "airflow", "repo": "apache", "current_version": "1.2.3", "latest_version": "1.3.0", "detected_at": "2025-01-01T00:00:00Z" } ``` ### dip-catalog 차트 업데이트 흐름 (버전 디렉토리 유지) 신규 버전이 감지되면 dip-catalog 구조에 맞춰 **버전 디렉토리를 추가**한다. 기존 버전 디렉토리는 유지한다. ``` 1) helm pull / --version # 최신 차트 다운로드 2) tar xzf -.tgz # 압축 해제 3) manifests/helm/// 로 이동 # 버전 디렉토리 생성 4) chart_updater: 이전 버전 디렉토리에서 파일 복사 - custom-values.yaml → 그대로 복사 - CUSTOM-README.md → 그대로 복사 (배포 관련 내용 유지) - BUILD-README.md → 복사 + 버전 번호 치환 (from_version → to_version) 5) generate_upgrade_doc → CUSTOM-README.md에 업그레이드 주의사항 섹션 추가 (항상 실행) ``` --- ## 3. Helm Diff Engine ### 입력 ```json { "chart": "airflow", "from_version": "1.2.3", "to_version": "1.3.0", "values_override": {}, "chart_path": "manifests/helm/airflow/1.3.0" } ``` > dip-catalog 구조에서는 `chart_path`를 우선 사용한다. ### 처리 단계 ``` 1. (repo 구조) helm pull / --version → chart_old/ 2. (repo 구조) helm pull / --version → chart_new/ 1'. (dip-catalog) manifests/helm/// 복사 → chart_old/ 2'. (dip-catalog) manifests/helm/// 복사 → chart_new/ 3. values.yaml 비교 → Values Diff 4. helm template 결과 비교 → Template Diff 5. CRD schema 비교 → CRD Diff 6. Chart.yaml 비교 → Dependency Diff 7. 결과 병합 → Structured Diff JSON ``` ### helm template 표준 옵션 재현성을 위해 아래 옵션을 고정한다. ``` helm template \ --values values_override.yaml \ --include-crds \ --kube-version \ --api-versions ``` > `target_k8s_version`과 `api-versions`는 환경별 설정값으로 관리한다. > dip-catalog의 경우 `custom-values.yaml`이 존재하면 `values_override` 기본값으로 적용한다. ### 에러 처리 | 상황 | 대응 | |------|------| | helm pull 실패 | 재시도 3회 → 실패 시 알림 후 중단 | | chart 미존재 | 로그 기록 + 스킵 | | helm template 렌더링 오류 | 오류 내용 JSON에 포함, partial diff 생성 | | 네트워크 타임아웃 | 60s timeout 설정, 재시도 | --- ## 4. Values Diff 설계 ### 비교 항목 - `added`: 신규 버전에서 추가된 key - `removed`: 신규 버전에서 삭제된 key - `changed`: default 값이 변경된 key - `type_changed`: 값의 타입이 변경된 key (string → int 등) ### 처리 방식 values.yaml을 **flat key** 형태로 변환 후 비교한다. - dip-catalog에서는 `custom-values.yaml`을 기본 values_override로 사용한다. ```yaml # 중첩 구조 예시 image: tag: 1.2.3 pullPolicy: IfNotPresent # flat key 변환 결과 image.tag: 1.2.3 image.pullPolicy: IfNotPresent ``` > **주의**: key 이동(rename)은 `removed` + `added`로 표현된다. 의미적 rename 감지는 기본 비활성화하며, 필요한 경우 heuristic(유사도 기반) 옵션으로 제공한다. ### 출력 ```json { "values": { "added": ["resources.limits.cpu", "resources.limits.memory"], "removed": ["ingress.enabled"], "changed": { "image.tag": { "old": "1.2.3", "new": "1.3.0" }, "replicaCount": { "old": 1, "new": 2 } }, "type_changed": [ { "key": "workers.replicas", "old_type": "string", "new_type": "integer" } ] } } ``` --- ## 5. Template Diff 설계 ### 처리 방식 ```bash helm template --values values_override.yaml > old.yaml helm template --values values_override.yaml > new.yaml ``` YAML을 **리소스 단위**로 분리 후 비교한다 (`kind` + `metadata.name` 기준). - `generateName`만 존재하는 리소스는 템플릿 파일명 + 순번으로 안정적 ID를 생성한다. - Cluster-scoped 리소스는 namespace를 무시한다. ### 비교 리소스 타입 | 리소스 | 분석 항목 | |--------|---------| | Deployment / StatefulSet | container image, env, resource limits, replicas | | Service | port, targetPort, type | | Ingress | rules, TLS, annotations | | ConfigMap | data key 추가/삭제/변경 | | CRD | 별도 CRD Diff로 처리 | | ServiceAccount | annotations | ### 출력 ```json { "templates": { "Deployment/airflow-scheduler": { "image_changed": true, "image": { "old": "apache/airflow:1.2.3", "new": "apache/airflow:1.3.0" }, "env_added": ["AIRFLOW__CORE__NEW_SETTING"], "env_removed": [], "resource_limits_changed": true }, "Service/airflow-webserver": { "port_changed": false } } } ``` --- ## 6. CRD Diff 설계 ### 비교 항목 | 항목 | 설명 | |------|------| | schema 변경 | OpenAPI v3 schema 필드 변경 | | required 필드 추가 | 기존 CR에 영향 | | field 제거 | 기존 CR의 해당 필드 무시됨 | | version 변경 | storage version 변경 시 migration 필요 | | webhook 변경 | conversion webhook 추가/제거 | ### 출력 ```json { "crd": { "AirflowCluster": { "changed": true, "breaking": true, "breaking_reasons": ["required field added: spec.executor"], "schema_changed": true, "version_changed": false, "fields_removed": [], "fields_added": ["spec.executor"], "required_fields_added": ["spec.executor"] } } } ``` --- ## 7. Dependency Diff 설계 Chart.yaml의 `dependencies` 블록 비교. ```json { "dependencies": { "added": ["redis"], "removed": [], "version_changed": { "postgresql": { "old": "12.1.0", "new": "13.0.0" } } } } ``` --- ## 8. 최종 Structured Diff JSON LLM Summarizer에 전달되는 통합 출력: ```json { "chart": "airflow", "from_version": "1.2.3", "to_version": "1.3.0", "generated_at": "2025-01-01T00:00:00Z", "values": { ... }, "templates": { ... }, "crd": { ... }, "dependencies": { ... }, "errors": [] } ``` `errors` 필드에는 렌더링 실패 등의 부분적 오류를 포함한다. LLM은 이를 참고하여 분석 범위를 명시해야 한다. --- ## 9. 관련 문서 - [02-breaking-change-rules.md](02-breaking-change-rules.md) — Breaking Change 판단 로직 - [04-skill-interface.md](04-skill-interface.md) — `helm_diff` Skill 인터페이스