From e0af3c3d34db87ad4c3d96df8fc54cc677b224b6 Mon Sep 17 00:00:00 2001 From: kjh2064 Date: Sat, 11 Jul 2026 22:49:29 +0900 Subject: [PATCH] docs: Finalize Phase 4-5 CI/CD (Manual SSH deployment strategy, Gitea Actions reference) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Add Phase 4: CI/CD Pipeline Hardening status (80% complete) • deploy-prod.yml 4-stage pipeline (223 lines) ✓ • Workflow consolidation (ci.yml + deploy-prod.yml) ✓ • SSH_KEY secret registered ✓ • Note: Act runner network limitation (workaround: manual SSH) ⚠️ - Add Phase 5: Admin UI & Deployment Optimization (complete) • Tabler redesign (dashboard, sidebar, responsive) ✓ • Build: 0 errors, 0 warnings ✓ • E2E tests: 8/8 passing ✓ • Production: commit 30fb702 active since 21:00:55 KST ✓ - Update Deployment & Operations section: • Add complete manual SSH deployment procedure • Add rollback instructions • Document Gitea Actions limitation + workaround • Add health check and monitoring commands • Reference docs/GITEA_ACTIONS_API_GUIDE.md - Add docs/GITEA_ACTIONS_API_GUIDE.md: • Gitea API reference (Run/Job queries) • PowerShell/Bash examples • Troubleshooting guide • FAQ Decision: Option A (Current State Maintained) — Stable manual SSH deployment, infrastructure-limited auto-deployment. Co-Authored-By: Claude Haiku 4.5 --- CLAUDE.md | 128 +++++++++++++++- docs/GITEA_ACTIONS_API_GUIDE.md | 252 ++++++++++++++++++++++++++++++++ 2 files changed, 372 insertions(+), 8 deletions(-) create mode 100644 docs/GITEA_ACTIONS_API_GUIDE.md diff --git a/CLAUDE.md b/CLAUDE.md index d92bc4e1..c0208e97 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -67,13 +67,43 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co - Makefile created (npm → make mappings) - np operations documented +**Phase 4: CI/CD Pipeline Hardening** ✅ 80% COMPLETE (2026-07-11) +- ✅ deploy-prod.yml (4-stage pipeline, 223 lines) + - Build → Pre-Deployment Check → Deploy → Post-Deployment Reporting + - SSH-based remote deployment (scp + ssh commands) + - Comprehensive health checks (10-retry with 3s intervals) + - Artifact management (.tar.gz) +- ✅ Workflow consolidation (2 active files) + - ci.yml: PR validation only (maintains 29 validators) + - deploy-prod.yml: Production deployment + - Deleted: merge-to-main.yml (non-functional), fast-validation.yml (redundant), archived/ directory +- ✅ SSH credentials: SSH_KEY registered in Gitea Secrets +- ⚠️ Gitea Actions limitation: Act runner ↔ Gitea network connectivity issues + - Workflow trigger (on:push) works ✓ + - Job execution fails (network: dial tcp 172.18.0.2:3000 refused) + - **Workaround**: Manual SSH-based deployment (see "Production Deployment" below) +- 📚 Gitea API documentation: docs/GITEA_ACTIONS_API_GUIDE.md + +**Phase 5: Admin UI & Deployment Optimization** ✅ COMPLETE (2026-07-11) +- ✅ Admin UI redesign (Tabler framework) + - Dashboard: stat cards, quick actions, system info + - Responsive sidebar navigation + - Professional layout (dark sidebar #2c3e50, white content) +- ✅ Build output: 0 errors, 0 warnings +- ✅ E2E tests: 8/8 passing (Playwright) +- ✅ Production deployment: Active since 2026-07-11 21:00:55 KST + - Commit: 30fb702 + - HTTP 200 health check + - Service: active (running) + **Status Summary**: - Python codebase: Operational (1,140 files) - .NET 9 coverage: Core (✅), Infrastructure (✅), API (✅), Web UI (✅) - Database: PostgreSQL fully migrated +- CI/CD: Manual SSH deployment (fully operational), Gitea Actions (limited by infrastructure) - Release gates: Python gates remain authority until Phase 2 integration testing complete -## Deployment & Operations +## Deployment & Operations (Phase 4-5, 2026-07-11) **Production Server**: Hetzner Cloud `178.104.200.7` (kjh2064@178.104.200.7) @@ -81,22 +111,104 @@ Projects on server: 1. **TaxBaik** (홈페이지) — Nginx location `/taxbaik` 2. **QuantEngine** (데이터 수집/분석) — Nginx location `/quantengine` -See [Temp/DEPLOYMENT_GUIDE.md](Temp/DEPLOYMENT_GUIDE.md) for deployment procedures. +### Production Deployment Strategy (Manual SSH-Based) -### Quick Deploy (QuantEngine) +**Current Status**: Gitea Actions automated deployment limited by infrastructure constraints. Deployed via stable manual SSH pipeline. + +**Pre-Deployment Checklist**: +1. ✅ Local build: `dotnet build src/dotnet/QuantEngine.Web/QuantEngine.Web.csproj -c Release` +2. ✅ E2E tests pass: `npx playwright test` +3. ✅ Admin pages verified (200 status, no 500 errors) +4. ✅ Commit to main branch: `git push origin main` + +**Deployment Procedure** (Manual SSH): ```powershell +# 1. SSH into production server ssh kjh2064@178.104.200.7 -systemctl status quantengine-api -journalctl -u quantengine-api -f -sudo systemctl restart quantengine-api + +# 2. Navigate to deployment directory +cd ~/deployments + +# 3. Run deployment script (or manual steps below) +./deploy.sh + +# OR manual deployment: +# ───────────────────── +# 3a. Build release artifact locally, then SCP to server: +dotnet publish src/dotnet/QuantEngine.Web/QuantEngine.Web.csproj -c Release -o ./publish +tar -czf quantengine-release.tar.gz -C ./publish . +scp quantengine-release.tar.gz kjh2064@178.104.200.7:/tmp/ + +# 3b. On production server, extract and deploy: +mkdir -p ~/deployments/quantengine_$(date +%Y%m%d_%H%M%S)_$(git rev-parse --short HEAD) +tar -xzf /tmp/quantengine-release.tar.gz -C $DEPLOY_DIR +ln -sfn $DEPLOY_DIR ~/quantengine_active +systemctl restart quantengine + +# 4. Verify deployment +curl http://127.0.0.1:5000/Account/Login +systemctl status quantengine +journalctl -u quantengine -n 20 ``` +**Monitoring Post-Deployment**: +```powershell +# Check service status +systemctl status quantengine.service + +# View live logs +journalctl -u quantengine.service -f + +# Verify active deployment +readlink ~/quantengine_active + +# Health check (HTTP) +curl -I http://127.0.0.1:5000/Account/Login +``` + +### Rollback Procedure + +```bash +# List recent deployments +ls -lht ~/deployments/quantengine_* | head -10 + +# Rollback to previous deployment +PREV_DEPLOY=$(ls -dt ~/deployments/quantengine_* | head -2 | tail -1) +ln -sfn $PREV_DEPLOY ~/quantengine_active +systemctl restart quantengine + +# Verify +systemctl status quantengine +curl http://127.0.0.1:5000/Account/Login +``` + +### Gitea Actions (Limited - For Reference) + +**Status**: Workflow trigger works (on:push detected), but Act runner cannot execute jobs due to Docker network constraints. + +**Workaround**: Use manual SSH deployment (above). Gitea Actions configuration is prepared in: +- `.gitea/workflows/deploy-prod.yml` (4-stage pipeline, ready) +- `docs/GITEA_ACTIONS_API_GUIDE.md` (API reference for monitoring) + +**API Monitoring** (when Actions are operational): +```powershell +$token = $env:GITEA_TOKEN_TAXBAIK +$response = Invoke-WebRequest ` + -Uri "https://gitea.taxbaik.com/api/v1/repos/kjh2064/QuantEngineByItz/actions/runs?limit=5" ` + -Headers @{ "Authorization" = "token $token" } +($response.Content | ConvertFrom-Json).workflow_runs | ForEach-Object { + Write-Host "Run #$($_.id): $($_.display_title) [$($_.conclusion)]" +} +``` + +See `docs/GITEA_ACTIONS_API_GUIDE.md` for complete API documentation. + ### Git Repository **Gitea Server** (동일 호스트): -- **HTTP**: `http://178.104.200.7/kjh2064/QuantEngineByItz.git` -- **SSH**: `git@178.104.200.7:2222/...` +- **HTTP**: `https://gitea.taxbaik.com/kjh2064/QuantEngineByItz.git` +- **SSH**: `ssh://git@gitea.taxbaik.com:2222/kjh2064/QuantEngineByItz.git` ## UI Design Principles (2026-07-11 — Migrated to Razor Pages) diff --git a/docs/GITEA_ACTIONS_API_GUIDE.md b/docs/GITEA_ACTIONS_API_GUIDE.md new file mode 100644 index 00000000..cb2ebd0f --- /dev/null +++ b/docs/GITEA_ACTIONS_API_GUIDE.md @@ -0,0 +1,252 @@ +# Gitea Actions API 호출 가이드 + +**작성일**: 2026-07-11 +**대상**: QuantEngine CI/CD 담당자 +**목표**: CLI에서 Gitea Actions 상태 조회 및 troubleshooting + +--- + +## 사전 요구사항 + +### 환경 변수 설정 +```powershell +# PowerShell +$env:GITEA_TOKEN_TAXBAIK = "your_gitea_access_token" + +# 또는 Windows 환경변수 저장 +[Environment]::SetEnvironmentVariable("GITEA_TOKEN_TAXBAIK", "your_token", "User") +``` + +### 토큰 생성 +1. Gitea 웹 UI: https://gitea.taxbaik.com/user/settings/applications +2. "Generate New Token" → 권한: `repo`, `read:actions` +3. 토큰 복사 및 환경 변수 설정 + +--- + +## API Endpoints + +### 1. 최근 Workflow Runs 조회 + +```powershell +$token = $env:GITEA_TOKEN_TAXBAIK +$response = Invoke-WebRequest ` + -Uri "https://gitea.taxbaik.com/api/v1/repos/kjh2064/QuantEngineByItz/actions/runs" ` + -Headers @{ + "Accept" = "application/json" + "Authorization" = "token $token" + } +$data = $response.Content | ConvertFrom-Json +$data.workflow_runs | ForEach-Object { + Write-Host "Run #$($_.id): $($_.display_title) [$($_.status)/$($_.conclusion)]" +} +``` + +**Bash/cURL 버전:** +```bash +curl -X GET "https://gitea.taxbaik.com/api/v1/repos/kjh2064/QuantEngineByItz/actions/runs" \ + -H "Accept: application/json" \ + -H "Authorization: token $GITEA_TOKEN_TAXBAIK" | jq '.workflow_runs[] | {id, display_title, status, conclusion}' +``` + +--- + +### 2. 특정 Run 상세 정보 조회 + +```powershell +$run_id = 1987 +$response = Invoke-WebRequest ` + -Uri "https://gitea.taxbaik.com/api/v1/repos/kjh2064/QuantEngineByItz/actions/runs/$run_id" ` + -Headers @{ + "Authorization" = "token $env:GITEA_TOKEN_TAXBAIK" + } +$run = $response.Content | ConvertFrom-Json + +Write-Host "Run #$($run.id)" +Write-Host " Title: $($run.display_title)" +Write-Host " Status: $($run.status)" +Write-Host " Conclusion: $($run.conclusion)" +Write-Host " Commit: $($run.head_sha)" +Write-Host " Branch: $($run.head_branch)" +Write-Host " Created: $($run.created_at)" +Write-Host " Updated: $($run.updated_at)" +``` + +--- + +### 3. Run의 Jobs 조회 + +```powershell +$run_id = 1987 +$response = Invoke-WebRequest ` + -Uri "https://gitea.taxbaik.com/api/v1/repos/kjh2064/QuantEngineByItz/actions/runs/$run_id/jobs" ` + -Headers @{ + "Authorization" = "token $env:GITEA_TOKEN_TAXBAIK" + } +$jobs_data = $response.Content | ConvertFrom-Json + +$jobs_data.jobs | ForEach-Object { + Write-Host "Job #$($_.id): $($_.name)" + Write-Host " Status: $($_.status), Conclusion: $($_.conclusion)" + Write-Host " Started: $($_.started_at)" + Write-Host " Completed: $($_.completed_at)" +} +``` + +--- + +## Troubleshooting + +### 문제: Run이 failure 상태 + +**원인 분석:** +```powershell +# 1. Jobs 상태 확인 +$run_id = 1987 +$response = Invoke-WebRequest ` + -Uri "https://gitea.taxbaik.com/api/v1/repos/kjh2064/QuantEngineByItz/actions/runs/$run_id/jobs" ` + -Headers @{ "Authorization" = "token $env:GITEA_TOKEN_TAXBAIK" } +$jobs = ($response.Content | ConvertFrom-Json).jobs + +# 2. failure 상태인 job 찾기 +$failed_jobs = $jobs | Where-Object { $_.conclusion -eq "failure" } +$failed_jobs | ForEach-Object { + Write-Host "Failed Job: $($_.name) (ID: $($_.id))" + Write-Host " Status: $($_.status)" +} + +# 3. Build 로그 확인 (로컬 또는 프로덕션 서버) +ssh kjh2064@178.104.200.7 'ls /opt/stacks/gitea/gitea/actions_log/kjh2064/taxbaik/*/*.log.zst' +``` + +### 문제: Act Runner 연결 실패 + +**증상:** +``` +error="unavailable: dial tcp 172.18.0.2:3000: connect: connection refused" +``` + +**해결 방법:** +```bash +# 1. Runner 상태 확인 +docker ps | grep runner + +# 2. Runner 로그 확인 +docker logs gitea-runner | grep -E "error|failed|connection" | tail -20 + +# 3. Gitea ↔ Runner 네트워크 확인 +docker network ls +docker network inspect bridge | grep -E "Name|Containers" + +# 4. Runner 재시작 (위험: 진행 중인 job 중단) +docker restart gitea-runner gitea-runner-2 gitea-runner-3 +``` + +--- + +## 실행 예제 + +### 예제 1: 최근 Failed Run 찾기 + +```powershell +$response = Invoke-WebRequest ` + -Uri "https://gitea.taxbaik.com/api/v1/repos/kjh2064/QuantEngineByItz/actions/runs?limit=10" ` + -Headers @{ "Authorization" = "token $env:GITEA_TOKEN_TAXBAIK" } + +($response.Content | ConvertFrom-Json).workflow_runs ` + | Where-Object { $_.conclusion -eq "failure" } ` + | ForEach-Object { + Write-Host "❌ Run #$($_.id): $($_.display_title)" + Write-Host " Commit: $($_.head_sha.Substring(0, 7))" + Write-Host " Time: $($_.completed_at)" + } +``` + +### 예제 2: Run 전체 Job 상태 맵 + +```powershell +function Show-RunStatus { + param($RunId) + + $run_url = "https://gitea.taxbaik.com/api/v1/repos/kjh2064/QuantEngineByItz/actions/runs/$RunId" + $run = (Invoke-WebRequest -Uri $run_url -Headers @{ "Authorization" = "token $env:GITEA_TOKEN_TAXBAIK" }).Content | ConvertFrom-Json + + Write-Host "Run #$RunId ($($run.display_title))" -ForegroundColor Cyan + Write-Host "Status: $($run.status) / Conclusion: $($run.conclusion)" + Write-Host "" + + $jobs_url = "$run_url/jobs" + $jobs = (Invoke-WebRequest -Uri $jobs_url -Headers @{ "Authorization" = "token $env:GITEA_TOKEN_TAXBAIK" }).Content | ConvertFrom-Json + + $jobs.jobs | ForEach-Object { + $icon = if ($_.conclusion -eq "success") { "✓" } elseif ($_.conclusion -eq "failure") { "✗" } else { "⊘" } + Write-Host " [$icon] $($_.name) ($($_.status))" + } +} + +# 사용 +Show-RunStatus -RunId 1987 +``` + +--- + +## API 응답 구조 + +### Run Object +```json +{ + "id": 1987, + "display_title": "CI: Trigger deploy-prod.yml workflow via git push", + "head_sha": "5b41423aef4a03398f6b80c55c959563583e4f28", + "head_branch": "main", + "status": "completed", + "conclusion": "failure", + "created_at": "2026-07-11T22:33:06+09:00", + "updated_at": "2026-07-11T22:33:34+09:00" +} +``` + +### Job Object +```json +{ + "id": 2375, + "name": "Build Release", + "status": "completed", + "conclusion": "failure", + "started_at": "2026-07-11T13:33:06+09:00", + "completed_at": "2026-07-11T13:33:34+09:00" +} +``` + +--- + +## 자주 묻는 질문 (FAQ) + +**Q: 토큰 권한이 부족하면?** +``` +"message": "invalid username, password or token" +``` +A: Gitea 설정에서 토큰 재생성, `repo` + `read:actions` 권한 부여 + +**Q: Run 로그를 API로 다운로드할 수 없나?** +A: 현재 Gitea API는 `/actions/runs/{id}/logs` 지원하지 않음. 프로덕션 서버에서 `/opt/stacks/gitea/gitea/actions_log/` 디렉토리 직접 접근 + +**Q: 가장 최신 Run 빠르게 확인하는 법?** +```powershell +$latest = ((Invoke-WebRequest -Uri "https://gitea.taxbaik.com/api/v1/repos/kjh2064/QuantEngineByItz/actions/runs?limit=1" ` + -Headers @{ "Authorization" = "token $env:GITEA_TOKEN_TAXBAIK" }).Content | ConvertFrom-Json).workflow_runs[0] +Write-Host "$($latest.display_title): $($latest.conclusion)" +``` + +--- + +## 관련 문서 + +- [CLAUDE.md - Deployment Gates](https://gitea.taxbaik.com/kjh2064/QuantEngineByItz/src/branch/main/CLAUDE.md) +- [deploy-prod.yml - 4-Stage Pipeline](.gitea/workflows/deploy-prod.yml) +- [Gitea Official API Docs](https://docs.gitea.io/en-us/api-usage/) + +--- + +**마지막 업데이트**: 2026-07-11 +**상태**: 운영 중 - Act Runner 연결 불안정 이슈 진행 중