# GitHub Actions CI/CD 파이프라인 구축 가이드

## 📋 목차
1. [개요](#개요)
2. [사전 준비사항](#사전-준비사항)
3. [GitHub 저장소 환경 구성](#github-저장소-환경-구성)
4. [디렉토리 구조](#디렉토리-구조)
5. [Kustomize 구조 설명](#kustomize-구조-설명)
6. [GitHub Actions 워크플로우](#github-actions-워크플로우)
7. [배포 방법](#배포-방법)
8. [롤백 방법](#롤백-방법)
9. [SonarQube 설정](#sonarqube-설정)
10. [트러블슈팅](#트러블슈팅)

---

## 개요

HGZero 프로젝트의 백엔드 서비스를 위한 GitHub Actions 기반 CI/CD 파이프라인입니다.

### 주요 기능
- ✅ Gradle 기반 빌드 및 테스트
- ✅ SonarQube 코드 품질 분석 (선택적)
- ✅ Azure Container Registry에 Docker 이미지 빌드 및 푸시
- ✅ Kustomize를 사용한 환경별(dev/staging/prod) 배포
- ✅ AKS 클러스터 자동 배포

### 지원 서비스
- **user**: 사용자 관리 서비스
- **meeting**: 회의 관리 서비스
- **stt**: 음성 인식 서비스
- **ai**: AI 처리 서비스
- **notification**: 알림 서비스

---

## 사전 준비사항

### 1. 프로젝트 정보
- **시스템명**: hgzero
- **ACR 이름**: acrdigitalgarage02
- **리소스 그룹**: rg-digitalgarage-02
- **AKS 클러스터**: aks-digitalgarage-02
- **네임스페이스**: hgzero
- **JDK 버전**: 21

### 2. 필수 도구
- Git
- kubectl
- Azure CLI
- Kustomize (자동 설치됨)

---

## GitHub 저장소 환경 구성

### 1. Repository Secrets 설정

`Repository Settings > Secrets and variables > Actions > Repository secrets`에 다음 항목을 등록하세요:

#### Azure 인증 정보
```json
AZURE_CREDENTIALS:
{
  "clientId": "{클라이언트ID}",
  "clientSecret": "{클라이언트시크릿}",
  "subscriptionId": "{구독ID}",
  "tenantId": "{테넌트ID}"
}
```

**예시:**
```json
{
  "clientId": "5e4b5b41-7208-48b7-b821-d6d5acf50ecf",
  "clientSecret": "ldu8Q~GQEzFYU.dJX7_QsahR7n7C2xqkIM6hqbV8",
  "subscriptionId": "2513dd36-7978-48e3-9a7c-b221d4874f66",
  "tenantId": "4f0a3bfd-1156-4cce-8dc2-a049a13dba23"
}
```

#### ACR Credentials

ACR Credential을 확인하려면:
```bash
az acr credential show --name acrdigitalgarage02
```

등록할 Secrets:
```
ACR_USERNAME: acrdigitalgarage02
ACR_PASSWORD: {ACR 패스워드}
```

#### SonarQube 설정

**SONAR_HOST_URL 확인:**
```bash
kubectl get svc -n sonarqube
```
출력된 External IP를 사용하여 `http://{External IP}` 형식으로 설정

**SONAR_TOKEN 생성:**
1. SonarQube에 로그인 (기본: admin/admin)
2. 우측 상단 'Administrator' > My Account 클릭
3. Security 탭 선택 후 토큰 생성

등록할 Secrets:
```
SONAR_TOKEN: {SonarQube 토큰}
SONAR_HOST_URL: http://{External IP}
```

#### Docker Hub (Rate Limit 해결용)

**패스워드 생성:**
1. [Docker Hub](https://hub.docker.com) 로그인
2. 우측 상단 프로필 아이콘 > Account Settings
3. 좌측 메뉴 'Personal Access Tokens' 클릭하여 생성

등록할 Secrets:
```
DOCKERHUB_USERNAME: {Docker Hub 사용자명}
DOCKERHUB_PASSWORD: {Docker Hub 패스워드 또는 토큰}
```

### 2. Repository Variables 설정

`Repository Settings > Secrets and variables > Actions > Variables > Repository variables`에 등록:

```
ENVIRONMENT: dev
SKIP_SONARQUBE: true
```

---

## 디렉토리 구조

```
.github/
├── workflows/
│   └── backend-cicd.yaml              # GitHub Actions 워크플로우
├── kustomize/
│   ├── base/                          # 기본 Kubernetes 매니페스트
│   │   ├── common/                    # 공통 리소스
│   │   │   ├── cm-common.yaml
│   │   │   ├── secret-common.yaml
│   │   │   ├── secret-imagepull.yaml
│   │   │   └── ingress.yaml
│   │   ├── user/                      # User 서비스
│   │   │   ├── deployment.yaml
│   │   │   ├── service.yaml
│   │   │   └── secret-user.yaml
│   │   ├── meeting/                   # Meeting 서비스
│   │   ├── stt/                       # STT 서비스
│   │   ├── ai/                        # AI 서비스
│   │   ├── notification/              # Notification 서비스
│   │   └── kustomization.yaml
│   └── overlays/                      # 환경별 오버레이
│       ├── dev/                       # 개발 환경
│       │   ├── kustomization.yaml
│       │   ├── cm-common-patch.yaml
│       │   ├── secret-common-patch.yaml
│       │   ├── ingress-patch.yaml
│       │   ├── deployment-{service}-patch.yaml
│       │   └── secret-{service}-patch.yaml
│       ├── staging/                   # 스테이징 환경
│       └── prod/                      # 프로덕션 환경
├── config/                            # 환경별 설정
│   ├── deploy_env_vars_dev
│   ├── deploy_env_vars_staging
│   └── deploy_env_vars_prod
└── scripts/
    └── deploy-actions.sh              # 수동 배포 스크립트
```

---

## Kustomize 구조 설명

### Base 구조

Base는 모든 환경에서 공통으로 사용되는 기본 매니페스트입니다.

**주요 리소스:**
- **ConfigMap (cm-common)**: 환경 변수, 프로파일 설정
- **Secret (secret-common)**: JWT 시크릿, Redis 패스워드
- **Ingress**: API 라우팅 규칙
- **Deployment**: 각 서비스별 배포 설정
- **Service**: 각 서비스별 ClusterIP 서비스
- **Secret**: 각 서비스별 데이터베이스 연결 정보

### Overlay 구조

각 환경(dev/staging/prod)별로 Base를 오버라이드합니다.

#### DEV 환경
- **Replicas**: 1
- **Resources**: CPU 256m-1024m, Memory 256Mi-1024Mi
- **Profile**: dev
- **DDL**: update
- **Log Level**: DEBUG
- **Image Tag**: dev-{timestamp}

#### STAGING 환경
- **Replicas**: 2
- **Resources**: CPU 512m-2048m, Memory 512Mi-2048Mi
- **Profile**: staging
- **DDL**: validate
- **Log Level**: INFO
- **Image Tag**: staging-{timestamp}
- **SSL**: Enabled

#### PROD 환경
- **Replicas**: 3
- **Resources**: CPU 1024m-4096m, Memory 1024Mi-4096Mi
- **Profile**: prod
- **DDL**: validate
- **Log Level**: WARN
- **JWT Expiration**: 짧게 설정 (보안 강화)
- **Image Tag**: prod-{timestamp}
- **SSL**: Enabled

---

## GitHub Actions 워크플로우

### 트리거 조건

1. **Push 이벤트**:
   - 브랜치: `main`, `develop`
   - 경로: 서비스 코드 변경 시 (`user/**`, `meeting/**` 등)

2. **Pull Request**:
   - 대상 브랜치: `main`

3. **수동 실행 (workflow_dispatch)**:
   - Environment 선택: dev/staging/prod
   - SonarQube 분석 스킵 선택: true/false

### 워크플로우 단계

#### 1. Build Job
1. 소스코드 체크아웃
2. JDK 21 설정
3. 환경 결정 (input 또는 기본값 dev)
4. Gradle 빌드 (테스트 제외)
5. SonarQube 분석 (선택적)
6. 빌드 아티팩트 업로드
7. 이미지 태그 생성 (타임스탬프 기반)

#### 2. Release Job
1. 빌드 아티팩트 다운로드
2. Docker Buildx 설정
3. Docker Hub 로그인 (Rate Limit 방지)
4. ACR 로그인
5. 각 서비스별 Docker 이미지 빌드 및 푸시

#### 3. Deploy Job
1. Azure CLI 설치 및 로그인
2. kubectl 설정
3. AKS Credentials 가져오기
4. 네임스페이스 생성
5. Kustomize 설치
6. 이미지 태그 업데이트
7. 매니페스트 적용
8. Deployment Ready 대기

---

## 배포 방법

### 1. 자동 배포 (Push/PR)

코드를 `main` 또는 `develop` 브랜치에 push하면 자동으로 dev 환경에 배포됩니다.

```bash
git add .
git commit -m "feat: 새로운 기능 추가"
git push origin develop
```

### 2. 수동 배포 (GitHub Actions UI)

1. GitHub Repository > Actions 탭 이동
2. "Backend Services CI/CD" 워크플로우 선택
3. "Run workflow" 버튼 클릭
4. 환경 선택 (dev/staging/prod)
5. SonarQube 분석 스킵 여부 선택
6. "Run workflow" 실행

### 3. 로컬에서 수동 배포

```bash
# 스크립트 실행 권한 확인
chmod +x .github/scripts/deploy-actions.sh

# DEV 환경에 배포 (기본)
./.github/scripts/deploy-actions.sh dev latest

# STAGING 환경에 특정 이미지 태그로 배포
./.github/scripts/deploy-actions.sh staging 20250127120000

# PROD 환경에 배포
./.github/scripts/deploy-actions.sh prod 20250127120000
```

---

## 롤백 방법

### 1. GitHub Actions를 통한 롤백

1. GitHub > Actions > 성공한 이전 워크플로우 선택
2. "Re-run all jobs" 클릭
3. 이전 버전으로 재배포됨

### 2. kubectl을 이용한 롤백

```bash
# 특정 Revision으로 롤백
kubectl rollout undo deployment/user -n hgzero --to-revision=2

# 이전 버전으로 롤백
kubectl rollout undo deployment/user -n hgzero

# 롤백 상태 확인
kubectl rollout status deployment/user -n hgzero

# Rollout 히스토리 확인
kubectl rollout history deployment/user -n hgzero
```

### 3. 수동 스크립트를 이용한 롤백

```bash
# 이전 안정 버전의 이미지 태그로 배포
./.github/scripts/deploy-actions.sh dev 20250126110000
```

---

## SonarQube 설정

### 프로젝트 생성

각 서비스별로 SonarQube 프로젝트를 생성하세요:
- hgzero-user-dev
- hgzero-meeting-dev
- hgzero-stt-dev
- hgzero-ai-dev
- hgzero-notification-dev

### Quality Gate 설정

기본 Quality Gate 설정:
- **Coverage**: >= 80%
- **Duplicated Lines**: <= 3%
- **Maintainability Rating**: <= A
- **Reliability Rating**: <= A
- **Security Rating**: <= A

### Gradle 설정 (이미 구성됨)

```gradle
// build.gradle
plugins {
    id 'org.sonarqube' version '4.0.0.2929'
    id 'jacoco'
}

sonarqube {
    properties {
        property "sonar.projectKey", "hgzero-${project.name}"
        property "sonar.projectName", "hgzero-${project.name}"
    }
}

jacocoTestReport {
    reports {
        xml.enabled true
    }
}
```

---

## 트러블슈팅

### 1. 이미지 Pull 실패

**증상**: `ImagePullBackOff` 또는 `ErrImagePull`

**해결 방법**:
```bash
# ACR 로그인 테스트
az acr login --name acrdigitalgarage02

# Image Pull Secret 재생성
kubectl delete secret acr-secret -n hgzero
kubectl create secret docker-registry acr-secret \
  --docker-server=acrdigitalgarage02.azurecr.io \
  --docker-username=acrdigitalgarage02 \
  --docker-password={ACR_PASSWORD} \
  -n hgzero
```

### 2. Deployment 타임아웃

**증상**: `deployment "user" exceeded its progress deadline`

**해결 방법**:
```bash
# Pod 상태 확인
kubectl get pods -n hgzero

# Pod 로그 확인
kubectl logs -n hgzero {pod-name}

# Events 확인
kubectl describe pod -n hgzero {pod-name}
```

### 3. Health Check 실패

**증상**: Deployment가 Ready 상태로 전환되지 않음

**해결 방법**:
```bash
# Actuator health 엔드포인트 확인
kubectl exec -n hgzero {pod-name} -- curl http://localhost:8080/actuator/health

# 애플리케이션 로그 확인
kubectl logs -n hgzero {pod-name} -f
```

### 4. Kustomize 빌드 오류

**증상**: `kustomize build` 실패

**해결 방법**:
```bash
# 로컬에서 Kustomize 검증
kubectl kustomize .github/kustomize/overlays/dev

# YAML 문법 검증
yamllint .github/kustomize/overlays/dev/*.yaml
```

### 5. SonarQube 연결 실패

**증상**: SonarQube Analysis 단계에서 연결 오류

**해결 방법**:
1. SONAR_HOST_URL이 올바른지 확인
2. SONAR_TOKEN이 유효한지 확인
3. SonarQube 서비스 상태 확인:
   ```bash
   kubectl get pods -n sonarqube
   kubectl logs -n sonarqube {sonarqube-pod}
   ```

### 6. 환경 변수 로드 실패

**증상**: 환경 설정 파일을 찾을 수 없음

**해결 방법**:
```bash
# 파일 존재 확인
ls -la .github/config/

# 파일 내용 확인
cat .github/config/deploy_env_vars_dev
```

---

## 참고 자료

- [Kustomize 공식 문서](https://kustomize.io/)
- [GitHub Actions 문서](https://docs.github.com/en/actions)
- [Azure Container Registry 문서](https://docs.microsoft.com/en-us/azure/container-registry/)
- [AKS 문서](https://docs.microsoft.com/en-us/azure/aks/)
- [SonarQube 문서](https://docs.sonarqube.org/)

---

## 문의 및 지원

문제가 발생하거나 질문이 있으시면:
1. GitHub Issues에 등록
2. DevOps 팀에 문의 (송주영)
3. Slack #devops 채널

---

**작성일**: 2025-01-27
**작성자**: DevOps Team (주영)
**버전**: 1.0.0
