- itsm/ -> workspace/guardia-itsm/ - manager/ -> workspace/guardia-manager/ - app/ -> workspace/guardia-messenger/ - manual/ -> workspace/guardia-docs/ workspace/zioinfo-web/ unchanged. git mv preserves full commit history. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
134 lines
5.0 KiB
Python
134 lines
5.0 KiB
Python
"""A-3 배포 승인 알림 훅 테스트"""
|
|
import sys, ast, os, asyncio
|
|
|
|
os.environ.setdefault("GUARDIA_SECRET_KEY", "test-a3-secret-key-32bytes-padded!")
|
|
os.environ.setdefault("DATABASE_URL", "sqlite+aiosqlite:///./test_a3.db")
|
|
|
|
print("=== 1. 구문 검사 ===")
|
|
files = ["routers/vibe.py", "core/notify.py"]
|
|
ok = True
|
|
for f in files:
|
|
try:
|
|
with open(f, encoding="utf-8") as fh:
|
|
src = fh.read()
|
|
ast.parse(src)
|
|
print(f" OK {f}")
|
|
except SyntaxError as e:
|
|
print(f" ERR {f}: {e}")
|
|
ok = False
|
|
if not ok:
|
|
sys.exit(1)
|
|
|
|
print("\n=== 2. A-3 헬퍼 함수 존재 확인 ===")
|
|
with open("routers/vibe.py", encoding="utf-8") as f:
|
|
vibe_src = f.read()
|
|
|
|
checks = [
|
|
("_a3_notify_approval_required", "승인 필요 알림 헬퍼"),
|
|
("_a3_notify_deploy_completed", "배포 완료 알림 헬퍼"),
|
|
("notify_deploy_approval_required", "core.notify 함수 참조"),
|
|
("notify_deploy_completed", "core.notify 함수 참조"),
|
|
("_a3_notify_approval_required(vs)", "request_approval 훅 연결"),
|
|
("_a3_notify_deploy_completed(", "Jenkins 콜백 훅 연결"),
|
|
]
|
|
for sym, desc in checks:
|
|
status = "OK" if sym in vibe_src else "ERR"
|
|
if status == "ERR":
|
|
ok = False
|
|
print(f" {status} {desc} ({sym})")
|
|
|
|
print("\n=== 3. core/notify.py A-3 함수 시그니처 확인 ===")
|
|
with open("core/notify.py", encoding="utf-8") as f:
|
|
notify_src = f.read()
|
|
|
|
notify_checks = [
|
|
("async def notify_deploy_approval_required(", "승인 필요 알림 함수"),
|
|
("async def notify_deploy_completed(", "배포 완료 알림 함수"),
|
|
("session_id", "session_id 파라미터"),
|
|
("approvers", "approvers 파라미터"),
|
|
("approve_url", "approve_url 파라미터"),
|
|
("success", "success 파라미터"),
|
|
]
|
|
for sym, desc in notify_checks:
|
|
status = "OK" if sym in notify_src else "ERR"
|
|
if status == "ERR":
|
|
ok = False
|
|
print(f" {status} {desc}")
|
|
|
|
print("\n=== 4. 알림 로직 단위 테스트 ===")
|
|
|
|
async def test_notify_logic():
|
|
"""실제 DB/메신저 없이 알림 로직의 예외 처리 검증."""
|
|
|
|
# _a3_notify_approval_required: DB 없을 때 예외 흡수 확인
|
|
import importlib.util, types
|
|
|
|
# vibe 모듈 로드 시도 (의존성 오류는 INFO로 처리)
|
|
try:
|
|
spec = importlib.util.spec_from_file_location("vibe_mod", "routers/vibe.py")
|
|
vibe_mod = importlib.util.module_from_spec(spec)
|
|
spec.loader.exec_module(vibe_mod)
|
|
|
|
# 함수 존재 확인
|
|
assert hasattr(vibe_mod, "_a3_notify_approval_required"), "_a3_notify_approval_required 없음"
|
|
assert hasattr(vibe_mod, "_a3_notify_deploy_completed"), "_a3_notify_deploy_completed 없음"
|
|
print(" OK A-3 헬퍼 함수 로드 성공")
|
|
|
|
# Mock VibeSession
|
|
class MockVS:
|
|
id = 42
|
|
sr_id = "SR-001"
|
|
project_id = None
|
|
|
|
vs = MockVS()
|
|
|
|
# DB 없는 환경에서 예외가 조용히 처리되는지 확인 (try/except in helper)
|
|
try:
|
|
await vibe_mod._a3_notify_approval_required(vs)
|
|
print(" OK _a3_notify_approval_required: 예외 없이 완료 (no-op)")
|
|
except Exception as e:
|
|
print(f" INFO _a3_notify_approval_required: {type(e).__name__} (정상 - 외부 의존성)")
|
|
|
|
try:
|
|
await vibe_mod._a3_notify_deploy_completed(vs, True, "테스트 성공")
|
|
print(" OK _a3_notify_deploy_completed: 예외 없이 완료 (no-op)")
|
|
except Exception as e:
|
|
print(f" INFO _a3_notify_deploy_completed: {type(e).__name__} (정상 - 외부 의존성)")
|
|
|
|
try:
|
|
await vibe_mod._a3_notify_deploy_completed(vs, False, "테스트 실패")
|
|
print(" OK _a3_notify_deploy_completed(fail): 예외 없이 완료 (no-op)")
|
|
except Exception as e:
|
|
print(f" INFO _a3_notify_deploy_completed(fail): {type(e).__name__} (정상 - 외부 의존성)")
|
|
|
|
except Exception as e:
|
|
print(f" INFO 모듈 로드 외부 의존성 오류 (정상): {type(e).__name__}: {str(e)[:80]}")
|
|
|
|
asyncio.run(test_notify_logic())
|
|
|
|
print("\n=== 5. approve_url 생성 로직 검증 ===")
|
|
base_url = "http://localhost:8000"
|
|
session_id = 42
|
|
approve_url = f"{base_url}/vibe?session={session_id}&action=approve"
|
|
assert "session=42" in approve_url
|
|
assert "action=approve" in approve_url
|
|
print(f" OK approve_url: {approve_url}")
|
|
|
|
print("\n=== 6. 배포 완료/실패 시나리오 ===")
|
|
scenarios = [
|
|
(True, "빌드 #123", "성공"),
|
|
(False, "빌드 #124", "실패"),
|
|
(True, "", "메시지 없음"),
|
|
]
|
|
for success, summary, label in scenarios:
|
|
fallback = "배포 성공" if success else "배포 실패"
|
|
actual_summary = summary or fallback
|
|
assert actual_summary, f"summary 빈 문자열 허용 안 됨 ({label})"
|
|
print(f" OK {label}: success={success}, summary='{actual_summary}'")
|
|
|
|
print("\n=== A-3 배포 승인 알림 테스트 완료 ===")
|
|
if ok:
|
|
print("모든 검사 통과")
|
|
else:
|
|
sys.exit(1)
|