From aff388df2d182743a18a2fbb4a98f0053816c9bf Mon Sep 17 00:00:00 2001 From: kjh2064 Date: Sat, 4 Jul 2026 10:46:45 +0900 Subject: [PATCH] fix: stabilize green-blue deploy verification --- .gitea/workflows/deploy.yml | 54 ++++++++++++++++++++++++++++--------- deploy_gb.sh | 43 +++++++++++++++++++++++++++-- 2 files changed, 82 insertions(+), 15 deletions(-) diff --git a/.gitea/workflows/deploy.yml b/.gitea/workflows/deploy.yml index ca7083a..3d9b406 100644 --- a/.gitea/workflows/deploy.yml +++ b/.gitea/workflows/deploy.yml @@ -170,6 +170,7 @@ jobs: DEPLOY_HOME="/home/kjh2064" DEPLOY_DIR="\$DEPLOY_HOME/deployments/taxbaik_${TIMESTAMP}" TIMESTAMP="${TIMESTAMP}" + COMMIT="${COMMIT}" echo "--- [1/5] 압축 해제 ---" mkdir -p "\$DEPLOY_DIR" @@ -233,39 +234,57 @@ jobs: echo "--- [5/5] 헬스 체크 (최대 60초) ---" ATTEMPTS=20 for i in \$(seq 1 \$ATTEMPTS); do - STATUS=\$(curl -sf -o /dev/null -w '%{http_code}' http://127.0.0.1:5001/taxbaik/ 2>/dev/null || echo "000") + STATUS=\$(curl -sf -o /dev/null -w '%{http_code}' http://127.0.0.1:5001/taxbaik/healthz 2>/dev/null || echo "000") if [ "\$STATUS" = "200" ]; then - echo "✓ [1/4] 메인 페이지 로드 완료" + echo "✓ [1/6] 헬스 체크 완료" - # 검증 1: CSS 파일 로드 + # 검증 1: 메인 페이지 로드. 앱/프록시/PathBase 조합에서 canonical redirect가 + # 발생할 수 있으므로 리다이렉트를 따라가 최종 200을 검증한다. + MAIN_STATUS=\$(curl -fsSL -o /dev/null -w '%{http_code}' http://127.0.0.1:5001/taxbaik/ 2>/dev/null || echo "000") + if [ "\$MAIN_STATUS" != "200" ]; then + echo "❌ 메인 페이지 로드 실패 (상태: \$MAIN_STATUS)" >&2 + exit 1 + fi + echo "✓ [2/6] 메인 페이지 로드 완료" + + # 검증 2: CSS 파일 로드 CSS_STATUS=\$(curl -sf -o /dev/null -w '%{http_code}' http://127.0.0.1:5001/taxbaik/css/admin.css 2>/dev/null || echo "000") if [ "\$CSS_STATUS" != "200" ]; then echo "❌ CSS 파일 로드 실패 (상태: \$CSS_STATUS)" >&2 exit 1 fi - echo "✓ [2/4] CSS 파일 로드 완료" + echo "✓ [3/6] CSS 파일 로드 완료" - # 검증 2: 버전 정보 + # 검증 3: 버전 정보. 파일 존재만 보면 5001이 잘못된 구 프로세스를 + # 가리키는 장애를 놓치므로, HTTP 응답이 이번 커밋인지 확인한다. if [ ! -s "\$DEPLOY_DIR/wwwroot/version.json" ]; then echo "❌ version.json 누락" >&2 exit 1 fi - echo "✓ [3/4] 버전 정보 확인 완료" + VERSION_JSON=\$(curl -fsS http://127.0.0.1:5001/taxbaik/version.json 2>/dev/null || true) + if ! printf '%s' "\$VERSION_JSON" | grep -q "\"version\": \"\$COMMIT\""; then + echo "❌ 5001 프록시가 이번 배포 버전을 제공하지 않음" >&2 + echo " expected: \$COMMIT" >&2 + echo " actual: \$VERSION_JSON" >&2 + echo " 확인: 5001 포트가 TaxBaik.Proxy.dll인지, /home/kjh2064/taxbaik_port가 새 포트인지 점검" >&2 + exit 1 + fi + echo "✓ [4/6] 버전 정보 확인 완료" # 검증 4: 5001 프록시 확인 if ! ss -tlnp | grep -q ':5001 '; then echo "❌ 5001 프록시가 실행 중이 아님" >&2 exit 1 fi - echo "✓ [4/5] 5001 프록시 확인 완료" + echo "✓ [5/6] 5001 프록시 확인 완료" # 검증 5: 관리자 로그인 페이지 - LOGIN_STATUS=\$(curl -sf -o /dev/null -w '%{http_code}' http://127.0.0.1:5001/taxbaik/admin/login 2>/dev/null || echo "000") + LOGIN_STATUS=\$(curl -fsSL -o /dev/null -w '%{http_code}' http://127.0.0.1:5001/taxbaik/admin/login 2>/dev/null || echo "000") if [ "\$LOGIN_STATUS" != "200" ]; then echo "❌ 관리자 로그인 페이지 로드 실패 (상태: \$LOGIN_STATUS)" >&2 exit 1 fi - echo "✓ [5/5] 관리자 페이지 로드 완료" + echo "✓ [6/6] 관리자 페이지 로드 완료" echo "✓ 서비스 정상 (시도 \$i/\$ATTEMPTS)" # 구 배포 디렉토리 정리 (최근 5개 보존) @@ -275,10 +294,19 @@ jobs: fi if [ "\$i" -eq "\$ATTEMPTS" ]; then echo "=== FATAL: 서비스가 \$ATTEMPTS회 시도 후에도 응답하지 않음 ===" >&2 - echo "--- systemd 상태 ---" >&2 - systemctl is-active taxbaik >&2 || true - echo "--- 최근 로그 50줄 ---" >&2 - journalctl -u taxbaik --no-pager -n 50 >&2 + echo "--- 5001 listener ---" >&2 + ss -tlnp 2>/dev/null | grep ':5001 ' >&2 || true + echo "--- active port file ---" >&2 + cat "\$DEPLOY_HOME/taxbaik_port" >&2 || true + echo "--- 신규 앱 로그 ---" >&2 + ACTIVE_PORT=\$(cat "\$DEPLOY_HOME/taxbaik_port" 2>/dev/null | tr -d '[:space:]' || true) + if [ -n "\$ACTIVE_PORT" ] && [ -s "\$DEPLOY_DIR/web_\${ACTIVE_PORT}.log" ]; then + tail -n 80 "\$DEPLOY_DIR/web_\${ACTIVE_PORT}.log" >&2 + else + ls -la "\$DEPLOY_DIR" >&2 || true + fi + echo "--- proxy 로그 ---" >&2 + tail -n 80 "\$DEPLOY_HOME/taxbaik_proxy.log" >&2 || true exit 1 fi echo " 대기 중... (\$i/\$ATTEMPTS, HTTP \$STATUS)" diff --git a/deploy_gb.sh b/deploy_gb.sh index e40ac9a..4ed5adc 100644 --- a/deploy_gb.sh +++ b/deploy_gb.sh @@ -48,17 +48,56 @@ if [ ! -s "$DEPLOY_DIR/proxy/TaxBaik.Proxy.dll" ]; then exit 1 fi +is_taxbaik_proxy_on_5001() { + local pids + pids=$(ss -tlnp 2>/dev/null | grep ':5001 ' | grep -oP 'pid=\K\d+' | sort -u || true) + [ -n "$pids" ] || return 1 + + for pid in $pids; do + if tr '\0' ' ' < "/proc/$pid/cmdline" 2>/dev/null | grep -q 'TaxBaik.Proxy.dll'; then + return 0 + fi + done + + return 1 +} + # 0. Ensure the local TCP proxy exists and is running. # Nginx and external traffic always enter through 127.0.0.1:5001. -if ! ss -tln | grep -q ':5001 '; then +if ss -tln | grep -q ':5001 ' && ! is_taxbaik_proxy_on_5001; then + echo "⚠️ Port 5001 is occupied by a non-proxy process. Attempting to stop legacy taxbaik.service..." + echo " Current listener:" >&2 + ss -tlnp 2>/dev/null | grep ':5001 ' >&2 || true + + if command -v systemctl >/dev/null 2>&1 && systemctl is-active --quiet taxbaik 2>/dev/null; then + if command -v sudo >/dev/null 2>&1 && sudo -n true 2>/dev/null; then + sudo -n systemctl stop taxbaik || true + sudo -n systemctl disable taxbaik || true + sleep 2 + else + echo " sudo -n is unavailable; cannot stop legacy taxbaik.service automatically." >&2 + fi + fi + + if ss -tln | grep -q ':5001 ' && ! is_taxbaik_proxy_on_5001; then + echo "❌ Port 5001 is still occupied by a non-proxy process. Abort deploy to avoid routing traffic to the wrong app." >&2 + echo " Expected: TaxBaik.Proxy.dll on 127.0.0.1:5001" >&2 + echo " Manual fix: sudo systemctl stop taxbaik && sudo systemctl disable taxbaik" >&2 + ss -tlnp 2>/dev/null | grep ':5001 ' >&2 || true + exit 1 + fi +fi + +if ! is_taxbaik_proxy_on_5001; then echo "=== Starting proxy on 127.0.0.1:5001 ===" cd "$DEPLOY_DIR/proxy" nohup /usr/bin/dotnet TaxBaik.Proxy.dll > "$DEPLOY_HOME/taxbaik_proxy.log" 2>&1 & sleep 2 fi -if ! ss -tln | grep -q ':5001 '; then +if ! is_taxbaik_proxy_on_5001; then echo "❌ Proxy on 127.0.0.1:5001 is not running. Abort deploy." >&2 + ss -tlnp 2>/dev/null | grep ':5001 ' >&2 || true exit 1 fi