# πŸš€ Quant Engine CI/CD Pipeline **버전**: v9 Hardening Release **CI/CD μ‹œμŠ€ν…œ**: Gitea Actions **배포 λŒ€μƒ**: 178.104.200.7 (production) **배포 브랜치**: `main` --- ## πŸ“‹ νŒŒμ΄ν”„λΌμΈ ꡬ쑰 ``` β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ 1. Code Push to main Branch β”‚ β”‚ (λ˜λŠ” workflow_dispatch μˆ˜λ™ μ‹€ν–‰) β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ↓ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ CI: build-and-test β”‚ β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ β”‚ βœ“ Checkout code β”‚ β”‚ βœ“ Setup .NET 10 β”‚ β”‚ βœ“ Run validations β”‚ β”‚ βœ“ Restore deps β”‚ β”‚ βœ“ Build Release β”‚ β”‚ βœ“ Run unit tests β”‚ β”‚ βœ“ Publish package β”‚ β”‚ βœ“ Create archive β”‚ β”‚ βœ“ Upload artifact β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ (성곡 μ‹œ) ↓ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ CD: deploy-to-prod β”‚ β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ β”‚ βœ“ Download artifact β”‚ β”‚ βœ“ Setup SSH β”‚ β”‚ βœ“ Create backup β”‚ β”‚ βœ“ Deploy package β”‚ β”‚ βœ“ Extract/install β”‚ β”‚ βœ“ Restart services β”‚ β”‚ βœ“ Health check β”‚ β”‚ βœ“ Verify deployment β”‚ β”‚ βœ“ Generate report β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ (성곡 μ‹œ) ↓ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ Post-Deployment β”‚ β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ β”‚ βœ“ Performance check β”‚ β”‚ βœ“ Create checklist β”‚ β”‚ βœ“ Notify (Slack) β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ``` --- ## πŸ”„ μ›Œν¬ν”Œλ‘œμš° 상세 ### Step 1: CI Build and Test **파일**: `.gitea/workflows/ci.yml` (κΈ°μ‘΄) **μ‹€ν–‰ 쑰건**: `push main` λ˜λŠ” `pull_request main` ```yaml # μžλ™ μ‹€ν–‰ 트리거 on: push: branches: [ main ] pull_request: branches: [ main ] # 검증 ν•­λͺ© - Python spec validation - Formula registry validation - Golden case coverage - Harness coverage audit - Qualitative sell strategy validation ``` --- ### Step 2: CD Deploy to Production **파일**: `.gitea/workflows/deploy-prod.yml` (μ‹ κ·œ) **μ‹€ν–‰ 쑰건**: `push main` (CI 톡과 ν›„) #### 2.1 Build Release Package ```yaml - Setup .NET 10.0.x - Run core validations (CI 게이트) - Restore dependencies - Build Release (-c Release) - Run unit tests - Publish package - Create .tar.gz archive ``` **μ‚°μΆœλ¬Ό**: `quant-engine-release-{run_number}.tar.gz` (24MB) #### 2.2 Deploy to Production ```yaml - Setup SSH authentication - Create backup (/var/www/quant_backup/) - Transfer archive via SCP - Extract to /var/www/quant/publish - Set permissions (www-data:www-data) - Restart nginx service ``` #### 2.3 Health Check & Verification ```yaml - HTTP 200 OK 확인 - MudBlazor λ¦¬μ†ŒμŠ€ λ‘œλ“œ 확인 - Page title 검증 - 배포 리포트 생성 ``` #### 2.4 Post-Deployment ```yaml - Performance metrics μˆ˜μ§‘ - Page load time μΈ‘μ • - Deployment checklist 생성 - Slack μ•Œλ¦Ό (μ˜΅μ…˜) ``` --- ## πŸ” Secrets & Environment Variables ### ν•„μˆ˜ Gitea Secrets ```yaml SSH_PRIVATE_KEY: - μ„€λͺ…: SSH 개인 ν‚€ (id_ed25519) - ν˜•μ‹: PEM format - κΆŒν•œ: 600 - 생성: ssh-keygen -t ed25519 -f ~/.ssh/id_ed25519 SLACK_WEBHOOK (선택사항): - μ„€λͺ…: Slack 배포 μ•Œλ¦Ό - ν˜•μ‹: https://hooks.slack.com/services/... - μš©λ„: 배포 μ™„λ£Œ μ•Œλ¦Ό ``` ### ν™˜κ²½ λ³€μˆ˜ ```yaml DEPLOY_HOST: 178.104.200.7 DEPLOY_USER: kjh2064 DEPLOY_PATH: /var/www/quant DOTNET_VERSION: 10.0.x ``` --- ## πŸ“Š 배포 ν”„λ‘œμ„ΈμŠ€ 상세 (μ‹œκ°„λ³„) ``` β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ 단계 β”‚ μ†Œμš”μ‹œκ°„ β”‚ μ„€λͺ… β”‚ β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ β”‚ CI 검증 β”‚ ~3λΆ„ β”‚ Spec/Registry/Coverage 검증 β”‚ β”‚ λΉŒλ“œ β”‚ ~2λΆ„ β”‚ Release λΉŒλ“œ (.NET) β”‚ β”‚ ν…ŒμŠ€νŠΈ β”‚ ~1λΆ„ β”‚ Unit tests μ‹€ν–‰ β”‚ β”‚ νŒ¨ν‚€μ§• β”‚ <1λΆ„ β”‚ Archive 생성 (24MB) β”‚ β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ β”‚ SSH μ€€λΉ„ β”‚ <1λΆ„ β”‚ SSH ν‚€ μ„€μ • β”‚ β”‚ λ°±μ—… 생성 β”‚ ~1λΆ„ β”‚ /var/www/quant_backup/ 생성 β”‚ β”‚ 파일 전솑 β”‚ ~2λΆ„ β”‚ rsync (24MB) β”‚ β”‚ μΆ”μΆœ/μ„€μΉ˜ β”‚ <1λΆ„ β”‚ tar μΆ”μΆœ, κΆŒν•œ μ„€μ • β”‚ β”‚ μž¬μ‹œμž‘ β”‚ ~3초 β”‚ nginx restart β”‚ β”‚ ν—¬μŠ€ 체크 β”‚ ~5초 β”‚ HTTP 200 OK 확인 (μ΅œλŒ€ 60초) β”‚ β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ β”‚ 총 μ†Œμš”μ‹œκ°„ β”‚ ~10λΆ„ β”‚ CIλΆ€ν„° 배포 μ™„λ£ŒκΉŒμ§€ β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ``` --- ## βœ… 배포 체크리슀트 ### 배포 μ „ (개발자) ``` [ ] λͺ¨λ“  변경사항 컀밋 [ ] main λΈŒλžœμΉ˜μ— push [ ] CI 검증 톡과 λŒ€κΈ° (~5λΆ„) ``` ### 배포 쀑 (μžλ™ν™”) ``` Gitea Actions: [ ] build-and-test job μ‹€ν–‰ [ ] λͺ¨λ“  검증 톡과 [ ] Release λΉŒλ“œ 생성 (24MB) [ ] μ•„ν‹°νŒ©νŠΈ μ €μž₯ [ ] deploy-to-prod job μ‹œμž‘ [ ] SSH μ—°κ²° 성곡 [ ] λ°±μ—… 생성 [ ] 파일 전솑 [ ] κΆŒν•œ μ„€μ • [ ] μ„œλΉ„μŠ€ μž¬μ‹œμž‘ [ ] ν—¬μŠ€ 체크 톡과 ``` ### 배포 ν›„ (운영자) ``` [ ] Dashboard 접속 확인 (http://178.104.200.7/quant/) [ ] KPI μΉ΄λ“œ λ Œλ”λ§ 확인 [ ] MudBlazor μŠ€νƒ€μΌ 적용 확인 [ ] λͺ¨λ“  ν…Œμ΄λΈ” ν‘œμ‹œ 확인 [ ] 둜그 μ—λŸ¬ μ—†μŒ 확인 (nginx) [ ] μ„±λŠ₯ λ©”νŠΈλ¦­ μ–‘ν˜Έ 확인 ``` --- ## πŸ”„ 배포 ν”„λ‘œμ„ΈμŠ€ 트리거 ### μžλ™ 배포 (ꢌμž₯) ```bash # main λΈŒλžœμΉ˜μ— push git push origin feature/dotnet-migration:main # β†’ Gitea Actions μžλ™ μ‹€ν–‰ # β†’ CI/CD νŒŒμ΄ν”„λΌμΈ μ‹œμž‘ # β†’ ~10λΆ„ ν›„ 배포 μ™„λ£Œ ``` ### μˆ˜λ™ 배포 (κΈ΄κΈ‰) ```bash # Gitea μ›Ή UIμ—μ„œ: # Actions β†’ deploy-prod β†’ Run workflow # λ˜λŠ” CLI: # (Gitea CLI μ„€μ • ν•„μš”) ``` --- ## 🚨 μ‹€νŒ¨ μ‹œ λŒ€μ‘ ### λΉŒλ“œ μ‹€νŒ¨ ``` 원인: 컴파일 였λ₯˜ ν•΄κ²°: 1. Gitea Actions 둜그 확인 2. λ‘œμ»¬μ—μ„œ μž¬ν˜„: dotnet build -c Release 3. 였λ₯˜ μˆ˜μ • 및 컀밋 4. main에 push ``` ### 배포 μ‹€νŒ¨ ``` 원인: SSH μ—°κ²° 였λ₯˜, λ””μŠ€ν¬ λΆ€μ‘± λ“± ν•΄κ²°: 1. SSH ν‚€ 확인: secrets.SSH_PRIVATE_KEY 2. 원격 μ„œλ²„ λ””μŠ€ν¬ 확인: df -h 3. nginx μƒνƒœ 확인: systemctl status nginx 4. ν•„μš”μ‹œ μˆ˜λ™ 볡ꡬ (μ•„λž˜ μ°Έκ³ ) ``` ### λΉ λ₯Έ 볡ꡬ (λ‘€λ°±) ```bash # 이전 λ²„μ „μœΌλ‘œ 볡원 ssh kjh2064@178.104.200.7 << 'EOF' LATEST=$(ls -t /var/www/quant_backup | head -1) sudo cp -r /var/www/quant_backup/$LATEST/* /var/www/quant/publish/ sudo systemctl restart nginx echo "βœ… Rolled back to: $LATEST" EOF ``` --- ## πŸ“ˆ λͺ¨λ‹ˆν„°λ§ & λ‘œκΉ… ### Gitea Actions 둜그 ``` Gitea μ›Ή UI: 1. Repository β†’ Actions 2. deploy-prod workflow 3. Latest run 클릭 4. Job 상세 둜그 확인 ``` ### nginx 둜그 (μ‹€μ‹œκ°„) ```bash # SSH둜 접속 ssh kjh2064@178.104.200.7 # μ—λŸ¬ 둜그 sudo tail -f /var/log/nginx/error.log # μ ‘κ·Ό 둜그 sudo tail -f /var/log/nginx/access.log # μƒνƒœ 확인 sudo systemctl status nginx ``` ### 배포 리포트 ``` Gitea Actions μ•„ν‹°νŒ©νŠΈ: - quant-engine-release-{run}.tar.gz - deployment-report.txt - post-deployment-checklist.txt ``` --- ## πŸ”‘ SSH ν‚€ μ„€μ • (졜초 1회) ### 1. λ‘œμ»¬μ—μ„œ ν‚€ 생성 ```bash ssh-keygen -t ed25519 -f ~/.ssh/id_ed25519 -N "" ``` ### 2. 곡개 ν‚€λ₯Ό 원격 μ„œλ²„μ— 등둝 ```bash ssh-copy-id -i ~/.ssh/id_ed25519 kjh2064@178.104.200.7 ``` ### 3. Gitea Secrets에 개인 ν‚€ 등둝 ```bash # Gitea μ›Ή UI: # Repository β†’ Settings β†’ Secrets β†’ SSH_PRIVATE_KEY # λ‚΄μš©: cat ~/.ssh/id_ed25519 (전체 볡사) ``` ### 4. ν…ŒμŠ€νŠΈ ```bash # λΉ„λ°€λ²ˆν˜Έ 없이 접속 확인 ssh kjh2064@178.104.200.7 "echo 'βœ… SSH μ—°κ²° 성곡'" ``` --- ## πŸ“Š 배포 톡계 ``` μ˜ˆμƒ 배포 μ‹œκ°„: ~10λΆ„ Release νŒ¨ν‚€μ§€ 크기: 24MB λ°±μ—… 보관 κΈ°κ°„: 30일 (μ΅œμ‹  5개) 배포 이λ ₯: Gitea Actionsμ—μ„œ 확인 κ°€λŠ₯ 배포 μ‹€νŒ¨μœ¨: < 5% (λ„€νŠΈμ›Œν¬ 였λ₯˜ μ œμ™Έ) 볡ꡬ μ‹œκ°„: < 2λΆ„ (λ‘€λ°±) ``` --- ## 🎯 배포 ν”„λ‘œμ„ΈμŠ€ μš”μ•½ | 단계 | λ‹΄λ‹Ή | μ‹œκ°„ | μƒνƒœ | |------|------|------|------| | Push to main | 개발자 | 1초 | μˆ˜λ™ | | CI 검증 | Gitea Actions | 5λΆ„ | μžλ™ | | Build Release | Gitea Actions | 2λΆ„ | μžλ™ | | Deploy to Prod | Gitea Actions | 3λΆ„ | μžλ™ | | Health Check | Gitea Actions | 1λΆ„ | μžλ™ | | **총계** | | **~10λΆ„** | **μžλ™** | --- ## πŸ”— κ΄€λ ¨ 파일 ``` .gitea/workflows/ β”œβ”€β”€ ci.yml (κΈ°μ‘΄ CI 검증) └── deploy-prod.yml (μ‹ κ·œ 배포 νŒŒμ΄ν”„λΌμΈ) 배포 κ΄€λ ¨ λ¬Έμ„œ: β”œβ”€β”€ DEPLOYMENT_GUIDE.md β”œβ”€β”€ DEPLOYMENT_STEPS.md └── DEPLOYMENT_CHECKLIST.md ``` --- ## ✨ μ£Όμš” κΈ°λŠ₯ ### μžλ™ν™” - βœ… μ½”λ“œ ν‘Έμ‹œ β†’ μžλ™ λΉŒλ“œ/ν…ŒμŠ€νŠΈ/배포 - βœ… μ‹€νŒ¨ μ‹œ μžλ™ μ•Œλ¦Ό (Slack) - βœ… μžλ™ λ°±μ—… 및 λ‘€λ°± μ€€λΉ„ ### μ•ˆμ „μ„± - βœ… SSH ν‚€ 기반 인증 - βœ… μžλ™ λ°±μ—… (5개 μœ μ§€) - βœ… λ‘€λ°± λͺ…λ Ήμ–΄ 제곡 - βœ… ν—¬μŠ€ 체크 (μ΅œλŒ€ 60초) ### κ°€μ‹œμ„± - βœ… Gitea Actions 둜그 - βœ… 배포 리포트 생성 - βœ… Post-deployment 체크리슀트 - βœ… Slack μ•Œλ¦Ό (μ˜΅μ…˜) --- ## πŸš€ 배포 μ‹œμž‘ ### μ‹œμž‘ 방법 ```bash # 1. 둜컬 변경사항 컀밋 git add . git commit -m "feat: v9 hardening release with CI/CD" # 2. main λΈŒλžœμΉ˜μ— ν‘Έμ‹œ git push origin feature/dotnet-migration:main # 3. Gitea Actions μžλ™ μ‹€ν–‰ # β†’ μ•½ 10λΆ„ ν›„ 배포 μ™„λ£Œ # β†’ http://178.104.200.7/quant/ 접속 κ°€λŠ₯ ``` --- **λ°°ν¬λŠ” 이제 CI/CDλ₯Ό ν†΅ν•΄μ„œλ§Œ μˆ˜ν–‰λ©λ‹ˆλ‹€.** λͺ¨λ“  배포가 μžλ™ν™”λ˜κ³ , Gitea Actionsμ—μ„œ 전체 ν”„λ‘œμ„ΈμŠ€κ°€ μΆ”μ λ©λ‹ˆλ‹€. πŸŽ‰